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
20class GURL;
21
22namespace base {
23class DictionaryValue;
24}
25
26namespace net {
27class URLFetcher;
28}
29
30namespace extensions {
31class Extension;
32class 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
43class 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 InvokeCallback(const std::string& error);
65  virtual void CompleteInstall(const std::string& error);
66
67  // Template Method's hooks to be implemented by subclasses.
68
69  // Called at certain check points of the workflow to decide whether it makes
70  // sense to proceed with installation. A requestor can be a website that
71  // initiated an inline installation, or a command line option.
72  virtual bool CheckRequestorAlive() const = 0;
73
74  // Requestor's URL, if any. Should be an empty GURL if URL is meaningless
75  // (e.g. for a command line option).
76  virtual const GURL& GetRequestorURL() const = 0;
77
78  // Should a new tab be opened after installation to show the newly installed
79  // extension's icon?
80  virtual bool ShouldShowPostInstallUI() const = 0;
81
82  // Should pop up an "App installed" bubble after installation?
83  virtual bool ShouldShowAppInstalledBubble() const = 0;
84
85  // In the very least this should return a dummy WebContents (required
86  // by some calls even when no prompt or other UI is shown). A non-dummy
87  // WebContents is required if the prompt returned by CreateInstallPromt()
88  // contains a navigable link(s). Returned WebContents should correspond
89  // to |profile| passed into the constructor.
90  virtual content::WebContents* GetWebContents() const = 0;
91
92  // Should return an installation prompt with desired properties or NULL if
93  // no prompt should be shown.
94  virtual scoped_refptr<ExtensionInstallPrompt::Prompt> CreateInstallPrompt()
95      const = 0;
96
97  // Perform all necessary checks to make sure inline install is permitted,
98  // e.g. in the extension's properties in the store. The implementation may
99  // choose to ignore such properties.
100  virtual bool CheckInlineInstallPermitted(
101      const base::DictionaryValue& webstore_data,
102      std::string* error) const = 0;
103
104  // Perform all necessary checks to make sure that requestor is allowed to
105  // initiate this install (e.g. that the requestor's URL matches the verified
106  // author's site specified in the extension's properties in the store).
107  virtual bool CheckRequestorPermitted(
108      const base::DictionaryValue& webstore_data,
109      std::string* error) const = 0;
110
111  // Perform all necessary checks after the manifest has been parsed to make
112  // sure that the install should still proceed.
113  virtual bool CheckInstallValid(
114      const base::DictionaryValue& manifest,
115      std::string* error);
116
117  // Returns an install UI to be shown. By default, this returns an install UI
118  // that is a transient child of the host window for GetWebContents().
119  virtual scoped_ptr<ExtensionInstallPrompt> CreateInstallUI();
120
121  // Create an approval to pass installation parameters to the CrxInstaller.
122  virtual scoped_ptr<WebstoreInstaller::Approval> CreateApproval() const;
123
124  // Accessors to be used by subclasses.
125  bool show_user_count() const { return show_user_count_; }
126  const std::string& localized_user_count() const {
127    return localized_user_count_;
128  }
129  double average_rating() const { return average_rating_; }
130  int rating_count() const { return rating_count_; }
131  void set_install_source(WebstoreInstaller::InstallSource source) {
132    install_source_ = source;
133  }
134  WebstoreInstaller::InstallSource install_source() const {
135    return install_source_;
136  }
137  Profile* profile() const { return profile_; }
138  const std::string& id() const { return id_; }
139  const base::DictionaryValue* manifest() const { return manifest_.get(); }
140
141 private:
142  friend class base::RefCountedThreadSafe<WebstoreStandaloneInstaller>;
143  FRIEND_TEST_ALL_PREFIXES(WebstoreStandaloneInstallerTest, DomainVerification);
144
145  // Several delegate/client interface implementations follow. The normal flow
146  // (for successful installs) is:
147  //
148  // 1. BeginInstall: starts the fetch of data from the webstore
149  // 2. OnURLFetchComplete: starts the parsing of data from the webstore
150  // 3. OnWebstoreResponseParseSuccess: starts the parsing of the manifest and
151  //    fetching of icon data.
152  // 4. OnWebstoreParseSuccess: shows the install UI
153  // 5. InstallUIProceed: initiates the .crx download/install
154  //
155  // All flows (whether successful or not) end up in CompleteInstall, which
156  // informs our delegate of success/failure.
157
158  // WebstoreDataFetcherDelegate interface implementation.
159  virtual void OnWebstoreRequestFailure() OVERRIDE;
160
161  virtual void OnWebstoreResponseParseSuccess(
162      scoped_ptr<base::DictionaryValue> webstore_data) OVERRIDE;
163
164  virtual void OnWebstoreResponseParseFailure(
165      const std::string& error) OVERRIDE;
166
167  // WebstoreInstallHelper::Delegate interface implementation.
168  virtual void OnWebstoreParseSuccess(
169      const std::string& id,
170      const SkBitmap& icon,
171      base::DictionaryValue* parsed_manifest) OVERRIDE;
172  virtual void OnWebstoreParseFailure(
173      const std::string& id,
174      InstallHelperResultCode result_code,
175      const std::string& error_message) OVERRIDE;
176
177  // ExtensionInstallPrompt::Delegate interface implementation.
178  virtual void InstallUIProceed() OVERRIDE;
179  virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
180
181  // WebstoreInstaller::Delegate interface implementation.
182  virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE;
183  virtual void OnExtensionInstallFailure(
184      const std::string& id,
185      const std::string& error,
186      WebstoreInstaller::FailureReason reason) OVERRIDE;
187
188  void ShowInstallUI();
189  void OnWebStoreDataFetcherDone();
190
191  // Input configuration.
192  std::string id_;
193  Callback callback_;
194  Profile* profile_;
195  WebstoreInstaller::InstallSource install_source_;
196
197  // Installation dialog and its underlying prompt.
198  scoped_ptr<ExtensionInstallPrompt> install_ui_;
199  scoped_refptr<ExtensionInstallPrompt::Prompt> install_prompt_;
200
201  // For fetching webstore JSON data.
202  scoped_ptr<WebstoreDataFetcher> webstore_data_fetcher_;
203
204  // Extracted from the webstore JSON data response.
205  std::string localized_name_;
206  std::string localized_description_;
207  bool show_user_count_;
208  std::string localized_user_count_;
209  double average_rating_;
210  int rating_count_;
211  scoped_ptr<base::DictionaryValue> webstore_data_;
212  scoped_ptr<base::DictionaryValue> manifest_;
213  SkBitmap icon_;
214
215  // Created by ShowInstallUI() when a prompt is shown (if
216  // the implementor returns a non-NULL in CreateInstallPrompt()).
217  scoped_refptr<Extension> localized_extension_for_display_;
218
219  DISALLOW_IMPLICIT_CONSTRUCTORS(WebstoreStandaloneInstaller);
220};
221
222}  // namespace extensions
223
224#endif  // CHROME_BROWSER_EXTENSIONS_WEBSTORE_STANDALONE_INSTALLER_H_
225