Chromium Code Reviews| Index: chrome/browser/extensions/bundle_installer.cc |
| diff --git a/chrome/browser/extensions/bundle_installer.cc b/chrome/browser/extensions/bundle_installer.cc |
| index 0d2677f8f270ce44e846f5ae86ae6b634ae07581..b235cab6c0a656eaf09952008ba9ce0fef065213 100644 |
| --- a/chrome/browser/extensions/bundle_installer.cc |
| +++ b/chrome/browser/extensions/bundle_installer.cc |
| @@ -26,6 +26,7 @@ |
| #include "extensions/common/permissions/permission_set.h" |
| #include "extensions/common/permissions/permissions_data.h" |
| #include "ui/base/l10n/l10n_util.h" |
| +#include "ui/gfx/image/image_skia.h" |
| namespace extensions { |
| @@ -39,11 +40,9 @@ enum AutoApproveForTest { |
| AutoApproveForTest g_auto_approve_for_test = DO_NOT_SKIP; |
| -// Creates a dummy extension and sets the manifest's name to the item's |
| -// localized name. |
| scoped_refptr<Extension> CreateDummyExtension( |
| const BundleInstaller::Item& item, |
| - base::DictionaryValue* manifest, |
| + const base::DictionaryValue& manifest, |
| content::BrowserContext* browser_context) { |
| // We require localized names so we can have nice error messages when we can't |
| // parse an extension manifest. |
| @@ -52,7 +51,7 @@ scoped_refptr<Extension> CreateDummyExtension( |
| std::string error; |
| scoped_refptr<Extension> extension = Extension::Create(base::FilePath(), |
| Manifest::INTERNAL, |
| - *manifest, |
| + manifest, |
| Extension::NO_FLAGS, |
| item.id, |
| &error); |
| @@ -63,18 +62,6 @@ scoped_refptr<Extension> CreateDummyExtension( |
| return extension; |
| } |
| -bool IsAppPredicate(scoped_refptr<const Extension> extension) { |
| - return extension->is_app(); |
| -} |
| - |
| -struct MatchIdFunctor { |
| - explicit MatchIdFunctor(const std::string& id) : id(id) {} |
| - bool operator()(scoped_refptr<const Extension> extension) { |
| - return extension->id() == id; |
| - } |
| - std::string id; |
| -}; |
| - |
| // Holds the message IDs for BundleInstaller::GetHeadingTextFor. |
| const int kHeadingIds[3][4] = { |
| { |
| @@ -101,19 +88,26 @@ void BundleInstaller::SetAutoApproveForTesting(bool auto_approve) { |
| BundleInstaller::Item::Item() : state(STATE_PENDING) {} |
| -base::string16 BundleInstaller::Item::GetNameForDisplay() { |
| +BundleInstaller::Item::~Item() {} |
| + |
| +base::string16 BundleInstaller::Item::GetNameForDisplay() const { |
| base::string16 name = base::UTF8ToUTF16(localized_name); |
| base::i18n::AdjustStringForLocaleDirection(&name); |
| return l10n_util::GetStringFUTF16(IDS_EXTENSION_PERMISSION_LINE, name); |
| } |
| BundleInstaller::BundleInstaller(Browser* browser, |
| + const std::string& name, |
| + const SkBitmap& icon, |
| + const std::string& authuser, |
| const BundleInstaller::ItemList& items) |
| : approved_(false), |
| browser_(browser), |
| + name_(name), |
| + icon_(icon), |
| + authuser_(authuser), |
| host_desktop_type_(browser->host_desktop_type()), |
| - profile_(browser->profile()), |
| - delegate_(NULL) { |
| + profile_(browser->profile()) { |
| BrowserList::AddObserver(this); |
| for (size_t i = 0; i < items.size(); ++i) { |
| items_[items[i].id] = items[i]; |
| @@ -121,42 +115,54 @@ BundleInstaller::BundleInstaller(Browser* browser, |
| } |
| } |
| +BundleInstaller::~BundleInstaller() { |
| + BrowserList::RemoveObserver(this); |
| +} |
| + |
| BundleInstaller::ItemList BundleInstaller::GetItemsWithState( |
| Item::State state) const { |
| ItemList list; |
| - for (ItemMap::const_iterator i = items_.begin(); i != items_.end(); ++i) { |
| - if (i->second.state == state) |
| - list.push_back(i->second); |
| + for (const std::pair<std::string, Item>& entry : items_) { |
| + if (entry.second.state == state) |
| + list.push_back(entry.second); |
| } |
| return list; |
| } |
| -void BundleInstaller::PromptForApproval(Delegate* delegate) { |
| - delegate_ = delegate; |
| +bool BundleInstaller::HasItemWithState(Item::State state) const { |
| + return CountItemsWithState(state) > 0; |
| +} |
| + |
| +size_t BundleInstaller::CountItemsWithState(Item::State state) const { |
| + return std::count_if(items_.begin(), items_.end(), |
| + [&state] (const std::pair<std::string, Item>& entry) { |
|
asargent_no_longer_on_chrome
2015/03/26 18:12:50
Is there any advantage to capturing state by refer
Marc Treib
2015/03/27 11:52:12
You're right, there's really no point to capturing
|
| + return entry.second.state == state; |
| + }); |
| +} |
| - AddRef(); // Balanced in ReportApproved() and ReportCanceled(). |
| +void BundleInstaller::PromptForApproval(const ApprovalCallback& callback) { |
| + approval_callback_ = callback; |
| ParseManifests(); |
| } |
| void BundleInstaller::CompleteInstall(content::WebContents* web_contents, |
| - Delegate* delegate) { |
| + const base::Closure& callback) { |
| + DCHECK(web_contents); |
| CHECK(approved_); |
| - delegate_ = delegate; |
| - |
| - AddRef(); // Balanced in ReportComplete(); |
| + install_callback_ = callback; |
| - if (GetItemsWithState(Item::STATE_PENDING).empty()) { |
| - ReportComplete(); |
| + if (!HasItemWithState(Item::STATE_PENDING)) { |
| + install_callback_.Run(); |
| return; |
| } |
| // Start each WebstoreInstaller. |
| - for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) { |
| - if (i->second.state != Item::STATE_PENDING) |
| + for (const std::pair<std::string, Item>& entry : items_) { |
| + if (entry.second.state != Item::STATE_PENDING) |
| continue; |
| // Since we've already confirmed the permissions, create an approval that |
| @@ -164,17 +170,20 @@ void BundleInstaller::CompleteInstall(content::WebContents* web_contents, |
| scoped_ptr<WebstoreInstaller::Approval> approval( |
| WebstoreInstaller::Approval::CreateWithNoInstallPrompt( |
| profile_, |
| - i->first, |
| - scoped_ptr<base::DictionaryValue>( |
| - parsed_manifests_[i->first]->DeepCopy()), true)); |
| + entry.first, |
| + make_scoped_ptr(parsed_manifests_[entry.first]->DeepCopy()), |
| + true)); |
| approval->use_app_installed_bubble = false; |
| approval->skip_post_install_ui = true; |
| + approval->authuser = authuser_; |
| + approval->installing_icon = |
| + gfx::ImageSkia::CreateFrom1xBitmap(entry.second.icon); |
| scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller( |
| profile_, |
| this, |
| web_contents, |
| - i->first, |
| + entry.first, |
| approval.Pass(), |
| WebstoreInstaller::INSTALL_SOURCE_OTHER); |
| installer->Start(); |
| @@ -185,14 +194,15 @@ base::string16 BundleInstaller::GetHeadingTextFor(Item::State state) const { |
| // For STATE_FAILED, we can't tell if the items were apps or extensions |
| // so we always show the same message. |
| if (state == Item::STATE_FAILED) { |
| - if (GetItemsWithState(state).size()) |
| + if (HasItemWithState(state)) |
| return l10n_util::GetStringUTF16(IDS_EXTENSION_BUNDLE_ERROR_HEADING); |
| return base::string16(); |
| } |
| - size_t total = GetItemsWithState(state).size(); |
| + size_t total = CountItemsWithState(state); |
| size_t apps = std::count_if( |
| - dummy_extensions_.begin(), dummy_extensions_.end(), &IsAppPredicate); |
| + dummy_extensions_.begin(), dummy_extensions_.end(), |
| + [] (const scoped_refptr<const Extension>& ext) { return ext->is_app(); }); |
| bool has_apps = apps > 0; |
| bool has_extensions = apps < total; |
| @@ -205,51 +215,34 @@ base::string16 BundleInstaller::GetHeadingTextFor(Item::State state) const { |
| if (!msg_id) |
| return base::string16(); |
| - return l10n_util::GetStringUTF16(msg_id); |
| -} |
| + // Only the "pending" message (in the confirmation prompt) contains the |
| + // bundle name. |
| + if (state == Item::STATE_PENDING) |
| + return l10n_util::GetStringFUTF16(msg_id, base::UTF8ToUTF16(name_)); |
| -BundleInstaller::~BundleInstaller() { |
| - BrowserList::RemoveObserver(this); |
| + return l10n_util::GetStringUTF16(msg_id); |
| } |
| void BundleInstaller::ParseManifests() { |
| if (items_.empty()) { |
| - ReportCanceled(false); |
| + approval_callback_.Run(APPROVAL_ERROR); |
| return; |
| } |
| - for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) { |
| + net::URLRequestContextGetter* context_getter = |
| + browser_ ? browser_->profile()->GetRequestContext() : nullptr; |
| + |
| + for (const std::pair<std::string, Item>& entry : items_) { |
| scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper( |
| - this, i->first, i->second.manifest, GURL(), nullptr); |
| + this, entry.first, entry.second.manifest, entry.second.icon_url, |
| + context_getter); |
| helper->Start(); |
| } |
| } |
| -void BundleInstaller::ReportApproved() { |
| - if (delegate_) |
| - delegate_->OnBundleInstallApproved(); |
| - |
| - Release(); // Balanced in PromptForApproval(). |
| -} |
| - |
| -void BundleInstaller::ReportCanceled(bool user_initiated) { |
| - if (delegate_) |
| - delegate_->OnBundleInstallCanceled(user_initiated); |
| - |
| - Release(); // Balanced in PromptForApproval(). |
| -} |
| - |
| -void BundleInstaller::ReportComplete() { |
| - if (delegate_) |
| - delegate_->OnBundleInstallCompleted(); |
| - |
| - Release(); // Balanced in CompleteInstall(). |
| -} |
| - |
| void BundleInstaller::ShowPromptIfDoneParsing() { |
| // We don't prompt until all the manifests have been parsed. |
| - ItemList pending_items = GetItemsWithState(Item::STATE_PENDING); |
| - if (pending_items.size() != dummy_extensions_.size()) |
| + if (CountItemsWithState(Item::STATE_PENDING) != dummy_extensions_.size()) |
| return; |
| ShowPrompt(); |
| @@ -258,7 +251,7 @@ void BundleInstaller::ShowPromptIfDoneParsing() { |
| void BundleInstaller::ShowPrompt() { |
| // Abort if we couldn't create any Extensions out of the manifests. |
| if (dummy_extensions_.empty()) { |
| - ReportCanceled(false); |
| + approval_callback_.Run(APPROVAL_ERROR); |
| return; |
| } |
| @@ -290,21 +283,22 @@ void BundleInstaller::ShowPrompt() { |
| void BundleInstaller::ShowInstalledBubbleIfDone() { |
| // We're ready to show the installed bubble when no items are pending. |
| - if (!GetItemsWithState(Item::STATE_PENDING).empty()) |
| + if (HasItemWithState(Item::STATE_PENDING)) |
| return; |
| if (browser_) |
| ShowInstalledBubble(this, browser_); |
| - ReportComplete(); |
| + install_callback_.Run(); |
| } |
| void BundleInstaller::OnWebstoreParseSuccess( |
| const std::string& id, |
| const SkBitmap& icon, |
| base::DictionaryValue* manifest) { |
| + items_[id].icon = icon; |
| dummy_extensions_.push_back( |
| - CreateDummyExtension(items_[id], manifest, profile_)); |
| + CreateDummyExtension(items_[id], *manifest, profile_)); |
| parsed_manifests_[id] = linked_ptr<base::DictionaryValue>(manifest); |
| ShowPromptIfDoneParsing(); |
| @@ -321,14 +315,14 @@ void BundleInstaller::OnWebstoreParseFailure( |
| void BundleInstaller::InstallUIProceed() { |
| approved_ = true; |
| - ReportApproved(); |
| + approval_callback_.Run(APPROVED); |
| } |
| void BundleInstaller::InstallUIAbort(bool user_initiated) { |
| - for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) |
| - i->second.state = Item::STATE_FAILED; |
| + for (std::pair<const std::string, Item>& entry : items_) |
| + entry.second.state = Item::STATE_FAILED; |
| - ReportCanceled(user_initiated); |
| + approval_callback_.Run(user_initiated ? USER_CANCELED : APPROVAL_ERROR); |
| } |
| void BundleInstaller::OnExtensionInstallSuccess(const std::string& id) { |
| @@ -344,20 +338,19 @@ void BundleInstaller::OnExtensionInstallFailure( |
| items_[id].state = Item::STATE_FAILED; |
| ExtensionList::iterator i = std::find_if( |
| - dummy_extensions_.begin(), dummy_extensions_.end(), MatchIdFunctor(id)); |
| + dummy_extensions_.begin(), dummy_extensions_.end(), |
| + [&id] (const scoped_refptr<const Extension>& ext) { |
| + return ext->id() == id; |
| + }); |
| CHECK(dummy_extensions_.end() != i); |
| dummy_extensions_.erase(i); |
| ShowInstalledBubbleIfDone(); |
| } |
| -void BundleInstaller::OnBrowserAdded(Browser* browser) {} |
| - |
| void BundleInstaller::OnBrowserRemoved(Browser* browser) { |
| if (browser_ == browser) |
| - browser_ = NULL; |
| + browser_ = nullptr; |
| } |
| -void BundleInstaller::OnBrowserSetLastActive(Browser* browser) {} |
| - |
| } // namespace extensions |