blob: bcce7d8afa3bb17bf5eff200a2f6f806ffd9c420 [file] [log] [blame]
[email protected]5a20b192012-03-01 06:01:571// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]4a0765a2009-05-08 23:12:255#include "chrome/browser/shell_integration.h"
6
[email protected]c5efb952011-11-01 01:28:367#include "base/bind.h"
[email protected]28375ae2010-02-05 04:45:508#include "base/command_line.h"
thestig18dfb7a52014-08-26 10:44:049#include "base/files/file_util.h"
pmonette5207d8952016-03-22 15:53:0810#include "base/metrics/histogram.h"
[email protected]24a555b62013-06-10 22:01:1711#include "base/strings/string_util.h"
pmonette9c1457f2015-11-19 20:29:3112#include "base/strings/stringprintf.h"
[email protected]e309f312013-06-07 21:50:0813#include "base/strings/utf_string_conversions.h"
[email protected]124901f52013-03-27 14:42:1014#include "base/threading/thread_restrictions.h"
avi664c07b2015-12-26 02:18:3115#include "build/build_config.h"
[email protected]ba26a442013-02-20 15:32:5516#include "chrome/browser/policy/policy_path_parser.h"
[email protected]b96aa932009-08-12 21:34:4917#include "chrome/common/chrome_paths.h"
[email protected]28375ae2010-02-05 04:45:5018#include "chrome/common/chrome_switches.h"
brettwb1fc1b82016-02-02 00:19:0819#include "components/prefs/pref_service.h"
sdefresne9fb67692015-08-03 18:48:2220#include "components/version_info/version_info.h"
[email protected]c38831a12011-10-28 12:44:4921#include "content/public/browser/browser_thread.h"
initial.commit09911bf2008-07-26 23:55:2922
[email protected]931d1042013-04-05 17:50:4423#if defined(OS_CHROMEOS)
24#include "chromeos/chromeos_switches.h"
25#endif
26
[email protected]2f5bc322013-12-04 08:58:1527#if !defined(OS_WIN)
sdefresne9fb67692015-08-03 18:48:2228#include "chrome/common/channel_info.h"
[email protected]af39f002014-08-22 10:18:1829#include "chrome/grit/chromium_strings.h"
[email protected]2f5bc322013-12-04 08:58:1530#include "ui/base/l10n/l10n_util.h"
31#endif
32
[email protected]631bb742011-11-02 11:29:3933using content::BrowserThread;
34
pmonette9fa59e882016-02-10 00:12:1935namespace shell_integration {
36
pmonette034a03d92015-10-02 21:04:2737namespace {
38
pmonette9fa59e882016-02-10 00:12:1939const struct AppModeInfo* gAppModeInfo = nullptr;
pmonette034a03d92015-10-02 21:04:2740
41} // namespace
42
43#if !defined(OS_WIN)
pmonette9fa59e882016-02-10 00:12:1944bool SetAsDefaultBrowserInteractive() {
pmonette034a03d92015-10-02 21:04:2745 return false;
46}
47
pmonette9fa59e882016-02-10 00:12:1948bool SetAsDefaultProtocolClientInteractive(const std::string& protocol) {
pmonette034a03d92015-10-02 21:04:2749 return false;
50}
51#endif // !defined(OS_WIN)
52
pmonette9fa59e882016-02-10 00:12:1953DefaultWebClientSetPermission CanSetAsDefaultProtocolClient() {
[email protected]a01481b2011-07-15 04:30:0254 // Allowed as long as the browser can become the operating system default
55 // browser.
pmonette5207d8952016-03-22 15:53:0856 return CanSetAsDefaultBrowser();
[email protected]a01481b2011-07-15 04:30:0257}
58
pmonette034a03d92015-10-02 21:04:2759#if !defined(OS_WIN)
pmonette9fa59e882016-02-10 00:12:1960bool IsElevationNeededForSettingDefaultProtocolClient() {
pmonette034a03d92015-10-02 21:04:2761 return false;
62}
63#endif // !defined(OS_WIN)
[email protected]9561bc912012-03-07 02:41:1664
pmonette9fa59e882016-02-10 00:12:1965void SetAppModeInfo(const struct AppModeInfo* info) {
[email protected]9561bc912012-03-07 02:41:1666 gAppModeInfo = info;
67}
68
pmonette9fa59e882016-02-10 00:12:1969const struct AppModeInfo* AppModeInfo() {
[email protected]9561bc912012-03-07 02:41:1670 return gAppModeInfo;
71}
72
pmonette9fa59e882016-02-10 00:12:1973bool IsRunningInAppMode() {
[email protected]9561bc912012-03-07 02:41:1674 return gAppModeInfo != NULL;
75}
76
pmonette9fa59e882016-02-10 00:12:1977base::CommandLine CommandLineArgsForLauncher(
[email protected]2f1c09d2011-01-14 14:58:1478 const GURL& url,
[email protected]5c93a0c12012-05-02 19:45:2479 const std::string& extension_app_id,
[email protected]650b2d52013-02-10 03:41:4580 const base::FilePath& profile_path) {
[email protected]124901f52013-03-27 14:42:1081 base::ThreadRestrictions::AssertIOAllowed();
avi556c05022014-12-22 23:31:4382 base::CommandLine new_cmd_line(base::CommandLine::NO_PROGRAM);
[email protected]28375ae2010-02-05 04:45:5083
[email protected]fb06aea82014-02-26 15:48:4784 AppendProfileArgs(
85 extension_app_id.empty() ? base::FilePath() : profile_path,
86 &new_cmd_line);
[email protected]28375ae2010-02-05 04:45:5087
88 // If |extension_app_id| is present, we use the kAppId switch rather than
89 // the kApp switch (the launch url will be read from the extension app
90 // during launch.
[email protected]ec5b50d2010-10-09 16:35:1891 if (!extension_app_id.empty()) {
[email protected]b10392932011-03-08 21:28:1492 new_cmd_line.AppendSwitchASCII(switches::kAppId, extension_app_id);
[email protected]64048bd2010-03-08 23:28:5893 } else {
[email protected]28375ae2010-02-05 04:45:5094 // Use '--app=url' instead of just 'url' to launch the browser with minimal
95 // chrome.
96 // Note: Do not change this flag! Old Gears shortcuts will break if you do!
[email protected]b10392932011-03-08 21:28:1497 new_cmd_line.AppendSwitchASCII(switches::kApp, url.spec());
[email protected]28375ae2010-02-05 04:45:5098 }
[email protected]b10392932011-03-08 21:28:1499 return new_cmd_line;
[email protected]28375ae2010-02-05 04:45:50100}
101
pmonette9fa59e882016-02-10 00:12:19102void AppendProfileArgs(const base::FilePath& profile_path,
103 base::CommandLine* command_line) {
[email protected]fb06aea82014-02-26 15:48:47104 DCHECK(command_line);
avi556c05022014-12-22 23:31:43105 const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess();
[email protected]fb06aea82014-02-26 15:48:47106
107 // Use the same UserDataDir for new launches that we currently have set.
108 base::FilePath user_data_dir =
109 cmd_line.GetSwitchValuePath(switches::kUserDataDir);
110#if defined(OS_MACOSX) || defined(OS_WIN)
111 policy::path_parser::CheckUserDataDirPolicy(&user_data_dir);
112#endif
113 if (!user_data_dir.empty()) {
114 // Make sure user_data_dir is an absolute path.
115 user_data_dir = base::MakeAbsoluteFilePath(user_data_dir);
116 if (!user_data_dir.empty() && base::PathExists(user_data_dir))
117 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
118 }
119
120#if defined(OS_CHROMEOS)
121 base::FilePath profile = cmd_line.GetSwitchValuePath(
122 chromeos::switches::kLoginProfile);
123 if (!profile.empty())
124 command_line->AppendSwitchPath(chromeos::switches::kLoginProfile, profile);
125#else
126 if (!profile_path.empty())
127 command_line->AppendSwitchPath(switches::kProfileDirectory,
128 profile_path.BaseName());
129#endif
130}
131
[email protected]bd046bd42012-06-08 05:07:32132#if !defined(OS_WIN)
pmonette9fa59e882016-02-10 00:12:19133base::string16 GetAppShortcutsSubdirName() {
sdefresne9fb67692015-08-03 18:48:22134 if (chrome::GetChannel() == version_info::Channel::CANARY)
[email protected]2f5bc322013-12-04 08:58:15135 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME_CANARY);
136 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME);
137}
pmonette868ca642015-09-02 14:34:02138#endif // !defined(OS_WIN)
[email protected]bd046bd42012-06-08 05:07:32139
pmonette034a03d92015-10-02 21:04:27140///////////////////////////////////////////////////////////////////////////////
pmonette9fa59e882016-02-10 00:12:19141// DefaultWebClientWorker
[email protected]d24c4012009-07-28 01:57:31142//
initial.commit09911bf2008-07-26 23:55:29143
pmonette9fa59e882016-02-10 00:12:19144void DefaultWebClientWorker::StartCheckIsDefault() {
pmonette9c1457f2015-11-19 20:29:31145 BrowserThread::PostTask(
146 BrowserThread::FILE, FROM_HERE,
147 base::Bind(&DefaultWebClientWorker::CheckIsDefault, this));
[email protected]4468a5b2011-05-26 07:48:02148}
149
pmonette9fa59e882016-02-10 00:12:19150void DefaultWebClientWorker::StartSetAsDefault() {
pmonette8db6a8be2016-02-11 01:50:31151 BrowserThread::PostTask(
152 BrowserThread::FILE, FROM_HERE,
153 base::Bind(&DefaultWebClientWorker::SetAsDefault, this));
initial.commit09911bf2008-07-26 23:55:29154}
155
[email protected]d24c4012009-07-28 01:57:31156///////////////////////////////////////////////////////////////////////////////
pmonette5207d8952016-03-22 15:53:08157// DefaultWebClientWorker, protected:
[email protected]d24c4012009-07-28 01:57:31158
pmonette5207d8952016-03-22 15:53:08159DefaultWebClientWorker::DefaultWebClientWorker(
160 const DefaultWebClientWorkerCallback& callback,
161 const char* worker_name)
162 : callback_(callback), worker_name_(worker_name) {}
163
164DefaultWebClientWorker::~DefaultWebClientWorker() = default;
[email protected]d24c4012009-07-28 01:57:31165
pmonette9fa59e882016-02-10 00:12:19166void DefaultWebClientWorker::OnCheckIsDefaultComplete(
[email protected]4468a5b2011-05-26 07:48:02167 DefaultWebClientState state) {
thestig00844cea2015-09-08 21:44:52168 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]264f74d12009-09-04 23:39:58169 UpdateUI(state);
pmonette9c1457f2015-11-19 20:29:31170
171 if (check_default_should_report_success_) {
172 check_default_should_report_success_ = false;
173
174 ReportAttemptResult(state == DefaultWebClientState::IS_DEFAULT
175 ? AttemptResult::SUCCESS
176 : AttemptResult::NO_ERRORS_NOT_DEFAULT);
177 }
[email protected]d24c4012009-07-28 01:57:31178}
179
pmonette9fa59e882016-02-10 00:12:19180void DefaultWebClientWorker::OnSetAsDefaultAttemptComplete(
pmonettef89ac7c72015-10-06 03:22:01181 AttemptResult result) {
thestig00844cea2015-09-08 21:44:52182 DCHECK_CURRENTLY_ON(BrowserThread::UI);
pmonettef89ac7c72015-10-06 03:22:01183
pmonette5207d8952016-03-22 15:53:08184 // Report failures here. Successes are reported in
185 // OnCheckIsDefaultComplete() after checking that the change is verified.
186 check_default_should_report_success_ = result == AttemptResult::SUCCESS;
187 if (!check_default_should_report_success_)
188 ReportAttemptResult(result);
pmonettef89ac7c72015-10-06 03:22:01189
pmonette5207d8952016-03-22 15:53:08190 // Start the default browser check. The default state will be reported to
191 // the caller via the |callback_|.
192 StartCheckIsDefault();
193}
pmonettef89ac7c72015-10-06 03:22:01194
pmonette5207d8952016-03-22 15:53:08195///////////////////////////////////////////////////////////////////////////////
196// DefaultWebClientWorker, private:
pmonettef89ac7c72015-10-06 03:22:01197
pmonette5207d8952016-03-22 15:53:08198void DefaultWebClientWorker::CheckIsDefault() {
199 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
200 DefaultWebClientState state = CheckIsDefaultImpl();
201 BrowserThread::PostTask(
202 BrowserThread::UI, FROM_HERE,
203 base::Bind(&DefaultBrowserWorker::OnCheckIsDefaultComplete, this, state));
204}
205
206void DefaultWebClientWorker::SetAsDefault() {
207 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
208 AttemptResult result = SetAsDefaultImpl();
209 BrowserThread::PostTask(
210 BrowserThread::UI, FROM_HERE,
211 base::Bind(&DefaultBrowserWorker::OnSetAsDefaultAttemptComplete, this,
212 result));
[email protected]d24c4012009-07-28 01:57:31213}
214
pmonette9fa59e882016-02-10 00:12:19215void DefaultWebClientWorker::ReportAttemptResult(AttemptResult result) {
pmonette9c1457f2015-11-19 20:29:31216 base::LinearHistogram::FactoryGet(
pmonette5207d8952016-03-22 15:53:08217 base::StringPrintf("%s.SetDefaultResult", worker_name_), 1,
pmonette9c1457f2015-11-19 20:29:31218 AttemptResult::NUM_ATTEMPT_RESULT_TYPES,
219 AttemptResult::NUM_ATTEMPT_RESULT_TYPES + 1,
220 base::HistogramBase::kUmaTargetedHistogramFlag)
221 ->Add(result);
pmonettef89ac7c72015-10-06 03:22:01222}
223
pmonette9fa59e882016-02-10 00:12:19224void DefaultWebClientWorker::UpdateUI(DefaultWebClientState state) {
pmonettef9461d1a2016-03-08 18:13:47225 if (!callback_.is_null()) {
226 switch (state) {
227 case NOT_DEFAULT:
pmonetteb9204142016-03-08 20:02:44228 callback_.Run(NOT_DEFAULT);
pmonettef9461d1a2016-03-08 18:13:47229 break;
230 case IS_DEFAULT:
pmonetteb9204142016-03-08 20:02:44231 callback_.Run(IS_DEFAULT);
pmonettef9461d1a2016-03-08 18:13:47232 break;
233 case UNKNOWN_DEFAULT:
pmonetteb9204142016-03-08 20:02:44234 callback_.Run(UNKNOWN_DEFAULT);
pmonettef9461d1a2016-03-08 18:13:47235 break;
236 case NUM_DEFAULT_STATES:
pmonetteb9204142016-03-08 20:02:44237 NOTREACHED();
pmonettef9461d1a2016-03-08 18:13:47238 break;
239 }
[email protected]d24c4012009-07-28 01:57:31240 }
initial.commit09911bf2008-07-26 23:55:29241}
[email protected]4468a5b2011-05-26 07:48:02242
[email protected]4468a5b2011-05-26 07:48:02243///////////////////////////////////////////////////////////////////////////////
pmonette9fa59e882016-02-10 00:12:19244// DefaultBrowserWorker
[email protected]4468a5b2011-05-26 07:48:02245//
246
pmonette586ab5b32016-03-07 19:50:37247DefaultBrowserWorker::DefaultBrowserWorker(
248 const DefaultWebClientWorkerCallback& callback)
pmonette5207d8952016-03-22 15:53:08249 : DefaultWebClientWorker(callback, "DefaultBrowser") {}
pmonettef89ac7c72015-10-06 03:22:01250
[email protected]4468a5b2011-05-26 07:48:02251///////////////////////////////////////////////////////////////////////////////
252// DefaultBrowserWorker, private:
253
pmonette5207d8952016-03-22 15:53:08254DefaultBrowserWorker::~DefaultBrowserWorker() = default;
255
256DefaultWebClientState DefaultBrowserWorker::CheckIsDefaultImpl() {
257 return GetDefaultBrowser();
[email protected]4468a5b2011-05-26 07:48:02258}
259
pmonette5207d8952016-03-22 15:53:08260DefaultWebClientWorker::AttemptResult DefaultBrowserWorker::SetAsDefaultImpl() {
pmonettef89ac7c72015-10-06 03:22:01261 AttemptResult result = AttemptResult::FAILURE;
262 switch (CanSetAsDefaultBrowser()) {
263 case SET_DEFAULT_NOT_ALLOWED:
[email protected]bd046bd42012-06-08 05:07:32264 NOTREACHED();
pmonettef89ac7c72015-10-06 03:22:01265 break;
266 case SET_DEFAULT_UNATTENDED:
267 if (SetAsDefaultBrowser())
268 result = AttemptResult::SUCCESS;
269 break;
270 case SET_DEFAULT_INTERACTIVE:
pmonette8db6a8be2016-02-11 01:50:31271 if (interactive_permitted_ && SetAsDefaultBrowserInteractive())
pmonettef89ac7c72015-10-06 03:22:01272 result = AttemptResult::SUCCESS;
273 break;
[email protected]bd046bd42012-06-08 05:07:32274 }
pmonette5207d8952016-03-22 15:53:08275 return result;
pmonette9c1457f2015-11-19 20:29:31276}
277
[email protected]4468a5b2011-05-26 07:48:02278///////////////////////////////////////////////////////////////////////////////
pmonette9fa59e882016-02-10 00:12:19279// DefaultProtocolClientWorker
[email protected]4468a5b2011-05-26 07:48:02280//
281
pmonette9fa59e882016-02-10 00:12:19282DefaultProtocolClientWorker::DefaultProtocolClientWorker(
pmonette586ab5b32016-03-07 19:50:37283 const DefaultWebClientWorkerCallback& callback,
284 const std::string& protocol)
pmonette5207d8952016-03-22 15:53:08285 : DefaultWebClientWorker(callback, "DefaultProtocolClient"),
286 protocol_(protocol) {}
287
288///////////////////////////////////////////////////////////////////////////////
289// DefaultProtocolClientWorker, protected:
290
291DefaultProtocolClientWorker::~DefaultProtocolClientWorker() = default;
[email protected]4468a5b2011-05-26 07:48:02292
293///////////////////////////////////////////////////////////////////////////////
294// DefaultProtocolClientWorker, private:
295
pmonette5207d8952016-03-22 15:53:08296DefaultWebClientState DefaultProtocolClientWorker::CheckIsDefaultImpl() {
297 return IsDefaultProtocolClient(protocol_);
[email protected]4468a5b2011-05-26 07:48:02298}
299
pmonette5207d8952016-03-22 15:53:08300DefaultWebClientWorker::AttemptResult
301DefaultProtocolClientWorker::SetAsDefaultImpl() {
pmonettef89ac7c72015-10-06 03:22:01302 AttemptResult result = AttemptResult::FAILURE;
303 switch (CanSetAsDefaultProtocolClient()) {
304 case SET_DEFAULT_NOT_ALLOWED:
305 // Not allowed, do nothing.
[email protected]e7f79872013-09-13 01:39:31306 break;
pmonettef89ac7c72015-10-06 03:22:01307 case SET_DEFAULT_UNATTENDED:
308 if (SetAsDefaultProtocolClient(protocol_))
309 result = AttemptResult::SUCCESS;
[email protected]ee9d89d2012-09-25 18:21:03310 break;
pmonettef89ac7c72015-10-06 03:22:01311 case SET_DEFAULT_INTERACTIVE:
pmonette8db6a8be2016-02-11 01:50:31312 if (interactive_permitted_ &&
pmonettef89ac7c72015-10-06 03:22:01313 SetAsDefaultProtocolClientInteractive(protocol_)) {
314 result = AttemptResult::SUCCESS;
[email protected]ee9d89d2012-09-25 18:21:03315 }
316 break;
[email protected]ee9d89d2012-09-25 18:21:03317 }
pmonette5207d8952016-03-22 15:53:08318 return result;
pmonette9c1457f2015-11-19 20:29:31319}
pmonette9fa59e882016-02-10 00:12:19320
321} // namespace shell_integration