Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / installer / util / master_preferences.cc
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 #include "chrome/installer/util/master_preferences.h"
6
7 #include "base/environment.h"
8 #include "base/files/file_util.h"
9 #include "base/json/json_string_value_serializer.h"
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/path_service.h"
13 #include "base/strings/string_util.h"
14 #include "chrome/common/env_vars.h"
15 #include "chrome/common/pref_names.h"
16 #include "chrome/installer/util/master_preferences_constants.h"
17 #include "chrome/installer/util/util_constants.h"
18
19 namespace {
20
21 const char kFirstRunTabs[] = "first_run_tabs";
22
23 base::LazyInstance<installer::MasterPreferences> g_master_preferences =
24     LAZY_INSTANCE_INITIALIZER;
25
26 bool GetURLFromValue(const base::Value* in_value, std::string* out_value) {
27   return in_value && out_value && in_value->GetAsString(out_value);
28 }
29
30 std::vector<std::string> GetNamedList(const char* name,
31                                       const base::DictionaryValue* prefs) {
32   std::vector<std::string> list;
33   if (!prefs)
34     return list;
35
36   const base::ListValue* value_list = NULL;
37   if (!prefs->GetList(name, &value_list))
38     return list;
39
40   list.reserve(value_list->GetSize());
41   for (size_t i = 0; i < value_list->GetSize(); ++i) {
42     const base::Value* entry;
43     std::string url_entry;
44     if (!value_list->Get(i, &entry) || !GetURLFromValue(entry, &url_entry)) {
45       NOTREACHED();
46       break;
47     }
48     list.push_back(url_entry);
49   }
50   return list;
51 }
52
53 base::DictionaryValue* ParseDistributionPreferences(
54     const std::string& json_data) {
55   JSONStringValueSerializer json(json_data);
56   std::string error;
57   scoped_ptr<base::Value> root(json.Deserialize(NULL, &error));
58   if (!root.get()) {
59     LOG(WARNING) << "Failed to parse master prefs file: " << error;
60     return NULL;
61   }
62   if (!root->IsType(base::Value::TYPE_DICTIONARY)) {
63     LOG(WARNING) << "Failed to parse master prefs file: "
64                  << "Root item must be a dictionary.";
65     return NULL;
66   }
67   return static_cast<base::DictionaryValue*>(root.release());
68 }
69
70 }  // namespace
71
72 namespace installer {
73
74 MasterPreferences::MasterPreferences() : distribution_(NULL),
75                                          preferences_read_from_file_(false),
76                                          chrome_(true),
77                                          chrome_app_launcher_(false),
78                                          multi_install_(false) {
79   InitializeFromCommandLine(*CommandLine::ForCurrentProcess());
80 }
81
82 MasterPreferences::MasterPreferences(const CommandLine& cmd_line)
83     : distribution_(NULL),
84       preferences_read_from_file_(false),
85       chrome_(true),
86       chrome_app_launcher_(false),
87       multi_install_(false) {
88   InitializeFromCommandLine(cmd_line);
89 }
90
91 MasterPreferences::MasterPreferences(const base::FilePath& prefs_path)
92     : distribution_(NULL),
93       preferences_read_from_file_(false),
94       chrome_(true),
95       chrome_app_launcher_(false),
96       multi_install_(false) {
97   std::string json_data;
98   // Failure to read the file is ignored as |json_data| will be the empty string
99   // and the remainder of this MasterPreferences object should still be
100   // initialized as best as possible.
101   if (base::PathExists(prefs_path) &&
102       !base::ReadFileToString(prefs_path, &json_data)) {
103     LOG(ERROR) << "Failed to read preferences from " << prefs_path.value();
104   }
105   if (InitializeFromString(json_data))
106     preferences_read_from_file_ = true;
107 }
108
109 MasterPreferences::MasterPreferences(const std::string& prefs)
110     : distribution_(NULL),
111       preferences_read_from_file_(false),
112       chrome_(true),
113       chrome_app_launcher_(false),
114       multi_install_(false) {
115   InitializeFromString(prefs);
116 }
117
118 MasterPreferences::~MasterPreferences() {
119 }
120
121 void MasterPreferences::InitializeFromCommandLine(const CommandLine& cmd_line) {
122 #if defined(OS_WIN)
123   if (cmd_line.HasSwitch(installer::switches::kInstallerData)) {
124     base::FilePath prefs_path(cmd_line.GetSwitchValuePath(
125         installer::switches::kInstallerData));
126     this->MasterPreferences::MasterPreferences(prefs_path);
127   } else {
128     master_dictionary_.reset(new base::DictionaryValue());
129   }
130
131   DCHECK(master_dictionary_.get());
132
133   // A simple map from command line switches to equivalent switches in the
134   // distribution dictionary.  Currently all switches added will be set to
135   // 'true'.
136   static const struct CmdLineSwitchToDistributionSwitch {
137     const char* cmd_line_switch;
138     const char* distribution_switch;
139   } translate_switches[] = {
140     { installer::switches::kAutoLaunchChrome,
141       installer::master_preferences::kAutoLaunchChrome },
142     { installer::switches::kChromeAppHostDeprecated,
143       installer::master_preferences::kChromeAppHostDeprecated },
144     { installer::switches::kChromeAppLauncher,
145       installer::master_preferences::kChromeAppLauncher },
146     { installer::switches::kChrome,
147       installer::master_preferences::kChrome },
148     { installer::switches::kDisableLogging,
149       installer::master_preferences::kDisableLogging },
150     { installer::switches::kMsi,
151       installer::master_preferences::kMsi },
152     { installer::switches::kMultiInstall,
153       installer::master_preferences::kMultiInstall },
154     { installer::switches::kDoNotRegisterForUpdateLaunch,
155       installer::master_preferences::kDoNotRegisterForUpdateLaunch },
156     { installer::switches::kDoNotLaunchChrome,
157       installer::master_preferences::kDoNotLaunchChrome },
158     { installer::switches::kMakeChromeDefault,
159       installer::master_preferences::kMakeChromeDefault },
160     { installer::switches::kSystemLevel,
161       installer::master_preferences::kSystemLevel },
162     { installer::switches::kVerboseLogging,
163       installer::master_preferences::kVerboseLogging },
164   };
165
166   std::string name(installer::master_preferences::kDistroDict);
167   for (int i = 0; i < arraysize(translate_switches); ++i) {
168     if (cmd_line.HasSwitch(translate_switches[i].cmd_line_switch)) {
169       name.assign(installer::master_preferences::kDistroDict);
170       name.append(".").append(translate_switches[i].distribution_switch);
171       master_dictionary_->SetBoolean(name, true);
172     }
173   }
174
175   // See if the log file path was specified on the command line.
176   std::wstring str_value(cmd_line.GetSwitchValueNative(
177       installer::switches::kLogFile));
178   if (!str_value.empty()) {
179     name.assign(installer::master_preferences::kDistroDict);
180     name.append(".").append(installer::master_preferences::kLogFile);
181     master_dictionary_->SetString(name, str_value);
182   }
183
184   // Handle the special case of --system-level being implied by the presence of
185   // the kGoogleUpdateIsMachineEnvVar environment variable.
186   scoped_ptr<base::Environment> env(base::Environment::Create());
187   if (env != NULL) {
188     std::string is_machine_var;
189     env->GetVar(env_vars::kGoogleUpdateIsMachineEnvVar, &is_machine_var);
190     if (!is_machine_var.empty() && is_machine_var[0] == '1') {
191       VLOG(1) << "Taking system-level from environment.";
192       name.assign(installer::master_preferences::kDistroDict);
193       name.append(".").append(installer::master_preferences::kSystemLevel);
194       master_dictionary_->SetBoolean(name, true);
195     }
196   }
197
198   // Cache a pointer to the distribution dictionary. Ignore errors if any.
199   master_dictionary_->GetDictionary(installer::master_preferences::kDistroDict,
200                                     &distribution_);
201
202   InitializeProductFlags();
203 #endif
204 }
205
206 bool MasterPreferences::InitializeFromString(const std::string& json_data) {
207   if (!json_data.empty())
208     master_dictionary_.reset(ParseDistributionPreferences(json_data));
209
210   bool data_is_valid = true;
211   if (!master_dictionary_.get()) {
212     master_dictionary_.reset(new base::DictionaryValue());
213     data_is_valid = false;
214   } else {
215     // Cache a pointer to the distribution dictionary.
216     master_dictionary_->GetDictionary(
217         installer::master_preferences::kDistroDict, &distribution_);
218   }
219
220   InitializeProductFlags();
221   EnforceLegacyPreferences();
222   return data_is_valid;
223 }
224
225 void MasterPreferences::InitializeProductFlags() {
226   // Make sure we start out with the correct defaults.
227   multi_install_ = false;
228   chrome_app_launcher_ = false;
229   chrome_ = true;
230
231   GetBool(installer::master_preferences::kMultiInstall, &multi_install_);
232
233   GetBool(installer::master_preferences::kChromeAppLauncher,
234           &chrome_app_launcher_);
235
236   // The deprecated switch --app-host behaves like --app-launcher.
237   bool chrome_app_host = false;
238   GetBool(installer::master_preferences::kChromeAppHostDeprecated,
239           &chrome_app_host);
240   chrome_app_launcher_ = chrome_app_launcher_ || chrome_app_host;
241
242   // When multi-install is specified, the checks are pretty simple (in theory):
243   // In order to be installed/uninstalled, each product must have its switch
244   // present on the command line.
245   // When multi-install is not set, operate on Chrome.
246   if (multi_install_) {
247     if (!GetBool(installer::master_preferences::kChrome, &chrome_))
248       chrome_ = false;
249   } else {
250     chrome_ = true;
251   }
252 }
253
254 void MasterPreferences::EnforceLegacyPreferences() {
255   // If create_all_shortcuts was explicitly set to false, set
256   // do_not_create_(desktop|quick_launch)_shortcut to true.
257   bool create_all_shortcuts = true;
258   GetBool(installer::master_preferences::kCreateAllShortcuts,
259           &create_all_shortcuts);
260   if (!create_all_shortcuts) {
261     distribution_->SetBoolean(
262         installer::master_preferences::kDoNotCreateDesktopShortcut, true);
263     distribution_->SetBoolean(
264         installer::master_preferences::kDoNotCreateQuickLaunchShortcut, true);
265   }
266
267   // If there is no entry for kURLsToRestoreOnStartup and there is one for
268   // kURLsToRestoreOnStartupOld, copy the old to the new.
269   const base::ListValue* startup_urls_list = NULL;
270   if (master_dictionary_ &&
271       !master_dictionary_->GetList(prefs::kURLsToRestoreOnStartup, NULL) &&
272       master_dictionary_->GetList(prefs::kURLsToRestoreOnStartupOld,
273                                   &startup_urls_list) &&
274       startup_urls_list) {
275     base::ListValue* new_startup_urls_list = startup_urls_list->DeepCopy();
276     master_dictionary_->Set(prefs::kURLsToRestoreOnStartup,
277                             new_startup_urls_list);
278   }
279 }
280
281 bool MasterPreferences::GetBool(const std::string& name, bool* value) const {
282   bool ret = false;
283   if (distribution_)
284     ret = distribution_->GetBoolean(name, value);
285   return ret;
286 }
287
288 bool MasterPreferences::GetInt(const std::string& name, int* value) const {
289   bool ret = false;
290   if (distribution_)
291     ret = distribution_->GetInteger(name, value);
292   return ret;
293 }
294
295 bool MasterPreferences::GetString(const std::string& name,
296                                   std::string* value) const {
297   bool ret = false;
298   if (distribution_)
299     ret = (distribution_->GetString(name, value) && !value->empty());
300   return ret;
301 }
302
303 std::vector<std::string> MasterPreferences::GetFirstRunTabs() const {
304   return GetNamedList(kFirstRunTabs, master_dictionary_.get());
305 }
306
307 bool MasterPreferences::GetExtensionsBlock(
308     base::DictionaryValue** extensions) const {
309   return master_dictionary_->GetDictionary(
310       master_preferences::kExtensionsBlock, extensions);
311 }
312
313 std::string MasterPreferences::GetVariationsSeed() const {
314   return ExtractPrefString(prefs::kVariationsSeed);
315 }
316
317 std::string MasterPreferences::GetVariationsSeedSignature() const {
318   return ExtractPrefString(prefs::kVariationsSeedSignature);
319 }
320
321 std::string MasterPreferences::ExtractPrefString(
322     const std::string& name) const {
323   std::string result;
324   scoped_ptr<base::Value> pref_value;
325   if (master_dictionary_->Remove(name, &pref_value)) {
326     if (!pref_value->GetAsString(&result))
327       NOTREACHED();
328   }
329   return result;
330 }
331
332 // static
333 const MasterPreferences& MasterPreferences::ForCurrentProcess() {
334   return g_master_preferences.Get();
335 }
336
337 }  // namespace installer