blob: 46d749623963117100a5748083cf0edf5074c189 [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"
[email protected]3853a4c2013-02-11 17:15:5710#include "base/prefs/pref_service.h"
[email protected]24a555b62013-06-10 22:01:1711#include "base/strings/string_util.h"
[email protected]e309f312013-06-07 21:50:0812#include "base/strings/utf_string_conversions.h"
[email protected]124901f52013-03-27 14:42:1013#include "base/threading/thread_restrictions.h"
[email protected]ba26a442013-02-20 15:32:5514#include "chrome/browser/policy/policy_path_parser.h"
[email protected]b96aa932009-08-12 21:34:4915#include "chrome/common/chrome_paths.h"
[email protected]28375ae2010-02-05 04:45:5016#include "chrome/common/chrome_switches.h"
[email protected]c38831a12011-10-28 12:44:4917#include "content/public/browser/browser_thread.h"
initial.commit09911bf2008-07-26 23:55:2918
[email protected]931d1042013-04-05 17:50:4419#if defined(OS_CHROMEOS)
20#include "chromeos/chromeos_switches.h"
21#endif
22
[email protected]2f5bc322013-12-04 08:58:1523#if !defined(OS_WIN)
24#include "chrome/common/chrome_version_info.h"
[email protected]af39f002014-08-22 10:18:1825#include "chrome/grit/chromium_strings.h"
[email protected]2f5bc322013-12-04 08:58:1526#include "ui/base/l10n/l10n_util.h"
27#endif
28
[email protected]631bb742011-11-02 11:29:3929using content::BrowserThread;
30
[email protected]bd046bd42012-06-08 05:07:3231ShellIntegration::DefaultWebClientSetPermission
32 ShellIntegration::CanSetAsDefaultProtocolClient() {
[email protected]a01481b2011-07-15 04:30:0233 // Allowed as long as the browser can become the operating system default
34 // browser.
35 return CanSetAsDefaultBrowser();
36}
37
[email protected]9561bc912012-03-07 02:41:1638static const struct ShellIntegration::AppModeInfo* gAppModeInfo = NULL;
39
40// static
41void ShellIntegration::SetAppModeInfo(const struct AppModeInfo* info) {
42 gAppModeInfo = info;
43}
44
45// static
46const struct ShellIntegration::AppModeInfo* ShellIntegration::AppModeInfo() {
47 return gAppModeInfo;
48}
49
50// static
51bool ShellIntegration::IsRunningInAppMode() {
52 return gAppModeInfo != NULL;
53}
54
[email protected]b10392932011-03-08 21:28:1455// static
avi556c05022014-12-22 23:31:4356base::CommandLine ShellIntegration::CommandLineArgsForLauncher(
[email protected]2f1c09d2011-01-14 14:58:1457 const GURL& url,
[email protected]5c93a0c12012-05-02 19:45:2458 const std::string& extension_app_id,
[email protected]650b2d52013-02-10 03:41:4559 const base::FilePath& profile_path) {
[email protected]124901f52013-03-27 14:42:1060 base::ThreadRestrictions::AssertIOAllowed();
avi556c05022014-12-22 23:31:4361 base::CommandLine new_cmd_line(base::CommandLine::NO_PROGRAM);
[email protected]28375ae2010-02-05 04:45:5062
[email protected]fb06aea82014-02-26 15:48:4763 AppendProfileArgs(
64 extension_app_id.empty() ? base::FilePath() : profile_path,
65 &new_cmd_line);
[email protected]28375ae2010-02-05 04:45:5066
67 // If |extension_app_id| is present, we use the kAppId switch rather than
68 // the kApp switch (the launch url will be read from the extension app
69 // during launch.
[email protected]ec5b50d2010-10-09 16:35:1870 if (!extension_app_id.empty()) {
[email protected]b10392932011-03-08 21:28:1471 new_cmd_line.AppendSwitchASCII(switches::kAppId, extension_app_id);
[email protected]64048bd2010-03-08 23:28:5872 } else {
[email protected]28375ae2010-02-05 04:45:5073 // Use '--app=url' instead of just 'url' to launch the browser with minimal
74 // chrome.
75 // Note: Do not change this flag! Old Gears shortcuts will break if you do!
[email protected]b10392932011-03-08 21:28:1476 new_cmd_line.AppendSwitchASCII(switches::kApp, url.spec());
[email protected]28375ae2010-02-05 04:45:5077 }
[email protected]b10392932011-03-08 21:28:1478 return new_cmd_line;
[email protected]28375ae2010-02-05 04:45:5079}
80
[email protected]fb06aea82014-02-26 15:48:4781// static
avi556c05022014-12-22 23:31:4382void ShellIntegration::AppendProfileArgs(const base::FilePath& profile_path,
83 base::CommandLine* command_line) {
[email protected]fb06aea82014-02-26 15:48:4784 DCHECK(command_line);
avi556c05022014-12-22 23:31:4385 const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess();
[email protected]fb06aea82014-02-26 15:48:4786
87 // Use the same UserDataDir for new launches that we currently have set.
88 base::FilePath user_data_dir =
89 cmd_line.GetSwitchValuePath(switches::kUserDataDir);
90#if defined(OS_MACOSX) || defined(OS_WIN)
91 policy::path_parser::CheckUserDataDirPolicy(&user_data_dir);
92#endif
93 if (!user_data_dir.empty()) {
94 // Make sure user_data_dir is an absolute path.
95 user_data_dir = base::MakeAbsoluteFilePath(user_data_dir);
96 if (!user_data_dir.empty() && base::PathExists(user_data_dir))
97 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
98 }
99
100#if defined(OS_CHROMEOS)
101 base::FilePath profile = cmd_line.GetSwitchValuePath(
102 chromeos::switches::kLoginProfile);
103 if (!profile.empty())
104 command_line->AppendSwitchPath(chromeos::switches::kLoginProfile, profile);
105#else
106 if (!profile_path.empty())
107 command_line->AppendSwitchPath(switches::kProfileDirectory,
108 profile_path.BaseName());
109#endif
110}
111
[email protected]bd046bd42012-06-08 05:07:32112#if !defined(OS_WIN)
[email protected]2f5bc322013-12-04 08:58:15113
114base::string16 ShellIntegration::GetAppShortcutsSubdirName() {
115 if (chrome::VersionInfo::GetChannel() == chrome::VersionInfo::CHANNEL_CANARY)
116 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME_CANARY);
117 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME);
118}
119
[email protected]bd046bd42012-06-08 05:07:32120// static
121bool ShellIntegration::SetAsDefaultBrowserInteractive() {
122 return false;
123}
[email protected]ee9d89d2012-09-25 18:21:03124
125// static
126bool ShellIntegration::SetAsDefaultProtocolClientInteractive(
127 const std::string& protocol) {
128 return false;
129}
[email protected]bd046bd42012-06-08 05:07:32130#endif
131
[email protected]693baa5d2012-06-22 22:23:38132bool ShellIntegration::DefaultWebClientObserver::IsOwnedByWorker() {
133 return false;
134}
135
136bool ShellIntegration::DefaultWebClientObserver::
137 IsInteractiveSetDefaultPermitted() {
138 return false;
139}
140
[email protected]d24c4012009-07-28 01:57:31141///////////////////////////////////////////////////////////////////////////////
[email protected]4468a5b2011-05-26 07:48:02142// ShellIntegration::DefaultWebClientWorker
[email protected]d24c4012009-07-28 01:57:31143//
initial.commit09911bf2008-07-26 23:55:29144
[email protected]4468a5b2011-05-26 07:48:02145ShellIntegration::DefaultWebClientWorker::DefaultWebClientWorker(
146 DefaultWebClientObserver* observer)
[email protected]0d3dc8e22009-11-03 02:27:01147 : observer_(observer) {
initial.commit09911bf2008-07-26 23:55:29148}
149
[email protected]4468a5b2011-05-26 07:48:02150void ShellIntegration::DefaultWebClientWorker::StartCheckIsDefault() {
151 if (observer_) {
152 observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
153 BrowserThread::PostTask(
154 BrowserThread::FILE, FROM_HERE,
[email protected]c5efb952011-11-01 01:28:36155 base::Bind(
156 &DefaultWebClientWorker::ExecuteCheckIsDefault, this));
[email protected]4468a5b2011-05-26 07:48:02157 }
158}
159
160void ShellIntegration::DefaultWebClientWorker::StartSetAsDefault() {
[email protected]693baa5d2012-06-22 22:23:38161 bool interactive_permitted = false;
[email protected]4468a5b2011-05-26 07:48:02162 if (observer_) {
163 observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
[email protected]693baa5d2012-06-22 22:23:38164 interactive_permitted = observer_->IsInteractiveSetDefaultPermitted();
[email protected]4468a5b2011-05-26 07:48:02165 }
[email protected]0c7d74f2010-10-11 11:55:26166 BrowserThread::PostTask(
167 BrowserThread::FILE, FROM_HERE,
[email protected]693baa5d2012-06-22 22:23:38168 base::Bind(&DefaultWebClientWorker::ExecuteSetAsDefault, this,
169 interactive_permitted));
initial.commit09911bf2008-07-26 23:55:29170}
171
[email protected]4468a5b2011-05-26 07:48:02172void ShellIntegration::DefaultWebClientWorker::ObserverDestroyed() {
[email protected]d24c4012009-07-28 01:57:31173 // Our associated view has gone away, so we shouldn't call back to it if
174 // our worker thread returns after the view is dead.
[email protected]bcb999d2011-05-31 15:11:35175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]d24c4012009-07-28 01:57:31176 observer_ = NULL;
177}
178
179///////////////////////////////////////////////////////////////////////////////
[email protected]4468a5b2011-05-26 07:48:02180// DefaultWebClientWorker, private:
[email protected]d24c4012009-07-28 01:57:31181
[email protected]4468a5b2011-05-26 07:48:02182void ShellIntegration::DefaultWebClientWorker::ExecuteCheckIsDefault() {
[email protected]0c7d74f2010-10-11 11:55:26183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]4468a5b2011-05-26 07:48:02184 DefaultWebClientState state = CheckIsDefault();
[email protected]0c7d74f2010-10-11 11:55:26185 BrowserThread::PostTask(
186 BrowserThread::UI, FROM_HERE,
[email protected]c5efb952011-11-01 01:28:36187 base::Bind(
188 &DefaultWebClientWorker::CompleteCheckIsDefault, this, state));
[email protected]d24c4012009-07-28 01:57:31189}
190
[email protected]4468a5b2011-05-26 07:48:02191void ShellIntegration::DefaultWebClientWorker::CompleteCheckIsDefault(
192 DefaultWebClientState state) {
[email protected]0c7d74f2010-10-11 11:55:26193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]264f74d12009-09-04 23:39:58194 UpdateUI(state);
[email protected]97e2e3f2011-07-22 10:21:25195 // The worker has finished everything it needs to do, so free the observer
196 // if we own it.
197 if (observer_ && observer_->IsOwnedByWorker()) {
198 delete observer_;
199 observer_ = NULL;
200 }
[email protected]d24c4012009-07-28 01:57:31201}
202
[email protected]693baa5d2012-06-22 22:23:38203void ShellIntegration::DefaultWebClientWorker::ExecuteSetAsDefault(
204 bool interactive_permitted) {
[email protected]0c7d74f2010-10-11 11:55:26205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]693baa5d2012-06-22 22:23:38206
207 bool result = SetAsDefault(interactive_permitted);
[email protected]0c7d74f2010-10-11 11:55:26208 BrowserThread::PostTask(
209 BrowserThread::UI, FROM_HERE,
[email protected]693baa5d2012-06-22 22:23:38210 base::Bind(&DefaultWebClientWorker::CompleteSetAsDefault, this, result));
[email protected]d24c4012009-07-28 01:57:31211}
212
[email protected]693baa5d2012-06-22 22:23:38213void ShellIntegration::DefaultWebClientWorker::CompleteSetAsDefault(
214 bool succeeded) {
[email protected]0c7d74f2010-10-11 11:55:26215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]693baa5d2012-06-22 22:23:38216 // First tell the observer what the SetAsDefault call has returned.
217 if (observer_)
218 observer_->OnSetAsDefaultConcluded(succeeded);
[email protected]4468a5b2011-05-26 07:48:02219 // Set as default completed, check again to make sure it stuck...
220 StartCheckIsDefault();
[email protected]d24c4012009-07-28 01:57:31221}
222
[email protected]4468a5b2011-05-26 07:48:02223void ShellIntegration::DefaultWebClientWorker::UpdateUI(
224 DefaultWebClientState state) {
[email protected]d24c4012009-07-28 01:57:31225 if (observer_) {
[email protected]264f74d12009-09-04 23:39:58226 switch (state) {
[email protected]89886652012-12-11 18:09:07227 case NOT_DEFAULT:
[email protected]4468a5b2011-05-26 07:48:02228 observer_->SetDefaultWebClientUIState(STATE_NOT_DEFAULT);
[email protected]264f74d12009-09-04 23:39:58229 break;
[email protected]89886652012-12-11 18:09:07230 case IS_DEFAULT:
[email protected]4468a5b2011-05-26 07:48:02231 observer_->SetDefaultWebClientUIState(STATE_IS_DEFAULT);
[email protected]264f74d12009-09-04 23:39:58232 break;
[email protected]89886652012-12-11 18:09:07233 case UNKNOWN_DEFAULT:
[email protected]4468a5b2011-05-26 07:48:02234 observer_->SetDefaultWebClientUIState(STATE_UNKNOWN);
[email protected]264f74d12009-09-04 23:39:58235 break;
236 default:
237 break;
238 }
[email protected]d24c4012009-07-28 01:57:31239 }
initial.commit09911bf2008-07-26 23:55:29240}
[email protected]4468a5b2011-05-26 07:48:02241
242///////////////////////////////////////////////////////////////////////////////
243// ShellIntegration::DefaultBrowserWorker
244//
245
246ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker(
247 DefaultWebClientObserver* observer)
248 : DefaultWebClientWorker(observer) {
249}
250
251///////////////////////////////////////////////////////////////////////////////
252// DefaultBrowserWorker, private:
253
254ShellIntegration::DefaultWebClientState
255ShellIntegration::DefaultBrowserWorker::CheckIsDefault() {
[email protected]89886652012-12-11 18:09:07256 return ShellIntegration::GetDefaultBrowser();
[email protected]4468a5b2011-05-26 07:48:02257}
258
[email protected]693baa5d2012-06-22 22:23:38259bool ShellIntegration::DefaultBrowserWorker::SetAsDefault(
[email protected]bd046bd42012-06-08 05:07:32260 bool interactive_permitted) {
[email protected]693baa5d2012-06-22 22:23:38261 bool result = false;
[email protected]bd046bd42012-06-08 05:07:32262 switch (ShellIntegration::CanSetAsDefaultBrowser()) {
263 case ShellIntegration::SET_DEFAULT_UNATTENDED:
[email protected]693baa5d2012-06-22 22:23:38264 result = ShellIntegration::SetAsDefaultBrowser();
[email protected]bd046bd42012-06-08 05:07:32265 break;
266 case ShellIntegration::SET_DEFAULT_INTERACTIVE:
267 if (interactive_permitted)
[email protected]693baa5d2012-06-22 22:23:38268 result = ShellIntegration::SetAsDefaultBrowserInteractive();
[email protected]bd046bd42012-06-08 05:07:32269 break;
270 default:
271 NOTREACHED();
272 }
[email protected]693baa5d2012-06-22 22:23:38273
274 return result;
[email protected]4468a5b2011-05-26 07:48:02275}
276
277///////////////////////////////////////////////////////////////////////////////
278// ShellIntegration::DefaultProtocolClientWorker
279//
280
281ShellIntegration::DefaultProtocolClientWorker::DefaultProtocolClientWorker(
282 DefaultWebClientObserver* observer, const std::string& protocol)
283 : DefaultWebClientWorker(observer),
284 protocol_(protocol) {
285}
286
287///////////////////////////////////////////////////////////////////////////////
288// DefaultProtocolClientWorker, private:
289
290ShellIntegration::DefaultWebClientState
291ShellIntegration::DefaultProtocolClientWorker::CheckIsDefault() {
292 return ShellIntegration::IsDefaultProtocolClient(protocol_);
293}
294
[email protected]693baa5d2012-06-22 22:23:38295bool ShellIntegration::DefaultProtocolClientWorker::SetAsDefault(
[email protected]bd046bd42012-06-08 05:07:32296 bool interactive_permitted) {
[email protected]ee9d89d2012-09-25 18:21:03297 bool result = false;
298 switch (ShellIntegration::CanSetAsDefaultProtocolClient()) {
[email protected]e7f79872013-09-13 01:39:31299 case ShellIntegration::SET_DEFAULT_NOT_ALLOWED:
300 result = false;
301 break;
[email protected]ee9d89d2012-09-25 18:21:03302 case ShellIntegration::SET_DEFAULT_UNATTENDED:
303 result = ShellIntegration::SetAsDefaultProtocolClient(protocol_);
304 break;
305 case ShellIntegration::SET_DEFAULT_INTERACTIVE:
306 if (interactive_permitted) {
307 result = ShellIntegration::SetAsDefaultProtocolClientInteractive(
308 protocol_);
309 }
310 break;
[email protected]ee9d89d2012-09-25 18:21:03311 }
312
313 return result;
[email protected]4468a5b2011-05-26 07:48:02314}