1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_WEBSTORE_INSTALLER_H_
#define CHROME_BROWSER_EXTENSIONS_WEBSTORE_INSTALLER_H_
#include <list>
#include <string>
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/scoped_observer.h"
#include "base/supports_user_data.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_observer.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/manifest_handlers/shared_module_info.h"
#include "ui/gfx/image/image_skia.h"
#include "url/gurl.h"
class Profile;
namespace base {
class FilePath;
}
namespace content {
class WebContents;
}
namespace extensions {
class CrxInstaller;
class Extension;
class ExtensionRegistry;
class Manifest;
// Downloads and installs extensions from the web store.
class WebstoreInstaller : public content::NotificationObserver,
public ExtensionRegistryObserver,
public content::DownloadItem::Observer,
public content::WebContentsObserver,
public base::RefCountedThreadSafe<
WebstoreInstaller,
content::BrowserThread::DeleteOnUIThread> {
public:
enum InstallSource {
// Inline installs trigger slightly different behavior (install source
// is different, download referrers are the item's page in the gallery).
INSTALL_SOURCE_INLINE,
INSTALL_SOURCE_APP_LAUNCHER,
INSTALL_SOURCE_OTHER
};
enum FailureReason {
FAILURE_REASON_CANCELLED,
FAILURE_REASON_DEPENDENCY_NOT_FOUND,
FAILURE_REASON_DEPENDENCY_NOT_SHARED_MODULE,
FAILURE_REASON_OTHER
};
enum ManifestCheckLevel {
// Do not check for any manifest equality.
MANIFEST_CHECK_LEVEL_NONE,
// Only check that the expected and actual permissions have the same
// effective permissions.
MANIFEST_CHECK_LEVEL_LOOSE,
// All data in the expected and actual manifests must match.
MANIFEST_CHECK_LEVEL_STRICT,
};
class Delegate {
public:
virtual void OnExtensionDownloadStarted(const std::string& id,
content::DownloadItem* item);
virtual void OnExtensionDownloadProgress(const std::string& id,
content::DownloadItem* item);
virtual void OnExtensionInstallSuccess(const std::string& id) = 0;
virtual void OnExtensionInstallFailure(const std::string& id,
const std::string& error,
FailureReason reason) = 0;
protected:
virtual ~Delegate() {}
};
// Contains information about what parts of the extension install process can
// be skipped or modified. If one of these is present, it means that a CRX
// download was initiated by WebstoreInstaller. The Approval instance should
// be checked further for additional details.
struct Approval : public base::SupportsUserData::Data {
static scoped_ptr<Approval> CreateWithInstallPrompt(Profile* profile);
// Creates an Approval for installing a shared module.
static scoped_ptr<Approval> CreateForSharedModule(Profile* profile);
// Creates an Approval that will skip putting up an install confirmation
// prompt if the actual manifest from the extension to be installed matches
// |parsed_manifest|. The |strict_manifest_check| controls whether we want
// to require an exact manifest match, or are willing to tolerate a looser
// check just that the effective permissions are the same.
static scoped_ptr<Approval> CreateWithNoInstallPrompt(
Profile* profile,
const std::string& extension_id,
scoped_ptr<base::DictionaryValue> parsed_manifest,
bool strict_manifest_check);
~Approval() override;
// The extension id that was approved for installation.
std::string extension_id;
// The profile the extension should be installed into.
Profile* profile;
// The expected manifest, before localization.
scoped_ptr<Manifest> manifest;
// Whether to use a bubble notification when an app is installed, instead of
// the default behavior of transitioning to the new tab page.
bool use_app_installed_bubble;
// Whether to skip the post install UI like the extension installed bubble.
bool skip_post_install_ui;
// Whether to skip the install dialog once the extension has been downloaded
// and unpacked. One reason this can be true is that in the normal webstore
// installation, the dialog is shown earlier, before any download is done,
// so there's no need to show it again.
bool skip_install_dialog;
// Whether we should enable the launcher before installing the app.
bool enable_launcher;
// Manifest check level for checking actual manifest against expected
// manifest.
ManifestCheckLevel manifest_check_level;
// Used to show the install dialog.
ExtensionInstallPrompt::ShowDialogCallback show_dialog_callback;
// The icon to use to display the extension while it is installing.
gfx::ImageSkia installing_icon;
// A dummy extension created from |manifest|;
scoped_refptr<Extension> dummy_extension;
// Required minimum version.
scoped_ptr<Version> minimum_version;
// Ephemeral apps are transiently installed.
bool is_ephemeral;
// The authuser index required to download the item being installed. May be
// the empty string, in which case no authuser parameter is used.
std::string authuser;
private:
Approval();
};
// Gets the Approval associated with the |download|, or NULL if there's none.
// Note that the Approval is owned by |download|.
static const Approval* GetAssociatedApproval(
const content::DownloadItem& download);
// Creates a WebstoreInstaller for downloading and installing the extension
// with the given |id| from the Chrome Web Store. If |delegate| is not NULL,
// it will be notified when the install succeeds or fails. The installer will
// use the specified |controller| to download the extension. Only one
// WebstoreInstaller can use a specific controller at any given time. This
// also associates the |approval| with this install.
// Note: the delegate should stay alive until being called back.
WebstoreInstaller(Profile* profile,
Delegate* delegate,
content::WebContents* web_contents,
const std::string& id,
scoped_ptr<Approval> approval,
InstallSource source);
// Starts downloading and installing the extension.
void Start();
// content::NotificationObserver.
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// ExtensionRegistryObserver.
void OnExtensionInstalled(content::BrowserContext* browser_context,
const Extension* extension,
bool is_update) override;
// Removes the reference to the delegate passed in the constructor. Used when
// the delegate object must be deleted before this object.
void InvalidateDelegate();
// Instead of using the default download directory, use |directory| instead.
// This does *not* transfer ownership of |directory|.
static void SetDownloadDirectoryForTests(base::FilePath* directory);
private:
FRIEND_TEST_ALL_PREFIXES(WebstoreInstallerTest, PlatformParams);
friend struct content::BrowserThread::DeleteOnThread<
content::BrowserThread::UI>;
friend class base::DeleteHelper<WebstoreInstaller>;
~WebstoreInstaller() override;
// Helper to get install URL.
static GURL GetWebstoreInstallURL(const std::string& extension_id,
InstallSource source);
// DownloadManager::DownloadUrl callback.
void OnDownloadStarted(content::DownloadItem* item,
content::DownloadInterruptReason interrupt_reason);
// DownloadItem::Observer implementation:
void OnDownloadUpdated(content::DownloadItem* download) override;
void OnDownloadDestroyed(content::DownloadItem* download) override;
// Downloads next pending module in |pending_modules_|.
void DownloadNextPendingModule();
// Downloads and installs a single Crx with the given |extension_id|.
// This function is used for both the extension Crx and dependences.
void DownloadCrx(const std::string& extension_id, InstallSource source);
// Starts downloading the extension to |file_path|.
void StartDownload(const base::FilePath& file_path);
// Updates the InstallTracker with the latest download progress.
void UpdateDownloadProgress();
// Creates and starts CrxInstaller for the downloaded extension package.
void StartCrxInstaller(const content::DownloadItem& item);
// Reports an install |error| to the delegate for the given extension if this
// managed its installation. This also removes the associated PendingInstall.
void ReportFailure(const std::string& error, FailureReason reason);
// Reports a successful install to the delegate for the given extension if
// this managed its installation. This also removes the associated
// PendingInstall.
void ReportSuccess();
// Records stats regarding an interrupted webstore download item.
void RecordInterrupt(const content::DownloadItem* download) const;
content::NotificationRegistrar registrar_;
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observer_;
Profile* profile_;
Delegate* delegate_;
std::string id_;
InstallSource install_source_;
// The DownloadItem is owned by the DownloadManager and is valid from when
// OnDownloadStarted is called (with no error) until OnDownloadDestroyed().
content::DownloadItem* download_item_;
// Used to periodically update the extension's download status. This will
// trigger at least every second, though sometimes more frequently (depending
// on number of modules, etc).
base::OneShotTimer<WebstoreInstaller> download_progress_timer_;
scoped_ptr<Approval> approval_;
GURL download_url_;
scoped_refptr<CrxInstaller> crx_installer_;
// Pending modules.
std::list<SharedModuleInfo::ImportInfo> pending_modules_;
// Total extension modules we need download and install (the main module and
// depedences).
int total_modules_;
bool download_started_;
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_WEBSTORE_INSTALLER_H_
|