Index: chrome/browser/extensions/api/webstore/bundle_installer.cc |
diff --git a/chrome/browser/extensions/api/webstore/bundle_installer.cc b/chrome/browser/extensions/api/webstore/bundle_installer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7ed0895a2709c3cad06d24892911d5b6c9404faf |
--- /dev/null |
+++ b/chrome/browser/extensions/api/webstore/bundle_installer.cc |
@@ -0,0 +1,262 @@ |
+// Copyright (c) 2011 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. |
+ |
+#include "chrome/browser/extensions/api/webstore/bundle_installer.h" |
+ |
+#include <string> |
+#include <vector> |
+ |
+#include "base/stl_util.h" |
+#include "base/values.h" |
+#include "chrome/browser/extensions/crx_installer.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/browser/ui/browser.h" |
+#include "chrome/browser/ui/browser_list.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/navigation_controller.h" |
+#include "content/public/browser/web_contents.h" |
+ |
+using content::NavigationController; |
+ |
+namespace webstore { |
+ |
+namespace { |
+ |
+enum AutoApproveForTest { |
+ DO_NOT_SKIP = 0, |
+ PROCEED, |
+ ABORT |
+}; |
+ |
+AutoApproveForTest auto_approve_for_test = DO_NOT_SKIP; |
Aaron Boodman
2012/02/17 01:59:33
g_auto_approve...
jstritar
2012/02/17 22:29:09
Done.
|
+ |
+} // namespace |
+ |
+// static |
+void BundleInstaller::SetAutoApproveForTesting(bool auto_approve) { |
+ auto_approve_for_test = auto_approve ? PROCEED : ABORT; |
+} |
+ |
+scoped_refptr<Extension> Item::CreateDummyExtension(DictionaryValue* manifest) { |
+ // We require localized names so we can have nice error messages when we can't |
+ // parse an extension manifest. |
+ CHECK(!localized_name.empty()); |
+ |
+ manifest->SetString(extension_manifest_keys::kName, localized_name); |
+ |
+ std::string error; |
+ return Extension::Create( |
Aaron Boodman
2012/02/17 01:59:33
You can move the arguments up one line.
jstritar
2012/02/17 22:29:09
Done.
|
+ FilePath(), |
+ Extension::INTERNAL, |
+ *manifest, |
+ Extension::NO_FLAGS, |
+ id, |
+ &error); |
+} |
+ |
+BundleInstaller::BundleInstaller(Profile* profile, const ItemList& items) |
+ : profile_(profile), |
Aaron Boodman
2012/02/17 01:59:33
You need to initialize approved_ too.
jstritar
2012/02/17 22:29:09
Done.
|
+ controller_(NULL), |
+ delegate_(NULL) { |
+ for (size_t i = 0; i < items.size(); ++i) |
+ pending_items_[items[i].id] = items[i]; |
+} |
+ |
+BundleInstaller::~BundleInstaller() { |
+ STLDeleteContainerPairSecondPointers( |
Aaron Boodman
2012/02/17 01:59:33
You can just make the map be: std::map<int, linked
jstritar
2012/02/17 22:29:09
Nice, do you pretty much only use linked_ptrs in S
Aaron Boodman
2012/02/18 11:11:54
Yeah, I don't really know of any use for them othe
|
+ parsed_manifests_.begin(), parsed_manifests_.end()); |
+} |
+ |
+ItemList BundleInstaller::GetInstalledItems() const { |
+ return GetItemMapAsList(installed_items_); |
+} |
+ |
+ItemList BundleInstaller::GetFailedItems() const { |
+ return GetItemMapAsList(failed_items_); |
+} |
+ |
+void BundleInstaller::PromptForApproval(Delegate* delegate) { |
+ delegate_ = delegate; |
+ |
+ AddRef(); // Balanced in ReportApproved() and ReportCanceled(). |
+ |
+ ParseManifests(); |
+} |
+ |
+void BundleInstaller::CompleteInstall(NavigationController* controller, |
+ Delegate* delegate) { |
+ controller_ = controller; |
+ delegate_ = delegate; |
+ |
+ AddRef(); // Balanced in ReportComplete(); |
+ |
+ if (!approved_ || pending_items_.empty()) { |
+ ReportComplete(); |
+ return; |
+ } |
+ |
+ // Start each WebstoreInstaller. |
+ for (ItemMap::iterator i = pending_items_.begin(); |
+ i != pending_items_.end(); ++i) { |
+ scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller( |
+ profile_, |
+ this, |
+ controller_, |
+ i->first, |
+ WebstoreInstaller::FLAG_NONE); |
+ installer->Start(); |
+ } |
+} |
+ |
+void BundleInstaller::ReportApproved() { |
+ if (delegate_) |
+ delegate_->OnBundleInstallApproved(); |
+ |
+ Release(); // Balanced in ParseManifests(). |
+} |
+ |
+void BundleInstaller::ReportCanceled(bool user_initiated) { |
+ if (delegate_) |
+ delegate_->OnBundleInstallCanceled(user_initiated); |
+ |
+ Release(); // Balanced in ParseManifests(). |
+} |
+ |
+void BundleInstaller::ReportComplete() { |
+ if (delegate_) |
+ delegate_->OnBundleInstallCompleted(); |
+ |
+ Release(); // Balanced in CompleteInstall(). |
+} |
+ |
+void BundleInstaller::OnWebstoreParseSuccess( |
+ const std::string& id, |
+ const SkBitmap& icon, |
+ DictionaryValue* manifest) { |
+ dummy_extensions_.push_back( |
+ pending_items_[id].CreateDummyExtension(manifest)); |
+ parsed_manifests_[id] = manifest; |
+ |
+ ShowPromptIfDoneParsing(); |
+} |
+ |
+void BundleInstaller::OnWebstoreParseFailure( |
+ const std::string& id, |
+ WebstoreInstallHelper::Delegate::InstallHelperResultCode result_code, |
+ const std::string& error_message) { |
+ failed_items_[id] = pending_items_[id]; |
+ pending_items_.erase(id); |
+ |
+ ShowPromptIfDoneParsing(); |
+} |
+ |
+void BundleInstaller::InstallUIProceed() { |
+ approved_ = true; |
+ for (ItemMap::iterator i = pending_items_.begin(); |
+ i != pending_items_.end(); ++i) { |
+ // Create a whitelist entry for each of the approved extensions. |
+ CrxInstaller::WhitelistEntry* entry = new CrxInstaller::WhitelistEntry; |
+ entry->parsed_manifest.reset(parsed_manifests_[i->first]->DeepCopy()); |
+ entry->localized_name = i->second.localized_name; |
+ entry->use_app_installed_bubble = false; |
+ entry->skip_post_install_ui = true; |
+ CrxInstaller::SetWhitelistEntry(i->first, entry); |
+ } |
+ ReportApproved(); |
+} |
+ |
+void BundleInstaller::InstallUIAbort(bool user_initiated) { |
+ failed_items_.insert(pending_items_.begin(), pending_items_.end()); |
+ pending_items_.clear(); |
+ |
+ ReportCanceled(user_initiated); |
+} |
+ |
+void BundleInstaller::OnExtensionInstallSuccess(const std::string& id) { |
+ installed_items_[id] = pending_items_[id]; |
+ pending_items_.erase(id); |
Aaron Boodman
2012/02/17 01:59:33
Instead of moving things between lists this way, c
jstritar
2012/02/17 22:29:09
Done.
|
+ |
+ ShowInstalledBubbleIfDone(); |
+} |
+ |
+void BundleInstaller::OnExtensionInstallFailure(const std::string& id, |
+ const std::string& error) { |
+ failed_items_[id] = pending_items_[id]; |
+ pending_items_.erase(id); |
+ |
+ ShowInstalledBubbleIfDone(); |
+} |
+ |
+ItemList BundleInstaller::GetItemMapAsList( |
+ const BundleInstaller::ItemMap& item_map) { |
+ ItemList list; |
+ |
+ for (ItemMap::const_iterator i = item_map.begin(); i != item_map.end(); ++i) |
+ list.push_back(i->second); |
+ |
+ return list; |
+} |
+ |
+// static |
+void BundleInstaller::ShowInstalledBubble( |
+ const BundleInstaller* bundle, Browser* browser) { |
+ // TODO(jstritar): provide platform specific implementations. |
+} |
+ |
+void BundleInstaller::ParseManifests() { |
Aaron Boodman
2012/02/17 01:59:33
I think it would be easier to read if you put the
jstritar
2012/02/17 22:29:09
Done.
|
+ if (pending_items_.empty()) { |
+ ReportCanceled(false); |
+ return; |
+ } |
+ |
+ for (ItemMap::iterator i = pending_items_.begin(); |
+ i != pending_items_.end(); ++i) { |
+ scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper( |
+ this, i->first, i->second.manifest, "", GURL(), NULL); |
+ helper->Start(); |
+ } |
+} |
+ |
+void BundleInstaller::ShowPromptIfDoneParsing() { |
+ // We don't prompt until all the manifests have been parsed. |
+ if (pending_items_.size() != dummy_extensions_.size()) |
+ return; |
+ |
+ ShowPrompt(); |
+} |
+ |
+void BundleInstaller::ShowPrompt() { |
+ if (pending_items_.empty()) { |
+ ReportCanceled(false); |
+ return; |
+ } |
+ |
+ scoped_refptr<ExtensionPermissionSet> permissions; |
+ for (size_t i = 0; i < dummy_extensions_.size(); ++i) { |
+ permissions = ExtensionPermissionSet::CreateUnion( |
+ permissions, dummy_extensions_[i]->required_permission_set()); |
+ } |
+ |
+ // TODO(jstritar): show the actual prompt. |
+ if (auto_approve_for_test == PROCEED) |
+ InstallUIProceed(); |
+ else if (auto_approve_for_test == ABORT) |
+ InstallUIAbort(true); |
+ else |
+ InstallUIAbort(false); |
+} |
+ |
+void BundleInstaller::ShowInstalledBubbleIfDone() { |
+ // We're ready to show the installed bubble when no items are pending. |
+ if (!pending_items_.empty()) |
+ return; |
+ |
+ Browser* browser = BrowserList::GetLastActiveWithProfile(profile_); |
Aaron Boodman
2012/02/17 01:59:33
It seems that it would be better to pass a Browser
jstritar
2012/02/17 22:29:09
Done. Went with a Browser (rather than TabContents
|
+ if (browser) |
+ ShowInstalledBubble(this, browser); |
+ |
+ ReportComplete(); |
+} |
+ |
+} // namespace webstore |