blob: ca8157b6cf415eed6dd845d89fedbbc273b51f16 [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
pmonette32a5cfb42016-04-11 22:04:4427#if defined(OS_WIN)
28#include "base/win/windows_version.h"
29#include "chrome/browser/shell_integration_win.h"
30#endif
31
[email protected]2f5bc322013-12-04 08:58:1532#if !defined(OS_WIN)
sdefresne9fb67692015-08-03 18:48:2233#include "chrome/common/channel_info.h"
[email protected]af39f002014-08-22 10:18:1834#include "chrome/grit/chromium_strings.h"
[email protected]2f5bc322013-12-04 08:58:1535#include "ui/base/l10n/l10n_util.h"
36#endif
37
[email protected]631bb742011-11-02 11:29:3938using content::BrowserThread;
39
pmonette9fa59e882016-02-10 00:12:1940namespace shell_integration {
41
pmonette034a03d92015-10-02 21:04:2742namespace {
43
pmonette9fa59e882016-02-10 00:12:1944const struct AppModeInfo* gAppModeInfo = nullptr;
pmonette034a03d92015-10-02 21:04:2745
46} // namespace
47
pmonette32a5cfb42016-04-11 22:04:4448bool CanSetAsDefaultBrowser() {
49 return GetDefaultWebClientSetPermission() != SET_DEFAULT_NOT_ALLOWED;
[email protected]a01481b2011-07-15 04:30:0250}
51
pmonette034a03d92015-10-02 21:04:2752#if !defined(OS_WIN)
pmonette9fa59e882016-02-10 00:12:1953bool IsElevationNeededForSettingDefaultProtocolClient() {
pmonette034a03d92015-10-02 21:04:2754 return false;
55}
56#endif // !defined(OS_WIN)
[email protected]9561bc912012-03-07 02:41:1657
pmonette9fa59e882016-02-10 00:12:1958void SetAppModeInfo(const struct AppModeInfo* info) {
[email protected]9561bc912012-03-07 02:41:1659 gAppModeInfo = info;
60}
61
pmonette9fa59e882016-02-10 00:12:1962const struct AppModeInfo* AppModeInfo() {
[email protected]9561bc912012-03-07 02:41:1663 return gAppModeInfo;
64}
65
pmonette9fa59e882016-02-10 00:12:1966bool IsRunningInAppMode() {
[email protected]9561bc912012-03-07 02:41:1667 return gAppModeInfo != NULL;
68}
69
pmonette9fa59e882016-02-10 00:12:1970base::CommandLine CommandLineArgsForLauncher(
[email protected]2f1c09d2011-01-14 14:58:1471 const GURL& url,
[email protected]5c93a0c12012-05-02 19:45:2472 const std::string& extension_app_id,
[email protected]650b2d52013-02-10 03:41:4573 const base::FilePath& profile_path) {
[email protected]124901f52013-03-27 14:42:1074 base::ThreadRestrictions::AssertIOAllowed();
avi556c05022014-12-22 23:31:4375 base::CommandLine new_cmd_line(base::CommandLine::NO_PROGRAM);
[email protected]28375ae2010-02-05 04:45:5076
[email protected]fb06aea82014-02-26 15:48:4777 AppendProfileArgs(
78 extension_app_id.empty() ? base::FilePath() : profile_path,
79 &new_cmd_line);
[email protected]28375ae2010-02-05 04:45:5080
81 // If |extension_app_id| is present, we use the kAppId switch rather than
82 // the kApp switch (the launch url will be read from the extension app
83 // during launch.
[email protected]ec5b50d2010-10-09 16:35:1884 if (!extension_app_id.empty()) {
[email protected]b10392932011-03-08 21:28:1485 new_cmd_line.AppendSwitchASCII(switches::kAppId, extension_app_id);
[email protected]64048bd2010-03-08 23:28:5886 } else {
[email protected]28375ae2010-02-05 04:45:5087 // Use '--app=url' instead of just 'url' to launch the browser with minimal
88 // chrome.
89 // Note: Do not change this flag! Old Gears shortcuts will break if you do!
[email protected]b10392932011-03-08 21:28:1490 new_cmd_line.AppendSwitchASCII(switches::kApp, url.spec());
[email protected]28375ae2010-02-05 04:45:5091 }
[email protected]b10392932011-03-08 21:28:1492 return new_cmd_line;
[email protected]28375ae2010-02-05 04:45:5093}
94
pmonette9fa59e882016-02-10 00:12:1995void AppendProfileArgs(const base::FilePath& profile_path,
96 base::CommandLine* command_line) {
[email protected]fb06aea82014-02-26 15:48:4797 DCHECK(command_line);
avi556c05022014-12-22 23:31:4398 const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess();
[email protected]fb06aea82014-02-26 15:48:4799
100 // Use the same UserDataDir for new launches that we currently have set.
101 base::FilePath user_data_dir =
102 cmd_line.GetSwitchValuePath(switches::kUserDataDir);
103#if defined(OS_MACOSX) || defined(OS_WIN)
104 policy::path_parser::CheckUserDataDirPolicy(&user_data_dir);
105#endif
106 if (!user_data_dir.empty()) {
107 // Make sure user_data_dir is an absolute path.
108 user_data_dir = base::MakeAbsoluteFilePath(user_data_dir);
109 if (!user_data_dir.empty() && base::PathExists(user_data_dir))
110 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
111 }
112
113#if defined(OS_CHROMEOS)
114 base::FilePath profile = cmd_line.GetSwitchValuePath(
115 chromeos::switches::kLoginProfile);
116 if (!profile.empty())
117 command_line->AppendSwitchPath(chromeos::switches::kLoginProfile, profile);
118#else
119 if (!profile_path.empty())
120 command_line->AppendSwitchPath(switches::kProfileDirectory,
121 profile_path.BaseName());
122#endif
123}
124
[email protected]bd046bd42012-06-08 05:07:32125#if !defined(OS_WIN)
pmonette9fa59e882016-02-10 00:12:19126base::string16 GetAppShortcutsSubdirName() {
sdefresne9fb67692015-08-03 18:48:22127 if (chrome::GetChannel() == version_info::Channel::CANARY)
[email protected]2f5bc322013-12-04 08:58:15128 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME_CANARY);
129 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME);
130}
pmonette868ca642015-09-02 14:34:02131#endif // !defined(OS_WIN)
[email protected]bd046bd42012-06-08 05:07:32132
pmonette034a03d92015-10-02 21:04:27133///////////////////////////////////////////////////////////////////////////////
pmonette9fa59e882016-02-10 00:12:19134// DefaultWebClientWorker
[email protected]d24c4012009-07-28 01:57:31135//
initial.commit09911bf2008-07-26 23:55:29136
pmonette9fa59e882016-02-10 00:12:19137void DefaultWebClientWorker::StartCheckIsDefault() {
pmonette9c1457f2015-11-19 20:29:31138 BrowserThread::PostTask(
139 BrowserThread::FILE, FROM_HERE,
pmonette60a702c2016-03-22 22:59:40140 base::Bind(&DefaultWebClientWorker::CheckIsDefault, this, false));
[email protected]4468a5b2011-05-26 07:48:02141}
142
pmonette9fa59e882016-02-10 00:12:19143void DefaultWebClientWorker::StartSetAsDefault() {
pmonette8db6a8be2016-02-11 01:50:31144 BrowserThread::PostTask(
145 BrowserThread::FILE, FROM_HERE,
146 base::Bind(&DefaultWebClientWorker::SetAsDefault, this));
initial.commit09911bf2008-07-26 23:55:29147}
148
[email protected]d24c4012009-07-28 01:57:31149///////////////////////////////////////////////////////////////////////////////
pmonette5207d8952016-03-22 15:53:08150// DefaultWebClientWorker, protected:
[email protected]d24c4012009-07-28 01:57:31151
pmonette5207d8952016-03-22 15:53:08152DefaultWebClientWorker::DefaultWebClientWorker(
153 const DefaultWebClientWorkerCallback& callback,
154 const char* worker_name)
155 : callback_(callback), worker_name_(worker_name) {}
156
157DefaultWebClientWorker::~DefaultWebClientWorker() = default;
[email protected]d24c4012009-07-28 01:57:31158
pmonette9fa59e882016-02-10 00:12:19159void DefaultWebClientWorker::OnCheckIsDefaultComplete(
pmonette60a702c2016-03-22 22:59:40160 DefaultWebClientState state,
161 bool is_following_set_as_default) {
thestig00844cea2015-09-08 21:44:52162 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]264f74d12009-09-04 23:39:58163 UpdateUI(state);
pmonette9c1457f2015-11-19 20:29:31164
pmonette60a702c2016-03-22 22:59:40165 if (is_following_set_as_default)
166 ReportSetDefaultResult(state);
pmonette5207d8952016-03-22 15:53:08167}
pmonettef89ac7c72015-10-06 03:22:01168
pmonette5207d8952016-03-22 15:53:08169///////////////////////////////////////////////////////////////////////////////
170// DefaultWebClientWorker, private:
pmonettef89ac7c72015-10-06 03:22:01171
pmonette60a702c2016-03-22 22:59:40172void DefaultWebClientWorker::CheckIsDefault(bool is_following_set_as_default) {
pmonette5207d8952016-03-22 15:53:08173 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
174 DefaultWebClientState state = CheckIsDefaultImpl();
175 BrowserThread::PostTask(
176 BrowserThread::UI, FROM_HERE,
pmonette60a702c2016-03-22 22:59:40177 base::Bind(&DefaultBrowserWorker::OnCheckIsDefaultComplete, this, state,
178 is_following_set_as_default));
pmonette5207d8952016-03-22 15:53:08179}
180
181void DefaultWebClientWorker::SetAsDefault() {
182 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
pmonette32a5cfb42016-04-11 22:04:44183
184 // SetAsDefaultImpl will make sure the callback is executed exactly once.
185 SetAsDefaultImpl(
186 base::Bind(&DefaultWebClientWorker::CheckIsDefault, this, true));
[email protected]d24c4012009-07-28 01:57:31187}
188
pmonette60a702c2016-03-22 22:59:40189void DefaultWebClientWorker::ReportSetDefaultResult(
190 DefaultWebClientState state) {
pmonette9c1457f2015-11-19 20:29:31191 base::LinearHistogram::FactoryGet(
pmonette60a702c2016-03-22 22:59:40192 base::StringPrintf("%s.SetDefaultResult2", worker_name_), 1,
193 DefaultWebClientState::NUM_DEFAULT_STATES,
194 DefaultWebClientState::NUM_DEFAULT_STATES + 1,
pmonette9c1457f2015-11-19 20:29:31195 base::HistogramBase::kUmaTargetedHistogramFlag)
pmonette60a702c2016-03-22 22:59:40196 ->Add(state);
pmonettef89ac7c72015-10-06 03:22:01197}
198
pmonette9fa59e882016-02-10 00:12:19199void DefaultWebClientWorker::UpdateUI(DefaultWebClientState state) {
pmonettef9461d1a2016-03-08 18:13:47200 if (!callback_.is_null()) {
201 switch (state) {
202 case NOT_DEFAULT:
pmonetteb9204142016-03-08 20:02:44203 callback_.Run(NOT_DEFAULT);
pmonettef9461d1a2016-03-08 18:13:47204 break;
205 case IS_DEFAULT:
pmonetteb9204142016-03-08 20:02:44206 callback_.Run(IS_DEFAULT);
pmonettef9461d1a2016-03-08 18:13:47207 break;
208 case UNKNOWN_DEFAULT:
pmonetteb9204142016-03-08 20:02:44209 callback_.Run(UNKNOWN_DEFAULT);
pmonettef9461d1a2016-03-08 18:13:47210 break;
211 case NUM_DEFAULT_STATES:
pmonetteb9204142016-03-08 20:02:44212 NOTREACHED();
pmonettef9461d1a2016-03-08 18:13:47213 break;
214 }
[email protected]d24c4012009-07-28 01:57:31215 }
initial.commit09911bf2008-07-26 23:55:29216}
[email protected]4468a5b2011-05-26 07:48:02217
218///////////////////////////////////////////////////////////////////////////////
pmonette9fa59e882016-02-10 00:12:19219// DefaultBrowserWorker
[email protected]4468a5b2011-05-26 07:48:02220//
221
pmonette586ab5b32016-03-07 19:50:37222DefaultBrowserWorker::DefaultBrowserWorker(
223 const DefaultWebClientWorkerCallback& callback)
pmonette5207d8952016-03-22 15:53:08224 : DefaultWebClientWorker(callback, "DefaultBrowser") {}
pmonettef89ac7c72015-10-06 03:22:01225
[email protected]4468a5b2011-05-26 07:48:02226///////////////////////////////////////////////////////////////////////////////
227// DefaultBrowserWorker, private:
228
pmonette5207d8952016-03-22 15:53:08229DefaultBrowserWorker::~DefaultBrowserWorker() = default;
230
231DefaultWebClientState DefaultBrowserWorker::CheckIsDefaultImpl() {
232 return GetDefaultBrowser();
[email protected]4468a5b2011-05-26 07:48:02233}
234
pmonette32a5cfb42016-04-11 22:04:44235void DefaultBrowserWorker::SetAsDefaultImpl(
236 const base::Closure& on_finished_callback) {
237 switch (GetDefaultWebClientSetPermission()) {
pmonettef89ac7c72015-10-06 03:22:01238 case SET_DEFAULT_NOT_ALLOWED:
[email protected]bd046bd42012-06-08 05:07:32239 NOTREACHED();
pmonettef89ac7c72015-10-06 03:22:01240 break;
241 case SET_DEFAULT_UNATTENDED:
pmonette60a702c2016-03-22 22:59:40242 SetAsDefaultBrowser();
pmonettef89ac7c72015-10-06 03:22:01243 break;
244 case SET_DEFAULT_INTERACTIVE:
pmonette32a5cfb42016-04-11 22:04:44245#if defined(OS_WIN)
246 if (interactive_permitted_) {
247 // The Windows 8 API for choosing the default browser was deprecated on
248 // Windows 10.
249 if (base::win::GetVersion() >= base::win::VERSION_WIN10) {
250 win::SetAsDefaultBrowserUsingSystemSettings(on_finished_callback);
251 return;
252 } else {
253 win::SetAsDefaultBrowserUsingIntentPicker();
254 }
255 }
256#endif // defined(OS_WIN)
pmonettef89ac7c72015-10-06 03:22:01257 break;
[email protected]bd046bd42012-06-08 05:07:32258 }
pmonette32a5cfb42016-04-11 22:04:44259 on_finished_callback.Run();
pmonette9c1457f2015-11-19 20:29:31260}
261
[email protected]4468a5b2011-05-26 07:48:02262///////////////////////////////////////////////////////////////////////////////
pmonette9fa59e882016-02-10 00:12:19263// DefaultProtocolClientWorker
[email protected]4468a5b2011-05-26 07:48:02264//
265
pmonette9fa59e882016-02-10 00:12:19266DefaultProtocolClientWorker::DefaultProtocolClientWorker(
pmonette586ab5b32016-03-07 19:50:37267 const DefaultWebClientWorkerCallback& callback,
268 const std::string& protocol)
pmonette5207d8952016-03-22 15:53:08269 : DefaultWebClientWorker(callback, "DefaultProtocolClient"),
270 protocol_(protocol) {}
271
272///////////////////////////////////////////////////////////////////////////////
273// DefaultProtocolClientWorker, protected:
274
275DefaultProtocolClientWorker::~DefaultProtocolClientWorker() = default;
[email protected]4468a5b2011-05-26 07:48:02276
277///////////////////////////////////////////////////////////////////////////////
278// DefaultProtocolClientWorker, private:
279
pmonette5207d8952016-03-22 15:53:08280DefaultWebClientState DefaultProtocolClientWorker::CheckIsDefaultImpl() {
281 return IsDefaultProtocolClient(protocol_);
[email protected]4468a5b2011-05-26 07:48:02282}
283
pmonette32a5cfb42016-04-11 22:04:44284void DefaultProtocolClientWorker::SetAsDefaultImpl(
285 const base::Closure& on_finished_callback) {
286 switch (GetDefaultWebClientSetPermission()) {
pmonettef89ac7c72015-10-06 03:22:01287 case SET_DEFAULT_NOT_ALLOWED:
288 // Not allowed, do nothing.
[email protected]e7f79872013-09-13 01:39:31289 break;
pmonettef89ac7c72015-10-06 03:22:01290 case SET_DEFAULT_UNATTENDED:
pmonette60a702c2016-03-22 22:59:40291 SetAsDefaultProtocolClient(protocol_);
[email protected]ee9d89d2012-09-25 18:21:03292 break;
pmonettef89ac7c72015-10-06 03:22:01293 case SET_DEFAULT_INTERACTIVE:
pmonette32a5cfb42016-04-11 22:04:44294#if defined(OS_WIN)
295 // TODO(pmonette): Implement a working flow for Windows 10.
296 if (interactive_permitted_)
297 win::SetAsDefaultProtocolClientUsingIntentPicker(protocol_);
298#endif // defined(OS_WIN)
[email protected]ee9d89d2012-09-25 18:21:03299 break;
[email protected]ee9d89d2012-09-25 18:21:03300 }
pmonette32a5cfb42016-04-11 22:04:44301 on_finished_callback.Run();
pmonette9c1457f2015-11-19 20:29:31302}
pmonette9fa59e882016-02-10 00:12:19303
304} // namespace shell_integration