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_BUNDLE_INSTALLER_H_
6#define CHROME_BROWSER_EXTENSIONS_BUNDLE_INSTALLER_H_
7
8#include <string>
9#include <vector>
10
11#include "base/memory/linked_ptr.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/strings/string16.h"
14#include "chrome/browser/extensions/extension_install_prompt.h"
15#include "chrome/browser/extensions/webstore_install_helper.h"
16#include "chrome/browser/extensions/webstore_installer.h"
17#include "chrome/browser/ui/browser_list_observer.h"
18#include "chrome/browser/ui/host_desktop.h"
19#include "extensions/common/extension.h"
20
21namespace base {
22class DictionaryValue;
23}  // namespace base
24
25namespace content {
26class WebContents;
27}  // namespace content
28
29class Browser;
30class Profile;
31
32namespace extensions {
33
34// Manages the installation life cycle for extension bundles.
35//
36// We install bundles in two steps:
37//  1) PromptForApproval: parse manifests and prompt the user
38//  2) CompleteInstall: install the CRXs and show confirmation bubble
39//
40class BundleInstaller : public WebstoreInstallHelper::Delegate,
41                        public ExtensionInstallPrompt::Delegate,
42                        public WebstoreInstaller::Delegate,
43                        public chrome::BrowserListObserver,
44                        public base::RefCountedThreadSafe<BundleInstaller> {
45 public:
46  // Auto approve or cancel the permission prompt.
47  static void SetAutoApproveForTesting(bool approve);
48
49  class Delegate {
50   public:
51    virtual void OnBundleInstallApproved() {}
52    virtual void OnBundleInstallCanceled(bool user_initiated) {}
53    virtual void OnBundleInstallCompleted() {}
54
55   protected:
56    virtual ~Delegate() {}
57  };
58
59  // Represents an individual member of the bundle.
60  struct Item {
61    // Items are in the PENDING state until they've been installed, or the
62    // install has failed or been canceled.
63    enum State {
64      STATE_PENDING,
65      STATE_INSTALLED,
66      STATE_FAILED
67    };
68
69    Item();
70
71    // Gets the localized name, formatted for display in the prompt or bubble.
72    base::string16 GetNameForDisplay();
73
74    std::string id;
75    std::string manifest;
76    std::string localized_name;
77    State state;
78  };
79
80  typedef std::vector<Item> ItemList;
81
82  BundleInstaller(Browser* browser, const ItemList& items);
83
84  // Returns true if the user has approved the bundle's permissions.
85  bool approved() const { return approved_; }
86
87  // Gets the items in the given state.
88  ItemList GetItemsWithState(Item::State state) const;
89
90  // Parses the extension manifests and then prompts the user to approve their
91  // permissions. One of OnBundleInstallApproved or OnBundleInstallCanceled
92  // will be called when complete if |delegate| is not NULL.
93  // Note: the |delegate| must stay alive until receiving the callback.
94  void PromptForApproval(Delegate* delegate);
95
96  // If the bundle has been approved, this downloads and installs the member
97  // extensions. OnBundleInstallComplete will be called when the process is
98  // complete and |delegate| is not NULL. The download process uses the
99  // NavigationController of the specified |web_contents|. When complete, we
100  // show a confirmation bubble in the specified |browser|.
101  // Note: the |delegate| must stay alive until receiving the callback.
102  void CompleteInstall(content::WebContents* web_contents, Delegate* delegate);
103
104  // We change the headings in the install prompt and installed bubble depending
105  // on whether the bundle contains apps, extensions or both. This method gets
106  // the correct heading for the items in the specified |state|, or an empty
107  // string if no items are in the |state|.
108  //   STATE_PENDING   - install prompt
109  //   STATE_INSTALLED - installed bubble successful installs list
110  //   STATE_FAILED    - installed bubble failed installs list
111  base::string16 GetHeadingTextFor(Item::State state) const;
112
113 private:
114  friend class base::RefCountedThreadSafe<BundleInstaller>;
115
116  typedef std::map<std::string, Item> ItemMap;
117  typedef std::map<std::string, linked_ptr<base::DictionaryValue> > ManifestMap;
118
119  virtual ~BundleInstaller();
120
121  // Displays the install bubble for |bundle| on |browser|.
122  // Note: this is a platform specific implementation.
123  static void ShowInstalledBubble(const BundleInstaller* bundle,
124                                  Browser* browser);
125
126  // Parses the manifests using WebstoreInstallHelper.
127  void ParseManifests();
128
129  // Notifies the delegate that the installation has been approved.
130  void ReportApproved();
131
132  // Notifies the delegate that the installation was canceled.
133  void ReportCanceled(bool user_initiated);
134
135  // Notifies the delegate that the installation is complete.
136  void ReportComplete();
137
138  // Prompts the user to install the bundle once we have dummy extensions for
139  // all the pending items.
140  void ShowPromptIfDoneParsing();
141
142  // Prompts the user to install the bundle.
143  void ShowPrompt();
144
145  // Displays the installed bubble once all items have installed or failed.
146  void ShowInstalledBubbleIfDone();
147
148  // WebstoreInstallHelper::Delegate 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 implementation:
159  virtual void InstallUIProceed() OVERRIDE;
160  virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
161
162  // WebstoreInstaller::Delegate 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  // chrome::BrowserListObserver implementation:
170  virtual void OnBrowserAdded(Browser* browser) OVERRIDE;
171  virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
172  virtual void OnBrowserSetLastActive(Browser* browser) OVERRIDE;
173
174  // Holds the Extensions used to generate the permission warnings.
175  ExtensionList dummy_extensions_;
176
177  // Holds the parsed manifests, indexed by the extension ids.
178  ManifestMap parsed_manifests_;
179
180  // True if the user has approved the bundle.
181  bool approved_;
182
183  // Holds the bundle's Items, indexed by their ids.
184  ItemMap items_;
185
186  // The browser to show the confirmation bubble for.
187  Browser* browser_;
188
189  // The desktop type of the browser.
190  chrome::HostDesktopType host_desktop_type_;
191
192  // The profile that the bundle should be installed in.
193  Profile* profile_;
194
195  // The UI that shows the confirmation prompt.
196  scoped_ptr<ExtensionInstallPrompt> install_ui_;
197
198  Delegate* delegate_;
199
200  DISALLOW_COPY_AND_ASSIGN(BundleInstaller);
201};
202
203}  // namespace extensions
204
205#endif  // CHROME_BROWSER_EXTENSIONS_BUNDLE_INSTALLER_H_
206