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.
4
5#ifndef CHROME_BROWSER_CHROMEOS_CUSTOMIZATION_DOCUMENT_H_
6#define CHROME_BROWSER_CHROMEOS_CUSTOMIZATION_DOCUMENT_H_
7
8#include <string>
9#include <vector>
10
11#include "base/compiler_specific.h"
12#include "base/gtest_prod_util.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/memory/singleton.h"
15#include "base/memory/weak_ptr.h"
16#include "base/values.h"
17#include "net/url_request/url_fetcher_delegate.h"
18#include "url/gurl.h"
19
20class PrefRegistrySimple;
21class Profile;
22
23namespace base {
24class DictionaryValue;
25class FilePath;
26}
27
28namespace extensions {
29class ExternalLoader;
30}
31
32namespace net {
33class URLFetcher;
34}
35
36namespace user_prefs {
37class PrefRegistrySyncable;
38}
39
40// This test is in global namespace so it must be declared here.
41void Test__InitStartupCustomizationDocument(const std::string& manifest);
42
43namespace chromeos {
44
45class CustomizationWallpaperDownloader;
46class ServicesCustomizationExternalLoader;
47
48namespace system {
49class StatisticsProvider;
50}  // system
51
52// Base class for OEM customization document classes.
53class CustomizationDocument {
54 public:
55  virtual ~CustomizationDocument();
56
57  // Return true if the document was successfully fetched and parsed.
58  bool IsReady() const { return root_.get(); }
59
60 protected:
61  explicit CustomizationDocument(const std::string& accepted_version);
62
63  virtual bool LoadManifestFromFile(const base::FilePath& manifest_path);
64  virtual bool LoadManifestFromString(const std::string& manifest);
65
66  std::string GetLocaleSpecificString(const std::string& locale,
67                                      const std::string& dictionary_name,
68                                      const std::string& entry_name) const;
69
70  scoped_ptr<base::DictionaryValue> root_;
71
72  // Value of the "version" attribute that is supported.
73  // Otherwise config is not loaded.
74  std::string accepted_version_;
75
76 private:
77  DISALLOW_COPY_AND_ASSIGN(CustomizationDocument);
78};
79
80// OEM startup customization document class.
81// Now StartupCustomizationDocument is loaded in c-tor so just after create it
82// may be ready or not (if manifest is missing or corrupted) and this state
83// won't be changed later (i.e. IsReady() always return the same value).
84class StartupCustomizationDocument : public CustomizationDocument {
85 public:
86  static StartupCustomizationDocument* GetInstance();
87
88  std::string GetEULAPage(const std::string& locale) const;
89
90  // These methods can be called even if !IsReady(), in this case VPD values
91  // will be returned.
92  //
93  // Raw value of "initial_locale" like initial_locale="en-US,sv,da,fi,no" .
94  const std::string& initial_locale() const { return initial_locale_; }
95
96  // Vector of individual locale values.
97  const std::vector<std::string>& configured_locales() const;
98
99  // Default locale value (first value in initial_locale list).
100  const std::string& initial_locale_default() const;
101  const std::string& initial_timezone() const { return initial_timezone_; }
102  const std::string& keyboard_layout() const { return keyboard_layout_; }
103
104 private:
105  FRIEND_TEST_ALL_PREFIXES(StartupCustomizationDocumentTest, Basic);
106  FRIEND_TEST_ALL_PREFIXES(StartupCustomizationDocumentTest, VPD);
107  FRIEND_TEST_ALL_PREFIXES(StartupCustomizationDocumentTest, BadManifest);
108  FRIEND_TEST_ALL_PREFIXES(ServicesCustomizationDocumentTest, MultiLanguage);
109  friend class OobeLocalizationTest;
110  friend void ::Test__InitStartupCustomizationDocument(
111      const std::string& manifest);
112  friend struct DefaultSingletonTraits<StartupCustomizationDocument>;
113
114  // C-tor for singleton construction.
115  StartupCustomizationDocument();
116
117  // C-tor for test construction.
118  StartupCustomizationDocument(system::StatisticsProvider* provider,
119                               const std::string& manifest);
120
121  virtual ~StartupCustomizationDocument();
122
123  void Init(system::StatisticsProvider* provider);
124
125  // If |attr| exists in machine stat, assign it to |value|.
126  void InitFromMachineStatistic(const char* attr, std::string* value);
127
128  std::string initial_locale_;
129  std::vector<std::string> configured_locales_;
130  std::string initial_timezone_;
131  std::string keyboard_layout_;
132
133  DISALLOW_COPY_AND_ASSIGN(StartupCustomizationDocument);
134};
135
136// OEM services customization document class.
137// ServicesCustomizationDocument is fetched from network therefore it is not
138// ready just after creation. Fetching of the manifest should be initiated
139// outside this class by calling StartFetching() or EnsureCustomizationApplied()
140// methods.
141// User of the file should check IsReady before use it.
142class ServicesCustomizationDocument : public CustomizationDocument,
143                                      private net::URLFetcherDelegate {
144 public:
145  static ServicesCustomizationDocument* GetInstance();
146
147  // Registers preferences.
148  static void RegisterPrefs(PrefRegistrySimple* registry);
149  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
150
151  static const char kManifestUrl[];
152
153  // Return true if the customization was applied. Customization is applied only
154  // once per machine.
155  static bool WasOOBECustomizationApplied();
156
157  // If customization has not been applied, start fetching and applying.
158  void EnsureCustomizationApplied();
159
160  // Returns Closure with the EnsureCustomizationApplied() method.
161  base::Closure EnsureCustomizationAppliedClosure();
162
163  // Start fetching customization document.
164  void StartFetching();
165
166  // Apply customization and save in machine options that customization was
167  // applied successfully. Return true if customization was applied.
168  bool ApplyOOBECustomization();
169
170  // Returns true if default wallpaper URL attribute found in manifest.
171  // |out_url| is set to attribute value.
172  bool GetDefaultWallpaperUrl(GURL* out_url) const;
173
174  // Returns list of default apps.
175  bool GetDefaultApps(std::vector<std::string>* ids) const;
176
177  // Creates an extensions::ExternalLoader that will provide OEM default apps.
178  // Cache of OEM default apps stored in profile preferences.
179  extensions::ExternalLoader* CreateExternalLoader(Profile* profile);
180
181  // Returns the name of the folder for OEM apps for given |locale|.
182  std::string GetOemAppsFolderName(const std::string& locale) const;
183
184  // Initialize instance of ServicesCustomizationDocument for tests that will
185  // override singleton until ShutdownForTesting is called.
186  static void InitializeForTesting();
187
188  // Remove instance of ServicesCustomizationDocument for tests.
189  static void ShutdownForTesting();
190
191  // These methods are also called by WallpaperManager to get "global default"
192  // customized wallpaper path (and to init default wallpaper path from it)
193  // before first wallpaper is shown.
194  static base::FilePath GetCustomizedWallpaperCacheDir();
195  static base::FilePath GetCustomizedWallpaperDownloadedFileName();
196
197  CustomizationWallpaperDownloader* wallpaper_downloader_for_testing() {
198    return wallpaper_downloader_.get();
199  }
200
201 private:
202  friend struct DefaultSingletonTraits<ServicesCustomizationDocument>;
203  FRIEND_TEST_ALL_PREFIXES(CustomizationWallpaperDownloaderBrowserTest,
204                           OEMWallpaperIsPresent);
205  FRIEND_TEST_ALL_PREFIXES(CustomizationWallpaperDownloaderBrowserTest,
206                           OEMWallpaperRetryFetch);
207
208  typedef std::vector<base::WeakPtr<ServicesCustomizationExternalLoader> >
209      ExternalLoaders;
210
211  // Guard for a single application task (wallpaper downloading, for example).
212  class ApplyingTask;
213
214  // C-tor for singleton construction.
215  ServicesCustomizationDocument();
216
217  // C-tor for test construction.
218  explicit ServicesCustomizationDocument(const std::string& manifest);
219
220  virtual ~ServicesCustomizationDocument();
221
222  // Save applied state in machine settings.
223  static void SetApplied(bool val);
224
225  // Overriden from CustomizationDocument:
226  virtual bool LoadManifestFromString(const std::string& manifest) OVERRIDE;
227
228  // Overriden from net::URLFetcherDelegate:
229  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
230
231  // Initiate file fetching. Wait for online status.
232  void StartFileFetch();
233
234  // Initiate file fetching. Don't wait for online status.
235  void DoStartFileFetch();
236
237  // Executes on FILE thread and reads file to string.
238  static void ReadFileInBackground(
239      base::WeakPtr<ServicesCustomizationDocument> self,
240      const base::FilePath& file);
241
242  // Called on UI thread with results of ReadFileInBackground.
243  void OnManifesteRead(const std::string& manifest);
244
245  // Method called when manifest was successfully loaded.
246  void OnManifestLoaded();
247
248  // Returns list of default apps in ExternalProvider format.
249  static scoped_ptr<base::DictionaryValue> GetDefaultAppsInProviderFormat(
250      const base::DictionaryValue& root);
251
252  // Update cached manifest for |profile|.
253  void UpdateCachedManifest(Profile* profile);
254
255  // Customization document not found for give ID.
256  void OnCustomizationNotFound();
257
258  // Set OEM apps folder name for AppListSyncableService for |profile|.
259  void SetOemFolderName(Profile* profile, const base::DictionaryValue& root);
260
261  // Returns the name of the folder for OEM apps for given |locale|.
262  std::string GetOemAppsFolderNameImpl(
263      const std::string& locale,
264      const base::DictionaryValue& root) const;
265
266  // Start download of wallpaper image if needed.
267  void StartOEMWallpaperDownload(const GURL& wallpaper_url,
268                                 scoped_ptr<ApplyingTask> applying);
269
270  // Check that current customized wallpaper cache exists. Once wallpaper is
271  // downloaded, it's never updated (even if manifest is re-fetched).
272  // Start wallpaper download if needed.
273  void CheckAndApplyWallpaper();
274
275  // Intermediate function to pass the result of PathExists to ApplyWallpaper.
276  void OnCheckedWallpaperCacheExists(scoped_ptr<bool> exists,
277                                     scoped_ptr<ApplyingTask> applying);
278
279  // Called after downloaded wallpaper has been checked.
280  void ApplyWallpaper(bool default_wallpaper_file_exists,
281                      scoped_ptr<ApplyingTask> applying);
282
283  // Set Shell default wallpaper to customized.
284  // It's wrapped as a callback and passed as a parameter to
285  // CustomizationWallpaperDownloader.
286  void OnOEMWallpaperDownloaded(scoped_ptr<ApplyingTask> applying,
287                                bool success,
288                                const GURL& wallpaper_url);
289
290  // Register one of Customization applying tasks.
291  void ApplyingTaskStarted();
292
293  // Mark task finished and check for "all customization applied".
294  void ApplyingTaskFinished(bool success);
295
296  // Services customization manifest URL.
297  GURL url_;
298
299  // URLFetcher instance.
300  scoped_ptr<net::URLFetcher> url_fetcher_;
301
302  // How many times we already tried to fetch customization manifest file.
303  int num_retries_;
304
305  // Manifest fetch is already in progress.
306  bool fetch_started_;
307
308  // Delay between checks for network online state.
309  base::TimeDelta network_delay_;
310
311  // Known external loaders.
312  ExternalLoaders external_loaders_;
313
314  scoped_ptr<CustomizationWallpaperDownloader> wallpaper_downloader_;
315
316  // This is barrier until customization is applied.
317  // When number of finished tasks match number of started - customization is
318  // applied.
319  size_t apply_tasks_started_;
320  size_t apply_tasks_finished_;
321
322  // This is the number of successfully finished customization tasks.
323  // If it matches number of tasks finished - customization is applied
324  // successfully.
325  size_t apply_tasks_success_;
326
327  // Weak factory for callbacks.
328  base::WeakPtrFactory<ServicesCustomizationDocument> weak_ptr_factory_;
329
330  DISALLOW_COPY_AND_ASSIGN(ServicesCustomizationDocument);
331};
332
333}  // namespace chromeos
334
335#endif  // CHROME_BROWSER_CHROMEOS_CUSTOMIZATION_DOCUMENT_H_
336