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

Side by Side Diff: chrome/browser/installable/installable_manager.cc

Issue 2942513002: Allow banners to trigger on sites which don't register a service worker onload. (Closed)
Patch Set: Less flaky test Created 3 years, 6 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/installable/installable_manager.h" 5 #include "chrome/browser/installable/installable_manager.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "chrome/browser/manifest/manifest_icon_downloader.h" 10 #include "chrome/browser/manifest/manifest_icon_downloader.h"
11 #include "chrome/browser/manifest/manifest_icon_selector.h" 11 #include "chrome/browser/manifest/manifest_icon_selector.h"
12 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ssl/security_state_tab_helper.h" 13 #include "chrome/browser/ssl/security_state_tab_helper.h"
14 #include "components/security_state/core/security_state.h" 14 #include "components/security_state/core/security_state.h"
15 #include "content/public/browser/browser_context.h" 15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/navigation_handle.h" 17 #include "content/public/browser/navigation_handle.h"
18 #include "content/public/browser/service_worker_context.h"
19 #include "content/public/browser/storage_partition.h" 18 #include "content/public/browser/storage_partition.h"
20 #include "net/base/url_util.h" 19 #include "net/base/url_util.h"
21 #include "third_party/WebKit/public/platform/WebDisplayMode.h" 20 #include "third_party/WebKit/public/platform/WebDisplayMode.h"
22 21
23 using IconPurpose = content::Manifest::Icon::IconPurpose; 22 using IconPurpose = content::Manifest::Icon::IconPurpose;
24 23
25 namespace { 24 namespace {
26 25
27 const char kPngExtension[] = ".png"; 26 const char kPngExtension[] = ".png";
28 27
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 69
71 DEFINE_WEB_CONTENTS_USER_DATA_KEY(InstallableManager); 70 DEFINE_WEB_CONTENTS_USER_DATA_KEY(InstallableManager);
72 71
73 struct InstallableManager::ManifestProperty { 72 struct InstallableManager::ManifestProperty {
74 InstallableStatusCode error = NO_ERROR_DETECTED; 73 InstallableStatusCode error = NO_ERROR_DETECTED;
75 GURL url; 74 GURL url;
76 content::Manifest manifest; 75 content::Manifest manifest;
77 bool fetched = false; 76 bool fetched = false;
78 }; 77 };
79 78
80 struct InstallableManager::InstallableProperty { 79 struct InstallableManager::ValidManifestProperty {
81 InstallableStatusCode error = NO_ERROR_DETECTED; 80 InstallableStatusCode error = NO_ERROR_DETECTED;
82 bool installable = false; 81 bool is_valid = false;
83 bool fetched = false; 82 bool fetched = false;
84 }; 83 };
85 84
85 struct InstallableManager::ServiceWorkerProperty {
86 InstallableStatusCode error = NO_ERROR_DETECTED;
87 bool has_worker = false;
88 bool is_waiting = false;
89 bool fetched = false;
90 };
91
86 struct InstallableManager::IconProperty { 92 struct InstallableManager::IconProperty {
87 IconProperty() : 93 IconProperty() :
88 error(NO_ERROR_DETECTED), url(), icon(), fetched(false) { } 94 error(NO_ERROR_DETECTED), url(), icon(), fetched(false) { }
89 IconProperty(IconProperty&& other) = default; 95 IconProperty(IconProperty&& other) = default;
90 IconProperty& operator=(IconProperty&& other) = default; 96 IconProperty& operator=(IconProperty&& other) = default;
91 97
92 InstallableStatusCode error = NO_ERROR_DETECTED; 98 InstallableStatusCode error = NO_ERROR_DETECTED;
93 GURL url; 99 GURL url;
94 std::unique_ptr<SkBitmap> icon; 100 std::unique_ptr<SkBitmap> icon;
95 bool fetched; 101 bool fetched;
96 102
97 private: 103 private:
98 // This class contains a std::unique_ptr and therefore must be move-only. 104 // This class contains a std::unique_ptr and therefore must be move-only.
99 DISALLOW_COPY_AND_ASSIGN(IconProperty); 105 DISALLOW_COPY_AND_ASSIGN(IconProperty);
100 }; 106 };
101 107
102 InstallableManager::InstallableManager(content::WebContents* web_contents) 108 InstallableManager::InstallableManager(content::WebContents* web_contents)
103 : content::WebContentsObserver(web_contents), 109 : content::WebContentsObserver(web_contents),
104 manifest_(new ManifestProperty()), 110 manifest_(base::MakeUnique<ManifestProperty>()),
105 installable_(new InstallableProperty()), 111 valid_manifest_(base::MakeUnique<ValidManifestProperty>()),
112 worker_(base::MakeUnique<ServiceWorkerProperty>()),
113 service_worker_context_(nullptr),
106 page_status_(InstallabilityCheckStatus::NOT_STARTED), 114 page_status_(InstallabilityCheckStatus::NOT_STARTED),
107 menu_open_count_(0), 115 menu_open_count_(0),
108 menu_item_add_to_homescreen_count_(0), 116 menu_item_add_to_homescreen_count_(0),
109 is_active_(false), 117 is_active_(false),
110 is_pwa_check_complete_(false), 118 is_pwa_check_complete_(false),
111 weak_factory_(this) {} 119 weak_factory_(this) {
120 // This is null in unit tests.
121 if (web_contents) {
122 content::StoragePartition* storage_partition =
123 content::BrowserContext::GetStoragePartition(
124 Profile::FromBrowserContext(web_contents->GetBrowserContext()),
125 web_contents->GetSiteInstance());
126 DCHECK(storage_partition);
112 127
113 InstallableManager::~InstallableManager() = default; 128 service_worker_context_ = storage_partition->GetServiceWorkerContext();
129 service_worker_context_->AddObserver(this);
130 }
131 }
132
133 InstallableManager::~InstallableManager() {
134 // Null in unit tests.
135 if (service_worker_context_)
136 service_worker_context_->RemoveObserver(this);
137 }
114 138
115 // static 139 // static
116 bool InstallableManager::IsContentSecure(content::WebContents* web_contents) { 140 bool InstallableManager::IsContentSecure(content::WebContents* web_contents) {
117 if (!web_contents) 141 if (!web_contents)
118 return false; 142 return false;
119 143
120 // Whitelist localhost. Check the VisibleURL to match what the 144 // Whitelist localhost. Check the VisibleURL to match what the
121 // SecurityStateTabHelper looks at. 145 // SecurityStateTabHelper looks at.
122 if (net::IsLocalhost(web_contents->GetVisibleURL().HostNoBrackets())) 146 if (net::IsLocalhost(web_contents->GetVisibleURL().HostNoBrackets()))
123 return true; 147 return true;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 246
223 void InstallableManager::SetIconFetched(const IconParams& params) { 247 void InstallableManager::SetIconFetched(const IconParams& params) {
224 icons_[params].fetched = true; 248 icons_[params].fetched = true;
225 } 249 }
226 250
227 InstallableStatusCode InstallableManager::GetErrorCode( 251 InstallableStatusCode InstallableManager::GetErrorCode(
228 const InstallableParams& params) { 252 const InstallableParams& params) {
229 if (manifest_->error != NO_ERROR_DETECTED) 253 if (manifest_->error != NO_ERROR_DETECTED)
230 return manifest_->error; 254 return manifest_->error;
231 255
232 if (params.check_installable && installable_->error != NO_ERROR_DETECTED) 256 if (params.check_installable) {
233 return installable_->error; 257 if (valid_manifest_->error != NO_ERROR_DETECTED)
258 return valid_manifest_->error;
259 if (worker_->error != NO_ERROR_DETECTED)
260 return worker_->error;
261 }
234 262
235 if (params.fetch_valid_primary_icon) { 263 if (params.fetch_valid_primary_icon) {
236 IconProperty& icon = icons_[ParamsForPrimaryIcon(params)]; 264 IconProperty& icon = icons_[ParamsForPrimaryIcon(params)];
237 if (icon.error != NO_ERROR_DETECTED) 265 if (icon.error != NO_ERROR_DETECTED)
238 return icon.error; 266 return icon.error;
239 } 267 }
240 268
241 if (params.fetch_valid_badge_icon) { 269 if (params.fetch_valid_badge_icon) {
242 IconProperty& icon = icons_[ParamsForBadgeIcon(params)]; 270 IconProperty& icon = icons_[ParamsForBadgeIcon(params)];
243 271
244 // If the error is NO_ACCEPTABLE_ICON, there is no icon suitable as a badge 272 // If the error is NO_ACCEPTABLE_ICON, there is no icon suitable as a badge
245 // in the manifest. Ignore this case since we only want to fail the check if 273 // in the manifest. Ignore this case since we only want to fail the check if
246 // there was a suitable badge icon specified and we couldn't fetch it. 274 // there was a suitable badge icon specified and we couldn't fetch it.
247 if (icon.error != NO_ERROR_DETECTED && icon.error != NO_ACCEPTABLE_ICON) 275 if (icon.error != NO_ERROR_DETECTED && icon.error != NO_ACCEPTABLE_ICON)
248 return icon.error; 276 return icon.error;
249 } 277 }
250 278
251 return NO_ERROR_DETECTED; 279 return NO_ERROR_DETECTED;
252 } 280 }
253 281
254 InstallableStatusCode InstallableManager::manifest_error() const { 282 InstallableStatusCode InstallableManager::manifest_error() const {
255 return manifest_->error; 283 return manifest_->error;
256 } 284 }
257 285
258 InstallableStatusCode InstallableManager::installable_error() const { 286 InstallableStatusCode InstallableManager::valid_manifest_error() const {
259 return installable_->error; 287 return valid_manifest_->error;
260 } 288 }
261 289
262 void InstallableManager::set_installable_error( 290 void InstallableManager::set_valid_manifest_error(
263 InstallableStatusCode error_code) { 291 InstallableStatusCode error_code) {
264 installable_->error = error_code; 292 valid_manifest_->error = error_code;
293 }
294
295 InstallableStatusCode InstallableManager::worker_error() const {
296 return worker_->error;
297 }
298
299 bool InstallableManager::worker_waiting() const {
300 return worker_->is_waiting;
265 } 301 }
266 302
267 InstallableStatusCode InstallableManager::icon_error( 303 InstallableStatusCode InstallableManager::icon_error(
268 const IconParams& icon_params) { 304 const IconParams& icon_params) {
269 return icons_[icon_params].error; 305 return icons_[icon_params].error;
270 } 306 }
271 307
272 GURL& InstallableManager::icon_url(const IconParams& icon_params) { 308 GURL& InstallableManager::icon_url(const IconParams& icon_params) {
273 return icons_[icon_params].url; 309 return icons_[icon_params].url;
274 } 310 }
275 311
276 const SkBitmap* InstallableManager::icon(const IconParams& icon_params) { 312 const SkBitmap* InstallableManager::icon(const IconParams& icon_params) {
277 return icons_[icon_params].icon.get(); 313 return icons_[icon_params].icon.get();
278 } 314 }
279 315
280 content::WebContents* InstallableManager::GetWebContents() { 316 content::WebContents* InstallableManager::GetWebContents() {
281 content::WebContents* contents = web_contents(); 317 content::WebContents* contents = web_contents();
282 if (!contents || contents->IsBeingDestroyed()) 318 if (!contents || contents->IsBeingDestroyed())
283 return nullptr; 319 return nullptr;
284 return contents; 320 return contents;
285 } 321 }
286 322
287 bool InstallableManager::IsComplete(const InstallableParams& params) const { 323 bool InstallableManager::IsComplete(const InstallableParams& params) const {
288 // Returns true if for all resources: 324 // Returns true if for all resources:
289 // a. the params did not request it, OR 325 // a. the params did not request it, OR
290 // b. the resource has been fetched/checked. 326 // b. the resource has been fetched/checked.
291 return manifest_->fetched && 327 return manifest_->fetched &&
292 (!params.check_installable || installable_->fetched) && 328 (!params.check_installable ||
329 (valid_manifest_->fetched && worker_->fetched)) &&
293 (!params.fetch_valid_primary_icon || 330 (!params.fetch_valid_primary_icon ||
294 IsIconFetched(ParamsForPrimaryIcon(params))) && 331 IsIconFetched(ParamsForPrimaryIcon(params))) &&
295 (!params.fetch_valid_badge_icon || 332 (!params.fetch_valid_badge_icon ||
296 IsIconFetched(ParamsForBadgeIcon(params))); 333 IsIconFetched(ParamsForBadgeIcon(params)));
297 } 334 }
298 335
299 void InstallableManager::Reset() { 336 void InstallableManager::Reset() {
300 // Prevent any outstanding callbacks to or from this object from being called. 337 // Prevent any outstanding callbacks to or from this object from being called.
301 weak_factory_.InvalidateWeakPtrs(); 338 weak_factory_.InvalidateWeakPtrs();
302 tasks_.clear(); 339 tasks_.clear();
303 icons_.clear(); 340 icons_.clear();
304 341
305 // We may have reset prior to completion, in which case |menu_open_count_| or 342 // We may have reset prior to completion, in which case |menu_open_count_| or
306 // |menu_item_add_to_homescreen_count_| might be nonzero and |page_status_| is 343 // |menu_item_add_to_homescreen_count_| might be nonzero and |page_status_| is
307 // one of NOT_STARTED or NOT_COMPLETED. If we completed, then these values 344 // one of NOT_STARTED or NOT_COMPLETED. If we completed, then these values
308 // cannot be anything except 0. 345 // cannot be anything except 0.
309 is_pwa_check_complete_ = false; 346 is_pwa_check_complete_ = false;
310 347
311 for (; menu_open_count_ > 0; --menu_open_count_) 348 for (; menu_open_count_ > 0; --menu_open_count_)
312 InstallableMetrics::RecordMenuOpenHistogram(page_status_); 349 InstallableMetrics::RecordMenuOpenHistogram(page_status_);
313 350
314 for (; menu_item_add_to_homescreen_count_ > 0; 351 for (; menu_item_add_to_homescreen_count_ > 0;
315 --menu_item_add_to_homescreen_count_) { 352 --menu_item_add_to_homescreen_count_) {
316 InstallableMetrics::RecordMenuItemAddToHomescreenHistogram(page_status_); 353 InstallableMetrics::RecordMenuItemAddToHomescreenHistogram(page_status_);
317 } 354 }
318 355
319 page_status_ = InstallabilityCheckStatus::NOT_STARTED; 356 page_status_ = InstallabilityCheckStatus::NOT_STARTED;
320 manifest_.reset(new ManifestProperty()); 357 manifest_ = base::MakeUnique<ManifestProperty>();
321 installable_.reset(new InstallableProperty()); 358 valid_manifest_ = base::MakeUnique<ValidManifestProperty>();
359 worker_ = base::MakeUnique<ServiceWorkerProperty>();
322 360
323 is_active_ = false; 361 is_active_ = false;
324 } 362 }
325 363
326 void InstallableManager::SetManifestDependentTasksComplete() { 364 void InstallableManager::SetManifestDependentTasksComplete() {
327 DCHECK(!tasks_.empty()); 365 DCHECK(!tasks_.empty());
328 const InstallableParams& params = tasks_[0].first; 366 const InstallableParams& params = tasks_[0].first;
329 367
330 installable_->fetched = true; 368 valid_manifest_->fetched = true;
369 worker_->fetched = true;
331 SetIconFetched(ParamsForPrimaryIcon(params)); 370 SetIconFetched(ParamsForPrimaryIcon(params));
332 SetIconFetched(ParamsForBadgeIcon(params)); 371 SetIconFetched(ParamsForBadgeIcon(params));
333 } 372 }
334 373
335 void InstallableManager::RunCallback(const Task& task, 374 void InstallableManager::RunCallback(const Task& task,
336 InstallableStatusCode code) { 375 InstallableStatusCode code) {
337 const InstallableParams& params = task.first; 376 const InstallableParams& params = task.first;
338 IconProperty null_icon; 377 IconProperty null_icon;
339 IconProperty* primary_icon = &null_icon; 378 IconProperty* primary_icon = &null_icon;
340 IconProperty* badge_icon = &null_icon; 379 IconProperty* badge_icon = &null_icon;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 tasks_.erase(tasks_.begin()); 423 tasks_.erase(tasks_.begin());
385 StartNextTask(); 424 StartNextTask();
386 return; 425 return;
387 } 426 }
388 427
389 if (!manifest_->fetched) { 428 if (!manifest_->fetched) {
390 FetchManifest(); 429 FetchManifest();
391 } else if (params.fetch_valid_primary_icon && 430 } else if (params.fetch_valid_primary_icon &&
392 !IsIconFetched(ParamsForPrimaryIcon(params))) { 431 !IsIconFetched(ParamsForPrimaryIcon(params))) {
393 CheckAndFetchBestIcon(ParamsForPrimaryIcon(params)); 432 CheckAndFetchBestIcon(ParamsForPrimaryIcon(params));
394 } else if (params.check_installable && !installable_->fetched) { 433 } else if (params.check_installable && !valid_manifest_->fetched) {
395 CheckInstallable(); 434 CheckInstallable();
435 } else if (params.check_installable && !worker_->fetched) {
436 CheckServiceWorker();
396 } else if (params.fetch_valid_badge_icon && 437 } else if (params.fetch_valid_badge_icon &&
397 !IsIconFetched(ParamsForBadgeIcon(params))) { 438 !IsIconFetched(ParamsForBadgeIcon(params))) {
398 CheckAndFetchBestIcon(ParamsForBadgeIcon(params)); 439 CheckAndFetchBestIcon(ParamsForBadgeIcon(params));
399 } else { 440 } else {
400 NOTREACHED(); 441 NOTREACHED();
401 } 442 }
402 } 443 }
403 444
404 void InstallableManager::FetchManifest() { 445 void InstallableManager::FetchManifest() {
405 DCHECK(!manifest_->fetched); 446 DCHECK(!manifest_->fetched);
(...skipping 18 matching lines...) Expand all
424 SetManifestDependentTasksComplete(); 465 SetManifestDependentTasksComplete();
425 } 466 }
426 467
427 manifest_->url = manifest_url; 468 manifest_->url = manifest_url;
428 manifest_->manifest = manifest; 469 manifest_->manifest = manifest;
429 manifest_->fetched = true; 470 manifest_->fetched = true;
430 WorkOnTask(); 471 WorkOnTask();
431 } 472 }
432 473
433 void InstallableManager::CheckInstallable() { 474 void InstallableManager::CheckInstallable() {
434 DCHECK(!installable_->fetched); 475 DCHECK(!valid_manifest_->fetched);
435 DCHECK(!manifest().IsEmpty()); 476 DCHECK(!manifest().IsEmpty());
436 477
437 if (IsManifestValidForWebApp(manifest())) { 478 valid_manifest_->is_valid = IsManifestValidForWebApp(manifest());
438 CheckServiceWorker(); 479 valid_manifest_->fetched = true;
439 } else { 480 WorkOnTask();
440 installable_->installable = false;
441 installable_->fetched = true;
442 WorkOnTask();
443 }
444 } 481 }
445 482
446 bool InstallableManager::IsManifestValidForWebApp( 483 bool InstallableManager::IsManifestValidForWebApp(
447 const content::Manifest& manifest) { 484 const content::Manifest& manifest) {
448 if (manifest.IsEmpty()) { 485 if (manifest.IsEmpty()) {
449 installable_->error = MANIFEST_EMPTY; 486 valid_manifest_->error = MANIFEST_EMPTY;
450 return false; 487 return false;
451 } 488 }
452 489
453 if (!manifest.start_url.is_valid()) { 490 if (!manifest.start_url.is_valid()) {
454 installable_->error = START_URL_NOT_VALID; 491 valid_manifest_->error = START_URL_NOT_VALID;
455 return false; 492 return false;
456 } 493 }
457 494
458 if ((manifest.name.is_null() || manifest.name.string().empty()) && 495 if ((manifest.name.is_null() || manifest.name.string().empty()) &&
459 (manifest.short_name.is_null() || manifest.short_name.string().empty())) { 496 (manifest.short_name.is_null() || manifest.short_name.string().empty())) {
460 installable_->error = MANIFEST_MISSING_NAME_OR_SHORT_NAME; 497 valid_manifest_->error = MANIFEST_MISSING_NAME_OR_SHORT_NAME;
461 return false; 498 return false;
462 } 499 }
463 500
464 // TODO(dominickn,mlamouri): when Chrome supports "minimal-ui", it should be 501 // TODO(dominickn,mlamouri): when Chrome supports "minimal-ui", it should be
465 // accepted. If we accept it today, it would fallback to "browser" and make 502 // accepted. If we accept it today, it would fallback to "browser" and make
466 // this check moot. See https://crbug.com/604390. 503 // this check moot. See https://crbug.com/604390.
467 if (manifest.display != blink::kWebDisplayModeStandalone && 504 if (manifest.display != blink::kWebDisplayModeStandalone &&
468 manifest.display != blink::kWebDisplayModeFullscreen) { 505 manifest.display != blink::kWebDisplayModeFullscreen) {
469 installable_->error = MANIFEST_DISPLAY_NOT_SUPPORTED; 506 valid_manifest_->error = MANIFEST_DISPLAY_NOT_SUPPORTED;
470 return false; 507 return false;
471 } 508 }
472 509
473 if (!DoesManifestContainRequiredIcon(manifest)) { 510 if (!DoesManifestContainRequiredIcon(manifest)) {
474 installable_->error = MANIFEST_MISSING_SUITABLE_ICON; 511 valid_manifest_->error = MANIFEST_MISSING_SUITABLE_ICON;
475 return false; 512 return false;
476 } 513 }
477 514
478 return true; 515 return true;
479 } 516 }
480 517
481 void InstallableManager::CheckServiceWorker() { 518 void InstallableManager::CheckServiceWorker() {
482 DCHECK(!installable_->fetched); 519 DCHECK(!worker_->fetched);
483 DCHECK(!manifest().IsEmpty()); 520 DCHECK(!manifest().IsEmpty());
484 DCHECK(manifest().start_url.is_valid()); 521 DCHECK(manifest().start_url.is_valid());
485 522
486 content::WebContents* web_contents = GetWebContents();
487
488 // Check to see if there is a single service worker controlling this page 523 // Check to see if there is a single service worker controlling this page
489 // and the manifest's start url. 524 // and the manifest's start url.
490 content::StoragePartition* storage_partition = 525 service_worker_context_->CheckHasServiceWorker(
491 content::BrowserContext::GetStoragePartition( 526 GetWebContents()->GetLastCommittedURL(), manifest().start_url,
492 Profile::FromBrowserContext(web_contents->GetBrowserContext()),
493 web_contents->GetSiteInstance());
494 DCHECK(storage_partition);
495
496 storage_partition->GetServiceWorkerContext()->CheckHasServiceWorker(
497 web_contents->GetLastCommittedURL(), manifest().start_url,
498 base::Bind(&InstallableManager::OnDidCheckHasServiceWorker, 527 base::Bind(&InstallableManager::OnDidCheckHasServiceWorker,
499 weak_factory_.GetWeakPtr())); 528 weak_factory_.GetWeakPtr()));
500 } 529 }
501 530
502 void InstallableManager::OnDidCheckHasServiceWorker( 531 void InstallableManager::OnDidCheckHasServiceWorker(
503 content::ServiceWorkerCapability capability) { 532 content::ServiceWorkerCapability capability) {
504 if (!GetWebContents()) 533 if (!GetWebContents())
505 return; 534 return;
506 535
507 switch (capability) { 536 switch (capability) {
508 case content::ServiceWorkerCapability::SERVICE_WORKER_WITH_FETCH_HANDLER: 537 case content::ServiceWorkerCapability::SERVICE_WORKER_WITH_FETCH_HANDLER:
509 installable_->installable = true; 538 worker_->has_worker = true;
510 break; 539 break;
511 case content::ServiceWorkerCapability::SERVICE_WORKER_NO_FETCH_HANDLER: 540 case content::ServiceWorkerCapability::SERVICE_WORKER_NO_FETCH_HANDLER:
512 installable_->installable = false; 541 worker_->has_worker = false;
513 installable_->error = NOT_OFFLINE_CAPABLE; 542 worker_->error = NOT_OFFLINE_CAPABLE;
514 break; 543 break;
515 case content::ServiceWorkerCapability::NO_SERVICE_WORKER: 544 case content::ServiceWorkerCapability::NO_SERVICE_WORKER:
516 installable_->installable = false; 545 InstallableParams& params = tasks_[0].first;
517 installable_->error = NO_MATCHING_SERVICE_WORKER; 546 if (params.wait_for_worker) {
547 // Wait for ServiceWorkerContextObserver::OnRegistrationStored. Set the
548 // param |wait_for_worker| to false so we only wait once per task.
549 params.wait_for_worker = false;
550 worker_->is_waiting = true;
551 OnWaitingForServiceWorker();
552 return;
553 }
554 worker_->has_worker = false;
555 worker_->error = NO_MATCHING_SERVICE_WORKER;
518 break; 556 break;
519 } 557 }
520 558
521 installable_->fetched = true; 559 worker_->fetched = true;
522 WorkOnTask(); 560 WorkOnTask();
523 } 561 }
524 562
525 void InstallableManager::CheckAndFetchBestIcon(const IconParams& params) { 563 void InstallableManager::CheckAndFetchBestIcon(const IconParams& params) {
526 DCHECK(!manifest().IsEmpty()); 564 DCHECK(!manifest().IsEmpty());
527 565
528 int ideal_icon_size_in_px = std::get<0>(params); 566 int ideal_icon_size_in_px = std::get<0>(params);
529 int minimum_icon_size_in_px = std::get<1>(params); 567 int minimum_icon_size_in_px = std::get<1>(params);
530 IconPurpose icon_purpose = std::get<2>(params); 568 IconPurpose icon_purpose = std::get<2>(params);
531 569
(...skipping 30 matching lines...) Expand all
562 if (bitmap.drawsNothing()) { 600 if (bitmap.drawsNothing()) {
563 icon.error = NO_ICON_AVAILABLE; 601 icon.error = NO_ICON_AVAILABLE;
564 } else { 602 } else {
565 icon.url = icon_url; 603 icon.url = icon_url;
566 icon.icon.reset(new SkBitmap(bitmap)); 604 icon.icon.reset(new SkBitmap(bitmap));
567 } 605 }
568 606
569 WorkOnTask(); 607 WorkOnTask();
570 } 608 }
571 609
610 void InstallableManager::OnRegistrationStored(const GURL& pattern) {
611 // If we aren't currently waiting, either:
612 // a) we've already failed the check, or
613 // b) we haven't yet called CheckHasServiceWorker.
614 // Otherwise if the scope doesn't match we keep waiting.
615 if (!worker_->is_waiting || !content::ServiceWorkerContext::ScopeMatches(
616 pattern, manifest().start_url)) {
617 return;
618 }
619
620 // This will call CheckHasServiceWorker to check whether the service worker
621 // controls the start_url and if it has a fetch handler.
622 worker_->is_waiting = false;
623 WorkOnTask();
624 }
625
572 void InstallableManager::DidFinishNavigation( 626 void InstallableManager::DidFinishNavigation(
573 content::NavigationHandle* handle) { 627 content::NavigationHandle* handle) {
574 if (handle->IsInMainFrame() && handle->HasCommitted() && 628 if (handle->IsInMainFrame() && handle->HasCommitted() &&
575 !handle->IsSameDocument()) { 629 !handle->IsSameDocument()) {
576 Reset(); 630 Reset();
577 } 631 }
578 } 632 }
579 633
580 void InstallableManager::WebContentsDestroyed() { 634 void InstallableManager::WebContentsDestroyed() {
581 Reset(); 635 Reset();
582 Observe(nullptr); 636 Observe(nullptr);
583 } 637 }
584 638
585 const GURL& InstallableManager::manifest_url() const { 639 const GURL& InstallableManager::manifest_url() const {
586 return manifest_->url; 640 return manifest_->url;
587 } 641 }
588 642
589 const content::Manifest& InstallableManager::manifest() const { 643 const content::Manifest& InstallableManager::manifest() const {
590 return manifest_->manifest; 644 return manifest_->manifest;
591 } 645 }
592 646
593 bool InstallableManager::is_installable() const { 647 bool InstallableManager::is_installable() const {
594 return installable_->installable; 648 return valid_manifest_->is_valid && worker_->has_worker;
595 } 649 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698