| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |