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