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

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: Don't cache NO_MATCHING_SERVICE_WORKER 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/profiles/profile.h" 10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ssl/security_state_tab_helper.h" 11 #include "chrome/browser/ssl/security_state_tab_helper.h"
12 #include "components/security_state/core/security_state.h" 12 #include "components/security_state/core/security_state.h"
13 #include "content/public/browser/browser_context.h" 13 #include "content/public/browser/browser_context.h"
14 #include "content/public/browser/browser_thread.h" 14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/browser/manifest_icon_downloader.h" 15 #include "content/public/browser/manifest_icon_downloader.h"
16 #include "content/public/browser/manifest_icon_selector.h" 16 #include "content/public/browser/manifest_icon_selector.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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 void InstallableManager::WorkOnTask() { 413 void InstallableManager::WorkOnTask() {
375 DCHECK(!tasks_.empty()); 414 DCHECK(!tasks_.empty());
376 const Task& task = tasks_[0]; 415 const Task& task = tasks_[0];
377 const InstallableParams& params = task.first; 416 const InstallableParams& params = task.first;
378 417
379 InstallableStatusCode code = GetErrorCode(params); 418 InstallableStatusCode code = GetErrorCode(params);
380 bool check_passed = (code == NO_ERROR_DETECTED); 419 bool check_passed = (code == NO_ERROR_DETECTED);
381 if (!check_passed || IsComplete(params)) { 420 if (!check_passed || IsComplete(params)) {
382 RecordQueuedMetricsOnTaskCompletion(params, check_passed); 421 RecordQueuedMetricsOnTaskCompletion(params, check_passed);
383 RunCallback(task, code); 422 RunCallback(task, code);
423
424 // Sites can always register a service worker after we finish checking, so
425 // don't cache a missing service worker error to ensure we always check
426 // again.
427 if (worker_error() == NO_MATCHING_SERVICE_WORKER)
428 worker_ = base::MakeUnique<ServiceWorkerProperty>();
384 tasks_.erase(tasks_.begin()); 429 tasks_.erase(tasks_.begin());
385 StartNextTask(); 430 StartNextTask();
386 return; 431 return;
387 } 432 }
388 433
389 if (!manifest_->fetched) { 434 if (!manifest_->fetched) {
390 FetchManifest(); 435 FetchManifest();
391 } else if (params.fetch_valid_primary_icon && 436 } else if (params.fetch_valid_primary_icon &&
392 !IsIconFetched(ParamsForPrimaryIcon(params))) { 437 !IsIconFetched(ParamsForPrimaryIcon(params))) {
393 CheckAndFetchBestIcon(ParamsForPrimaryIcon(params)); 438 CheckAndFetchBestIcon(ParamsForPrimaryIcon(params));
394 } else if (params.check_installable && !installable_->fetched) { 439 } else if (params.check_installable && !valid_manifest_->fetched) {
395 CheckInstallable(); 440 CheckInstallable();
441 } else if (params.check_installable && !worker_->fetched) {
442 CheckServiceWorker();
396 } else if (params.fetch_valid_badge_icon && 443 } else if (params.fetch_valid_badge_icon &&
397 !IsIconFetched(ParamsForBadgeIcon(params))) { 444 !IsIconFetched(ParamsForBadgeIcon(params))) {
398 CheckAndFetchBestIcon(ParamsForBadgeIcon(params)); 445 CheckAndFetchBestIcon(ParamsForBadgeIcon(params));
399 } else { 446 } else {
400 NOTREACHED(); 447 NOTREACHED();
401 } 448 }
402 } 449 }
403 450
404 void InstallableManager::FetchManifest() { 451 void InstallableManager::FetchManifest() {
405 DCHECK(!manifest_->fetched); 452 DCHECK(!manifest_->fetched);
(...skipping 18 matching lines...) Expand all
424 SetManifestDependentTasksComplete(); 471 SetManifestDependentTasksComplete();
425 } 472 }
426 473
427 manifest_->url = manifest_url; 474 manifest_->url = manifest_url;
428 manifest_->manifest = manifest; 475 manifest_->manifest = manifest;
429 manifest_->fetched = true; 476 manifest_->fetched = true;
430 WorkOnTask(); 477 WorkOnTask();
431 } 478 }
432 479
433 void InstallableManager::CheckInstallable() { 480 void InstallableManager::CheckInstallable() {
434 DCHECK(!installable_->fetched); 481 DCHECK(!valid_manifest_->fetched);
435 DCHECK(!manifest().IsEmpty()); 482 DCHECK(!manifest().IsEmpty());
436 483
437 if (IsManifestValidForWebApp(manifest())) { 484 valid_manifest_->is_valid = IsManifestValidForWebApp(manifest());
438 CheckServiceWorker(); 485 valid_manifest_->fetched = true;
439 } else { 486 WorkOnTask();
440 installable_->installable = false;
441 installable_->fetched = true;
442 WorkOnTask();
443 }
444 } 487 }
445 488
446 bool InstallableManager::IsManifestValidForWebApp( 489 bool InstallableManager::IsManifestValidForWebApp(
447 const content::Manifest& manifest) { 490 const content::Manifest& manifest) {
448 if (manifest.IsEmpty()) { 491 if (manifest.IsEmpty()) {
449 installable_->error = MANIFEST_EMPTY; 492 valid_manifest_->error = MANIFEST_EMPTY;
450 return false; 493 return false;
451 } 494 }
452 495
453 if (!manifest.start_url.is_valid()) { 496 if (!manifest.start_url.is_valid()) {
454 installable_->error = START_URL_NOT_VALID; 497 valid_manifest_->error = START_URL_NOT_VALID;
455 return false; 498 return false;
456 } 499 }
457 500
458 if ((manifest.name.is_null() || manifest.name.string().empty()) && 501 if ((manifest.name.is_null() || manifest.name.string().empty()) &&
459 (manifest.short_name.is_null() || manifest.short_name.string().empty())) { 502 (manifest.short_name.is_null() || manifest.short_name.string().empty())) {
460 installable_->error = MANIFEST_MISSING_NAME_OR_SHORT_NAME; 503 valid_manifest_->error = MANIFEST_MISSING_NAME_OR_SHORT_NAME;
461 return false; 504 return false;
462 } 505 }
463 506
464 // TODO(dominickn,mlamouri): when Chrome supports "minimal-ui", it should be 507 // 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 508 // accepted. If we accept it today, it would fallback to "browser" and make
466 // this check moot. See https://crbug.com/604390. 509 // this check moot. See https://crbug.com/604390.
467 if (manifest.display != blink::kWebDisplayModeStandalone && 510 if (manifest.display != blink::kWebDisplayModeStandalone &&
468 manifest.display != blink::kWebDisplayModeFullscreen) { 511 manifest.display != blink::kWebDisplayModeFullscreen) {
469 installable_->error = MANIFEST_DISPLAY_NOT_SUPPORTED; 512 valid_manifest_->error = MANIFEST_DISPLAY_NOT_SUPPORTED;
470 return false; 513 return false;
471 } 514 }
472 515
473 if (!DoesManifestContainRequiredIcon(manifest)) { 516 if (!DoesManifestContainRequiredIcon(manifest)) {
474 installable_->error = MANIFEST_MISSING_SUITABLE_ICON; 517 valid_manifest_->error = MANIFEST_MISSING_SUITABLE_ICON;
475 return false; 518 return false;
476 } 519 }
477 520
478 return true; 521 return true;
479 } 522 }
480 523
481 void InstallableManager::CheckServiceWorker() { 524 void InstallableManager::CheckServiceWorker() {
482 DCHECK(!installable_->fetched); 525 DCHECK(!worker_->fetched);
483 DCHECK(!manifest().IsEmpty()); 526 DCHECK(!manifest().IsEmpty());
484 DCHECK(manifest().start_url.is_valid()); 527 DCHECK(manifest().start_url.is_valid());
485 528
486 content::WebContents* web_contents = GetWebContents();
487
488 // Check to see if there is a single service worker controlling this page 529 // Check to see if there is a single service worker controlling this page
489 // and the manifest's start url. 530 // and the manifest's start url.
490 content::StoragePartition* storage_partition = 531 service_worker_context_->CheckHasServiceWorker(
491 content::BrowserContext::GetStoragePartition( 532 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, 533 base::Bind(&InstallableManager::OnDidCheckHasServiceWorker,
499 weak_factory_.GetWeakPtr())); 534 weak_factory_.GetWeakPtr()));
500 } 535 }
501 536
502 void InstallableManager::OnDidCheckHasServiceWorker( 537 void InstallableManager::OnDidCheckHasServiceWorker(
503 content::ServiceWorkerCapability capability) { 538 content::ServiceWorkerCapability capability) {
504 if (!GetWebContents()) 539 if (!GetWebContents())
505 return; 540 return;
506 541
507 switch (capability) { 542 switch (capability) {
508 case content::ServiceWorkerCapability::SERVICE_WORKER_WITH_FETCH_HANDLER: 543 case content::ServiceWorkerCapability::SERVICE_WORKER_WITH_FETCH_HANDLER:
509 installable_->installable = true; 544 worker_->has_worker = true;
510 break; 545 break;
511 case content::ServiceWorkerCapability::SERVICE_WORKER_NO_FETCH_HANDLER: 546 case content::ServiceWorkerCapability::SERVICE_WORKER_NO_FETCH_HANDLER:
512 installable_->installable = false; 547 worker_->has_worker = false;
513 installable_->error = NOT_OFFLINE_CAPABLE; 548 worker_->error = NOT_OFFLINE_CAPABLE;
514 break; 549 break;
515 case content::ServiceWorkerCapability::NO_SERVICE_WORKER: 550 case content::ServiceWorkerCapability::NO_SERVICE_WORKER:
516 installable_->installable = false; 551 InstallableParams& params = tasks_[0].first;
517 installable_->error = NO_MATCHING_SERVICE_WORKER; 552 if (params.wait_for_worker) {
553 // Wait for ServiceWorkerContextObserver::OnRegistrationStored. Set the
554 // param |wait_for_worker| to false so we only wait once per task.
555 params.wait_for_worker = false;
556 worker_->is_waiting = true;
557 OnWaitingForServiceWorker();
558 return;
559 }
560 worker_->has_worker = false;
561 worker_->error = NO_MATCHING_SERVICE_WORKER;
518 break; 562 break;
519 } 563 }
520 564
521 installable_->fetched = true; 565 worker_->fetched = true;
522 WorkOnTask(); 566 WorkOnTask();
523 } 567 }
524 568
525 void InstallableManager::CheckAndFetchBestIcon(const IconParams& params) { 569 void InstallableManager::CheckAndFetchBestIcon(const IconParams& params) {
526 DCHECK(!manifest().IsEmpty()); 570 DCHECK(!manifest().IsEmpty());
527 571
528 int ideal_icon_size_in_px = std::get<0>(params); 572 int ideal_icon_size_in_px = std::get<0>(params);
529 int minimum_icon_size_in_px = std::get<1>(params); 573 int minimum_icon_size_in_px = std::get<1>(params);
530 IconPurpose icon_purpose = std::get<2>(params); 574 IconPurpose icon_purpose = std::get<2>(params);
531 575
(...skipping 30 matching lines...) Expand all
562 if (bitmap.drawsNothing()) { 606 if (bitmap.drawsNothing()) {
563 icon.error = NO_ICON_AVAILABLE; 607 icon.error = NO_ICON_AVAILABLE;
564 } else { 608 } else {
565 icon.url = icon_url; 609 icon.url = icon_url;
566 icon.icon.reset(new SkBitmap(bitmap)); 610 icon.icon.reset(new SkBitmap(bitmap));
567 } 611 }
568 612
569 WorkOnTask(); 613 WorkOnTask();
570 } 614 }
571 615
616 void InstallableManager::OnRegistrationStored(const GURL& pattern) {
617 // If we aren't currently waiting, either:
618 // a) we've already failed the check, or
619 // b) we haven't yet called CheckHasServiceWorker.
620 // Otherwise if the scope doesn't match we keep waiting.
621 if (!worker_->is_waiting || !content::ServiceWorkerContext::ScopeMatches(
622 pattern, manifest().start_url)) {
623 return;
624 }
625
626 // This will call CheckHasServiceWorker to check whether the service worker
627 // controls the start_url and if it has a fetch handler.
628 worker_->is_waiting = false;
629 WorkOnTask();
630 }
631
572 void InstallableManager::DidFinishNavigation( 632 void InstallableManager::DidFinishNavigation(
573 content::NavigationHandle* handle) { 633 content::NavigationHandle* handle) {
574 if (handle->IsInMainFrame() && handle->HasCommitted() && 634 if (handle->IsInMainFrame() && handle->HasCommitted() &&
575 !handle->IsSameDocument()) { 635 !handle->IsSameDocument()) {
576 Reset(); 636 Reset();
577 } 637 }
578 } 638 }
579 639
580 void InstallableManager::WebContentsDestroyed() { 640 void InstallableManager::WebContentsDestroyed() {
581 Reset(); 641 Reset();
582 Observe(nullptr); 642 Observe(nullptr);
583 } 643 }
584 644
585 const GURL& InstallableManager::manifest_url() const { 645 const GURL& InstallableManager::manifest_url() const {
586 return manifest_->url; 646 return manifest_->url;
587 } 647 }
588 648
589 const content::Manifest& InstallableManager::manifest() const { 649 const content::Manifest& InstallableManager::manifest() const {
590 return manifest_->manifest; 650 return manifest_->manifest;
591 } 651 }
592 652
593 bool InstallableManager::is_installable() const { 653 bool InstallableManager::is_installable() const {
594 return installable_->installable; 654 return valid_manifest_->is_valid && worker_->has_worker;
595 } 655 }
OLDNEW
« no previous file with comments | « chrome/browser/installable/installable_manager.h ('k') | chrome/browser/installable/installable_manager_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698