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