blob: aaeb3203e4d12314d8f1fd3c2e96a23c6a2b3efd [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"
9#include "base/file_util.h"
[email protected]b96aa932009-08-12 21:34:4910#include "base/path_service.h"
[email protected]3853a4c2013-02-11 17:15:5711#include "base/prefs/pref_service.h"
[email protected]24a555b62013-06-10 22:01:1712#include "base/strings/string_util.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"
[email protected]ba26a442013-02-20 15:32:5515#include "chrome/browser/policy/policy_path_parser.h"
[email protected]b96aa932009-08-12 21:34:4916#include "chrome/common/chrome_paths.h"
[email protected]28375ae2010-02-05 04:45:5017#include "chrome/common/chrome_switches.h"
[email protected]e450fa62011-02-01 12:52:5618#include "chrome/common/pref_names.h"
[email protected]c38831a12011-10-28 12:44:4919#include "content/public/browser/browser_thread.h"
initial.commit09911bf2008-07-26 23:55:2920
[email protected]931d1042013-04-05 17:50:4421#if defined(OS_CHROMEOS)
22#include "chromeos/chromeos_switches.h"
23#endif
24
[email protected]2f5bc322013-12-04 08:58:1525#if !defined(OS_WIN)
26#include "chrome/common/chrome_version_info.h"
[email protected]af39f002014-08-22 10:18:1827#include "chrome/grit/chromium_strings.h"
[email protected]2f5bc322013-12-04 08:58:1528#include "ui/base/l10n/l10n_util.h"
29#endif
30
[email protected]631bb742011-11-02 11:29:3931using content::BrowserThread;
32
[email protected]bd046bd42012-06-08 05:07:3233ShellIntegration::DefaultWebClientSetPermission
34 ShellIntegration::CanSetAsDefaultProtocolClient() {
[email protected]a01481b2011-07-15 04:30:0235 // Allowed as long as the browser can become the operating system default
36 // browser.
37 return CanSetAsDefaultBrowser();
38}
39
[email protected]9561bc912012-03-07 02:41:1640static const struct ShellIntegration::AppModeInfo* gAppModeInfo = NULL;
41
42// static
43void ShellIntegration::SetAppModeInfo(const struct AppModeInfo* info) {
44 gAppModeInfo = info;
45}
46
47// static
48const struct ShellIntegration::AppModeInfo* ShellIntegration::AppModeInfo() {
49 return gAppModeInfo;
50}
51
52// static
53bool ShellIntegration::IsRunningInAppMode() {
54 return gAppModeInfo != NULL;
55}
56
[email protected]b10392932011-03-08 21:28:1457// static
58CommandLine ShellIntegration::CommandLineArgsForLauncher(
[email protected]2f1c09d2011-01-14 14:58:1459 const GURL& url,
[email protected]5c93a0c12012-05-02 19:45:2460 const std::string& extension_app_id,
[email protected]650b2d52013-02-10 03:41:4561 const base::FilePath& profile_path) {
[email protected]124901f52013-03-27 14:42:1062 base::ThreadRestrictions::AssertIOAllowed();
[email protected]b10392932011-03-08 21:28:1463 CommandLine new_cmd_line(CommandLine::NO_PROGRAM);
[email protected]28375ae2010-02-05 04:45:5064
[email protected]fb06aea82014-02-26 15:48:4765 AppendProfileArgs(
66 extension_app_id.empty() ? base::FilePath() : profile_path,
67 &new_cmd_line);
[email protected]28375ae2010-02-05 04:45:5068
69 // If |extension_app_id| is present, we use the kAppId switch rather than
70 // the kApp switch (the launch url will be read from the extension app
71 // during launch.
[email protected]ec5b50d2010-10-09 16:35:1872 if (!extension_app_id.empty()) {
[email protected]b10392932011-03-08 21:28:1473 new_cmd_line.AppendSwitchASCII(switches::kAppId, extension_app_id);
[email protected]64048bd2010-03-08 23:28:5874 } else {
[email protected]28375ae2010-02-05 04:45:5075 // Use '--app=url' instead of just 'url' to launch the browser with minimal
76 // chrome.
77 // Note: Do not change this flag! Old Gears shortcuts will break if you do!
[email protected]b10392932011-03-08 21:28:1478 new_cmd_line.AppendSwitchASCII(switches::kApp, url.spec());
[email protected]28375ae2010-02-05 04:45:5079 }
[email protected]b10392932011-03-08 21:28:1480 return new_cmd_line;
[email protected]28375ae2010-02-05 04:45:5081}
82
[email protected]fb06aea82014-02-26 15:48:4783// static
84void ShellIntegration::AppendProfileArgs(
85 const base::FilePath& profile_path,
86 CommandLine* command_line) {
87 DCHECK(command_line);
88 const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
89
90 // Use the same UserDataDir for new launches that we currently have set.
91 base::FilePath user_data_dir =
92 cmd_line.GetSwitchValuePath(switches::kUserDataDir);
93#if defined(OS_MACOSX) || defined(OS_WIN)
94 policy::path_parser::CheckUserDataDirPolicy(&user_data_dir);
95#endif
96 if (!user_data_dir.empty()) {
97 // Make sure user_data_dir is an absolute path.
98 user_data_dir = base::MakeAbsoluteFilePath(user_data_dir);
99 if (!user_data_dir.empty() && base::PathExists(user_data_dir))
100 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
101 }
102
103#if defined(OS_CHROMEOS)
104 base::FilePath profile = cmd_line.GetSwitchValuePath(
105 chromeos::switches::kLoginProfile);
106 if (!profile.empty())
107 command_line->AppendSwitchPath(chromeos::switches::kLoginProfile, profile);
108#else
109 if (!profile_path.empty())
110 command_line->AppendSwitchPath(switches::kProfileDirectory,
111 profile_path.BaseName());
112#endif
113}
114
[email protected]bd046bd42012-06-08 05:07:32115#if !defined(OS_WIN)
[email protected]2f5bc322013-12-04 08:58:15116
117base::string16 ShellIntegration::GetAppShortcutsSubdirName() {
118 if (chrome::VersionInfo::GetChannel() == chrome::VersionInfo::CHANNEL_CANARY)
119 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME_CANARY);
120 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME);
121}
122
[email protected]bd046bd42012-06-08 05:07:32123// static
124bool ShellIntegration::SetAsDefaultBrowserInteractive() {
125 return false;
126}
[email protected]ee9d89d2012-09-25 18:21:03127
128// static
129bool ShellIntegration::SetAsDefaultProtocolClientInteractive(
130 const std::string& protocol) {
131 return false;
132}
[email protected]bd046bd42012-06-08 05:07:32133#endif
134
[email protected]693baa5d2012-06-22 22:23:38135bool ShellIntegration::DefaultWebClientObserver::IsOwnedByWorker() {
136 return false;
137}
138
139bool ShellIntegration::DefaultWebClientObserver::
140 IsInteractiveSetDefaultPermitted() {
141 return false;
142}
143
[email protected]d24c4012009-07-28 01:57:31144///////////////////////////////////////////////////////////////////////////////
[email protected]4468a5b2011-05-26 07:48:02145// ShellIntegration::DefaultWebClientWorker
[email protected]d24c4012009-07-28 01:57:31146//
initial.commit09911bf2008-07-26 23:55:29147
[email protected]4468a5b2011-05-26 07:48:02148ShellIntegration::DefaultWebClientWorker::DefaultWebClientWorker(
149 DefaultWebClientObserver* observer)
[email protected]0d3dc8e22009-11-03 02:27:01150 : observer_(observer) {
initial.commit09911bf2008-07-26 23:55:29151}
152
[email protected]4468a5b2011-05-26 07:48:02153void ShellIntegration::DefaultWebClientWorker::StartCheckIsDefault() {
154 if (observer_) {
155 observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
156 BrowserThread::PostTask(
157 BrowserThread::FILE, FROM_HERE,
[email protected]c5efb952011-11-01 01:28:36158 base::Bind(
159 &DefaultWebClientWorker::ExecuteCheckIsDefault, this));
[email protected]4468a5b2011-05-26 07:48:02160 }
161}
162
163void ShellIntegration::DefaultWebClientWorker::StartSetAsDefault() {
[email protected]693baa5d2012-06-22 22:23:38164 bool interactive_permitted = false;
[email protected]4468a5b2011-05-26 07:48:02165 if (observer_) {
166 observer_->SetDefaultWebClientUIState(STATE_PROCESSING);
[email protected]693baa5d2012-06-22 22:23:38167 interactive_permitted = observer_->IsInteractiveSetDefaultPermitted();
[email protected]4468a5b2011-05-26 07:48:02168 }
[email protected]0c7d74f2010-10-11 11:55:26169 BrowserThread::PostTask(
170 BrowserThread::FILE, FROM_HERE,
[email protected]693baa5d2012-06-22 22:23:38171 base::Bind(&DefaultWebClientWorker::ExecuteSetAsDefault, this,
172 interactive_permitted));
initial.commit09911bf2008-07-26 23:55:29173}
174
[email protected]4468a5b2011-05-26 07:48:02175void ShellIntegration::DefaultWebClientWorker::ObserverDestroyed() {
[email protected]d24c4012009-07-28 01:57:31176 // Our associated view has gone away, so we shouldn't call back to it if
177 // our worker thread returns after the view is dead.
[email protected]bcb999d2011-05-31 15:11:35178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]d24c4012009-07-28 01:57:31179 observer_ = NULL;
180}
181
182///////////////////////////////////////////////////////////////////////////////
[email protected]4468a5b2011-05-26 07:48:02183// DefaultWebClientWorker, private:
[email protected]d24c4012009-07-28 01:57:31184
[email protected]4468a5b2011-05-26 07:48:02185void ShellIntegration::DefaultWebClientWorker::ExecuteCheckIsDefault() {
[email protected]0c7d74f2010-10-11 11:55:26186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]4468a5b2011-05-26 07:48:02187 DefaultWebClientState state = CheckIsDefault();
[email protected]0c7d74f2010-10-11 11:55:26188 BrowserThread::PostTask(
189 BrowserThread::UI, FROM_HERE,
[email protected]c5efb952011-11-01 01:28:36190 base::Bind(
191 &DefaultWebClientWorker::CompleteCheckIsDefault, this, state));
[email protected]d24c4012009-07-28 01:57:31192}
193
[email protected]4468a5b2011-05-26 07:48:02194void ShellIntegration::DefaultWebClientWorker::CompleteCheckIsDefault(
195 DefaultWebClientState state) {
[email protected]0c7d74f2010-10-11 11:55:26196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]264f74d12009-09-04 23:39:58197 UpdateUI(state);
[email protected]97e2e3f2011-07-22 10:21:25198 // The worker has finished everything it needs to do, so free the observer
199 // if we own it.
200 if (observer_ && observer_->IsOwnedByWorker()) {
201 delete observer_;
202 observer_ = NULL;
203 }
[email protected]d24c4012009-07-28 01:57:31204}
205
[email protected]693baa5d2012-06-22 22:23:38206void ShellIntegration::DefaultWebClientWorker::ExecuteSetAsDefault(
207 bool interactive_permitted) {
[email protected]0c7d74f2010-10-11 11:55:26208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]693baa5d2012-06-22 22:23:38209
210 bool result = SetAsDefault(interactive_permitted);
[email protected]0c7d74f2010-10-11 11:55:26211 BrowserThread::PostTask(
212 BrowserThread::UI, FROM_HERE,
[email protected]693baa5d2012-06-22 22:23:38213 base::Bind(&DefaultWebClientWorker::CompleteSetAsDefault, this, result));
[email protected]d24c4012009-07-28 01:57:31214}
215
[email protected]693baa5d2012-06-22 22:23:38216void ShellIntegration::DefaultWebClientWorker::CompleteSetAsDefault(
217 bool succeeded) {
[email protected]0c7d74f2010-10-11 11:55:26218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]693baa5d2012-06-22 22:23:38219 // First tell the observer what the SetAsDefault call has returned.
220 if (observer_)
221 observer_->OnSetAsDefaultConcluded(succeeded);
[email protected]4468a5b2011-05-26 07:48:02222 // Set as default completed, check again to make sure it stuck...
223 StartCheckIsDefault();
[email protected]d24c4012009-07-28 01:57:31224}
225
[email protected]4468a5b2011-05-26 07:48:02226void ShellIntegration::DefaultWebClientWorker::UpdateUI(
227 DefaultWebClientState state) {
[email protected]d24c4012009-07-28 01:57:31228 if (observer_) {
[email protected]264f74d12009-09-04 23:39:58229 switch (state) {
[email protected]89886652012-12-11 18:09:07230 case NOT_DEFAULT:
[email protected]4468a5b2011-05-26 07:48:02231 observer_->SetDefaultWebClientUIState(STATE_NOT_DEFAULT);
[email protected]264f74d12009-09-04 23:39:58232 break;
[email protected]89886652012-12-11 18:09:07233 case IS_DEFAULT:
[email protected]4468a5b2011-05-26 07:48:02234 observer_->SetDefaultWebClientUIState(STATE_IS_DEFAULT);
[email protected]264f74d12009-09-04 23:39:58235 break;
[email protected]89886652012-12-11 18:09:07236 case UNKNOWN_DEFAULT:
[email protected]4468a5b2011-05-26 07:48:02237 observer_->SetDefaultWebClientUIState(STATE_UNKNOWN);
[email protected]264f74d12009-09-04 23:39:58238 break;
239 default:
240 break;
241 }
[email protected]d24c4012009-07-28 01:57:31242 }
initial.commit09911bf2008-07-26 23:55:29243}
[email protected]4468a5b2011-05-26 07:48:02244
245///////////////////////////////////////////////////////////////////////////////
246// ShellIntegration::DefaultBrowserWorker
247//
248
249ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker(
250 DefaultWebClientObserver* observer)
251 : DefaultWebClientWorker(observer) {
252}
253
254///////////////////////////////////////////////////////////////////////////////
255// DefaultBrowserWorker, private:
256
257ShellIntegration::DefaultWebClientState
258ShellIntegration::DefaultBrowserWorker::CheckIsDefault() {
[email protected]89886652012-12-11 18:09:07259 return ShellIntegration::GetDefaultBrowser();
[email protected]4468a5b2011-05-26 07:48:02260}
261
[email protected]693baa5d2012-06-22 22:23:38262bool ShellIntegration::DefaultBrowserWorker::SetAsDefault(
[email protected]bd046bd42012-06-08 05:07:32263 bool interactive_permitted) {
[email protected]693baa5d2012-06-22 22:23:38264 bool result = false;
[email protected]bd046bd42012-06-08 05:07:32265 switch (ShellIntegration::CanSetAsDefaultBrowser()) {
266 case ShellIntegration::SET_DEFAULT_UNATTENDED:
[email protected]693baa5d2012-06-22 22:23:38267 result = ShellIntegration::SetAsDefaultBrowser();
[email protected]bd046bd42012-06-08 05:07:32268 break;
269 case ShellIntegration::SET_DEFAULT_INTERACTIVE:
270 if (interactive_permitted)
[email protected]693baa5d2012-06-22 22:23:38271 result = ShellIntegration::SetAsDefaultBrowserInteractive();
[email protected]bd046bd42012-06-08 05:07:32272 break;
273 default:
274 NOTREACHED();
275 }
[email protected]693baa5d2012-06-22 22:23:38276
277 return result;
[email protected]4468a5b2011-05-26 07:48:02278}
279
280///////////////////////////////////////////////////////////////////////////////
281// ShellIntegration::DefaultProtocolClientWorker
282//
283
284ShellIntegration::DefaultProtocolClientWorker::DefaultProtocolClientWorker(
285 DefaultWebClientObserver* observer, const std::string& protocol)
286 : DefaultWebClientWorker(observer),
287 protocol_(protocol) {
288}
289
290///////////////////////////////////////////////////////////////////////////////
291// DefaultProtocolClientWorker, private:
292
293ShellIntegration::DefaultWebClientState
294ShellIntegration::DefaultProtocolClientWorker::CheckIsDefault() {
295 return ShellIntegration::IsDefaultProtocolClient(protocol_);
296}
297
[email protected]693baa5d2012-06-22 22:23:38298bool ShellIntegration::DefaultProtocolClientWorker::SetAsDefault(
[email protected]bd046bd42012-06-08 05:07:32299 bool interactive_permitted) {
[email protected]ee9d89d2012-09-25 18:21:03300 bool result = false;
301 switch (ShellIntegration::CanSetAsDefaultProtocolClient()) {
[email protected]e7f79872013-09-13 01:39:31302 case ShellIntegration::SET_DEFAULT_NOT_ALLOWED:
303 result = false;
304 break;
[email protected]ee9d89d2012-09-25 18:21:03305 case ShellIntegration::SET_DEFAULT_UNATTENDED:
306 result = ShellIntegration::SetAsDefaultProtocolClient(protocol_);
307 break;
308 case ShellIntegration::SET_DEFAULT_INTERACTIVE:
309 if (interactive_permitted) {
310 result = ShellIntegration::SetAsDefaultProtocolClientInteractive(
311 protocol_);
312 }
313 break;
[email protected]ee9d89d2012-09-25 18:21:03314 }
315
316 return result;
[email protected]4468a5b2011-05-26 07:48:02317}