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 virtual 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 // Perform all necessary checks after the manifest has been parsed to make 111 // sure that the install should still proceed. 112 virtual bool CheckInstallValid( 113 const base::DictionaryValue& manifest, 114 std::string* error); 115 116 // Returns an install UI to be shown. By default, this returns an install UI 117 // that is a transient child of the host window for GetWebContents(). 118 virtual scoped_ptr<ExtensionInstallPrompt> CreateInstallUI(); 119 120 // Create an approval to pass installation parameters to the CrxInstaller. 121 virtual scoped_ptr<WebstoreInstaller::Approval> CreateApproval() const; 122 123 // Accessors to be used by subclasses. show_user_count()124 bool show_user_count() const { return show_user_count_; } localized_user_count()125 const std::string& localized_user_count() const { 126 return localized_user_count_; 127 } average_rating()128 double average_rating() const { return average_rating_; } rating_count()129 int rating_count() const { return rating_count_; } set_install_source(WebstoreInstaller::InstallSource source)130 void set_install_source(WebstoreInstaller::InstallSource source) { 131 install_source_ = source; 132 } install_source()133 WebstoreInstaller::InstallSource install_source() const { 134 return install_source_; 135 } profile()136 Profile* profile() const { return profile_; } id()137 const std::string& id() const { return id_; } manifest()138 const DictionaryValue* manifest() const { return manifest_.get(); } 139 140 private: 141 friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>; 142 FRIEND_TEST_ALL_PREFIXES(WebstoreStandaloneInstallerTest, DomainVerification); 143 144 // Several delegate/client interface implementations follow. The normal flow 145 // (for successful installs) is: 146 // 147 // 1. BeginInstall: starts the fetch of data from the webstore 148 // 2. OnURLFetchComplete: starts the parsing of data from the webstore 149 // 3. OnWebstoreResponseParseSuccess: starts the parsing of the manifest and 150 // fetching of icon data. 151 // 4. OnWebstoreParseSuccess: shows the install UI 152 // 5. InstallUIProceed: initiates the .crx download/install 153 // 154 // All flows (whether successful or not) end up in CompleteInstall, which 155 // informs our delegate of success/failure. 156 157 // WebstoreDataFetcherDelegate interface implementation. 158 virtual void OnWebstoreRequestFailure() OVERRIDE; 159 160 virtual void OnWebstoreResponseParseSuccess( 161 scoped_ptr<base::DictionaryValue> webstore_data) OVERRIDE; 162 163 virtual void OnWebstoreResponseParseFailure( 164 const std::string& error) OVERRIDE; 165 166 // WebstoreInstallHelper::Delegate interface implementation. 167 virtual void OnWebstoreParseSuccess( 168 const std::string& id, 169 const SkBitmap& icon, 170 base::DictionaryValue* parsed_manifest) OVERRIDE; 171 virtual void OnWebstoreParseFailure( 172 const std::string& id, 173 InstallHelperResultCode result_code, 174 const std::string& error_message) OVERRIDE; 175 176 // ExtensionInstallPrompt::Delegate interface implementation. 177 virtual void InstallUIProceed() OVERRIDE; 178 virtual void InstallUIAbort(bool user_initiated) OVERRIDE; 179 180 // WebstoreInstaller::Delegate interface implementation. 181 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE; 182 virtual void OnExtensionInstallFailure( 183 const std::string& id, 184 const std::string& error, 185 WebstoreInstaller::FailureReason reason) OVERRIDE; 186 187 void ShowInstallUI(); 188 189 // Input configuration. 190 std::string id_; 191 Callback callback_; 192 Profile* profile_; 193 WebstoreInstaller::InstallSource install_source_; 194 195 // Installation dialog and its underlying prompt. 196 scoped_ptr<ExtensionInstallPrompt> install_ui_; 197 scoped_ptr<ExtensionInstallPrompt::Prompt> install_prompt_; 198 199 // For fetching webstore JSON data. 200 scoped_ptr<WebstoreDataFetcher> webstore_data_fetcher_; 201 202 // Extracted from the webstore JSON data response. 203 std::string localized_name_; 204 std::string localized_description_; 205 bool show_user_count_; 206 std::string localized_user_count_; 207 double average_rating_; 208 int rating_count_; 209 scoped_ptr<DictionaryValue> webstore_data_; 210 scoped_ptr<DictionaryValue> manifest_; 211 SkBitmap icon_; 212 213 // Created by ShowInstallUI() when a prompt is shown (if 214 // the implementor returns a non-NULL in CreateInstallPrompt()). 215 scoped_refptr<Extension> localized_extension_for_display_; 216 217 DISALLOW_IMPLICIT_CONSTRUCTORS(WebstoreStandaloneInstaller); 218 }; 219 220 } // namespace extensions 221 222 #endif // CHROME_BROWSER_EXTENSIONS_WEBSTORE_STANDALONE_INSTALLER_H_ 223