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
|
// Copyright 2012 The Chromium Authors
// 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_STANDALONE_INSTALLER_H_
#define CHROME_BROWSER_EXTENSIONS_WEBSTORE_STANDALONE_INSTALLER_H_
#include <memory>
#include <optional>
#include <string>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "chrome/browser/extensions/active_install_data.h"
#include "chrome/browser/extensions/cws_item_service.pb.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/webstore_data_fetcher_delegate.h"
#include "chrome/browser/extensions/webstore_install_helper.h"
#include "chrome/browser/extensions/webstore_installer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_observer.h"
#include "chrome/common/extensions/webstore_install_result.h"
#include "extensions/buildflags/buildflags.h"
#include "third_party/skia/include/core/SkBitmap.h"
static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));
namespace extensions {
class Extension;
struct InstallApproval;
class ScopedActiveInstall;
class WebstoreDataFetcher;
// A a purely abstract base for concrete classes implementing various types of
// standalone installs:
// 1) Downloads and parses metadata from the webstore.
// 2) Optionally shows an install dialog.
// 3) Starts download once the user confirms (if confirmation was requested).
// 4) Optionally shows a post-install UI.
// Follows the Template Method pattern. Implementing subclasses must override
// the primitive hooks in the corresponding section below.
class WebstoreStandaloneInstaller
: public base::RefCountedThreadSafe<WebstoreStandaloneInstaller>,
public WebstoreDataFetcherDelegate,
public WebstoreInstallHelper::Delegate,
public ProfileObserver {
public:
// A callback for when the install process completes, successfully or not. If
// there was a failure, `success` will be false and `error` may contain a
// developer-readable error message about why it failed.
using Callback = base::OnceCallback<void(bool success,
const std::string& error,
webstore_install::Result result)>;
WebstoreStandaloneInstaller(const std::string& webstore_item_id,
Profile* profile,
Callback callback);
WebstoreStandaloneInstaller(const WebstoreStandaloneInstaller&) = delete;
WebstoreStandaloneInstaller& operator=(const WebstoreStandaloneInstaller&) =
delete;
void BeginInstall();
protected:
~WebstoreStandaloneInstaller() override;
// Runs the callback; primarily used for running a callback before it is
// cleared in AbortInstall(). This should only be called once for the lifetime
// of the class.
void RunCallback(
bool success, const std::string& error, webstore_install::Result result);
// Called when the install should be aborted. The callback is cleared.
void AbortInstall();
// Checks InstallTracker and returns true if the same extension is not
// currently being installed. Registers this install with the InstallTracker.
bool EnsureUniqueInstall(webstore_install::Result* reason,
std::string* error);
// Called when the install is complete.
virtual void CompleteInstall(webstore_install::Result result,
const std::string& error);
// Called when the installer should proceed to prompt the user.
void ProceedWithInstallPrompt();
// Lazily creates a dummy extension for display from the parsed manifest. This
// is safe to call from OnManifestParsed() onwards. The manifest may be
// invalid, thus the caller must check that the return value is not NULL.
scoped_refptr<const Extension> GetLocalizedExtensionForDisplay();
// Template Method's hooks to be implemented by subclasses.
// Called at certain check points of the workflow to decide whether it makes
// sense to proceed with installation. A requestor can be a website that
// initiated an inline installation, or a command line option.
virtual bool CheckRequestorAlive() const = 0;
// Should a new tab be opened after installation to show the newly installed
// extension's icon?
virtual bool ShouldShowPostInstallUI() const = 0;
// In the very least this should return a dummy WebContents (required
// by some calls even when no prompt or other UI is shown). A non-dummy
// WebContents is required if the prompt returned by CreateInstallPromt()
// contains a navigable link(s). Returned WebContents should correspond
// to `profile` passed into the constructor.
virtual content::WebContents* GetWebContents() const = 0;
// Should return an installation prompt with desired properties or NULL if
// no prompt should be shown.
virtual std::unique_ptr<ExtensionInstallPrompt::Prompt> CreateInstallPrompt()
const = 0;
// Will be called after the extension's manifest has been successfully parsed.
// Subclasses can perform asynchronous checks at this point and call
// ProceedWithInstallPrompt() to proceed with the install or otherwise call
// CompleteInstall() with an error code. The default implementation calls
// ProceedWithInstallPrompt().
virtual void OnManifestParsed();
// Returns an install UI to be shown. By default, this returns an install UI
// that is a transient child of the host window for GetWebContents().
virtual std::unique_ptr<ExtensionInstallPrompt> CreateInstallUI();
// Create an approval to pass installation parameters to the CrxInstaller.
virtual std::unique_ptr<InstallApproval> CreateApproval() const;
// Called once the install prompt has finished.
virtual void OnInstallPromptDone(
ExtensionInstallPrompt::DoneCallbackPayload payload);
// Accessors to be used by subclasses.
bool show_user_count() const { return show_user_count_; }
const std::string& localized_user_count() const {
return localized_user_count_;
}
double average_rating() const { return average_rating_; }
int rating_count() const { return rating_count_; }
const std::string& localized_rating_count() const {
return localized_rating_count_;
}
void set_install_source(WebstoreInstaller::InstallSource source) {
install_source_ = source;
}
WebstoreInstaller::InstallSource install_source() const {
return install_source_;
}
Profile* profile() const { return profile_; }
const std::string& id() const { return id_; }
const base::Value::Dict& manifest() const { return manifest_.value(); }
const Extension* localized_extension_for_display() const {
return localized_extension_for_display_.get();
}
private:
friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>;
// Several delegate/client interface implementations follow. The normal flow
// (for successful installs) with the item snippets API is:
//
// 1. BeginInstall: starts the fetch of data from the webstore.
// 2. WebstoreDataFetcher::OnFetchItemSnippetResponseReceived: starts the
// parsing of data from the webstore into a FetchItemSnippetResponse
// protobuf.
// 3. OnFetchItemSnippetParseSuccess: starts the parsing of the
// manifest and fetching of icon data.
// 4. OnWebstoreParseSuccess: shows the install UI
// 5. InstallUIProceed: initiates the .crx download/install
//
// All flows (whether successful or not) end up in CompleteInstall, which
// informs our delegate of success/failure.
// WebstoreDataFetcherDelegate interface implementation.
void OnWebstoreRequestFailure(const std::string& extension_id) override;
void OnFetchItemSnippetParseSuccess(
const std::string& extension_id,
FetchItemSnippetResponse item_snippet) override;
void OnWebstoreResponseParseFailure(const std::string& extension_id,
const std::string& error) override;
// WebstoreInstallHelper::Delegate interface implementation.
void OnWebstoreParseSuccess(const std::string& id,
const SkBitmap& icon,
base::Value::Dict parsed_manifest) override;
void OnWebstoreParseFailure(const std::string& id,
InstallHelperResultCode result_code,
const std::string& error_message) override;
// WebstoreInstaller::Delegate callbacks.
void OnExtensionInstallSuccess(const std::string& id);
void OnExtensionInstallFailure(const std::string& id,
const std::string& error,
WebstoreInstaller::FailureReason reason);
// ProfileObserver
void OnProfileWillBeDestroyed(Profile* profile) override;
void ShowInstallUI();
void OnWebStoreDataFetcherDone();
// Called when install either completes or aborts to clean up internal
// state and release the added reference from BeginInstall.
void CleanUp();
// Input configuration.
std::string id_;
Callback callback_;
raw_ptr<Profile> profile_;
base::ScopedObservation<Profile, ProfileObserver> observation_{this};
WebstoreInstaller::InstallSource install_source_{
WebstoreInstaller::INSTALL_SOURCE_INLINE};
// Installation dialog and its underlying prompt.
std::unique_ptr<ExtensionInstallPrompt> install_ui_;
std::unique_ptr<ExtensionInstallPrompt::Prompt> install_prompt_;
// For fetching webstore JSON data.
std::unique_ptr<WebstoreDataFetcher> webstore_data_fetcher_;
// Extracted from the webstore JSON data response.
std::string localized_name_;
std::string localized_description_;
bool show_user_count_{true};
std::string localized_user_count_;
double average_rating_{0.0};
std::string localized_rating_count_;
int rating_count_{0};
std::optional<base::Value::Dict> manifest_;
SkBitmap icon_;
// Active install registered with the InstallTracker.
std::unique_ptr<ScopedActiveInstall> scoped_active_install_;
// Created by ShowInstallUI() when a prompt is shown (if
// the implementor returns a non-NULL in CreateInstallPrompt()).
scoped_refptr<Extension> localized_extension_for_display_;
base::WeakPtrFactory<WebstoreStandaloneInstaller> weak_ptr_factory_{this};
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_WEBSTORE_STANDALONE_INSTALLER_H_
|