1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/customization_document.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/file_path.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/json/json_reader.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_tokenizer.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_util.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/time.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/utf_string_conversions.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/browser_process.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/cros/cros_library.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/cros/network_library.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/login/wizard_controller.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/system_access.h"
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/pref_service.h"
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile_manager.h"
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/browser_thread.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Manifest attributes names.
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kVersionAttr[] = "version";
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst char kDefaultAttr[] = "default";
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kInitialLocaleAttr[] = "initial_locale";
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kInitialTimezoneAttr[] = "initial_timezone";
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kKeyboardLayoutAttr[] = "keyboard_layout";
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kRegistrationUrlAttr[] = "registration_url";
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kHwidMapAttr[] = "hwid_map";
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kHwidMaskAttr[] = "hwid_mask";
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kSetupContentAttr[] = "setup_content";
373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kHelpPageAttr[] = "help_page";
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kEulaPageAttr[] = "eula_page";
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst char kAppContentAttr[] = "app_content";
403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kInitialStartPageAttr[] = "initial_start_page";
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char kSupportPageAttr[] = "support_page";
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kAcceptedManifestVersion[] = "1.0";
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kHwid[] = "hwid";
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Carrier deals attributes.
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kCarrierDealsAttr[] = "carrier_deals";
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kDealLocaleAttr[] = "deal_locale";
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kTopUpURLAttr[] = "top_up_url";
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kNotificationCountAttr[] = "notification_count";
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kDealExpireDateAttr[] = "expire_date";
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kLocalizedContentAttr[] = "localized_content";
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kNotificationTextAttr[] = "notification_text";
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Path to OEM partner startup customization manifest.
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kStartupCustomizationManifestPath[] =
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "/opt/oem/etc/startup_manifest.json";
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// URL where to fetch OEM services customization manifest from.
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kServicesCustomizationManifestUrl[] =
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    "file:///opt/oem/etc/services_manifest.json";
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Name of local state option that tracks if services customization has been
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// applied.
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst char kServicesCustomizationAppliedPref[] = "ServicesCustomizationApplied";
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Maximum number of retries to fetch file if network is not available.
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kMaxFetchRetries = 3;
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Delay between file fetch retries if network is not available.
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst int kRetriesDelayInSec = 2;
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // anonymous namespace
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::ServicesCustomizationDocument);
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chromeos {
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// CustomizationDocument implementation. ---------------------------------------
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CustomizationDocument::LoadManifestFromFile(
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const FilePath& manifest_path) {
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string manifest;
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!file_util::ReadFileToString(manifest_path, &manifest))
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return LoadManifestFromString(manifest);
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CustomizationDocument::LoadManifestFromString(
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& manifest) {
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<Value> root(base::JSONReader::Read(manifest, true));
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(root.get() != NULL);
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (root.get() == NULL)
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(root->GetType() == Value::TYPE_DICTIONARY);
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (root->GetType() == Value::TYPE_DICTIONARY) {
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    root_.reset(static_cast<DictionaryValue*>(root.release()));
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::string result;
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (root_->GetString(kVersionAttr, &result) &&
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        result == kAcceptedManifestVersion)
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return true;
103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(ERROR) << "Wrong customization manifest version";
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    root_.reset(NULL);
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return false;
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstd::string CustomizationDocument::GetLocaleSpecificString(
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const std::string& locale,
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const std::string& dictionary_name,
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const std::string& entry_name) const {
114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DictionaryValue* dictionary_content = NULL;
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!root_.get() ||
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !root_->GetDictionary(dictionary_name, &dictionary_content))
117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return std::string();
118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DictionaryValue* locale_dictionary = NULL;
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (dictionary_content->GetDictionary(locale, &locale_dictionary)) {
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::string result;
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (locale_dictionary->GetString(entry_name, &result))
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return result;
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DictionaryValue* default_dictionary = NULL;
127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (dictionary_content->GetDictionary(kDefaultAttr, &default_dictionary)) {
128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::string result;
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (default_dictionary->GetString(entry_name, &result))
130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      return result;
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return std::string();
134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// StartupCustomizationDocument implementation. --------------------------------
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenStartupCustomizationDocument::StartupCustomizationDocument() {
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  {
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Loading manifest causes us to do blocking IO on UI thread.
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Temporarily allow it until we fix http://crosbug.com/11103
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::ThreadRestrictions::ScopedAllowIO allow_io;
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    LoadManifestFromFile(FilePath(kStartupCustomizationManifestPath));
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Init(SystemAccess::GetInstance());
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenStartupCustomizationDocument::StartupCustomizationDocument(
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    SystemAccess* system_access, const std::string& manifest) {
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  LoadManifestFromString(manifest);
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Init(system_access);
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenStartupCustomizationDocument* StartupCustomizationDocument::GetInstance() {
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return Singleton<StartupCustomizationDocument,
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DefaultSingletonTraits<StartupCustomizationDocument> >::get();
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid StartupCustomizationDocument::Init(SystemAccess* system_access) {
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!IsReady())
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  root_->GetString(kInitialLocaleAttr, &initial_locale_);
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  root_->GetString(kInitialTimezoneAttr, &initial_timezone_);
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  root_->GetString(kKeyboardLayoutAttr, &keyboard_layout_);
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  root_->GetString(kRegistrationUrlAttr, &registration_url_);
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string hwid;
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (system_access->GetMachineStatistic(kHwid, &hwid)) {
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ListValue* hwid_list = NULL;
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (root_->GetList(kHwidMapAttr, &hwid_list)) {
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      for (size_t i = 0; i < hwid_list->GetSize(); ++i) {
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        DictionaryValue* hwid_dictionary = NULL;
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        std::string hwid_mask;
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        if (hwid_list->GetDictionary(i, &hwid_dictionary) &&
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            hwid_dictionary->GetString(kHwidMaskAttr, &hwid_mask)) {
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          if (MatchPattern(hwid, hwid_mask)) {
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            // If HWID for this machine matches some mask, use HWID specific
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            // settings.
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            std::string result;
181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            if (hwid_dictionary->GetString(kInitialLocaleAttr, &result))
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              initial_locale_ = result;
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            if (hwid_dictionary->GetString(kInitialTimezoneAttr, &result))
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              initial_timezone_ = result;
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            if (hwid_dictionary->GetString(kKeyboardLayoutAttr, &result))
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen              keyboard_layout_ = result;
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          }
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          // Don't break here to allow other entires to be applied if match.
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        } else {
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          LOG(ERROR) << "Syntax error in customization manifest";
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        }
194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    LOG(ERROR) << "HWID is missing in machine statistics";
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  system_access->GetMachineStatistic(kInitialLocaleAttr, &initial_locale_);
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  system_access->GetMachineStatistic(kInitialTimezoneAttr, &initial_timezone_);
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  system_access->GetMachineStatistic(kKeyboardLayoutAttr, &keyboard_layout_);
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstd::string StartupCustomizationDocument::GetHelpPage(
206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const std::string& locale) const {
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return GetLocaleSpecificString(locale, kSetupContentAttr, kHelpPageAttr);
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstd::string StartupCustomizationDocument::GetEULAPage(
211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const std::string& locale) const {
212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return GetLocaleSpecificString(locale, kSetupContentAttr, kEulaPageAttr);
213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// ServicesCustomizationDocument implementation. -------------------------------
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenServicesCustomizationDocument::CarrierDeal::CarrierDeal(
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* deal_dict)
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : notification_count(0),
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      localized_strings(NULL) {
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  deal_dict->GetString(kDealLocaleAttr, &deal_locale);
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  deal_dict->GetString(kTopUpURLAttr, &top_up_url);
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  deal_dict->GetInteger(kNotificationCountAttr, &notification_count);
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string date_string;
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (deal_dict->GetString(kDealExpireDateAttr, &date_string)) {
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!base::Time::FromString(ASCIIToWide(date_string).c_str(), &expire_date))
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      LOG(ERROR) << "Error parsing deal_expire_date: " << date_string;
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  deal_dict->GetDictionary(kLocalizedContentAttr, &localized_strings);
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::string ServicesCustomizationDocument::CarrierDeal::GetLocalizedString(
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& locale, const std::string& id) const {
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string result;
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (localized_strings) {
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DictionaryValue* locale_dict = NULL;
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (localized_strings->GetDictionary(locale, &locale_dict) &&
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        locale_dict->GetString(id, &result)) {
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return result;
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else if (localized_strings->GetDictionary(kDefaultAttr, &locale_dict) &&
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               locale_dict->GetString(id, &result)) {
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return result;
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return result;
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenServicesCustomizationDocument::ServicesCustomizationDocument()
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  : url_(kServicesCustomizationManifestUrl),
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    initial_locale_(WizardController::GetInitialLocale()) {
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenServicesCustomizationDocument::ServicesCustomizationDocument(
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& manifest, const std::string& initial_locale)
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : initial_locale_(initial_locale) {
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  LoadManifestFromString(manifest);
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenServicesCustomizationDocument* ServicesCustomizationDocument::GetInstance() {
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return Singleton<ServicesCustomizationDocument,
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DefaultSingletonTraits<ServicesCustomizationDocument> >::get();
263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ServicesCustomizationDocument::RegisterPrefs(PrefService* local_state) {
267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  local_state->RegisterBooleanPref(kServicesCustomizationAppliedPref, false);
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ServicesCustomizationDocument::WasApplied() {
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  PrefService* prefs = g_browser_process->local_state();
273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return prefs->GetBoolean(kServicesCustomizationAppliedPref);
274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static
277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ServicesCustomizationDocument::SetApplied(bool val) {
278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  PrefService* prefs = g_browser_process->local_state();
279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  prefs->SetBoolean(kServicesCustomizationAppliedPref, val);
280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ServicesCustomizationDocument::StartFetching() {
283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (url_.SchemeIsFile()) {
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NewRunnableMethod(this,
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            &ServicesCustomizationDocument::ReadFileInBackground,
287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            FilePath(url_.path())));
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    StartFileFetch();
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ServicesCustomizationDocument::ReadFileInBackground(const FilePath& file) {
294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string manifest;
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (file_util::ReadFileToString(file, &manifest)) {
298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        NewRunnableMethod(
300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            this,
301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            &ServicesCustomizationDocument::LoadManifestFromString,
302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            manifest));
303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    VLOG(1) << "Failed to load services customization manifest from: "
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            << file.value();
306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ServicesCustomizationDocument::StartFileFetch() {
310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(url_.is_valid());
311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url_fetcher_.reset(new URLFetcher(url_, URLFetcher::GET, this));
312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url_fetcher_->set_request_context(
313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ProfileManager::GetDefaultProfile()->GetRequestContext());
314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url_fetcher_->Start();
315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid ServicesCustomizationDocument::OnURLFetchComplete(
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const URLFetcher* source,
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const GURL& url,
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const net::URLRequestStatus& status,
321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    int response_code,
322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const ResponseCookies& cookies,
323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& data) {
324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (response_code == 200) {
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    LoadManifestFromString(data);
326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    NetworkLibrary* network = CrosLibrary::Get()->GetNetworkLibrary();
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!network->Connected() && num_retries_ < kMaxFetchRetries) {
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      num_retries_++;
330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      retry_timer_.Start(base::TimeDelta::FromSeconds(kRetriesDelayInSec),
331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                         this, &ServicesCustomizationDocument::StartFileFetch);
332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    LOG(ERROR) << "URL fetch for services customization failed:"
335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               << " response code = " << response_code
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen               << " URL = " << url.spec();
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ServicesCustomizationDocument::ApplyCustomization() {
341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(dpolukhin): apply customized apps, exts and support page.
342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SetApplied(true);
343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
346dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstd::string ServicesCustomizationDocument::GetInitialStartPage(
347dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const std::string& locale) const {
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return GetLocaleSpecificString(
349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      locale, kAppContentAttr, kInitialStartPageAttr);
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
352dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstd::string ServicesCustomizationDocument::GetSupportPage(
353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const std::string& locale) const {
354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return GetLocaleSpecificString(
355dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      locale, kAppContentAttr, kSupportPageAttr);
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst ServicesCustomizationDocument::CarrierDeal*
359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenServicesCustomizationDocument::GetCarrierDeal(const std::string& carrier_id,
360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                              bool check_restrictions) const {
361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  CarrierDeals::const_iterator iter = carrier_deals_.find(carrier_id);
362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (iter != carrier_deals_.end()) {
363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    CarrierDeal* deal = iter->second;
364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (check_restrictions) {
365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Deal locale has to match initial_locale (= launch country).
366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (initial_locale_ != deal->deal_locale)
367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return NULL;
368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Make sure that deal is still active,
369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // i.e. if deal expire date is defined, check it.
370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!deal->expire_date.is_null() &&
371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          deal->expire_date <= base::Time::Now()) {
372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return NULL;
373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return deal;
376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return NULL;
378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool ServicesCustomizationDocument::LoadManifestFromString(
382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const std::string& manifest) {
383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!CustomizationDocument::LoadManifestFromString(manifest))
384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
385ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
386ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DictionaryValue* carriers = NULL;
387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (root_.get() && root_->GetDictionary(kCarrierDealsAttr, &carriers)) {
388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    for (DictionaryValue::key_iterator iter = carriers->begin_keys();
389ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen         iter != carriers->end_keys(); ++iter) {
390ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     DictionaryValue* carrier_deal = NULL;
391ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     if (carriers->GetDictionary(*iter, &carrier_deal)) {
392ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       carrier_deals_[*iter] = new CarrierDeal(carrier_deal);
393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     }
394ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen   }
395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
396ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
398ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace chromeos
400