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