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 CompleteInstall(const std::string& error);
     65 
     66   // Template Method's hooks to be implemented by subclasses.
     67 
     68   // Called at certain check points of the workflow to decide whether it makes
     69   // sense to proceed with installation. A requestor can be a website that
     70   // initiated an inline installation, or a command line option.
     71   virtual bool CheckRequestorAlive() const = 0;
     72 
     73   // Requestor's URL, if any. Should be an empty GURL if URL is meaningless
     74   // (e.g. for a command line option).
     75   virtual const GURL& GetRequestorURL() const = 0;
     76 
     77   // Should a new tab be opened after installation to show the newly installed
     78   // extension's icon?
     79   virtual bool ShouldShowPostInstallUI() const = 0;
     80 
     81   // Should pop up an "App installed" bubble after installation?
     82   virtual bool ShouldShowAppInstalledBubble() const = 0;
     83 
     84   // In the very least this should return a dummy WebContents (required
     85   // by some calls even when no prompt or other UI is shown). A non-dummy
     86   // WebContents is required if the prompt returned by CreateInstallPromt()
     87   // contains a navigable link(s). Returned WebContents should correspond
     88   // to |profile| passed into the constructor.
     89   virtual content::WebContents* GetWebContents() const = 0;
     90 
     91   // Should return an installation prompt with desired properties or NULL if
     92   // no prompt should be shown.
     93   virtual scoped_ptr<ExtensionInstallPrompt::Prompt>
     94       CreateInstallPrompt() const = 0;
     95 
     96   // Perform all necessary checks to make sure inline install is permitted,
     97   // e.g. in the extension's properties in the store. The implementation may
     98   // choose to ignore such properties.
     99   virtual bool CheckInlineInstallPermitted(
    100       const base::DictionaryValue& webstore_data,
    101       std::string* error) const = 0;
    102 
    103   // Perform all necessary checks to make sure that requestor is allowed to
    104   // initiate this install (e.g. that the requestor's URL matches the verified
    105   // author's site specified in the extension's properties in the store).
    106   virtual bool CheckRequestorPermitted(
    107       const base::DictionaryValue& webstore_data,
    108       std::string* error) const = 0;
    109 
    110   // Returns an install UI to be shown. By default, this returns an install UI
    111   // that is a transient child of the host window for GetWebContents().
    112   virtual scoped_ptr<ExtensionInstallPrompt> CreateInstallUI();
    113 
    114   // Accessors to be used by subclasses.
    115   bool show_user_count() const { return show_user_count_; }
    116   const std::string& localized_user_count() const {
    117     return localized_user_count_;
    118   }
    119   double average_rating() const { return average_rating_; }
    120   int rating_count() const { return rating_count_; }
    121 
    122  private:
    123   friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>;
    124   FRIEND_TEST_ALL_PREFIXES(WebstoreStandaloneInstallerTest, DomainVerification);
    125 
    126   // Several delegate/client interface implementations follow. The normal flow
    127   // (for successful installs) is:
    128   //
    129   // 1. BeginInstall: starts the fetch of data from the webstore
    130   // 2. OnURLFetchComplete: starts the parsing of data from the webstore
    131   // 3. OnWebstoreResponseParseSuccess: starts the parsing of the manifest and
    132   //    fetching of icon data.
    133   // 4. OnWebstoreParseSuccess: shows the install UI
    134   // 5. InstallUIProceed: initiates the .crx download/install
    135   //
    136   // All flows (whether successful or not) end up in CompleteInstall, which
    137   // informs our delegate of success/failure.
    138 
    139   // WebstoreDataFetcherDelegate interface implementation.
    140   virtual void OnWebstoreRequestFailure() OVERRIDE;
    141 
    142   virtual void OnWebstoreResponseParseSuccess(
    143       base::DictionaryValue* webstore_data) OVERRIDE;
    144 
    145   virtual void OnWebstoreResponseParseFailure(
    146       const std::string& error) OVERRIDE;
    147 
    148   // WebstoreInstallHelper::Delegate interface implementation.
    149   virtual void OnWebstoreParseSuccess(
    150       const std::string& id,
    151       const SkBitmap& icon,
    152       base::DictionaryValue* parsed_manifest) OVERRIDE;
    153   virtual void OnWebstoreParseFailure(
    154       const std::string& id,
    155       InstallHelperResultCode result_code,
    156       const std::string& error_message) OVERRIDE;
    157 
    158   // ExtensionInstallPrompt::Delegate interface implementation.
    159   virtual void InstallUIProceed() OVERRIDE;
    160   virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
    161 
    162   // WebstoreInstaller::Delegate interface implementation.
    163   virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE;
    164   virtual void OnExtensionInstallFailure(
    165       const std::string& id,
    166       const std::string& error,
    167       WebstoreInstaller::FailureReason reason) OVERRIDE;
    168 
    169   void ShowInstallUI();
    170 
    171   // Input configuration.
    172   std::string id_;
    173   Callback callback_;
    174   Profile* profile_;
    175 
    176   // Installation dialog and its underlying prompt.
    177   scoped_ptr<ExtensionInstallPrompt> install_ui_;
    178   scoped_ptr<ExtensionInstallPrompt::Prompt> install_prompt_;
    179 
    180   // For fetching webstore JSON data.
    181   scoped_ptr<WebstoreDataFetcher> webstore_data_fetcher_;
    182 
    183   // Extracted from the webstore JSON data response.
    184   std::string localized_name_;
    185   std::string localized_description_;
    186   bool show_user_count_;
    187   std::string localized_user_count_;
    188   double average_rating_;
    189   int rating_count_;
    190   scoped_ptr<DictionaryValue> webstore_data_;
    191   scoped_ptr<DictionaryValue> manifest_;
    192   SkBitmap icon_;
    193 
    194   // Created by ShowInstallUI() when a prompt is shown (if
    195   // the implementor returns a non-NULL in CreateInstallPrompt()).
    196   scoped_refptr<Extension> localized_extension_for_display_;
    197 
    198   DISALLOW_IMPLICIT_CONSTRUCTORS(WebstoreStandaloneInstaller);
    199 };
    200 
    201 }  // namespace extensions
    202 
    203 #endif  // CHROME_BROWSER_EXTENSIONS_WEBSTORE_STANDALONE_INSTALLER_H_
    204