Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1427)

Side by Side Diff: chrome/browser/extensions/bundle_installer.cc

Issue 855513002: Add/resurrect support for bundles of WebStore items. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@testext_bundle
Patch Set: remove icon_data Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/bundle_installer.h" 5 #include "chrome/browser/extensions/bundle_installer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/i18n/rtl.h" 12 #include "base/i18n/rtl.h"
13 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h" 14 #include "base/values.h"
15 #include "chrome/browser/extensions/crx_installer.h" 15 #include "chrome/browser/extensions/crx_installer.h"
16 #include "chrome/browser/extensions/permissions_updater.h" 16 #include "chrome/browser/extensions/permissions_updater.h"
17 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser.h" 18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_finder.h" 19 #include "chrome/browser/ui/browser_finder.h"
20 #include "chrome/browser/ui/browser_list.h" 20 #include "chrome/browser/ui/browser_list.h"
21 #include "chrome/browser/ui/tabs/tab_strip_model.h" 21 #include "chrome/browser/ui/tabs/tab_strip_model.h"
22 #include "chrome/common/chrome_switches.h" 22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/grit/generated_resources.h" 23 #include "chrome/grit/generated_resources.h"
24 #include "content/public/browser/web_contents.h" 24 #include "content/public/browser/web_contents.h"
25 #include "extensions/common/extension.h" 25 #include "extensions/common/extension.h"
26 #include "extensions/common/permissions/permission_set.h" 26 #include "extensions/common/permissions/permission_set.h"
27 #include "extensions/common/permissions/permissions_data.h" 27 #include "extensions/common/permissions/permissions_data.h"
28 #include "ui/base/l10n/l10n_util.h" 28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/gfx/image/image_skia.h"
29 30
30 namespace extensions { 31 namespace extensions {
31 32
32 namespace { 33 namespace {
33 34
34 enum AutoApproveForTest { 35 enum AutoApproveForTest {
35 DO_NOT_SKIP = 0, 36 DO_NOT_SKIP = 0,
36 PROCEED, 37 PROCEED,
37 ABORT 38 ABORT
38 }; 39 };
39 40
40 AutoApproveForTest g_auto_approve_for_test = DO_NOT_SKIP; 41 AutoApproveForTest g_auto_approve_for_test = DO_NOT_SKIP;
41 42
42 // Creates a dummy extension and sets the manifest's name to the item's
43 // localized name.
44 scoped_refptr<Extension> CreateDummyExtension( 43 scoped_refptr<Extension> CreateDummyExtension(
45 const BundleInstaller::Item& item, 44 const BundleInstaller::Item& item,
46 base::DictionaryValue* manifest, 45 const base::DictionaryValue& manifest,
47 content::BrowserContext* browser_context) { 46 content::BrowserContext* browser_context) {
48 // We require localized names so we can have nice error messages when we can't 47 // We require localized names so we can have nice error messages when we can't
49 // parse an extension manifest. 48 // parse an extension manifest.
50 CHECK(!item.localized_name.empty()); 49 CHECK(!item.localized_name.empty());
51 50
52 std::string error; 51 std::string error;
53 scoped_refptr<Extension> extension = Extension::Create(base::FilePath(), 52 scoped_refptr<Extension> extension = Extension::Create(base::FilePath(),
54 Manifest::INTERNAL, 53 Manifest::INTERNAL,
55 *manifest, 54 manifest,
56 Extension::NO_FLAGS, 55 Extension::NO_FLAGS,
57 item.id, 56 item.id,
58 &error); 57 &error);
59 // Initialize permissions so that withheld permissions are displayed properly 58 // Initialize permissions so that withheld permissions are displayed properly
60 // in the install prompt. 59 // in the install prompt.
61 PermissionsUpdater(browser_context, PermissionsUpdater::INIT_FLAG_TRANSIENT) 60 PermissionsUpdater(browser_context, PermissionsUpdater::INIT_FLAG_TRANSIENT)
62 .InitializePermissions(extension.get()); 61 .InitializePermissions(extension.get());
63 return extension; 62 return extension;
64 } 63 }
65 64
66 bool IsAppPredicate(scoped_refptr<const Extension> extension) {
67 return extension->is_app();
68 }
69
70 struct MatchIdFunctor {
71 explicit MatchIdFunctor(const std::string& id) : id(id) {}
72 bool operator()(scoped_refptr<const Extension> extension) {
73 return extension->id() == id;
74 }
75 std::string id;
76 };
77
78 // Holds the message IDs for BundleInstaller::GetHeadingTextFor. 65 // Holds the message IDs for BundleInstaller::GetHeadingTextFor.
79 const int kHeadingIds[3][4] = { 66 const int kHeadingIds[3][4] = {
80 { 67 {
81 0, 68 0,
82 IDS_EXTENSION_BUNDLE_INSTALL_PROMPT_HEADING_EXTENSIONS, 69 IDS_EXTENSION_BUNDLE_INSTALL_PROMPT_HEADING_EXTENSIONS,
83 IDS_EXTENSION_BUNDLE_INSTALL_PROMPT_HEADING_APPS, 70 IDS_EXTENSION_BUNDLE_INSTALL_PROMPT_HEADING_APPS,
84 IDS_EXTENSION_BUNDLE_INSTALL_PROMPT_HEADING_EXTENSION_APPS 71 IDS_EXTENSION_BUNDLE_INSTALL_PROMPT_HEADING_EXTENSION_APPS
85 }, 72 },
86 { 73 {
87 0, 74 0,
88 IDS_EXTENSION_BUNDLE_INSTALLED_HEADING_EXTENSIONS, 75 IDS_EXTENSION_BUNDLE_INSTALLED_HEADING_EXTENSIONS,
89 IDS_EXTENSION_BUNDLE_INSTALLED_HEADING_APPS, 76 IDS_EXTENSION_BUNDLE_INSTALLED_HEADING_APPS,
90 IDS_EXTENSION_BUNDLE_INSTALLED_HEADING_EXTENSION_APPS 77 IDS_EXTENSION_BUNDLE_INSTALLED_HEADING_EXTENSION_APPS
91 } 78 }
92 }; 79 };
93 80
94 } // namespace 81 } // namespace
95 82
96 // static 83 // static
97 void BundleInstaller::SetAutoApproveForTesting(bool auto_approve) { 84 void BundleInstaller::SetAutoApproveForTesting(bool auto_approve) {
98 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)); 85 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType));
99 g_auto_approve_for_test = auto_approve ? PROCEED : ABORT; 86 g_auto_approve_for_test = auto_approve ? PROCEED : ABORT;
100 } 87 }
101 88
102 BundleInstaller::Item::Item() : state(STATE_PENDING) {} 89 BundleInstaller::Item::Item() : state(STATE_PENDING) {}
103 90
104 base::string16 BundleInstaller::Item::GetNameForDisplay() { 91 BundleInstaller::Item::~Item() {}
92
93 base::string16 BundleInstaller::Item::GetNameForDisplay() const {
105 base::string16 name = base::UTF8ToUTF16(localized_name); 94 base::string16 name = base::UTF8ToUTF16(localized_name);
106 base::i18n::AdjustStringForLocaleDirection(&name); 95 base::i18n::AdjustStringForLocaleDirection(&name);
107 return l10n_util::GetStringFUTF16(IDS_EXTENSION_PERMISSION_LINE, name); 96 return l10n_util::GetStringFUTF16(IDS_EXTENSION_PERMISSION_LINE, name);
108 } 97 }
109 98
110 BundleInstaller::BundleInstaller(Browser* browser, 99 BundleInstaller::BundleInstaller(Browser* browser,
100 const std::string& name,
101 const SkBitmap& icon,
102 const std::string& authuser,
111 const BundleInstaller::ItemList& items) 103 const BundleInstaller::ItemList& items)
112 : approved_(false), 104 : approved_(false),
113 browser_(browser), 105 browser_(browser),
106 name_(name),
107 icon_(icon),
108 authuser_(authuser),
114 host_desktop_type_(browser->host_desktop_type()), 109 host_desktop_type_(browser->host_desktop_type()),
115 profile_(browser->profile()), 110 profile_(browser->profile()) {
116 delegate_(NULL) {
117 BrowserList::AddObserver(this); 111 BrowserList::AddObserver(this);
118 for (size_t i = 0; i < items.size(); ++i) { 112 for (size_t i = 0; i < items.size(); ++i) {
119 items_[items[i].id] = items[i]; 113 items_[items[i].id] = items[i];
120 items_[items[i].id].state = Item::STATE_PENDING; 114 items_[items[i].id].state = Item::STATE_PENDING;
121 } 115 }
122 } 116 }
123 117
118 BundleInstaller::~BundleInstaller() {
119 BrowserList::RemoveObserver(this);
120 }
121
124 BundleInstaller::ItemList BundleInstaller::GetItemsWithState( 122 BundleInstaller::ItemList BundleInstaller::GetItemsWithState(
125 Item::State state) const { 123 Item::State state) const {
126 ItemList list; 124 ItemList list;
127 125
128 for (ItemMap::const_iterator i = items_.begin(); i != items_.end(); ++i) { 126 for (const std::pair<std::string, Item>& entry : items_) {
129 if (i->second.state == state) 127 if (entry.second.state == state)
130 list.push_back(i->second); 128 list.push_back(entry.second);
131 } 129 }
132 130
133 return list; 131 return list;
134 } 132 }
135 133
136 void BundleInstaller::PromptForApproval(Delegate* delegate) { 134 bool BundleInstaller::HasItemWithState(Item::State state) const {
137 delegate_ = delegate; 135 return CountItemsWithState(state) > 0;
136 }
138 137
139 AddRef(); // Balanced in ReportApproved() and ReportCanceled(). 138 size_t BundleInstaller::CountItemsWithState(Item::State state) const {
139 return std::count_if(items_.begin(), items_.end(),
140 [&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
141 return entry.second.state == state;
142 });
143 }
144
145 void BundleInstaller::PromptForApproval(const ApprovalCallback& callback) {
146 approval_callback_ = callback;
140 147
141 ParseManifests(); 148 ParseManifests();
142 } 149 }
143 150
144 void BundleInstaller::CompleteInstall(content::WebContents* web_contents, 151 void BundleInstaller::CompleteInstall(content::WebContents* web_contents,
145 Delegate* delegate) { 152 const base::Closure& callback) {
153 DCHECK(web_contents);
146 CHECK(approved_); 154 CHECK(approved_);
147 155
148 delegate_ = delegate; 156 install_callback_ = callback;
149 157
150 AddRef(); // Balanced in ReportComplete(); 158 if (!HasItemWithState(Item::STATE_PENDING)) {
151 159 install_callback_.Run();
152 if (GetItemsWithState(Item::STATE_PENDING).empty()) {
153 ReportComplete();
154 return; 160 return;
155 } 161 }
156 162
157 // Start each WebstoreInstaller. 163 // Start each WebstoreInstaller.
158 for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) { 164 for (const std::pair<std::string, Item>& entry : items_) {
159 if (i->second.state != Item::STATE_PENDING) 165 if (entry.second.state != Item::STATE_PENDING)
160 continue; 166 continue;
161 167
162 // Since we've already confirmed the permissions, create an approval that 168 // Since we've already confirmed the permissions, create an approval that
163 // lets CrxInstaller bypass the prompt. 169 // lets CrxInstaller bypass the prompt.
164 scoped_ptr<WebstoreInstaller::Approval> approval( 170 scoped_ptr<WebstoreInstaller::Approval> approval(
165 WebstoreInstaller::Approval::CreateWithNoInstallPrompt( 171 WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
166 profile_, 172 profile_,
167 i->first, 173 entry.first,
168 scoped_ptr<base::DictionaryValue>( 174 make_scoped_ptr(parsed_manifests_[entry.first]->DeepCopy()),
169 parsed_manifests_[i->first]->DeepCopy()), true)); 175 true));
170 approval->use_app_installed_bubble = false; 176 approval->use_app_installed_bubble = false;
171 approval->skip_post_install_ui = true; 177 approval->skip_post_install_ui = true;
178 approval->authuser = authuser_;
179 approval->installing_icon =
180 gfx::ImageSkia::CreateFrom1xBitmap(entry.second.icon);
172 181
173 scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller( 182 scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller(
174 profile_, 183 profile_,
175 this, 184 this,
176 web_contents, 185 web_contents,
177 i->first, 186 entry.first,
178 approval.Pass(), 187 approval.Pass(),
179 WebstoreInstaller::INSTALL_SOURCE_OTHER); 188 WebstoreInstaller::INSTALL_SOURCE_OTHER);
180 installer->Start(); 189 installer->Start();
181 } 190 }
182 } 191 }
183 192
184 base::string16 BundleInstaller::GetHeadingTextFor(Item::State state) const { 193 base::string16 BundleInstaller::GetHeadingTextFor(Item::State state) const {
185 // For STATE_FAILED, we can't tell if the items were apps or extensions 194 // For STATE_FAILED, we can't tell if the items were apps or extensions
186 // so we always show the same message. 195 // so we always show the same message.
187 if (state == Item::STATE_FAILED) { 196 if (state == Item::STATE_FAILED) {
188 if (GetItemsWithState(state).size()) 197 if (HasItemWithState(state))
189 return l10n_util::GetStringUTF16(IDS_EXTENSION_BUNDLE_ERROR_HEADING); 198 return l10n_util::GetStringUTF16(IDS_EXTENSION_BUNDLE_ERROR_HEADING);
190 return base::string16(); 199 return base::string16();
191 } 200 }
192 201
193 size_t total = GetItemsWithState(state).size(); 202 size_t total = CountItemsWithState(state);
194 size_t apps = std::count_if( 203 size_t apps = std::count_if(
195 dummy_extensions_.begin(), dummy_extensions_.end(), &IsAppPredicate); 204 dummy_extensions_.begin(), dummy_extensions_.end(),
205 [] (const scoped_refptr<const Extension>& ext) { return ext->is_app(); });
196 206
197 bool has_apps = apps > 0; 207 bool has_apps = apps > 0;
198 bool has_extensions = apps < total; 208 bool has_extensions = apps < total;
199 size_t index = (has_extensions << 0) + (has_apps << 1); 209 size_t index = (has_extensions << 0) + (has_apps << 1);
200 210
201 CHECK_LT(static_cast<size_t>(state), arraysize(kHeadingIds)); 211 CHECK_LT(static_cast<size_t>(state), arraysize(kHeadingIds));
202 CHECK_LT(index, arraysize(kHeadingIds[state])); 212 CHECK_LT(index, arraysize(kHeadingIds[state]));
203 213
204 int msg_id = kHeadingIds[state][index]; 214 int msg_id = kHeadingIds[state][index];
205 if (!msg_id) 215 if (!msg_id)
206 return base::string16(); 216 return base::string16();
207 217
218 // Only the "pending" message (in the confirmation prompt) contains the
219 // bundle name.
220 if (state == Item::STATE_PENDING)
221 return l10n_util::GetStringFUTF16(msg_id, base::UTF8ToUTF16(name_));
222
208 return l10n_util::GetStringUTF16(msg_id); 223 return l10n_util::GetStringUTF16(msg_id);
209 } 224 }
210 225
211 BundleInstaller::~BundleInstaller() {
212 BrowserList::RemoveObserver(this);
213 }
214
215 void BundleInstaller::ParseManifests() { 226 void BundleInstaller::ParseManifests() {
216 if (items_.empty()) { 227 if (items_.empty()) {
217 ReportCanceled(false); 228 approval_callback_.Run(APPROVAL_ERROR);
218 return; 229 return;
219 } 230 }
220 231
221 for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) { 232 net::URLRequestContextGetter* context_getter =
233 browser_ ? browser_->profile()->GetRequestContext() : nullptr;
234
235 for (const std::pair<std::string, Item>& entry : items_) {
222 scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper( 236 scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper(
223 this, i->first, i->second.manifest, GURL(), nullptr); 237 this, entry.first, entry.second.manifest, entry.second.icon_url,
238 context_getter);
224 helper->Start(); 239 helper->Start();
225 } 240 }
226 } 241 }
227 242
228 void BundleInstaller::ReportApproved() {
229 if (delegate_)
230 delegate_->OnBundleInstallApproved();
231
232 Release(); // Balanced in PromptForApproval().
233 }
234
235 void BundleInstaller::ReportCanceled(bool user_initiated) {
236 if (delegate_)
237 delegate_->OnBundleInstallCanceled(user_initiated);
238
239 Release(); // Balanced in PromptForApproval().
240 }
241
242 void BundleInstaller::ReportComplete() {
243 if (delegate_)
244 delegate_->OnBundleInstallCompleted();
245
246 Release(); // Balanced in CompleteInstall().
247 }
248
249 void BundleInstaller::ShowPromptIfDoneParsing() { 243 void BundleInstaller::ShowPromptIfDoneParsing() {
250 // We don't prompt until all the manifests have been parsed. 244 // We don't prompt until all the manifests have been parsed.
251 ItemList pending_items = GetItemsWithState(Item::STATE_PENDING); 245 if (CountItemsWithState(Item::STATE_PENDING) != dummy_extensions_.size())
252 if (pending_items.size() != dummy_extensions_.size())
253 return; 246 return;
254 247
255 ShowPrompt(); 248 ShowPrompt();
256 } 249 }
257 250
258 void BundleInstaller::ShowPrompt() { 251 void BundleInstaller::ShowPrompt() {
259 // Abort if we couldn't create any Extensions out of the manifests. 252 // Abort if we couldn't create any Extensions out of the manifests.
260 if (dummy_extensions_.empty()) { 253 if (dummy_extensions_.empty()) {
261 ReportCanceled(false); 254 approval_callback_.Run(APPROVAL_ERROR);
262 return; 255 return;
263 } 256 }
264 257
265 scoped_refptr<PermissionSet> permissions; 258 scoped_refptr<PermissionSet> permissions;
266 for (size_t i = 0; i < dummy_extensions_.size(); ++i) { 259 for (size_t i = 0; i < dummy_extensions_.size(); ++i) {
267 permissions = PermissionSet::CreateUnion( 260 permissions = PermissionSet::CreateUnion(
268 permissions.get(), 261 permissions.get(),
269 dummy_extensions_[i]->permissions_data()->active_permissions().get()); 262 dummy_extensions_[i]->permissions_data()->active_permissions().get());
270 } 263 }
271 264
(...skipping 11 matching lines...) Expand all
283 content::WebContents* web_contents = NULL; 276 content::WebContents* web_contents = NULL;
284 if (browser) 277 if (browser)
285 web_contents = browser->tab_strip_model()->GetActiveWebContents(); 278 web_contents = browser->tab_strip_model()->GetActiveWebContents();
286 install_ui_.reset(new ExtensionInstallPrompt(web_contents)); 279 install_ui_.reset(new ExtensionInstallPrompt(web_contents));
287 install_ui_->ConfirmBundleInstall(this, permissions.get()); 280 install_ui_->ConfirmBundleInstall(this, permissions.get());
288 } 281 }
289 } 282 }
290 283
291 void BundleInstaller::ShowInstalledBubbleIfDone() { 284 void BundleInstaller::ShowInstalledBubbleIfDone() {
292 // We're ready to show the installed bubble when no items are pending. 285 // We're ready to show the installed bubble when no items are pending.
293 if (!GetItemsWithState(Item::STATE_PENDING).empty()) 286 if (HasItemWithState(Item::STATE_PENDING))
294 return; 287 return;
295 288
296 if (browser_) 289 if (browser_)
297 ShowInstalledBubble(this, browser_); 290 ShowInstalledBubble(this, browser_);
298 291
299 ReportComplete(); 292 install_callback_.Run();
300 } 293 }
301 294
302 void BundleInstaller::OnWebstoreParseSuccess( 295 void BundleInstaller::OnWebstoreParseSuccess(
303 const std::string& id, 296 const std::string& id,
304 const SkBitmap& icon, 297 const SkBitmap& icon,
305 base::DictionaryValue* manifest) { 298 base::DictionaryValue* manifest) {
299 items_[id].icon = icon;
306 dummy_extensions_.push_back( 300 dummy_extensions_.push_back(
307 CreateDummyExtension(items_[id], manifest, profile_)); 301 CreateDummyExtension(items_[id], *manifest, profile_));
308 parsed_manifests_[id] = linked_ptr<base::DictionaryValue>(manifest); 302 parsed_manifests_[id] = linked_ptr<base::DictionaryValue>(manifest);
309 303
310 ShowPromptIfDoneParsing(); 304 ShowPromptIfDoneParsing();
311 } 305 }
312 306
313 void BundleInstaller::OnWebstoreParseFailure( 307 void BundleInstaller::OnWebstoreParseFailure(
314 const std::string& id, 308 const std::string& id,
315 WebstoreInstallHelper::Delegate::InstallHelperResultCode result_code, 309 WebstoreInstallHelper::Delegate::InstallHelperResultCode result_code,
316 const std::string& error_message) { 310 const std::string& error_message) {
317 items_[id].state = Item::STATE_FAILED; 311 items_[id].state = Item::STATE_FAILED;
318 312
319 ShowPromptIfDoneParsing(); 313 ShowPromptIfDoneParsing();
320 } 314 }
321 315
322 void BundleInstaller::InstallUIProceed() { 316 void BundleInstaller::InstallUIProceed() {
323 approved_ = true; 317 approved_ = true;
324 ReportApproved(); 318 approval_callback_.Run(APPROVED);
325 } 319 }
326 320
327 void BundleInstaller::InstallUIAbort(bool user_initiated) { 321 void BundleInstaller::InstallUIAbort(bool user_initiated) {
328 for (ItemMap::iterator i = items_.begin(); i != items_.end(); ++i) 322 for (std::pair<const std::string, Item>& entry : items_)
329 i->second.state = Item::STATE_FAILED; 323 entry.second.state = Item::STATE_FAILED;
330 324
331 ReportCanceled(user_initiated); 325 approval_callback_.Run(user_initiated ? USER_CANCELED : APPROVAL_ERROR);
332 } 326 }
333 327
334 void BundleInstaller::OnExtensionInstallSuccess(const std::string& id) { 328 void BundleInstaller::OnExtensionInstallSuccess(const std::string& id) {
335 items_[id].state = Item::STATE_INSTALLED; 329 items_[id].state = Item::STATE_INSTALLED;
336 330
337 ShowInstalledBubbleIfDone(); 331 ShowInstalledBubbleIfDone();
338 } 332 }
339 333
340 void BundleInstaller::OnExtensionInstallFailure( 334 void BundleInstaller::OnExtensionInstallFailure(
341 const std::string& id, 335 const std::string& id,
342 const std::string& error, 336 const std::string& error,
343 WebstoreInstaller::FailureReason reason) { 337 WebstoreInstaller::FailureReason reason) {
344 items_[id].state = Item::STATE_FAILED; 338 items_[id].state = Item::STATE_FAILED;
345 339
346 ExtensionList::iterator i = std::find_if( 340 ExtensionList::iterator i = std::find_if(
347 dummy_extensions_.begin(), dummy_extensions_.end(), MatchIdFunctor(id)); 341 dummy_extensions_.begin(), dummy_extensions_.end(),
342 [&id] (const scoped_refptr<const Extension>& ext) {
343 return ext->id() == id;
344 });
348 CHECK(dummy_extensions_.end() != i); 345 CHECK(dummy_extensions_.end() != i);
349 dummy_extensions_.erase(i); 346 dummy_extensions_.erase(i);
350 347
351 ShowInstalledBubbleIfDone(); 348 ShowInstalledBubbleIfDone();
352 } 349 }
353 350
354 void BundleInstaller::OnBrowserAdded(Browser* browser) {}
355
356 void BundleInstaller::OnBrowserRemoved(Browser* browser) { 351 void BundleInstaller::OnBrowserRemoved(Browser* browser) {
357 if (browser_ == browser) 352 if (browser_ == browser)
358 browser_ = NULL; 353 browser_ = nullptr;
359 } 354 }
360 355
361 void BundleInstaller::OnBrowserSetLastActive(Browser* browser) {}
362
363 } // namespace extensions 356 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698