OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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_BUNDLE_H_ |
| 6 #define CHROME_BROWSER_EXTENSIONS_WEBSTORE_BUNDLE_H_ |
| 7 #pragma once |
| 8 |
| 9 #include <string> |
| 10 #include <vector> |
| 11 |
| 12 #include "base/memory/scoped_vector.h" |
| 13 #include "chrome/browser/extensions/extension_install_ui.h" |
| 14 #include "chrome/browser/extensions/webstore_installer.h" |
| 15 #include "chrome/browser/extensions/webstore_install_helper.h" |
| 16 #include "chrome/common/extensions/extension.h" |
| 17 #include "content/public/browser/notification_registrar.h" |
| 18 |
| 19 class Browser; |
| 20 class Profile; |
| 21 |
| 22 // Manages the installation life cycle for bundles of extensions. |
| 23 // |
| 24 // The normal flow for successful installs is: |
| 25 // |
| 26 // Part A: user approval |
| 27 // 1. A WebstoreBundle is created with a list of items in STATE_INITIAL. |
| 28 // 2. PromptForApproval: starts parsing all the extension manifest data. |
| 29 // 3. OnWebstoreParseSuccess: creates the dummy extension out of the parsed |
| 30 // manifest data, moving items into STATE_PARSED. If no more items are in |
| 31 // STATE_INITIAL, calls ShowPrompt to display the install prompt. |
| 32 // 4. ShowPrompt: calculates the total permissions for items in STATE_PARSED, |
| 33 // and displays the install prompt. |
| 34 // 5. InstallUIProceed: transitions all STATE_PARSED items to STATE_APPROVED and |
| 35 // notifies the delegate via OnBundleInstallApproved. |
| 36 // |
| 37 // Part B: download and install |
| 38 // 1. CompleteInstall: starts installing the items by calling InstallNextItem. |
| 39 // 2. InstallNextItem: downloads and installs the first item in STATE_APPROVED. |
| 40 // 3. OnExtensionInstallSuccess: moves the item to STATE_INSTALLED and starts |
| 41 // installing the next item via InstallNextItem. |
| 42 // 4. InstallNextItem: when no more items are in STATE_APPROVED, this calls |
| 43 // ShowInstalledBubble to display the status bubble. |
| 44 // 5. ShowInstalledBubble: platform specific implementation that shows which |
| 45 // items succeeded and failed via the installed bubble. |
| 46 // |
| 47 // The normal state transitions for items are: |
| 48 // STATE_INITIAL -> STATE_PARSED -> STATE_APPROVED -> STATE_INSTALLED |
| 49 // |
| 50 // Items transition to STATE_NOT_INSTALLED if they fail any step of the flow. |
| 51 // |
| 52 class WebstoreBundle : public WebstoreInstallHelper::Delegate, |
| 53 public ExtensionInstallUI::Delegate, |
| 54 public WebstoreInstaller::Delegate, |
| 55 public base::RefCounted<WebstoreBundle> { |
| 56 public: |
| 57 // Auto approve or cancel the permission prompt. |
| 58 // Note: this should only be used for testing! |
| 59 static void SetAutoApproveForTesting(bool approve); |
| 60 |
| 61 class Delegate { |
| 62 public: |
| 63 virtual void OnBundleInstallApproved() {} |
| 64 virtual void OnBundleInstallCanceled(bool user_initiated) {} |
| 65 virtual void OnBundleInstallCompleted() {} |
| 66 }; |
| 67 |
| 68 // Represents an individual member of the bundle. |
| 69 // TODO(jstritar): we can probably combine this with WebstoreInstaller, and |
| 70 // have one class that handles the life cycle of a single extension install. |
| 71 class Item { |
| 72 public: |
| 73 enum State { |
| 74 STATE_INITIAL = 0, |
| 75 |
| 76 // The item's manfiest has been parsed and dummy extension created. |
| 77 STATE_PARSED, |
| 78 |
| 79 // The user has approved the item's permissions. |
| 80 STATE_APPROVED, |
| 81 |
| 82 // The item has been downloaded and installed successfully. |
| 83 STATE_INSTALLED, |
| 84 |
| 85 // The item has failed at any step. |
| 86 STATE_NOT_INSTALLED |
| 87 }; |
| 88 |
| 89 Item(const std::string& id, |
| 90 const std::string& manifest, |
| 91 const std::string& localized_name); |
| 92 ~Item(); |
| 93 |
| 94 // Parses a dummy extension from the |parsed_manifest|. |
| 95 void SetDummyExtension(base::DictionaryValue* parsed_manifest); |
| 96 |
| 97 void MarkApproved() { state_ = STATE_APPROVED; } |
| 98 void MarkInstalled() { state_ = STATE_INSTALLED; } |
| 99 void MarkNotInstalled() { state_ = STATE_NOT_INSTALLED; } |
| 100 |
| 101 State state() const { return state_; } |
| 102 |
| 103 const std::string& id() const { return id_; } |
| 104 const std::string& manifest() const { return manifest_; } |
| 105 const std::string& localized_name() const { return localized_name_; } |
| 106 |
| 107 // These two fields are only available after the STATE_PARSED stage. |
| 108 // The dummy extension is created from the parsed manifest, and is used |
| 109 // when displaying the install prompt. |
| 110 scoped_refptr<Extension> dummy_extension() const { |
| 111 return dummy_extension_; |
| 112 } |
| 113 base::DictionaryValue* parsed_manifest() const { |
| 114 return parsed_manifest_.get(); |
| 115 } |
| 116 |
| 117 private: |
| 118 std::string id_; |
| 119 std::string manifest_; |
| 120 std::string localized_name_; |
| 121 |
| 122 State state_; |
| 123 scoped_ptr<base::DictionaryValue> parsed_manifest_; |
| 124 scoped_refptr<Extension> dummy_extension_; |
| 125 |
| 126 DISALLOW_COPY_AND_ASSIGN(Item); |
| 127 }; |
| 128 |
| 129 enum ItemMatcher { |
| 130 MATCH_EXTENSIONS = 1 << 0, |
| 131 MATCH_APPS = 1 << 1, |
| 132 MATCH_ALL = (1 << 2) - 1 |
| 133 }; |
| 134 |
| 135 typedef ScopedVector<Item> ItemList; |
| 136 |
| 137 // Passes ownership of the items. |
| 138 WebstoreBundle(Profile* profile, ItemList* items); |
| 139 virtual ~WebstoreBundle(); |
| 140 |
| 141 // Parses the extension manifests and then prompts the user to approve their |
| 142 // permissions. One of OnBundleInstallApproved or OnBundleInstallCanceled |
| 143 // will be called when complete if |delegate| is not NULL. |
| 144 // Note: the |delegate| must stay alive until receiving the callback. |
| 145 void PromptForApproval(Delegate* delegate); |
| 146 |
| 147 // If the bundle has been approved, this downloads and installs the member |
| 148 // extensions. OnBundleInstallComplete will be called when the process is |
| 149 // complete and |delegate| is not NULL. The download process uses the |
| 150 // specified |controller|. |
| 151 // Note: the |delegate| must stay alive until receiving the callback. |
| 152 void CompleteInstall(NavigationController* controller, Delegate* delegate); |
| 153 |
| 154 // Returns true if this is the same bundle as |ids|. |
| 155 bool IsSameBundle(const std::vector<std::string>& ids); |
| 156 |
| 157 // Returns the list of member items in the given |state| that match |
| 158 // the specified |matcher| flags. |
| 159 // Note: the WebstoreBundle retains ownership of the items. |
| 160 std::vector<const Item*> GetItemsInState( |
| 161 Item::State state, int matcher) const; |
| 162 |
| 163 // Gets the prompt heading text for the bundle of items to be installed. |
| 164 string16 GetHeadingTextForPrompt() const; |
| 165 |
| 166 // Gets the installed bubble heading text for the bundle items that were |
| 167 // successfully installed, or an empty string if none were. |
| 168 string16 GetInstalledHeadingTextForBubble() const; |
| 169 |
| 170 // Gets the installed bubble heading text for the bundle items that failed to |
| 171 // install, or an empty string if they all succeeded. |
| 172 string16 GetFailedHeadingTextForBubble() const; |
| 173 |
| 174 // Returns true if this has apps that are in |state|. |
| 175 bool HasAppsInState(Item::State state) const; |
| 176 |
| 177 // Returns true if this has extensions that are in |state|. |
| 178 bool HasExtensionsInState(Item::State state) const; |
| 179 |
| 180 // WebstoreInstallHelper::Delegate implementation: |
| 181 virtual void OnWebstoreParseSuccess( |
| 182 const std::string& id, |
| 183 const SkBitmap& icon, |
| 184 base::DictionaryValue* parsed_manifest) OVERRIDE; |
| 185 virtual void OnWebstoreParseFailure( |
| 186 const std::string& id, |
| 187 InstallHelperResultCode result_code, |
| 188 const std::string& error_message) OVERRIDE; |
| 189 |
| 190 // ExtensionInstallUI::Delegate implementation: |
| 191 virtual void InstallUIProceed() OVERRIDE; |
| 192 virtual void InstallUIAbort(bool user_initiated) OVERRIDE; |
| 193 |
| 194 // WebstoreInstaller::Delegate implementation: |
| 195 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE; |
| 196 virtual void OnExtensionInstallFailure(const std::string& id, |
| 197 const std::string& error) OVERRIDE; |
| 198 |
| 199 private: |
| 200 // Gets the item for the given extension |id|. |
| 201 Item* GetItemById(const std::string& id); |
| 202 |
| 203 // Parses the member item's manifests using the WebstoreInstallHelper. |
| 204 void ParseManifests(); |
| 205 |
| 206 // Only one WebstoreInstaller can be active for a given controller, so |
| 207 // we install extensions in series. This method starts downloading the next |
| 208 // extension in STATE_APPROVED. |
| 209 void InstallNextItem(); |
| 210 |
| 211 // Notifies the delegate that the installation has been approved. |
| 212 void ReportApproved(); |
| 213 |
| 214 // Notifies the delegate that the installation was canceled. |
| 215 void ReportCanceled(bool user_initiated); |
| 216 |
| 217 // Notifies the delegate that the installation is complete. |
| 218 void ReportComplete(); |
| 219 |
| 220 // Prompts the user to install the bundle if there are no more member items in |
| 221 // STATE_INITIAL. |
| 222 void ShowPromptIfDoneParsing(); |
| 223 |
| 224 // Prompts the user to install the bundle. |
| 225 void ShowPrompt(); |
| 226 |
| 227 // Displays the install bubble if all member items are in STATE_INSTALLED or |
| 228 // STATE_NOT_INSTALLED. |
| 229 void ShowInstalledBubbleIfDone(); |
| 230 |
| 231 // Displays the install bubble for |bundle| on |browser|. |
| 232 // Note: this is a platform specific implementation. |
| 233 static void ShowInstalledBubble(const WebstoreBundle* bundle, |
| 234 Browser* browser); |
| 235 |
| 236 ItemList items_; |
| 237 |
| 238 // The profile that the bundle should be installed in. |
| 239 Profile* profile_; |
| 240 |
| 241 // The controller that the webstore installer should use. |
| 242 NavigationController* controller_; |
| 243 |
| 244 Delegate* delegate_; |
| 245 |
| 246 DISALLOW_COPY_AND_ASSIGN(WebstoreBundle); |
| 247 }; |
| 248 |
| 249 #endif // CHROME_BROWSER_EXTENSIONS_WEBSTORE_BUNDLE_H_ |
OLD | NEW |