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