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