Revert 168224 - Update V8 to version 3.15.4.
[chromium-blink-merge.git] / chrome / browser / chromeos / customization_document.cc
blob932ec75268e9270ab0a5bf1fe4e7a99c62a1666f
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/customization_document.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/file_path.h"
10 #include "base/file_util.h"
11 #include "base/json/json_reader.h"
12 #include "base/logging.h"
13 #include "base/string_tokenizer.h"
14 #include "base/string_util.h"
15 #include "base/time.h"
16 #include "base/utf_string_conversions.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/chromeos/cros/cros_library.h"
19 #include "chrome/browser/chromeos/cros/network_library.h"
20 #include "chrome/browser/chromeos/login/wizard_controller.h"
21 #include "chrome/browser/chromeos/system/statistics_provider.h"
22 #include "chrome/browser/prefs/pref_service.h"
23 #include "chrome/browser/profiles/profile_manager.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "net/url_request/url_fetcher.h"
27 using content::BrowserThread;
29 // Manifest attributes names.
31 namespace {
33 const char kVersionAttr[] = "version";
34 const char kDefaultAttr[] = "default";
35 const char kInitialLocaleAttr[] = "initial_locale";
36 const char kInitialTimezoneAttr[] = "initial_timezone";
37 const char kKeyboardLayoutAttr[] = "keyboard_layout";
38 const char kRegistrationUrlAttr[] = "registration_url";
39 const char kHwidMapAttr[] = "hwid_map";
40 const char kHwidMaskAttr[] = "hwid_mask";
41 const char kSetupContentAttr[] = "setup_content";
42 const char kHelpPageAttr[] = "help_page";
43 const char kEulaPageAttr[] = "eula_page";
44 const char kAppContentAttr[] = "app_content";
45 const char kInitialStartPageAttr[] = "initial_start_page";
46 const char kSupportPageAttr[] = "support_page";
48 const char kAcceptedManifestVersion[] = "1.0";
50 const char kHardwareClass[] = "hardware_class";
52 // Path to OEM partner startup customization manifest.
53 const char kStartupCustomizationManifestPath[] =
54 "/opt/oem/etc/startup_manifest.json";
56 // URL where to fetch OEM services customization manifest from.
57 const char kServicesCustomizationManifestUrl[] =
58 "file:///opt/oem/etc/services_manifest.json";
60 // Name of local state option that tracks if services customization has been
61 // applied.
62 const char kServicesCustomizationAppliedPref[] = "ServicesCustomizationApplied";
64 // Maximum number of retries to fetch file if network is not available.
65 const int kMaxFetchRetries = 3;
67 // Delay between file fetch retries if network is not available.
68 const int kRetriesDelayInSec = 2;
70 } // anonymous namespace
72 namespace chromeos {
74 // CustomizationDocument implementation. ---------------------------------------
76 CustomizationDocument::CustomizationDocument(
77 const std::string& accepted_version)
78 : accepted_version_(accepted_version) {}
80 CustomizationDocument::~CustomizationDocument() {}
82 bool CustomizationDocument::LoadManifestFromFile(
83 const FilePath& manifest_path) {
84 std::string manifest;
85 if (!file_util::ReadFileToString(manifest_path, &manifest))
86 return false;
87 return LoadManifestFromString(manifest);
90 bool CustomizationDocument::LoadManifestFromString(
91 const std::string& manifest) {
92 int error_code = 0;
93 std::string error;
94 scoped_ptr<Value> root(base::JSONReader::ReadAndReturnError(manifest,
95 base::JSON_ALLOW_TRAILING_COMMAS, &error_code, &error));
96 if (error_code != base::JSONReader::JSON_NO_ERROR)
97 LOG(ERROR) << error;
98 DCHECK(root.get() != NULL);
99 if (root.get() == NULL)
100 return false;
101 DCHECK(root->GetType() == Value::TYPE_DICTIONARY);
102 if (root->GetType() == Value::TYPE_DICTIONARY) {
103 root_.reset(static_cast<DictionaryValue*>(root.release()));
104 std::string result;
105 if (root_->GetString(kVersionAttr, &result) &&
106 result == accepted_version_)
107 return true;
109 LOG(ERROR) << "Wrong customization manifest version";
110 root_.reset(NULL);
112 return false;
115 std::string CustomizationDocument::GetLocaleSpecificString(
116 const std::string& locale,
117 const std::string& dictionary_name,
118 const std::string& entry_name) const {
119 DictionaryValue* dictionary_content = NULL;
120 if (!root_.get() ||
121 !root_->GetDictionary(dictionary_name, &dictionary_content))
122 return std::string();
124 DictionaryValue* locale_dictionary = NULL;
125 if (dictionary_content->GetDictionary(locale, &locale_dictionary)) {
126 std::string result;
127 if (locale_dictionary->GetString(entry_name, &result))
128 return result;
131 DictionaryValue* default_dictionary = NULL;
132 if (dictionary_content->GetDictionary(kDefaultAttr, &default_dictionary)) {
133 std::string result;
134 if (default_dictionary->GetString(entry_name, &result))
135 return result;
138 return std::string();
141 // StartupCustomizationDocument implementation. --------------------------------
143 StartupCustomizationDocument::StartupCustomizationDocument()
144 : CustomizationDocument(kAcceptedManifestVersion) {
146 // Loading manifest causes us to do blocking IO on UI thread.
147 // Temporarily allow it until we fix http://crosbug.com/11103
148 base::ThreadRestrictions::ScopedAllowIO allow_io;
149 LoadManifestFromFile(FilePath(kStartupCustomizationManifestPath));
151 Init(chromeos::system::StatisticsProvider::GetInstance());
154 StartupCustomizationDocument::StartupCustomizationDocument(
155 chromeos::system::StatisticsProvider* statistics_provider,
156 const std::string& manifest)
157 : CustomizationDocument(kAcceptedManifestVersion) {
158 LoadManifestFromString(manifest);
159 Init(statistics_provider);
162 StartupCustomizationDocument::~StartupCustomizationDocument() {}
164 StartupCustomizationDocument* StartupCustomizationDocument::GetInstance() {
165 return Singleton<StartupCustomizationDocument,
166 DefaultSingletonTraits<StartupCustomizationDocument> >::get();
169 void StartupCustomizationDocument::Init(
170 chromeos::system::StatisticsProvider* statistics_provider) {
171 if (IsReady()) {
172 root_->GetString(kInitialLocaleAttr, &initial_locale_);
173 root_->GetString(kInitialTimezoneAttr, &initial_timezone_);
174 root_->GetString(kKeyboardLayoutAttr, &keyboard_layout_);
175 root_->GetString(kRegistrationUrlAttr, &registration_url_);
177 std::string hwid;
178 if (statistics_provider->GetMachineStatistic(kHardwareClass, &hwid)) {
179 ListValue* hwid_list = NULL;
180 if (root_->GetList(kHwidMapAttr, &hwid_list)) {
181 for (size_t i = 0; i < hwid_list->GetSize(); ++i) {
182 DictionaryValue* hwid_dictionary = NULL;
183 std::string hwid_mask;
184 if (hwid_list->GetDictionary(i, &hwid_dictionary) &&
185 hwid_dictionary->GetString(kHwidMaskAttr, &hwid_mask)) {
186 if (MatchPattern(hwid, hwid_mask)) {
187 // If HWID for this machine matches some mask, use HWID specific
188 // settings.
189 std::string result;
190 if (hwid_dictionary->GetString(kInitialLocaleAttr, &result))
191 initial_locale_ = result;
193 if (hwid_dictionary->GetString(kInitialTimezoneAttr, &result))
194 initial_timezone_ = result;
196 if (hwid_dictionary->GetString(kKeyboardLayoutAttr, &result))
197 keyboard_layout_ = result;
199 // Don't break here to allow other entires to be applied if match.
200 } else {
201 LOG(ERROR) << "Syntax error in customization manifest";
205 } else {
206 LOG(ERROR) << "HWID is missing in machine statistics";
210 // If manifest doesn't exist still apply values from VPD.
211 statistics_provider->GetMachineStatistic(kInitialLocaleAttr,
212 &initial_locale_);
213 statistics_provider->GetMachineStatistic(kInitialTimezoneAttr,
214 &initial_timezone_);
215 statistics_provider->GetMachineStatistic(kKeyboardLayoutAttr,
216 &keyboard_layout_);
219 std::string StartupCustomizationDocument::GetHelpPage(
220 const std::string& locale) const {
221 return GetLocaleSpecificString(locale, kSetupContentAttr, kHelpPageAttr);
224 std::string StartupCustomizationDocument::GetEULAPage(
225 const std::string& locale) const {
226 return GetLocaleSpecificString(locale, kSetupContentAttr, kEulaPageAttr);
229 // ServicesCustomizationDocument implementation. -------------------------------
231 ServicesCustomizationDocument::ServicesCustomizationDocument()
232 : CustomizationDocument(kAcceptedManifestVersion),
233 url_(kServicesCustomizationManifestUrl) {
236 ServicesCustomizationDocument::ServicesCustomizationDocument(
237 const std::string& manifest)
238 : CustomizationDocument(kAcceptedManifestVersion) {
239 LoadManifestFromString(manifest);
242 ServicesCustomizationDocument::~ServicesCustomizationDocument() {}
244 // static
245 ServicesCustomizationDocument* ServicesCustomizationDocument::GetInstance() {
246 return Singleton<ServicesCustomizationDocument,
247 DefaultSingletonTraits<ServicesCustomizationDocument> >::get();
250 // static
251 void ServicesCustomizationDocument::RegisterPrefs(PrefService* local_state) {
252 local_state->RegisterBooleanPref(kServicesCustomizationAppliedPref, false,
253 PrefService::UNSYNCABLE_PREF);
256 // static
257 bool ServicesCustomizationDocument::WasApplied() {
258 PrefService* prefs = g_browser_process->local_state();
259 return prefs->GetBoolean(kServicesCustomizationAppliedPref);
262 // static
263 void ServicesCustomizationDocument::SetApplied(bool val) {
264 PrefService* prefs = g_browser_process->local_state();
265 prefs->SetBoolean(kServicesCustomizationAppliedPref, val);
268 void ServicesCustomizationDocument::StartFetching() {
269 if (url_.SchemeIsFile()) {
270 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
271 base::Bind(&ServicesCustomizationDocument::ReadFileInBackground,
272 base::Unretained(this), // this class is a singleton.
273 FilePath(url_.path())));
274 } else {
275 StartFileFetch();
279 void ServicesCustomizationDocument::ReadFileInBackground(const FilePath& file) {
280 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
282 std::string manifest;
283 if (file_util::ReadFileToString(file, &manifest)) {
284 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
285 base::Bind(
286 base::IgnoreResult(
287 &ServicesCustomizationDocument::LoadManifestFromString),
288 base::Unretained(this), // this class is a singleton.
289 manifest));
290 } else {
291 VLOG(1) << "Failed to load services customization manifest from: "
292 << file.value();
296 void ServicesCustomizationDocument::StartFileFetch() {
297 DCHECK(url_.is_valid());
298 url_fetcher_.reset(net::URLFetcher::Create(
299 url_, net::URLFetcher::GET, this));
300 url_fetcher_->SetRequestContext(
301 ProfileManager::GetDefaultProfile()->GetRequestContext());
302 url_fetcher_->Start();
305 void ServicesCustomizationDocument::OnURLFetchComplete(
306 const net::URLFetcher* source) {
307 if (source->GetResponseCode() == 200) {
308 std::string data;
309 source->GetResponseAsString(&data);
310 LoadManifestFromString(data);
311 } else {
312 NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary();
313 if (!network->Connected() && num_retries_ < kMaxFetchRetries) {
314 num_retries_++;
315 retry_timer_.Start(FROM_HERE,
316 base::TimeDelta::FromSeconds(kRetriesDelayInSec),
317 this, &ServicesCustomizationDocument::StartFileFetch);
318 return;
320 LOG(ERROR) << "URL fetch for services customization failed:"
321 << " response code = " << source->GetResponseCode()
322 << " URL = " << source->GetURL().spec();
326 bool ServicesCustomizationDocument::ApplyCustomization() {
327 // TODO(dpolukhin): apply customized apps, exts and support page.
328 SetApplied(true);
329 return true;
332 std::string ServicesCustomizationDocument::GetInitialStartPage(
333 const std::string& locale) const {
334 return GetLocaleSpecificString(
335 locale, kAppContentAttr, kInitialStartPageAttr);
338 std::string ServicesCustomizationDocument::GetSupportPage(
339 const std::string& locale) const {
340 return GetLocaleSpecificString(
341 locale, kAppContentAttr, kSupportPageAttr);
344 } // namespace chromeos