Home | History | Annotate | Download | only in extensions
      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_EXTENSIONS_WEBSTORE_INSTALLER_H_
      6 #define CHROME_BROWSER_EXTENSIONS_WEBSTORE_INSTALLER_H_
      7 
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "base/compiler_specific.h"
     12 #include "base/memory/ref_counted.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/supports_user_data.h"
     15 #include "base/values.h"
     16 #include "chrome/browser/extensions/extension_install_prompt.h"
     17 #include "content/public/browser/browser_thread.h"
     18 #include "content/public/browser/download_item.h"
     19 #include "content/public/browser/notification_observer.h"
     20 #include "content/public/browser/notification_registrar.h"
     21 #include "net/base/net_errors.h"
     22 #include "ui/gfx/image/image_skia.h"
     23 #include "url/gurl.h"
     24 
     25 class Profile;
     26 
     27 namespace base {
     28 class FilePath;
     29 }
     30 
     31 namespace content {
     32 class NavigationController;
     33 }
     34 
     35 namespace extensions {
     36 
     37 class Manifest;
     38 
     39 // Downloads and installs extensions from the web store.
     40 class WebstoreInstaller :public content::NotificationObserver,
     41                          public content::DownloadItem::Observer,
     42                          public base::RefCountedThreadSafe<
     43   WebstoreInstaller, content::BrowserThread::DeleteOnUIThread> {
     44  public:
     45   enum Flag {
     46     FLAG_NONE = 0,
     47 
     48     // Inline installs trigger slightly different behavior (install source
     49     // is different, download referrers are the item's page in the gallery).
     50     FLAG_INLINE_INSTALL = 1 << 0
     51   };
     52 
     53   enum FailureReason {
     54     FAILURE_REASON_CANCELLED,
     55     FAILURE_REASON_OTHER
     56   };
     57 
     58   class Delegate {
     59    public:
     60     virtual void OnExtensionDownloadStarted(const std::string& id,
     61                                             content::DownloadItem* item);
     62     virtual void OnExtensionDownloadProgress(const std::string& id,
     63                                              content::DownloadItem* item);
     64     virtual void OnExtensionInstallSuccess(const std::string& id) = 0;
     65     virtual void OnExtensionInstallFailure(const std::string& id,
     66                                            const std::string& error,
     67                                            FailureReason reason) = 0;
     68 
     69    protected:
     70     virtual ~Delegate() {}
     71   };
     72 
     73   // Contains information about what parts of the extension install process can
     74   // be skipped or modified. If one of these is present, it means that a CRX
     75   // download was initiated by WebstoreInstaller. The Approval instance should
     76   // be checked further for additional details.
     77   struct Approval : public base::SupportsUserData::Data {
     78     static scoped_ptr<Approval> CreateWithInstallPrompt(Profile* profile);
     79     static scoped_ptr<Approval> CreateWithNoInstallPrompt(
     80         Profile* profile,
     81         const std::string& extension_id,
     82         scoped_ptr<base::DictionaryValue> parsed_manifest);
     83 
     84     virtual ~Approval();
     85 
     86     // The extension id that was approved for installation.
     87     std::string extension_id;
     88 
     89     // The profile the extension should be installed into.
     90     Profile* profile;
     91 
     92     // The expected manifest, before localization.
     93     scoped_ptr<Manifest> manifest;
     94 
     95     // Whether to use a bubble notification when an app is installed, instead of
     96     // the default behavior of transitioning to the new tab page.
     97     bool use_app_installed_bubble;
     98 
     99     // Whether to skip the post install UI like the extension installed bubble.
    100     bool skip_post_install_ui;
    101 
    102     // Whether to skip the install dialog once the extension has been downloaded
    103     // and unpacked. One reason this can be true is that in the normal webstore
    104     // installation, the dialog is shown earlier, before any download is done,
    105     // so there's no need to show it again.
    106     bool skip_install_dialog;
    107 
    108     // Whether we should enable the launcher before installing the app.
    109     bool enable_launcher;
    110 
    111     // Used to show the install dialog.
    112     ExtensionInstallPrompt::ShowDialogCallback show_dialog_callback;
    113 
    114     // The icon to use to display the extension while it is installing.
    115     gfx::ImageSkia installing_icon;
    116 
    117    private:
    118     Approval();
    119   };
    120 
    121   // Gets the Approval associated with the |download|, or NULL if there's none.
    122   // Note that the Approval is owned by |download|.
    123   static const Approval* GetAssociatedApproval(
    124       const content::DownloadItem& download);
    125 
    126   // Creates a WebstoreInstaller for downloading and installing the extension
    127   // with the given |id| from the Chrome Web Store. If |delegate| is not NULL,
    128   // it will be notified when the install succeeds or fails. The installer will
    129   // use the specified |controller| to download the extension. Only one
    130   // WebstoreInstaller can use a specific controller at any given time. This
    131   // also associates the |approval| with this install.
    132   // Note: the delegate should stay alive until being called back.
    133   WebstoreInstaller(Profile* profile,
    134                     Delegate* delegate,
    135                     content::NavigationController* controller,
    136                     const std::string& id,
    137                     scoped_ptr<Approval> approval,
    138                     int flags);
    139 
    140   // Starts downloading and installing the extension.
    141   void Start();
    142 
    143   // content::NotificationObserver
    144   virtual void Observe(int type,
    145                        const content::NotificationSource& source,
    146                        const content::NotificationDetails& details) OVERRIDE;
    147 
    148   // Removes the reference to the delegate passed in the constructor. Used when
    149   // the delegate object must be deleted before this object.
    150   void InvalidateDelegate();
    151 
    152   // Instead of using the default download directory, use |directory| instead.
    153   // This does *not* transfer ownership of |directory|.
    154   static void SetDownloadDirectoryForTests(base::FilePath* directory);
    155 
    156  private:
    157   FRIEND_TEST_ALL_PREFIXES(WebstoreInstallerTest, PlatformParams);
    158   friend struct content::BrowserThread::DeleteOnThread<
    159    content::BrowserThread::UI>;
    160   friend class base::DeleteHelper<WebstoreInstaller>;
    161   virtual ~WebstoreInstaller();
    162 
    163   // Helper to get install URL.
    164   static GURL GetWebstoreInstallURL(const std::string& extension_id,
    165                                     const std::string& install_source);
    166 
    167   // DownloadManager::DownloadUrl callback.
    168   void OnDownloadStarted(content::DownloadItem* item, net::Error error);
    169 
    170   // DownloadItem::Observer implementation:
    171   virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE;
    172   virtual void OnDownloadDestroyed(content::DownloadItem* download) OVERRIDE;
    173 
    174   // Starts downloading the extension to |file_path|.
    175   void StartDownload(const base::FilePath& file_path);
    176 
    177   // Reports an install |error| to the delegate for the given extension if this
    178   // managed its installation. This also removes the associated PendingInstall.
    179   void ReportFailure(const std::string& error, FailureReason reason);
    180 
    181   // Reports a successful install to the delegate for the given extension if
    182   // this managed its installation. This also removes the associated
    183   // PendingInstall.
    184   void ReportSuccess();
    185 
    186   content::NotificationRegistrar registrar_;
    187   Profile* profile_;
    188   Delegate* delegate_;
    189   content::NavigationController* controller_;
    190   std::string id_;
    191   // The DownloadItem is owned by the DownloadManager and is valid from when
    192   // OnDownloadStarted is called (with no error) until OnDownloadDestroyed().
    193   content::DownloadItem* download_item_;
    194   scoped_ptr<Approval> approval_;
    195   GURL download_url_;
    196 };
    197 
    198 }  // namespace extensions
    199 
    200 #endif  // CHROME_BROWSER_EXTENSIONS_WEBSTORE_INSTALLER_H_
    201