Home | History | Annotate | Download | only in browser
      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/basictypes.h"
     11 #include "base/files/file_path.h"
     12 #include "base/memory/ref_counted.h"
     13 #include "base/strings/string16.h"
     14 #include "ui/gfx/image/image_family.h"
     15 #include "url/gurl.h"
     16 
     17 namespace base {
     18 class CommandLine;
     19 }
     20 
     21 class ShellIntegration {
     22  public:
     23   // Sets Chrome as the default browser (only for the current user). Returns
     24   // false if this operation fails.
     25   static bool SetAsDefaultBrowser();
     26 
     27   // Initiates an OS shell flow which (if followed by the user) should set
     28   // Chrome as the default browser. Returns false if the flow cannot be
     29   // initialized, if it is not supported (introduced for Windows 8) or if the
     30   // user cancels the operation. This is a blocking call and requires a FILE
     31   // thread. If Chrome is already default browser, no interactive dialog will be
     32   // shown and this method returns true.
     33   static bool SetAsDefaultBrowserInteractive();
     34 
     35   // Sets Chrome as the default client application for the given protocol
     36   // (only for the current user). Returns false if this operation fails.
     37   static bool SetAsDefaultProtocolClient(const std::string& protocol);
     38 
     39   // Initiates an OS shell flow which (if followed by the user) should set
     40   // Chrome as the default handler for |protocol|. Returns false if the flow
     41   // cannot be initialized, if it is not supported (introduced for Windows 8)
     42   // or if the user cancels the operation. This is a blocking call and requires
     43   // a FILE thread. If Chrome is already default for |protocol|, no interactive
     44   // dialog will be shown and this method returns true.
     45   static bool SetAsDefaultProtocolClientInteractive(
     46       const std::string& protocol);
     47 
     48   // In Windows 8 a browser can be made default-in-metro only in an interactive
     49   // flow. We will distinguish between two types of permissions here to avoid
     50   // forcing the user into UI interaction when this should not be done.
     51   enum DefaultWebClientSetPermission {
     52     SET_DEFAULT_NOT_ALLOWED,
     53     SET_DEFAULT_UNATTENDED,
     54     SET_DEFAULT_INTERACTIVE,
     55   };
     56 
     57   // Returns requirements for making the running browser the user's default.
     58   static DefaultWebClientSetPermission CanSetAsDefaultBrowser();
     59 
     60   // Returns requirements for making the running browser the user's default
     61   // client application for specific protocols.
     62   static DefaultWebClientSetPermission CanSetAsDefaultProtocolClient();
     63 
     64   // Returns a string representing the application to be launched given the
     65   // protocol of the requested url. This string may be a name or a path, but
     66   // neither is guaranteed and it should only be used as a display string.
     67   // Returns an empty string on failure.
     68   static base::string16 GetApplicationNameForProtocol(const GURL& url);
     69 
     70   // On Linux, it may not be possible to determine or set the default browser
     71   // on some desktop environments or configurations. So, we use this enum and
     72   // not a plain bool.
     73   enum DefaultWebClientState {
     74     NOT_DEFAULT,
     75     IS_DEFAULT,
     76     UNKNOWN_DEFAULT,
     77     NUM_DEFAULT_STATES
     78   };
     79 
     80   // Attempt to determine if this instance of Chrome is the default browser and
     81   // return the appropriate state. (Defined as being the handler for HTTP/HTTPS
     82   // protocols; we don't want to report "no" here if the user has simply chosen
     83   // to open HTML files in a text editor and FTP links with an FTP client.)
     84   static DefaultWebClientState GetDefaultBrowser();
     85 
     86   // Returns true if Firefox is likely to be the default browser for the current
     87   // user. This method is very fast so it can be invoked in the UI thread.
     88   static bool IsFirefoxDefaultBrowser();
     89 
     90   // Attempt to determine if this instance of Chrome is the default client
     91   // application for the given protocol and return the appropriate state.
     92   static DefaultWebClientState
     93       IsDefaultProtocolClient(const std::string& protocol);
     94 
     95   // Data that needs to be passed between the app launcher stub and Chrome.
     96   struct AppModeInfo {
     97   };
     98   static void SetAppModeInfo(const AppModeInfo* info);
     99   static const AppModeInfo* AppModeInfo();
    100 
    101   // Is the current instance of Chrome running in App mode.
    102   bool IsRunningInAppMode();
    103 
    104   // Set up command line arguments for launching a URL or an app.
    105   // The new command line reuses the current process's user data directory (and
    106   // login profile, for ChromeOS).
    107   // If |extension_app_id| is non-empty, the arguments use kAppId=<id>.
    108   // Otherwise, kApp=<url> is used.
    109   static base::CommandLine CommandLineArgsForLauncher(
    110       const GURL& url,
    111       const std::string& extension_app_id,
    112       const base::FilePath& profile_path);
    113 
    114   // Append command line arguments for launching a new chrome.exe process
    115   // based on the current process.
    116   // The new command line reuses the current process's user data directory and
    117   // profile.
    118   static void AppendProfileArgs(const base::FilePath& profile_path,
    119                                 base::CommandLine* command_line);
    120 
    121 #if defined(OS_WIN)
    122   // Generates an application user model ID (AppUserModelId) for a given app
    123   // name and profile path. The returned app id is in the format of
    124   // "|app_name|[.<profile_id>]". "profile_id" is appended when user override
    125   // the default value.
    126   // Note: If the app has an installation specific suffix (e.g. on user-level
    127   // Chrome installs), |app_name| should already be suffixed, this method will
    128   // then further suffix it with the profile id as described above.
    129   static base::string16 GetAppModelIdForProfile(const base::string16& app_name,
    130                                           const base::FilePath& profile_path);
    131 
    132   // Generates an application user model ID (AppUserModelId) for Chromium by
    133   // calling GetAppModelIdForProfile() with ShellUtil::GetAppId() as app_name.
    134   static base::string16 GetChromiumModelIdForProfile(
    135       const base::FilePath& profile_path);
    136 
    137   // Get the AppUserModelId for the App List, for the profile in |profile_path|.
    138   static base::string16 GetAppListAppModelIdForProfile(
    139       const base::FilePath& profile_path);
    140 
    141   // Migrates existing chrome shortcuts by tagging them with correct app id.
    142   // see http://crbug.com/28104
    143   static void MigrateChromiumShortcuts();
    144 
    145   // Migrates all shortcuts in |path| which point to |chrome_exe| such that they
    146   // have the appropriate AppUserModelId. Also makes sure those shortcuts have
    147   // the dual_mode property set if such is requested by |check_dual_mode|.
    148   // Returns the number of shortcuts migrated.
    149   // This method should not be called prior to Windows 7.
    150   // This method is only public for the sake of tests and shouldn't be called
    151   // externally otherwise.
    152   static int MigrateShortcutsInPathInternal(const base::FilePath& chrome_exe,
    153                                             const base::FilePath& path,
    154                                             bool check_dual_mode);
    155 
    156   // Returns the path to the Start Menu shortcut for the given Chrome.
    157   static base::FilePath GetStartMenuShortcut(const base::FilePath& chrome_exe);
    158 #endif  // defined(OS_WIN)
    159 
    160 #if !defined(OS_WIN)
    161   // TODO(calamity): replace with
    162   // BrowserDistribution::GetStartMenuShortcutSubfolder() once
    163   // BrowserDistribution is cross-platform.
    164   // Gets the name of the Chrome Apps menu folder in which to place app
    165   // shortcuts. This is needed for Mac and Linux.
    166   static base::string16 GetAppShortcutsSubdirName();
    167 #endif
    168 
    169   // The current default web client application UI state. This is used when
    170   // querying if Chrome is the default browser or the default handler
    171   // application for a url protocol, and communicates the state and result of
    172   // a request.
    173   enum DefaultWebClientUIState {
    174     STATE_PROCESSING,
    175     STATE_NOT_DEFAULT,
    176     STATE_IS_DEFAULT,
    177     STATE_UNKNOWN
    178   };
    179 
    180   class DefaultWebClientObserver {
    181    public:
    182     virtual ~DefaultWebClientObserver() {}
    183     // Updates the UI state to reflect the current default browser state.
    184     virtual void SetDefaultWebClientUIState(DefaultWebClientUIState state) = 0;
    185     // Called to notify the UI of the immediate result of invoking
    186     // SetAsDefault.
    187     virtual void OnSetAsDefaultConcluded(bool succeeded) {}
    188     // Observer classes that return true to OwnedByWorker are automatically
    189     // freed by the worker when they are no longer needed. False by default.
    190     virtual bool IsOwnedByWorker();
    191     // An observer can permit or decline set-as-default operation if it
    192     // requires triggering user interaction. By default not allowed.
    193     virtual bool IsInteractiveSetDefaultPermitted();
    194   };
    195 
    196   //  Helper objects that handle checking if Chrome is the default browser
    197   //  or application for a url protocol on Windows and Linux, and also setting
    198   //  it as the default. These operations are performed asynchronously on the
    199   //  file thread since registry access (on Windows) or the preference database
    200   //  (on Linux) are involved and this can be slow.
    201   class DefaultWebClientWorker
    202       : public base::RefCountedThreadSafe<DefaultWebClientWorker> {
    203    public:
    204     explicit DefaultWebClientWorker(DefaultWebClientObserver* observer);
    205 
    206     // Checks to see if Chrome is the default web client application. The result
    207     // will be passed back to the observer via the SetDefaultWebClientUIState
    208     // function. If there is no observer, this function does not do anything.
    209     void StartCheckIsDefault();
    210 
    211     // Sets Chrome as the default web client application. If there is an
    212     // observer, once the operation has completed the new default will be
    213     // queried and the current status reported via SetDefaultWebClientUIState.
    214     void StartSetAsDefault();
    215 
    216     // Called to notify the worker that the view is gone.
    217     void ObserverDestroyed();
    218 
    219    protected:
    220     friend class base::RefCountedThreadSafe<DefaultWebClientWorker>;
    221 
    222     virtual ~DefaultWebClientWorker() {}
    223 
    224    private:
    225     // Function that performs the check.
    226     virtual DefaultWebClientState CheckIsDefault() = 0;
    227 
    228     // Function that sets Chrome as the default web client. Returns false if
    229     // the operation fails or has been cancelled by the user.
    230     virtual bool SetAsDefault(bool interactive_permitted) = 0;
    231 
    232     // Function that handles performing the check on the file thread. This
    233     // function is posted as a task onto the file thread, where it performs
    234     // the check. When the check has finished the CompleteCheckIsDefault
    235     // function is posted to the UI thread, where the result is sent back to
    236     // the observer.
    237     void ExecuteCheckIsDefault();
    238 
    239     // Function that handles setting Chrome as the default web client on the
    240     // file thread. This function is posted as a task onto the file thread.
    241     // Once it is finished the CompleteSetAsDefault function is posted to the
    242     // UI thread which will check the status of Chrome as the default, and
    243     // send this to the observer.
    244     // |interactive_permitted| indicates if the routine is allowed to carry on
    245     // in context where user interaction is required (CanSetAsDefault*
    246     // returns SET_DEFAULT_INTERACTIVE).
    247     void ExecuteSetAsDefault(bool interactive_permitted);
    248 
    249     // Communicate results to the observer. This function is posted as a task
    250     // onto the UI thread by the ExecuteCheckIsDefault function running in the
    251     // file thread.
    252     void CompleteCheckIsDefault(DefaultWebClientState state);
    253 
    254     // When the action to set Chrome as the default has completed this function
    255     // is run. It is posted as a task back onto the UI thread by the
    256     // ExecuteSetAsDefault function running in the file thread. This function
    257     // will the start the check process, which, if an observer is present,
    258     // reports to it the new status.
    259     // |succeeded| is true if the actual call to a set-default function (from
    260     // ExecuteSetAsDefault) was successful.
    261     void CompleteSetAsDefault(bool succeeded);
    262 
    263     // Updates the UI in our associated view with the current default web
    264     // client state.
    265     void UpdateUI(DefaultWebClientState state);
    266 
    267     DefaultWebClientObserver* observer_;
    268 
    269     DISALLOW_COPY_AND_ASSIGN(DefaultWebClientWorker);
    270   };
    271 
    272   // Worker for checking and setting the default browser.
    273   class DefaultBrowserWorker : public DefaultWebClientWorker {
    274    public:
    275     explicit DefaultBrowserWorker(DefaultWebClientObserver* observer);
    276 
    277    private:
    278     virtual ~DefaultBrowserWorker() {}
    279 
    280     // Check if Chrome is the default browser.
    281     virtual DefaultWebClientState CheckIsDefault() OVERRIDE;
    282 
    283     // Set Chrome as the default browser.
    284     virtual bool SetAsDefault(bool interactive_permitted) OVERRIDE;
    285 
    286     DISALLOW_COPY_AND_ASSIGN(DefaultBrowserWorker);
    287   };
    288 
    289   // Worker for checking and setting the default client application
    290   // for a given protocol. A different worker instance is needed for each
    291   // protocol you are interested in, so to check or set the default for
    292   // multiple protocols you should use multiple worker objects.
    293   class DefaultProtocolClientWorker : public DefaultWebClientWorker {
    294    public:
    295     DefaultProtocolClientWorker(DefaultWebClientObserver* observer,
    296                                 const std::string& protocol);
    297 
    298     const std::string& protocol() const { return protocol_; }
    299 
    300    protected:
    301     virtual ~DefaultProtocolClientWorker() {}
    302 
    303    private:
    304     // Check is Chrome is the default handler for this protocol.
    305     virtual DefaultWebClientState CheckIsDefault() OVERRIDE;
    306 
    307     // Set Chrome as the default handler for this protocol.
    308     virtual bool SetAsDefault(bool interactive_permitted) OVERRIDE;
    309 
    310     std::string protocol_;
    311 
    312     DISALLOW_COPY_AND_ASSIGN(DefaultProtocolClientWorker);
    313   };
    314 };
    315 
    316 #endif  // CHROME_BROWSER_SHELL_INTEGRATION_H_
    317