shell_integration.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 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/bind.h" 8#include "base/command_line.h" 9#include "base/file_util.h" 10#include "base/path_service.h" 11#include "base/prefs/pref_service.h" 12#include "base/string_util.h" 13#include "base/utf_string_conversions.h" 14#include "chrome/browser/policy/policy_path_parser.h" 15#include "chrome/common/chrome_paths.h" 16#include "chrome/common/chrome_switches.h" 17#include "chrome/common/pref_names.h" 18#include "content/public/browser/browser_thread.h" 19 20using content::BrowserThread; 21 22ShellIntegration::DefaultWebClientSetPermission 23 ShellIntegration::CanSetAsDefaultProtocolClient() { 24 // Allowed as long as the browser can become the operating system default 25 // browser. 26 return CanSetAsDefaultBrowser(); 27} 28 29ShellIntegration::ShortcutInfo::ShortcutInfo() 30 : is_platform_app(false) { 31} 32 33ShellIntegration::ShortcutInfo::~ShortcutInfo() {} 34 35ShellIntegration::ShortcutLocations::ShortcutLocations() 36 : on_desktop(false), 37 in_applications_menu(false), 38 in_quick_launch_bar(false), 39 hidden(false) { 40} 41 42static const struct ShellIntegration::AppModeInfo* gAppModeInfo = NULL; 43 44// static 45void ShellIntegration::SetAppModeInfo(const struct AppModeInfo* info) { 46 gAppModeInfo = info; 47} 48 49// static 50const struct ShellIntegration::AppModeInfo* ShellIntegration::AppModeInfo() { 51 return gAppModeInfo; 52} 53 54// static 55bool ShellIntegration::IsRunningInAppMode() { 56 return gAppModeInfo != NULL; 57} 58 59// static 60CommandLine ShellIntegration::CommandLineArgsForLauncher( 61 const GURL& url, 62 const std::string& extension_app_id, 63 const base::FilePath& profile_path) { 64 const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); 65 CommandLine new_cmd_line(CommandLine::NO_PROGRAM); 66 67 // Use the same UserDataDir for new launches that we currently have set. 68 base::FilePath user_data_dir = 69 cmd_line.GetSwitchValuePath(switches::kUserDataDir); 70#if defined(OS_MACOSX) || defined(OS_WIN) 71 policy::path_parser::CheckUserDataDirPolicy(&user_data_dir); 72#endif 73 if (!user_data_dir.empty()) { 74 // Make sure user_data_dir is an absolute path. 75 if (file_util::AbsolutePath(&user_data_dir) && 76 file_util::PathExists(user_data_dir)) { 77 new_cmd_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir); 78 } 79 } 80 81#if defined(OS_CHROMEOS) 82 base::FilePath profile = cmd_line.GetSwitchValuePath(switches::kLoginProfile); 83 if (!profile.empty()) 84 new_cmd_line.AppendSwitchPath(switches::kLoginProfile, profile); 85#else 86 if (!profile_path.empty() && !extension_app_id.empty()) 87 new_cmd_line.AppendSwitchPath(switches::kProfileDirectory, 88 profile_path.BaseName()); 89#endif 90 91 // If |extension_app_id| is present, we use the kAppId switch rather than 92 // the kApp switch (the launch url will be read from the extension app 93 // during launch. 94 if (!extension_app_id.empty()) { 95 new_cmd_line.AppendSwitchASCII(switches::kAppId, extension_app_id); 96 } else { 97 // Use '--app=url' instead of just 'url' to launch the browser with minimal 98 // chrome. 99 // Note: Do not change this flag! Old Gears shortcuts will break if you do! 100 new_cmd_line.AppendSwitchASCII(switches::kApp, url.spec()); 101 } 102 return new_cmd_line; 103} 104 105#if !defined(OS_WIN) 106// static 107bool ShellIntegration::SetAsDefaultBrowserInteractive() { 108 return false; 109} 110 111// static 112bool ShellIntegration::SetAsDefaultProtocolClientInteractive( 113 const std::string& protocol) { 114 return false; 115} 116#endif 117 118bool ShellIntegration::DefaultWebClientObserver::IsOwnedByWorker() { 119 return false; 120} 121 122bool ShellIntegration::DefaultWebClientObserver:: 123 IsInteractiveSetDefaultPermitted() { 124 return false; 125} 126 127/////////////////////////////////////////////////////////////////////////////// 128// ShellIntegration::DefaultWebClientWorker 129// 130 131ShellIntegration::DefaultWebClientWorker::DefaultWebClientWorker( 132 DefaultWebClientObserver* observer) 133 : observer_(observer) { 134} 135 136void ShellIntegration::DefaultWebClientWorker::StartCheckIsDefault() { 137 if (observer_) { 138 observer_->SetDefaultWebClientUIState(STATE_PROCESSING); 139 BrowserThread::PostTask( 140 BrowserThread::FILE, FROM_HERE, 141 base::Bind( 142 &DefaultWebClientWorker::ExecuteCheckIsDefault, this)); 143 } 144} 145 146void ShellIntegration::DefaultWebClientWorker::StartSetAsDefault() { 147 bool interactive_permitted = false; 148 if (observer_) { 149 observer_->SetDefaultWebClientUIState(STATE_PROCESSING); 150 interactive_permitted = observer_->IsInteractiveSetDefaultPermitted(); 151 } 152 BrowserThread::PostTask( 153 BrowserThread::FILE, FROM_HERE, 154 base::Bind(&DefaultWebClientWorker::ExecuteSetAsDefault, this, 155 interactive_permitted)); 156} 157 158void ShellIntegration::DefaultWebClientWorker::ObserverDestroyed() { 159 // Our associated view has gone away, so we shouldn't call back to it if 160 // our worker thread returns after the view is dead. 161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 162 observer_ = NULL; 163} 164 165/////////////////////////////////////////////////////////////////////////////// 166// DefaultWebClientWorker, private: 167 168void ShellIntegration::DefaultWebClientWorker::ExecuteCheckIsDefault() { 169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 170 DefaultWebClientState state = CheckIsDefault(); 171 BrowserThread::PostTask( 172 BrowserThread::UI, FROM_HERE, 173 base::Bind( 174 &DefaultWebClientWorker::CompleteCheckIsDefault, this, state)); 175} 176 177void ShellIntegration::DefaultWebClientWorker::CompleteCheckIsDefault( 178 DefaultWebClientState state) { 179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 180 UpdateUI(state); 181 // The worker has finished everything it needs to do, so free the observer 182 // if we own it. 183 if (observer_ && observer_->IsOwnedByWorker()) { 184 delete observer_; 185 observer_ = NULL; 186 } 187} 188 189void ShellIntegration::DefaultWebClientWorker::ExecuteSetAsDefault( 190 bool interactive_permitted) { 191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 192 193 bool result = SetAsDefault(interactive_permitted); 194 BrowserThread::PostTask( 195 BrowserThread::UI, FROM_HERE, 196 base::Bind(&DefaultWebClientWorker::CompleteSetAsDefault, this, result)); 197} 198 199void ShellIntegration::DefaultWebClientWorker::CompleteSetAsDefault( 200 bool succeeded) { 201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 202 // First tell the observer what the SetAsDefault call has returned. 203 if (observer_) 204 observer_->OnSetAsDefaultConcluded(succeeded); 205 // Set as default completed, check again to make sure it stuck... 206 StartCheckIsDefault(); 207} 208 209void ShellIntegration::DefaultWebClientWorker::UpdateUI( 210 DefaultWebClientState state) { 211 if (observer_) { 212 switch (state) { 213 case NOT_DEFAULT: 214 observer_->SetDefaultWebClientUIState(STATE_NOT_DEFAULT); 215 break; 216 case IS_DEFAULT: 217 observer_->SetDefaultWebClientUIState(STATE_IS_DEFAULT); 218 break; 219 case UNKNOWN_DEFAULT: 220 observer_->SetDefaultWebClientUIState(STATE_UNKNOWN); 221 break; 222 default: 223 break; 224 } 225 } 226} 227 228/////////////////////////////////////////////////////////////////////////////// 229// ShellIntegration::DefaultBrowserWorker 230// 231 232ShellIntegration::DefaultBrowserWorker::DefaultBrowserWorker( 233 DefaultWebClientObserver* observer) 234 : DefaultWebClientWorker(observer) { 235} 236 237/////////////////////////////////////////////////////////////////////////////// 238// DefaultBrowserWorker, private: 239 240ShellIntegration::DefaultWebClientState 241ShellIntegration::DefaultBrowserWorker::CheckIsDefault() { 242 return ShellIntegration::GetDefaultBrowser(); 243} 244 245bool ShellIntegration::DefaultBrowserWorker::SetAsDefault( 246 bool interactive_permitted) { 247 bool result = false; 248 switch (ShellIntegration::CanSetAsDefaultBrowser()) { 249 case ShellIntegration::SET_DEFAULT_UNATTENDED: 250 result = ShellIntegration::SetAsDefaultBrowser(); 251 break; 252 case ShellIntegration::SET_DEFAULT_INTERACTIVE: 253 if (interactive_permitted) 254 result = ShellIntegration::SetAsDefaultBrowserInteractive(); 255 break; 256 default: 257 NOTREACHED(); 258 } 259 260 return result; 261} 262 263/////////////////////////////////////////////////////////////////////////////// 264// ShellIntegration::DefaultProtocolClientWorker 265// 266 267ShellIntegration::DefaultProtocolClientWorker::DefaultProtocolClientWorker( 268 DefaultWebClientObserver* observer, const std::string& protocol) 269 : DefaultWebClientWorker(observer), 270 protocol_(protocol) { 271} 272 273/////////////////////////////////////////////////////////////////////////////// 274// DefaultProtocolClientWorker, private: 275 276ShellIntegration::DefaultWebClientState 277ShellIntegration::DefaultProtocolClientWorker::CheckIsDefault() { 278 return ShellIntegration::IsDefaultProtocolClient(protocol_); 279} 280 281bool ShellIntegration::DefaultProtocolClientWorker::SetAsDefault( 282 bool interactive_permitted) { 283 bool result = false; 284 switch (ShellIntegration::CanSetAsDefaultProtocolClient()) { 285 case ShellIntegration::SET_DEFAULT_UNATTENDED: 286 result = ShellIntegration::SetAsDefaultProtocolClient(protocol_); 287 break; 288 case ShellIntegration::SET_DEFAULT_INTERACTIVE: 289 if (interactive_permitted) { 290 result = ShellIntegration::SetAsDefaultProtocolClientInteractive( 291 protocol_); 292 } 293 break; 294 default: 295 NOTREACHED(); 296 } 297 298 return result; 299} 300