shell_integration.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2009 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.
4
5#include "chrome/browser/shell_integration.h"
6
7#include "base/command_line.h"
8#include "base/file_util.h"
9#include "base/path_service.h"
10#include "base/string_util.h"
11#include "base/utf_string_conversions.h"
12#include "chrome/browser/browser_thread.h"
13#include "chrome/common/chrome_paths.h"
14#include "chrome/common/chrome_switches.h"
15
16ShellIntegration::ShortcutInfo::ShortcutInfo()
17    : create_on_desktop(false),
18      create_in_applications_menu(false),
19      create_in_quick_launch_bar(false) {
20}
21
22ShellIntegration::ShortcutInfo::~ShortcutInfo() {}
23
24std::string ShellIntegration::GetCommandLineArgumentsCommon(const GURL& url,
25    const string16& extension_app_id) {
26  const CommandLine cmd = *CommandLine::ForCurrentProcess();
27  std::wstring arguments_w;
28
29  // Use the same UserDataDir for new launches that we currently have set.
30  FilePath user_data_dir = cmd.GetSwitchValuePath(switches::kUserDataDir);
31  if (!user_data_dir.value().empty()) {
32    // Make sure user_data_dir is an absolute path.
33    if (file_util::AbsolutePath(&user_data_dir) &&
34        file_util::PathExists(user_data_dir)) {
35      // TODO: This is wrong in pathological quoting scenarios; we shouldn't be
36      // passing around command lines as strings at all.
37      arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kUserDataDir) +
38                     L"=\"" + user_data_dir.ToWStringHack() + L"\" ";
39    }
40  }
41
42#if defined(OS_CHROMEOS)
43  FilePath profile = cmd.GetSwitchValuePath(switches::kLoginProfile);
44  if (!profile.empty()) {
45    arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kLoginProfile) +
46        L"=\"" + profile.ToWStringHack() + L"\" ";
47  }
48#endif
49
50  // If |extension_app_id| is present, we use the kAppId switch rather than
51  // the kApp switch (the launch url will be read from the extension app
52  // during launch.
53  if (!extension_app_id.empty()) {
54    arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kAppId) +
55        L"=\"" + ASCIIToWide(UTF16ToASCII(extension_app_id));
56  } else {
57    // Use '--app=url' instead of just 'url' to launch the browser with minimal
58    // chrome.
59    // Note: Do not change this flag!  Old Gears shortcuts will break if you do!
60    std::string url_string = url.spec();
61    ReplaceSubstringsAfterOffset(&url_string, 0, "\\", "%5C");
62    ReplaceSubstringsAfterOffset(&url_string, 0, "\"", "%22");
63    ReplaceSubstringsAfterOffset(&url_string, 0, ";",  "%3B");
64    ReplaceSubstringsAfterOffset(&url_string, 0, "$",  "%24");
65#if defined(OS_WIN)  // Windows shortcuts can't escape % so we use \x instead.
66    ReplaceSubstringsAfterOffset(&url_string, 0, "%",  "\\x");
67#endif
68    std::wstring url_w = UTF8ToWide(url_string);
69    arguments_w += std::wstring(L"--") + ASCIIToWide(switches::kApp) +
70        L"=\"" + url_w + L"\"";
71  }
72  return WideToUTF8(arguments_w);
73}
74
75///////////////////////////////////////////////////////////////////////////////
76// ShellIntegration::DefaultBrowserWorker
77//
78
79ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker(
80    DefaultBrowserObserver* observer)
81    : observer_(observer) {
82}
83
84void ShellIntegration::DefaultBrowserWorker::StartCheckDefaultBrowser() {
85  observer_->SetDefaultBrowserUIState(STATE_PROCESSING);
86  BrowserThread::PostTask(
87      BrowserThread::FILE, FROM_HERE,
88      NewRunnableMethod(
89          this, &DefaultBrowserWorker::ExecuteCheckDefaultBrowser));
90}
91
92void ShellIntegration::DefaultBrowserWorker::StartSetAsDefaultBrowser() {
93  observer_->SetDefaultBrowserUIState(STATE_PROCESSING);
94  BrowserThread::PostTask(
95      BrowserThread::FILE, FROM_HERE,
96      NewRunnableMethod(
97          this, &DefaultBrowserWorker::ExecuteSetAsDefaultBrowser));
98}
99
100void ShellIntegration::DefaultBrowserWorker::ObserverDestroyed() {
101  // Our associated view has gone away, so we shouldn't call back to it if
102  // our worker thread returns after the view is dead.
103  observer_ = NULL;
104}
105
106///////////////////////////////////////////////////////////////////////////////
107// DefaultBrowserWorker, private:
108
109void ShellIntegration::DefaultBrowserWorker::ExecuteCheckDefaultBrowser() {
110  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
111  DefaultBrowserState state = ShellIntegration::IsDefaultBrowser();
112  BrowserThread::PostTask(
113      BrowserThread::UI, FROM_HERE,
114      NewRunnableMethod(
115          this, &DefaultBrowserWorker::CompleteCheckDefaultBrowser, state));
116}
117
118void ShellIntegration::DefaultBrowserWorker::CompleteCheckDefaultBrowser(
119    DefaultBrowserState state) {
120  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
121  UpdateUI(state);
122}
123
124void ShellIntegration::DefaultBrowserWorker::ExecuteSetAsDefaultBrowser() {
125  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
126  ShellIntegration::SetAsDefaultBrowser();
127  BrowserThread::PostTask(
128      BrowserThread::UI, FROM_HERE,
129      NewRunnableMethod(
130          this, &DefaultBrowserWorker::CompleteSetAsDefaultBrowser));
131}
132
133void ShellIntegration::DefaultBrowserWorker::CompleteSetAsDefaultBrowser() {
134  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
135  if (observer_) {
136    // Set as default completed, check again to make sure it stuck...
137    StartCheckDefaultBrowser();
138  }
139}
140
141void ShellIntegration::DefaultBrowserWorker::UpdateUI(
142    DefaultBrowserState state) {
143  if (observer_) {
144    switch (state) {
145      case NOT_DEFAULT_BROWSER:
146        observer_->SetDefaultBrowserUIState(STATE_NOT_DEFAULT);
147        break;
148      case IS_DEFAULT_BROWSER:
149        observer_->SetDefaultBrowserUIState(STATE_IS_DEFAULT);
150        break;
151      case UNKNOWN_DEFAULT_BROWSER:
152        observer_->SetDefaultBrowserUIState(STATE_UNKNOWN);
153        break;
154      default:
155        break;
156    }
157  }
158}
159