// 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_BUNDLE_INSTALLER_H_ #define CHROME_BROWSER_EXTENSIONS_BUNDLE_INSTALLER_H_ #include <string> #include <vector> #include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" #include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/webstore_install_helper.h" #include "chrome/browser/extensions/webstore_installer.h" #include "chrome/browser/ui/browser_list_observer.h" #include "chrome/browser/ui/host_desktop.h" #include "extensions/common/extension.h" namespace base { class DictionaryValue; } // namespace base namespace content { class NavigationController; } // namespace content class Browser; class Profile; namespace extensions { // Manages the installation life cycle for extension bundles. // // We install bundles in two steps: // 1) PromptForApproval: parse manifests and prompt the user // 2) CompleteInstall: install the CRXs and show confirmation bubble // class BundleInstaller : public WebstoreInstallHelper::Delegate, public ExtensionInstallPrompt::Delegate, public WebstoreInstaller::Delegate, public chrome::BrowserListObserver, public base::RefCountedThreadSafe<BundleInstaller> { public: // Auto approve or cancel the permission prompt. static void SetAutoApproveForTesting(bool approve); class Delegate { public: virtual void OnBundleInstallApproved() {} virtual void OnBundleInstallCanceled(bool user_initiated) {} virtual void OnBundleInstallCompleted() {} protected: virtual ~Delegate() {} }; // Represents an individual member of the bundle. struct Item { // Items are in the PENDING state until they've been installed, or the // install has failed or been canceled. enum State { STATE_PENDING, STATE_INSTALLED, STATE_FAILED }; Item(); // Gets the localized name, formatted for display in the prompt or bubble. base::string16 GetNameForDisplay(); std::string id; std::string manifest; std::string localized_name; State state; }; typedef std::vector<Item> ItemList; BundleInstaller(Browser* browser, const ItemList& items); // Returns true if the user has approved the bundle's permissions. bool approved() const { return approved_; } // Gets the items in the given state. ItemList GetItemsWithState(Item::State state) const; // Parses the extension manifests and then prompts the user to approve their // permissions. One of OnBundleInstallApproved or OnBundleInstallCanceled // will be called when complete if |delegate| is not NULL. // Note: the |delegate| must stay alive until receiving the callback. void PromptForApproval(Delegate* delegate); // If the bundle has been approved, this downloads and installs the member // extensions. OnBundleInstallComplete will be called when the process is // complete and |delegate| is not NULL. The download process uses the // specified |controller|. When complete, we show a confirmation bubble in // the specified |browser|. // Note: the |delegate| must stay alive until receiving the callback. void CompleteInstall(content::NavigationController* controller, Delegate* delegate); // We change the headings in the install prompt and installed bubble depending // on whether the bundle contains apps, extensions or both. This method gets // the correct heading for the items in the specified |state|, or an empty // string if no items are in the |state|. // STATE_PENDING - install prompt // STATE_INSTALLED - installed bubble successful installs list // STATE_FAILED - installed bubble failed installs list base::string16 GetHeadingTextFor(Item::State state) const; private: friend class base::RefCountedThreadSafe<BundleInstaller>; typedef std::map<std::string, Item> ItemMap; typedef std::map<std::string, linked_ptr<base::DictionaryValue> > ManifestMap; virtual ~BundleInstaller(); // Displays the install bubble for |bundle| on |browser|. // Note: this is a platform specific implementation. static void ShowInstalledBubble(const BundleInstaller* bundle, Browser* browser); // Parses the manifests using WebstoreInstallHelper. void ParseManifests(); // Notifies the delegate that the installation has been approved. void ReportApproved(); // Notifies the delegate that the installation was canceled. void ReportCanceled(bool user_initiated); // Notifies the delegate that the installation is complete. void ReportComplete(); // Prompts the user to install the bundle once we have dummy extensions for // all the pending items. void ShowPromptIfDoneParsing(); // Prompts the user to install the bundle. void ShowPrompt(); // Displays the installed bubble once all items have installed or failed. void ShowInstalledBubbleIfDone(); // WebstoreInstallHelper::Delegate implementation: virtual void OnWebstoreParseSuccess( const std::string& id, const SkBitmap& icon, base::DictionaryValue* parsed_manifest) OVERRIDE; virtual void OnWebstoreParseFailure( const std::string& id, InstallHelperResultCode result_code, const std::string& error_message) OVERRIDE; // ExtensionInstallPrompt::Delegate implementation: virtual void InstallUIProceed() OVERRIDE; virtual void InstallUIAbort(bool user_initiated) OVERRIDE; // WebstoreInstaller::Delegate implementation: virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE; virtual void OnExtensionInstallFailure( const std::string& id, const std::string& error, WebstoreInstaller::FailureReason reason) OVERRIDE; // chrome::BrowserListObserver implementation: virtual void OnBrowserAdded(Browser* browser) OVERRIDE; virtual void OnBrowserRemoved(Browser* browser) OVERRIDE; virtual void OnBrowserSetLastActive(Browser* browser) OVERRIDE; // Holds the Extensions used to generate the permission warnings. ExtensionList dummy_extensions_; // Holds the parsed manifests, indexed by the extension ids. ManifestMap parsed_manifests_; // True if the user has approved the bundle. bool approved_; // Holds the bundle's Items, indexed by their ids. ItemMap items_; // The browser to show the confirmation bubble for. Browser* browser_; // The desktop type of the browser. chrome::HostDesktopType host_desktop_type_; // The profile that the bundle should be installed in. Profile* profile_; // The UI that shows the confirmation prompt. scoped_ptr<ExtensionInstallPrompt> install_ui_; Delegate* delegate_; DISALLOW_COPY_AND_ASSIGN(BundleInstaller); }; } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_BUNDLE_INSTALLER_H_