[Android] Added UMA for search by image context menu.
[chromium-blink-merge.git] / chrome / installer / util / master_preferences.cc
blobd345e95c63c6cf3db3b218d6f19ff3e463b348ea
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/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"
19 namespace {
21 const char kFirstRunTabs[] = "first_run_tabs";
23 base::LazyInstance<installer::MasterPreferences> g_master_preferences =
24 LAZY_INSTANCE_INITIALIZER;
26 bool GetURLFromValue(const base::Value* in_value, std::string* out_value) {
27 return in_value && out_value && in_value->GetAsString(out_value);
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;
36 const base::ListValue* value_list = NULL;
37 if (!prefs->GetList(name, &value_list))
38 return list;
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;
48 list.push_back(url_entry);
50 return list;
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;
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;
67 return static_cast<base::DictionaryValue*>(root.release());
70 } // namespace
72 namespace installer {
74 MasterPreferences::MasterPreferences() : distribution_(NULL),
75 preferences_read_from_file_(false),
76 chrome_(true),
77 chrome_app_launcher_(false),
78 chrome_frame_(false),
79 multi_install_(false) {
80 InitializeFromCommandLine(*CommandLine::ForCurrentProcess());
83 MasterPreferences::MasterPreferences(const CommandLine& cmd_line)
84 : distribution_(NULL),
85 preferences_read_from_file_(false),
86 chrome_(true),
87 chrome_app_launcher_(false),
88 chrome_frame_(false),
89 multi_install_(false) {
90 InitializeFromCommandLine(cmd_line);
93 MasterPreferences::MasterPreferences(const base::FilePath& prefs_path)
94 : distribution_(NULL),
95 preferences_read_from_file_(false),
96 chrome_(true),
97 chrome_app_launcher_(false),
98 chrome_frame_(false),
99 multi_install_(false) {
100 std::string json_data;
101 // Failure to read the file is ignored as |json_data| will be the empty string
102 // and the remainder of this MasterPreferences object should still be
103 // initialized as best as possible.
104 if (base::PathExists(prefs_path) &&
105 !file_util::ReadFileToString(prefs_path, &json_data)) {
106 LOG(ERROR) << "Failed to read preferences from " << prefs_path.value();
108 if (InitializeFromString(json_data))
109 preferences_read_from_file_ = true;
112 MasterPreferences::MasterPreferences(const std::string& prefs)
113 : distribution_(NULL),
114 preferences_read_from_file_(false),
115 chrome_(true),
116 chrome_app_launcher_(false),
117 chrome_frame_(false),
118 multi_install_(false) {
119 InitializeFromString(prefs);
122 MasterPreferences::~MasterPreferences() {
125 void MasterPreferences::InitializeFromCommandLine(const CommandLine& cmd_line) {
126 #if defined(OS_WIN)
127 if (cmd_line.HasSwitch(installer::switches::kInstallerData)) {
128 base::FilePath prefs_path(cmd_line.GetSwitchValuePath(
129 installer::switches::kInstallerData));
130 this->MasterPreferences::MasterPreferences(prefs_path);
131 } else {
132 master_dictionary_.reset(new base::DictionaryValue());
135 DCHECK(master_dictionary_.get());
137 // A simple map from command line switches to equivalent switches in the
138 // distribution dictionary. Currently all switches added will be set to
139 // 'true'.
140 static const struct CmdLineSwitchToDistributionSwitch {
141 const char* cmd_line_switch;
142 const char* distribution_switch;
143 } translate_switches[] = {
144 { installer::switches::kAutoLaunchChrome,
145 installer::master_preferences::kAutoLaunchChrome },
146 { installer::switches::kChromeAppHostDeprecated,
147 installer::master_preferences::kChromeAppHostDeprecated },
148 { installer::switches::kChromeAppLauncher,
149 installer::master_preferences::kChromeAppLauncher },
150 { installer::switches::kChrome,
151 installer::master_preferences::kChrome },
152 { installer::switches::kChromeFrame,
153 installer::master_preferences::kChromeFrame },
154 { installer::switches::kChromeFrameReadyMode,
155 installer::master_preferences::kChromeFrameReadyMode },
156 { installer::switches::kDisableLogging,
157 installer::master_preferences::kDisableLogging },
158 { installer::switches::kMsi,
159 installer::master_preferences::kMsi },
160 { installer::switches::kMultiInstall,
161 installer::master_preferences::kMultiInstall },
162 { installer::switches::kDoNotRegisterForUpdateLaunch,
163 installer::master_preferences::kDoNotRegisterForUpdateLaunch },
164 { installer::switches::kDoNotLaunchChrome,
165 installer::master_preferences::kDoNotLaunchChrome },
166 { installer::switches::kMakeChromeDefault,
167 installer::master_preferences::kMakeChromeDefault },
168 { installer::switches::kSystemLevel,
169 installer::master_preferences::kSystemLevel },
170 { installer::switches::kVerboseLogging,
171 installer::master_preferences::kVerboseLogging },
174 std::string name(installer::master_preferences::kDistroDict);
175 for (int i = 0; i < arraysize(translate_switches); ++i) {
176 if (cmd_line.HasSwitch(translate_switches[i].cmd_line_switch)) {
177 name.assign(installer::master_preferences::kDistroDict);
178 name.append(".").append(translate_switches[i].distribution_switch);
179 master_dictionary_->SetBoolean(name, true);
183 // See if the log file path was specified on the command line.
184 std::wstring str_value(cmd_line.GetSwitchValueNative(
185 installer::switches::kLogFile));
186 if (!str_value.empty()) {
187 name.assign(installer::master_preferences::kDistroDict);
188 name.append(".").append(installer::master_preferences::kLogFile);
189 master_dictionary_->SetString(name, str_value);
192 // Handle the special case of --system-level being implied by the presence of
193 // the kGoogleUpdateIsMachineEnvVar environment variable.
194 scoped_ptr<base::Environment> env(base::Environment::Create());
195 if (env != NULL) {
196 std::string is_machine_var;
197 env->GetVar(env_vars::kGoogleUpdateIsMachineEnvVar, &is_machine_var);
198 if (!is_machine_var.empty() && is_machine_var[0] == '1') {
199 VLOG(1) << "Taking system-level from environment.";
200 name.assign(installer::master_preferences::kDistroDict);
201 name.append(".").append(installer::master_preferences::kSystemLevel);
202 master_dictionary_->SetBoolean(name, true);
206 // Cache a pointer to the distribution dictionary. Ignore errors if any.
207 master_dictionary_->GetDictionary(installer::master_preferences::kDistroDict,
208 &distribution_);
210 InitializeProductFlags();
211 #endif
214 bool MasterPreferences::InitializeFromString(const std::string& json_data) {
215 if (!json_data.empty())
216 master_dictionary_.reset(ParseDistributionPreferences(json_data));
218 bool data_is_valid = true;
219 if (!master_dictionary_.get()) {
220 master_dictionary_.reset(new base::DictionaryValue());
221 data_is_valid = false;
222 } else {
223 // Cache a pointer to the distribution dictionary.
224 master_dictionary_->GetDictionary(
225 installer::master_preferences::kDistroDict, &distribution_);
228 InitializeProductFlags();
229 EnforceLegacyPreferences();
230 return data_is_valid;
233 void MasterPreferences::InitializeProductFlags() {
234 // Make sure we start out with the correct defaults.
235 multi_install_ = false;
236 chrome_frame_ = false;
237 chrome_app_launcher_ = false;
238 chrome_ = true;
240 GetBool(installer::master_preferences::kMultiInstall, &multi_install_);
241 GetBool(installer::master_preferences::kChromeFrame, &chrome_frame_);
243 GetBool(installer::master_preferences::kChromeAppLauncher,
244 &chrome_app_launcher_);
246 // The deprecated switch --app-host behaves like --app-launcher.
247 bool chrome_app_host = false;
248 GetBool(installer::master_preferences::kChromeAppHostDeprecated,
249 &chrome_app_host);
250 chrome_app_launcher_ = chrome_app_launcher_ || chrome_app_host;
252 // When multi-install is specified, the checks are pretty simple (in theory):
253 // In order to be installed/uninstalled, each product must have its switch
254 // present on the command line.
255 // Before multi-install was introduced however, we only supported installing
256 // two products, Chrome and Chrome Frame. For the time being we need to
257 // continue to support this mode where multi-install is not set.
258 // So, when multi-install is not set, we continue to support mutually
259 // exclusive installation of Chrome and Chrome Frame.
260 if (multi_install_) {
261 if (!GetBool(installer::master_preferences::kChrome, &chrome_))
262 chrome_ = false;
263 } else {
264 // If chrome-frame is on the command line however, we only install CF.
265 chrome_ = !chrome_frame_;
269 void MasterPreferences::EnforceLegacyPreferences() {
270 // If create_all_shortcuts was explicitly set to false, set
271 // do_not_create_(desktop|quick_launch)_shortcut to true.
272 bool create_all_shortcuts = true;
273 GetBool(installer::master_preferences::kCreateAllShortcuts,
274 &create_all_shortcuts);
275 if (!create_all_shortcuts) {
276 distribution_->SetBoolean(
277 installer::master_preferences::kDoNotCreateDesktopShortcut, true);
278 distribution_->SetBoolean(
279 installer::master_preferences::kDoNotCreateQuickLaunchShortcut, true);
283 bool MasterPreferences::GetBool(const std::string& name, bool* value) const {
284 bool ret = false;
285 if (distribution_)
286 ret = distribution_->GetBoolean(name, value);
287 return ret;
290 bool MasterPreferences::GetInt(const std::string& name, int* value) const {
291 bool ret = false;
292 if (distribution_)
293 ret = distribution_->GetInteger(name, value);
294 return ret;
297 bool MasterPreferences::GetString(const std::string& name,
298 std::string* value) const {
299 bool ret = false;
300 if (distribution_)
301 ret = (distribution_->GetString(name, value) && !value->empty());
302 return ret;
305 std::vector<std::string> MasterPreferences::GetFirstRunTabs() const {
306 return GetNamedList(kFirstRunTabs, master_dictionary_.get());
309 bool MasterPreferences::GetExtensionsBlock(
310 base::DictionaryValue** extensions) const {
311 return master_dictionary_->GetDictionary(
312 master_preferences::kExtensionsBlock, extensions);
315 std::string MasterPreferences::GetVariationsSeed() const {
316 std::string variations_seed;
317 master_dictionary_->GetString(prefs::kVariationsSeed, &variations_seed);
318 return variations_seed;
321 // static
322 const MasterPreferences& MasterPreferences::ForCurrentProcess() {
323 return g_master_preferences.Get();
326 } // namespace installer