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_INSTALLER_H_ 6 #define CHROME_BROWSER_EXTENSIONS_WEBSTORE_INSTALLER_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/compiler_specific.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/supports_user_data.h" 15 #include "base/values.h" 16 #include "chrome/browser/extensions/extension_install_prompt.h" 17 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/download_item.h" 19 #include "content/public/browser/notification_observer.h" 20 #include "content/public/browser/notification_registrar.h" 21 #include "net/base/net_errors.h" 22 #include "ui/gfx/image/image_skia.h" 23 #include "url/gurl.h" 24 25 class Profile; 26 27 namespace base { 28 class FilePath; 29 } 30 31 namespace content { 32 class NavigationController; 33 } 34 35 namespace extensions { 36 37 class Manifest; 38 39 // Downloads and installs extensions from the web store. 40 class WebstoreInstaller :public content::NotificationObserver, 41 public content::DownloadItem::Observer, 42 public base::RefCountedThreadSafe< 43 WebstoreInstaller, content::BrowserThread::DeleteOnUIThread> { 44 public: 45 enum Flag { 46 FLAG_NONE = 0, 47 48 // Inline installs trigger slightly different behavior (install source 49 // is different, download referrers are the item's page in the gallery). 50 FLAG_INLINE_INSTALL = 1 << 0 51 }; 52 53 enum FailureReason { 54 FAILURE_REASON_CANCELLED, 55 FAILURE_REASON_OTHER 56 }; 57 58 class Delegate { 59 public: 60 virtual void OnExtensionDownloadStarted(const std::string& id, 61 content::DownloadItem* item); 62 virtual void OnExtensionDownloadProgress(const std::string& id, 63 content::DownloadItem* item); 64 virtual void OnExtensionInstallSuccess(const std::string& id) = 0; 65 virtual void OnExtensionInstallFailure(const std::string& id, 66 const std::string& error, 67 FailureReason reason) = 0; 68 69 protected: 70 virtual ~Delegate() {} 71 }; 72 73 // Contains information about what parts of the extension install process can 74 // be skipped or modified. If one of these is present, it means that a CRX 75 // download was initiated by WebstoreInstaller. The Approval instance should 76 // be checked further for additional details. 77 struct Approval : public base::SupportsUserData::Data { 78 static scoped_ptr<Approval> CreateWithInstallPrompt(Profile* profile); 79 static scoped_ptr<Approval> CreateWithNoInstallPrompt( 80 Profile* profile, 81 const std::string& extension_id, 82 scoped_ptr<base::DictionaryValue> parsed_manifest); 83 84 virtual ~Approval(); 85 86 // The extension id that was approved for installation. 87 std::string extension_id; 88 89 // The profile the extension should be installed into. 90 Profile* profile; 91 92 // The expected manifest, before localization. 93 scoped_ptr<Manifest> manifest; 94 95 // Whether to use a bubble notification when an app is installed, instead of 96 // the default behavior of transitioning to the new tab page. 97 bool use_app_installed_bubble; 98 99 // Whether to skip the post install UI like the extension installed bubble. 100 bool skip_post_install_ui; 101 102 // Whether to skip the install dialog once the extension has been downloaded 103 // and unpacked. One reason this can be true is that in the normal webstore 104 // installation, the dialog is shown earlier, before any download is done, 105 // so there's no need to show it again. 106 bool skip_install_dialog; 107 108 // Whether we should enable the launcher before installing the app. 109 bool enable_launcher; 110 111 // Used to show the install dialog. 112 ExtensionInstallPrompt::ShowDialogCallback show_dialog_callback; 113 114 // The icon to use to display the extension while it is installing. 115 gfx::ImageSkia installing_icon; 116 117 private: 118 Approval(); 119 }; 120 121 // Gets the Approval associated with the |download|, or NULL if there's none. 122 // Note that the Approval is owned by |download|. 123 static const Approval* GetAssociatedApproval( 124 const content::DownloadItem& download); 125 126 // Creates a WebstoreInstaller for downloading and installing the extension 127 // with the given |id| from the Chrome Web Store. If |delegate| is not NULL, 128 // it will be notified when the install succeeds or fails. The installer will 129 // use the specified |controller| to download the extension. Only one 130 // WebstoreInstaller can use a specific controller at any given time. This 131 // also associates the |approval| with this install. 132 // Note: the delegate should stay alive until being called back. 133 WebstoreInstaller(Profile* profile, 134 Delegate* delegate, 135 content::NavigationController* controller, 136 const std::string& id, 137 scoped_ptr<Approval> approval, 138 int flags); 139 140 // Starts downloading and installing the extension. 141 void Start(); 142 143 // content::NotificationObserver 144 virtual void Observe(int type, 145 const content::NotificationSource& source, 146 const content::NotificationDetails& details) OVERRIDE; 147 148 // Removes the reference to the delegate passed in the constructor. Used when 149 // the delegate object must be deleted before this object. 150 void InvalidateDelegate(); 151 152 // Instead of using the default download directory, use |directory| instead. 153 // This does *not* transfer ownership of |directory|. 154 static void SetDownloadDirectoryForTests(base::FilePath* directory); 155 156 private: 157 FRIEND_TEST_ALL_PREFIXES(WebstoreInstallerTest, PlatformParams); 158 friend struct content::BrowserThread::DeleteOnThread< 159 content::BrowserThread::UI>; 160 friend class base::DeleteHelper<WebstoreInstaller>; 161 virtual ~WebstoreInstaller(); 162 163 // Helper to get install URL. 164 static GURL GetWebstoreInstallURL(const std::string& extension_id, 165 const std::string& install_source); 166 167 // DownloadManager::DownloadUrl callback. 168 void OnDownloadStarted(content::DownloadItem* item, net::Error error); 169 170 // DownloadItem::Observer implementation: 171 virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE; 172 virtual void OnDownloadDestroyed(content::DownloadItem* download) OVERRIDE; 173 174 // Starts downloading the extension to |file_path|. 175 void StartDownload(const base::FilePath& file_path); 176 177 // Reports an install |error| to the delegate for the given extension if this 178 // managed its installation. This also removes the associated PendingInstall. 179 void ReportFailure(const std::string& error, FailureReason reason); 180 181 // Reports a successful install to the delegate for the given extension if 182 // this managed its installation. This also removes the associated 183 // PendingInstall. 184 void ReportSuccess(); 185 186 content::NotificationRegistrar registrar_; 187 Profile* profile_; 188 Delegate* delegate_; 189 content::NavigationController* controller_; 190 std::string id_; 191 // The DownloadItem is owned by the DownloadManager and is valid from when 192 // OnDownloadStarted is called (with no error) until OnDownloadDestroyed(). 193 content::DownloadItem* download_item_; 194 scoped_ptr<Approval> approval_; 195 GURL download_url_; 196 }; 197 198 } // namespace extensions 199 200 #endif // CHROME_BROWSER_EXTENSIONS_WEBSTORE_INSTALLER_H_ 201