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