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_STANDALONE_INSTALLER_H_
      6 #define CHROME_BROWSER_EXTENSIONS_WEBSTORE_STANDALONE_INSTALLER_H_
      7 
      8 #include <string>
      9 
     10 #include "base/callback.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "chrome/browser/extensions/extension_install_prompt.h"
     14 #include "chrome/browser/extensions/webstore_data_fetcher_delegate.h"
     15 #include "chrome/browser/extensions/webstore_install_helper.h"
     16 #include "chrome/browser/extensions/webstore_installer.h"
     17 #include "net/url_request/url_fetcher_delegate.h"
     18 #include "third_party/skia/include/core/SkBitmap.h"
     19 
     20 class GURL;
     21 
     22 namespace base {
     23 class DictionaryValue;
     24 }
     25 
     26 namespace net {
     27 class URLFetcher;
     28 }
     29 
     30 namespace extensions {
     31 class Extension;
     32 class WebstoreDataFetcher;
     33 
     34 // A a purely abstract base for concrete classes implementing various types of
     35 // standalone installs:
     36 // 1) Downloads and parses metadata from the webstore.
     37 // 2) Optionally shows an install dialog.
     38 // 3) Starts download once the user confirms (if confirmation was requested).
     39 // 4) Optionally shows a post-install UI.
     40 // Follows the Template Method pattern. Implementing subclasses must override
     41 // the primitive hooks in the corresponding section below.
     42 
     43 class WebstoreStandaloneInstaller
     44     : public base::RefCountedThreadSafe<WebstoreStandaloneInstaller>,
     45       public ExtensionInstallPrompt::Delegate,
     46       public WebstoreDataFetcherDelegate,
     47       public WebstoreInstaller::Delegate,
     48       public WebstoreInstallHelper::Delegate {
     49  public:
     50   // A callback for when the install process completes, successfully or not. If
     51   // there was a failure, |success| will be false and |error| may contain a
     52   // developer-readable error message about why it failed.
     53   typedef base::Callback<void(bool success, const std::string& error)> Callback;
     54 
     55   WebstoreStandaloneInstaller(const std::string& webstore_item_id,
     56                               Profile* profile,
     57                               const Callback& callback);
     58   void BeginInstall();
     59 
     60  protected:
     61   virtual ~WebstoreStandaloneInstaller();
     62 
     63   void AbortInstall();
     64   void InvokeCallback(const std::string& error);
     65   virtual void CompleteInstall(const std::string& error);
     66 
     67   // Template Method's hooks to be implemented by subclasses.
     68 
     69   // Called at certain check points of the workflow to decide whether it makes
     70   // sense to proceed with installation. A requestor can be a website that
     71   // initiated an inline installation, or a command line option.
     72   virtual bool CheckRequestorAlive() const = 0;
     73 
     74   // Requestor's URL, if any. Should be an empty GURL if URL is meaningless
     75   // (e.g. for a command line option).
     76   virtual const GURL& GetRequestorURL() const = 0;
     77 
     78   // Should a new tab be opened after installation to show the newly installed
     79   // extension's icon?
     80   virtual bool ShouldShowPostInstallUI() const = 0;
     81 
     82   // Should pop up an "App installed" bubble after installation?
     83   virtual bool ShouldShowAppInstalledBubble() const = 0;
     84 
     85   // In the very least this should return a dummy WebContents (required
     86   // by some calls even when no prompt or other UI is shown). A non-dummy
     87   // WebContents is required if the prompt returned by CreateInstallPromt()
     88   // contains a navigable link(s). Returned WebContents should correspond
     89   // to |profile| passed into the constructor.
     90   virtual content::WebContents* GetWebContents() const = 0;
     91 
     92   // Should return an installation prompt with desired properties or NULL if
     93   // no prompt should be shown.
     94   virtual scoped_refptr<ExtensionInstallPrompt::Prompt> CreateInstallPrompt()
     95       const = 0;
     96 
     97   // Perform all necessary checks to make sure inline install is permitted,
     98   // e.g. in the extension's properties in the store. The implementation may
     99   // choose to ignore such properties.
    100   virtual bool CheckInlineInstallPermitted(
    101       const base::DictionaryValue& webstore_data,
    102       std::string* error) const = 0;
    103 
    104   // Perform all necessary checks to make sure that requestor is allowed to
    105   // initiate this install (e.g. that the requestor's URL matches the verified
    106   // author's site specified in the extension's properties in the store).
    107   virtual bool CheckRequestorPermitted(
    108       const base::DictionaryValue& webstore_data,
    109       std::string* error) const = 0;
    110 
    111   // Perform all necessary checks after the manifest has been parsed to make
    112   // sure that the install should still proceed.
    113   virtual bool CheckInstallValid(
    114       const base::DictionaryValue& manifest,
    115       std::string* error);
    116 
    117   // Returns an install UI to be shown. By default, this returns an install UI
    118   // that is a transient child of the host window for GetWebContents().
    119   virtual scoped_ptr<ExtensionInstallPrompt> CreateInstallUI();
    120 
    121   // Create an approval to pass installation parameters to the CrxInstaller.
    122   virtual scoped_ptr<WebstoreInstaller::Approval> CreateApproval() const;
    123 
    124   // Accessors to be used by subclasses.
    125   bool show_user_count() const { return show_user_count_; }
    126   const std::string& localized_user_count() const {
    127     return localized_user_count_;
    128   }
    129   double average_rating() const { return average_rating_; }
    130   int rating_count() const { return rating_count_; }
    131   void set_install_source(WebstoreInstaller::InstallSource source) {
    132     install_source_ = source;
    133   }
    134   WebstoreInstaller::InstallSource install_source() const {
    135     return install_source_;
    136   }
    137   Profile* profile() const { return profile_; }
    138   const std::string& id() const { return id_; }
    139   const base::DictionaryValue* manifest() const { return manifest_.get(); }
    140 
    141  private:
    142   friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>;
    143   FRIEND_TEST_ALL_PREFIXES(WebstoreStandaloneInstallerTest, DomainVerification);
    144 
    145   // Several delegate/client interface implementations follow. The normal flow
    146   // (for successful installs) is:
    147   //
    148   // 1. BeginInstall: starts the fetch of data from the webstore
    149   // 2. OnURLFetchComplete: starts the parsing of data from the webstore
    150   // 3. OnWebstoreResponseParseSuccess: starts the parsing of the manifest and
    151   //    fetching of icon data.
    152   // 4. OnWebstoreParseSuccess: shows the install UI
    153   // 5. InstallUIProceed: initiates the .crx download/install
    154   //
    155   // All flows (whether successful or not) end up in CompleteInstall, which
    156   // informs our delegate of success/failure.
    157 
    158   // WebstoreDataFetcherDelegate interface implementation.
    159   virtual void OnWebstoreRequestFailure() OVERRIDE;
    160 
    161   virtual void OnWebstoreResponseParseSuccess(
    162       scoped_ptr<base::DictionaryValue> webstore_data) OVERRIDE;
    163 
    164   virtual void OnWebstoreResponseParseFailure(
    165       const std::string& error) OVERRIDE;
    166 
    167   // WebstoreInstallHelper::Delegate interface implementation.
    168   virtual void OnWebstoreParseSuccess(
    169       const std::string& id,
    170       const SkBitmap& icon,
    171       base::DictionaryValue* parsed_manifest) OVERRIDE;
    172   virtual void OnWebstoreParseFailure(
    173       const std::string& id,
    174       InstallHelperResultCode result_code,
    175       const std::string& error_message) OVERRIDE;
    176 
    177   // ExtensionInstallPrompt::Delegate interface implementation.
    178   virtual void InstallUIProceed() OVERRIDE;
    179   virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
    180 
    181   // WebstoreInstaller::Delegate interface implementation.
    182   virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE;
    183   virtual void OnExtensionInstallFailure(
    184       const std::string& id,
    185       const std::string& error,
    186       WebstoreInstaller::FailureReason reason) OVERRIDE;
    187 
    188   void ShowInstallUI();
    189   void OnWebStoreDataFetcherDone();
    190 
    191   // Input configuration.
    192   std::string id_;
    193   Callback callback_;
    194   Profile* profile_;
    195   WebstoreInstaller::InstallSource install_source_;
    196 
    197   // Installation dialog and its underlying prompt.
    198   scoped_ptr<ExtensionInstallPrompt> install_ui_;
    199   scoped_refptr<ExtensionInstallPrompt::Prompt> install_prompt_;
    200 
    201   // For fetching webstore JSON data.
    202   scoped_ptr<WebstoreDataFetcher> webstore_data_fetcher_;
    203 
    204   // Extracted from the webstore JSON data response.
    205   std::string localized_name_;
    206   std::string localized_description_;
    207   bool show_user_count_;
    208   std::string localized_user_count_;
    209   double average_rating_;
    210   int rating_count_;
    211   scoped_ptr<base::DictionaryValue> webstore_data_;
    212   scoped_ptr<base::DictionaryValue> manifest_;
    213   SkBitmap icon_;
    214 
    215   // Created by ShowInstallUI() when a prompt is shown (if
    216   // the implementor returns a non-NULL in CreateInstallPrompt()).
    217   scoped_refptr<Extension> localized_extension_for_display_;
    218 
    219   DISALLOW_IMPLICIT_CONSTRUCTORS(WebstoreStandaloneInstaller);
    220 };
    221 
    222 }  // namespace extensions
    223 
    224 #endif  // CHROME_BROWSER_EXTENSIONS_WEBSTORE_STANDALONE_INSTALLER_H_
    225