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 #ifndef CHROME_BROWSER_SHELL_INTEGRATION_H_ 6 #define CHROME_BROWSER_SHELL_INTEGRATION_H_ 7 8 #include <string> 9 10 #include "base/callback.h" 11 #include "base/files/file_path.h" 12 #include "base/macros.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/strings/string16.h" 15 #include "build/build_config.h" 16 #include "ui/gfx/image/image_family.h" 17 #include "url/gurl.h" 18 19 namespace base { 20 class CommandLine; 21 } 22 23 namespace shell_integration { 24 25 // Sets Chrome as the default browser (only for the current user). Returns false 26 // if this operation fails. This does not work on Windows version 8 or higher. 27 // Prefer to use the DefaultBrowserWorker class below since it works on all OSs. 28 bool SetAsDefaultBrowser(); 29 30 // Sets Chrome as the default client application for the given protocol 31 // (only for the current user). Returns false if this operation fails. 32 // Prefer to use the DefaultProtocolClientWorker class below since it works on 33 // all OSs. 34 bool SetAsDefaultProtocolClient(const std::string& protocol); 35 36 // The different types of permissions required to set a default web client. 37 enum DefaultWebClientSetPermission { 38 // The browser distribution is not permitted to be made default. 39 SET_DEFAULT_NOT_ALLOWED, 40 // No special permission or interaction is required to set the default 41 // browser. This is used in Linux, Mac and Windows 7 and under. 42 SET_DEFAULT_UNATTENDED, 43 // On Windows 8+, a browser can be made default only in an interactive flow. 44 SET_DEFAULT_INTERACTIVE, 45 }; 46 47 // Returns requirements for making the running browser either the default 48 // browser or the default client application for a specific protocols for the 49 // current user. 50 DefaultWebClientSetPermission GetDefaultWebClientSetPermission(); 51 52 // Returns true if the running browser can be set as the default browser, 53 // whether user interaction is needed or not. Use 54 // GetDefaultWebClientSetPermission() if this distinction is important. 55 bool CanSetAsDefaultBrowser(); 56 57 // Returns true if making the running browser the default client for any 58 // protocol requires elevated privileges. 59 bool IsElevationNeededForSettingDefaultProtocolClient(); 60 61 // Returns a string representing the application to be launched given the 62 // protocol of the requested url. This string may be a name or a path, but 63 // neither is guaranteed and it should only be used as a display string. 64 // Returns an empty string on failure. 65 base::string16 GetApplicationNameForProtocol(const GURL& url); 66 67 // Chrome's default web client state as a browser as a protocol client. If the 68 // current install mode is not default, the brand's other modes are 69 // checked. This allows callers to take specific action in case the current mode 70 // (e.g., Chrome Dev) is not the default handler, but another of the brand's 71 // modes (e.g., stable Chrome) is. 72 enum DefaultWebClientState { 73 // No install mode for the brand is the default client. 74 NOT_DEFAULT, 75 // The current install mode is the default client. 76 IS_DEFAULT, 77 // An error occurred while attempting to check the default client. 78 UNKNOWN_DEFAULT, 79 // The current install mode is not default, although one of the brand's 80 // other install modes is. 81 OTHER_MODE_IS_DEFAULT, 82 NUM_DEFAULT_STATES 83 }; 84 85 // Attempt to determine if this instance of Chrome is the default browser and 86 // return the appropriate state. (Defined as being the handler for HTTP/HTTPS 87 // protocols; we don't want to report "no" here if the user has simply chosen 88 // to open HTML files in a text editor and FTP links with an FTP client.) 89 DefaultWebClientState GetDefaultBrowser(); 90 91 // Returns true if Firefox is likely to be the default browser for the current 92 // user. This method is very fast so it can be invoked in the UI thread. 93 bool IsFirefoxDefaultBrowser(); 94 95 #if defined(OS_WIN) 96 // Returns true if IE is likely to be the default browser for the current 97 // user. This method is very fast so it can be invoked in the UI thread. 98 bool IsIEDefaultBrowser(); 99 100 // Returns the install id of the installation set as default browser. If no 101 // installation of Firefox is set as the default browser, returns an empty 102 // string. 103 // TODO(crbug/1011830): This should return the install id of the stable 104 // version if no version of Firefox is set as default browser. 105 std::string GetFirefoxProgIdSuffix(); 106 #endif 107 108 // Attempt to determine if this instance of Chrome is the default client 109 // application for the given protocol and return the appropriate state. 110 DefaultWebClientState IsDefaultProtocolClient(const std::string& protocol); 111 112 // Data that needs to be passed between the app launcher stub and Chrome. 113 struct AppModeInfo {}; 114 void SetAppModeInfo(const AppModeInfo* info); 115 const AppModeInfo* AppModeInfo(); 116 117 // Is the current instance of Chrome running in App mode. 118 bool IsRunningInAppMode(); 119 120 // Set up command line arguments for launching a URL or an app. 121 // The new command line reuses the current process's user data directory (and 122 // login profile, for ChromeOS). 123 // If |extension_app_id| is non-empty, the arguments use kAppId=<id>. 124 // Otherwise, kApp=<url> is used. 125 base::CommandLine CommandLineArgsForLauncher( 126 const GURL& url, 127 const std::string& extension_app_id, 128 const base::FilePath& profile_path); 129 130 // Append command line arguments for launching a new chrome.exe process 131 // based on the current process. 132 // The new command line reuses the current process's user data directory and 133 // profile. 134 void AppendProfileArgs(const base::FilePath& profile_path, 135 base::CommandLine* command_line); 136 137 #if !defined(OS_WIN) 138 // Gets the name of the Chrome Apps menu folder in which to place app 139 // shortcuts. This is needed for Mac and Linux. 140 base::string16 GetAppShortcutsSubdirName(); 141 #endif 142 143 // The type of callback used to communicate processing state to consumers of 144 // DefaultBrowserWorker and DefaultProtocolClientWorker. 145 using DefaultWebClientWorkerCallback = 146 base::OnceCallback<void(DefaultWebClientState)>; 147 148 // Helper objects that handle checking if Chrome is the default browser 149 // or application for a url protocol on Windows and Linux, and also setting 150 // it as the default. These operations are performed asynchronously on a 151 // blocking sequence since registry access (on Windows) or the preference 152 // database (on Linux) are involved and this can be slow. 153 // By default, the worker will present the user with an interactive flow if 154 // required by the platform. This can be suppressed via 155 // set_interactive_permitted(), in which case an attempt to set Chrome as 156 // the default handler will silently fail on such platforms. 157 class DefaultWebClientWorker 158 : public base::RefCountedThreadSafe<DefaultWebClientWorker> { 159 public: 160 // Controls whether the worker can use user interaction to set the default 161 // web client. If false, the set-as-default operation will fail on OS where 162 // it is required. set_interactive_permitted(bool interactive_permitted)163 void set_interactive_permitted(bool interactive_permitted) { 164 interactive_permitted_ = interactive_permitted; 165 } 166 167 // Checks to see if Chrome is the default web client application. The 168 // provided callback will be run to communicate the default state to the 169 // caller. 170 void StartCheckIsDefault(DefaultWebClientWorkerCallback callback); 171 172 // Sets Chrome as the default web client application. Once done, it will 173 // trigger a check for the default state using StartCheckIsDefault() to return 174 // the default state to the caller. 175 void StartSetAsDefault(DefaultWebClientWorkerCallback callback); 176 177 protected: 178 friend class base::RefCountedThreadSafe<DefaultWebClientWorker>; 179 180 explicit DefaultWebClientWorker(const char* worker_name); 181 virtual ~DefaultWebClientWorker(); 182 183 // Communicates the result via |callback|. When 184 // |is_following_set_as_default| is true, |state| will be reported to UMA as 185 // the result of the set-as-default operation. 186 void OnCheckIsDefaultComplete(DefaultWebClientState state, 187 bool is_following_set_as_default, 188 DefaultWebClientWorkerCallback callback); 189 190 // When false, the operation to set as default will fail for interactive 191 // flows. 192 bool interactive_permitted_ = true; 193 194 private: 195 // Checks whether Chrome is the default web client. Always called on a 196 // blocking sequence. When |is_following_set_as_default| is true, The default 197 // state will be reported to UMA as the result of the set-as-default 198 // operation. 199 void CheckIsDefault(bool is_following_set_as_default, 200 DefaultWebClientWorkerCallback callback); 201 202 // Sets Chrome as the default web client. Always called on a blocking 203 // sequence. 204 void SetAsDefault(DefaultWebClientWorkerCallback callback); 205 206 // Implementation of CheckIsDefault() and SetAsDefault() for subclasses. 207 virtual DefaultWebClientState CheckIsDefaultImpl() = 0; 208 209 // The callback may be run synchronously or at an arbitrary time later on this 210 // thread. 211 // Note: Subclasses MUST make sure |on_finished_callback| is executed. 212 virtual void SetAsDefaultImpl(base::OnceClosure on_finished_callback) = 0; 213 214 // Reports the result for the set-as-default operation. 215 void ReportSetDefaultResult(DefaultWebClientState state); 216 217 // Used to differentiate UMA metrics for setting the default browser and 218 // setting the default protocol client. The pointer must be valid for the 219 // lifetime of the worker. 220 const char* worker_name_; 221 222 DISALLOW_COPY_AND_ASSIGN(DefaultWebClientWorker); 223 }; 224 225 // Worker for checking and setting the default browser. 226 class DefaultBrowserWorker : public DefaultWebClientWorker { 227 public: 228 DefaultBrowserWorker(); 229 230 protected: 231 ~DefaultBrowserWorker() override; 232 233 private: 234 // Check if Chrome is the default browser. 235 DefaultWebClientState CheckIsDefaultImpl() override; 236 237 // Set Chrome as the default browser. 238 void SetAsDefaultImpl(base::OnceClosure on_finished_callback) override; 239 240 DISALLOW_COPY_AND_ASSIGN(DefaultBrowserWorker); 241 }; 242 243 // Worker for checking and setting the default client application 244 // for a given protocol. A different worker instance is needed for each 245 // protocol you are interested in, so to check or set the default for 246 // multiple protocols you should use multiple worker objects. 247 class DefaultProtocolClientWorker : public DefaultWebClientWorker { 248 public: 249 explicit DefaultProtocolClientWorker(const std::string& protocol); 250 protocol()251 const std::string& protocol() const { return protocol_; } 252 253 protected: 254 ~DefaultProtocolClientWorker() override; 255 256 private: 257 // Check if Chrome is the default handler for this protocol. 258 DefaultWebClientState CheckIsDefaultImpl() override; 259 260 // Set Chrome as the default handler for this protocol. 261 void SetAsDefaultImpl(base::OnceClosure on_finished_callback) override; 262 263 std::string protocol_; 264 265 DISALLOW_COPY_AND_ASSIGN(DefaultProtocolClientWorker); 266 }; 267 268 } // namespace shell_integration 269 270 #endif // CHROME_BROWSER_SHELL_INTEGRATION_H_ 271