| 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; |
| 265 } | 297 } |
| 266 | 298 |
| 267 InstallableStatusCode InstallableManager::icon_error( | 299 InstallableStatusCode InstallableManager::icon_error( |
| 268 const IconParams& icon_params) { | 300 const IconParams& icon_params) { |
| 269 return icons_[icon_params].error; | 301 return icons_[icon_params].error; |
| 270 } | 302 } |
| 271 | 303 |
| 272 GURL& InstallableManager::icon_url(const IconParams& icon_params) { | 304 GURL& InstallableManager::icon_url(const IconParams& icon_params) { |
| 273 return icons_[icon_params].url; | 305 return icons_[icon_params].url; |
| 274 } | 306 } |
| 275 | 307 |
| 276 const SkBitmap* InstallableManager::icon(const IconParams& icon_params) { | 308 const SkBitmap* InstallableManager::icon(const IconParams& icon_params) { |
| 277 return icons_[icon_params].icon.get(); | 309 return icons_[icon_params].icon.get(); |
| 278 } | 310 } |
| 279 | 311 |
| 280 content::WebContents* InstallableManager::GetWebContents() { | 312 content::WebContents* InstallableManager::GetWebContents() { |
| 281 content::WebContents* contents = web_contents(); | 313 content::WebContents* contents = web_contents(); |
| 282 if (!contents || contents->IsBeingDestroyed()) | 314 if (!contents || contents->IsBeingDestroyed()) |
| 283 return nullptr; | 315 return nullptr; |
| 284 return contents; | 316 return contents; |
| 285 } | 317 } |
| 286 | 318 |
| 287 bool InstallableManager::IsComplete(const InstallableParams& params) const { | 319 bool InstallableManager::IsComplete(const InstallableParams& params) const { |
| 288 // Returns true if for all resources: | 320 // Returns true if for all resources: |
| 289 // a. the params did not request it, OR | 321 // a. the params did not request it, OR |
| 290 // b. the resource has been fetched/checked. | 322 // b. the resource has been fetched/checked. |
| 291 return manifest_->fetched && | 323 return manifest_->fetched && |
| 292 (!params.check_installable || installable_->fetched) && | 324 (!params.check_installable || |
| 325 (valid_manifest_->fetched && worker_->fetched)) && |
| 293 (!params.fetch_valid_primary_icon || | 326 (!params.fetch_valid_primary_icon || |
| 294 IsIconFetched(ParamsForPrimaryIcon(params))) && | 327 IsIconFetched(ParamsForPrimaryIcon(params))) && |
| 295 (!params.fetch_valid_badge_icon || | 328 (!params.fetch_valid_badge_icon || |
| 296 IsIconFetched(ParamsForBadgeIcon(params))); | 329 IsIconFetched(ParamsForBadgeIcon(params))); |
| 297 } | 330 } |
| 298 | 331 |
| 299 void InstallableManager::Reset() { | 332 void InstallableManager::Reset() { |
| 300 // Prevent any outstanding callbacks to or from this object from being called. | 333 // Prevent any outstanding callbacks to or from this object from being called. |
| 301 weak_factory_.InvalidateWeakPtrs(); | 334 weak_factory_.InvalidateWeakPtrs(); |
| 302 tasks_.clear(); | 335 tasks_.clear(); |
| 303 icons_.clear(); | 336 icons_.clear(); |
| 304 | 337 |
| 305 // We may have reset prior to completion, in which case |menu_open_count_| or | 338 // 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 | 339 // |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 | 340 // one of NOT_STARTED or NOT_COMPLETED. If we completed, then these values |
| 308 // cannot be anything except 0. | 341 // cannot be anything except 0. |
| 309 is_pwa_check_complete_ = false; | 342 is_pwa_check_complete_ = false; |
| 310 | 343 |
| 311 for (; menu_open_count_ > 0; --menu_open_count_) | 344 for (; menu_open_count_ > 0; --menu_open_count_) |
| 312 InstallableMetrics::RecordMenuOpenHistogram(page_status_); | 345 InstallableMetrics::RecordMenuOpenHistogram(page_status_); |
| 313 | 346 |
| 314 for (; menu_item_add_to_homescreen_count_ > 0; | 347 for (; menu_item_add_to_homescreen_count_ > 0; |
| 315 --menu_item_add_to_homescreen_count_) { | 348 --menu_item_add_to_homescreen_count_) { |
| 316 InstallableMetrics::RecordMenuItemAddToHomescreenHistogram(page_status_); | 349 InstallableMetrics::RecordMenuItemAddToHomescreenHistogram(page_status_); |
| 317 } | 350 } |
| 318 | 351 |
| 319 page_status_ = InstallabilityCheckStatus::NOT_STARTED; | 352 page_status_ = InstallabilityCheckStatus::NOT_STARTED; |
| 320 manifest_.reset(new ManifestProperty()); | 353 manifest_ = base::MakeUnique<ManifestProperty>(); |
| 321 installable_.reset(new InstallableProperty()); | 354 valid_manifest_ = base::MakeUnique<ValidManifestProperty>(); |
| 355 worker_ = base::MakeUnique<ServiceWorkerProperty>(); |
| 322 | 356 |
| 323 is_active_ = false; | 357 is_active_ = false; |
| 324 } | 358 } |
| 325 | 359 |
| 326 void InstallableManager::SetManifestDependentTasksComplete() { | 360 void InstallableManager::SetManifestDependentTasksComplete() { |
| 327 DCHECK(!tasks_.empty()); | 361 DCHECK(!tasks_.empty()); |
| 328 const InstallableParams& params = tasks_[0].first; | 362 const InstallableParams& params = tasks_[0].first; |
| 329 | 363 |
| 330 installable_->fetched = true; | 364 valid_manifest_->fetched = true; |
| 365 worker_->fetched = true; |
| 331 SetIconFetched(ParamsForPrimaryIcon(params)); | 366 SetIconFetched(ParamsForPrimaryIcon(params)); |
| 332 SetIconFetched(ParamsForBadgeIcon(params)); | 367 SetIconFetched(ParamsForBadgeIcon(params)); |
| 333 } | 368 } |
| 334 | 369 |
| 335 void InstallableManager::RunCallback(const Task& task, | 370 void InstallableManager::RunCallback(const Task& task, |
| 336 InstallableStatusCode code) { | 371 InstallableStatusCode code) { |
| 337 const InstallableParams& params = task.first; | 372 const InstallableParams& params = task.first; |
| 338 IconProperty null_icon; | 373 IconProperty null_icon; |
| 339 IconProperty* primary_icon = &null_icon; | 374 IconProperty* primary_icon = &null_icon; |
| 340 IconProperty* badge_icon = &null_icon; | 375 IconProperty* badge_icon = &null_icon; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 tasks_.erase(tasks_.begin()); | 419 tasks_.erase(tasks_.begin()); |
| 385 StartNextTask(); | 420 StartNextTask(); |
| 386 return; | 421 return; |
| 387 } | 422 } |
| 388 | 423 |
| 389 if (!manifest_->fetched) { | 424 if (!manifest_->fetched) { |
| 390 FetchManifest(); | 425 FetchManifest(); |
| 391 } else if (params.fetch_valid_primary_icon && | 426 } else if (params.fetch_valid_primary_icon && |
| 392 !IsIconFetched(ParamsForPrimaryIcon(params))) { | 427 !IsIconFetched(ParamsForPrimaryIcon(params))) { |
| 393 CheckAndFetchBestIcon(ParamsForPrimaryIcon(params)); | 428 CheckAndFetchBestIcon(ParamsForPrimaryIcon(params)); |
| 394 } else if (params.check_installable && !installable_->fetched) { | 429 } else if (params.check_installable && !valid_manifest_->fetched) { |
| 395 CheckInstallable(); | 430 CheckInstallable(); |
| 431 } else if (params.check_installable && !worker_->fetched) { |
| 432 CheckServiceWorker(); |
| 396 } else if (params.fetch_valid_badge_icon && | 433 } else if (params.fetch_valid_badge_icon && |
| 397 !IsIconFetched(ParamsForBadgeIcon(params))) { | 434 !IsIconFetched(ParamsForBadgeIcon(params))) { |
| 398 CheckAndFetchBestIcon(ParamsForBadgeIcon(params)); | 435 CheckAndFetchBestIcon(ParamsForBadgeIcon(params)); |
| 399 } else { | 436 } else { |
| 400 NOTREACHED(); | 437 NOTREACHED(); |
| 401 } | 438 } |
| 402 } | 439 } |
| 403 | 440 |
| 404 void InstallableManager::FetchManifest() { | 441 void InstallableManager::FetchManifest() { |
| 405 DCHECK(!manifest_->fetched); | 442 DCHECK(!manifest_->fetched); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 424 SetManifestDependentTasksComplete(); | 461 SetManifestDependentTasksComplete(); |
| 425 } | 462 } |
| 426 | 463 |
| 427 manifest_->url = manifest_url; | 464 manifest_->url = manifest_url; |
| 428 manifest_->manifest = manifest; | 465 manifest_->manifest = manifest; |
| 429 manifest_->fetched = true; | 466 manifest_->fetched = true; |
| 430 WorkOnTask(); | 467 WorkOnTask(); |
| 431 } | 468 } |
| 432 | 469 |
| 433 void InstallableManager::CheckInstallable() { | 470 void InstallableManager::CheckInstallable() { |
| 434 DCHECK(!installable_->fetched); | 471 DCHECK(!valid_manifest_->fetched); |
| 435 DCHECK(!manifest().IsEmpty()); | 472 DCHECK(!manifest().IsEmpty()); |
| 436 | 473 |
| 437 if (IsManifestValidForWebApp(manifest())) { | 474 valid_manifest_->is_valid = IsManifestValidForWebApp(manifest()); |
| 438 CheckServiceWorker(); | 475 valid_manifest_->fetched = true; |
| 439 } else { | 476 WorkOnTask(); |
| 440 installable_->installable = false; | |
| 441 installable_->fetched = true; | |
| 442 WorkOnTask(); | |
| 443 } | |
| 444 } | 477 } |
| 445 | 478 |
| 446 bool InstallableManager::IsManifestValidForWebApp( | 479 bool InstallableManager::IsManifestValidForWebApp( |
| 447 const content::Manifest& manifest) { | 480 const content::Manifest& manifest) { |
| 448 if (manifest.IsEmpty()) { | 481 if (manifest.IsEmpty()) { |
| 449 installable_->error = MANIFEST_EMPTY; | 482 valid_manifest_->error = MANIFEST_EMPTY; |
| 450 return false; | 483 return false; |
| 451 } | 484 } |
| 452 | 485 |
| 453 if (!manifest.start_url.is_valid()) { | 486 if (!manifest.start_url.is_valid()) { |
| 454 installable_->error = START_URL_NOT_VALID; | 487 valid_manifest_->error = START_URL_NOT_VALID; |
| 455 return false; | 488 return false; |
| 456 } | 489 } |
| 457 | 490 |
| 458 if ((manifest.name.is_null() || manifest.name.string().empty()) && | 491 if ((manifest.name.is_null() || manifest.name.string().empty()) && |
| 459 (manifest.short_name.is_null() || manifest.short_name.string().empty())) { | 492 (manifest.short_name.is_null() || manifest.short_name.string().empty())) { |
| 460 installable_->error = MANIFEST_MISSING_NAME_OR_SHORT_NAME; | 493 valid_manifest_->error = MANIFEST_MISSING_NAME_OR_SHORT_NAME; |
| 461 return false; | 494 return false; |
| 462 } | 495 } |
| 463 | 496 |
| 464 // TODO(dominickn,mlamouri): when Chrome supports "minimal-ui", it should be | 497 // 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 | 498 // accepted. If we accept it today, it would fallback to "browser" and make |
| 466 // this check moot. See https://crbug.com/604390. | 499 // this check moot. See https://crbug.com/604390. |
| 467 if (manifest.display != blink::kWebDisplayModeStandalone && | 500 if (manifest.display != blink::kWebDisplayModeStandalone && |
| 468 manifest.display != blink::kWebDisplayModeFullscreen) { | 501 manifest.display != blink::kWebDisplayModeFullscreen) { |
| 469 installable_->error = MANIFEST_DISPLAY_NOT_SUPPORTED; | 502 valid_manifest_->error = MANIFEST_DISPLAY_NOT_SUPPORTED; |
| 470 return false; | 503 return false; |
| 471 } | 504 } |
| 472 | 505 |
| 473 if (!DoesManifestContainRequiredIcon(manifest)) { | 506 if (!DoesManifestContainRequiredIcon(manifest)) { |
| 474 installable_->error = MANIFEST_MISSING_SUITABLE_ICON; | 507 valid_manifest_->error = MANIFEST_MISSING_SUITABLE_ICON; |
| 475 return false; | 508 return false; |
| 476 } | 509 } |
| 477 | 510 |
| 478 return true; | 511 return true; |
| 479 } | 512 } |
| 480 | 513 |
| 481 void InstallableManager::CheckServiceWorker() { | 514 void InstallableManager::CheckServiceWorker() { |
| 482 DCHECK(!installable_->fetched); | 515 DCHECK(!worker_->fetched); |
| 483 DCHECK(!manifest().IsEmpty()); | 516 DCHECK(!manifest().IsEmpty()); |
| 484 DCHECK(manifest().start_url.is_valid()); | 517 DCHECK(manifest().start_url.is_valid()); |
| 485 | 518 |
| 486 content::WebContents* web_contents = GetWebContents(); | |
| 487 | |
| 488 // Check to see if there is a single service worker controlling this page | 519 // Check to see if there is a single service worker controlling this page |
| 489 // and the manifest's start url. | 520 // and the manifest's start url. |
| 490 content::StoragePartition* storage_partition = | 521 service_worker_context_->CheckHasServiceWorker( |
| 491 content::BrowserContext::GetStoragePartition( | 522 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, | 523 base::Bind(&InstallableManager::OnDidCheckHasServiceWorker, |
| 499 weak_factory_.GetWeakPtr())); | 524 weak_factory_.GetWeakPtr())); |
| 500 } | 525 } |
| 501 | 526 |
| 502 void InstallableManager::OnDidCheckHasServiceWorker( | 527 void InstallableManager::OnDidCheckHasServiceWorker( |
| 503 content::ServiceWorkerCapability capability) { | 528 content::ServiceWorkerCapability capability) { |
| 504 if (!GetWebContents()) | 529 if (!GetWebContents()) |
| 505 return; | 530 return; |
| 506 | 531 |
| 507 switch (capability) { | 532 switch (capability) { |
| 508 case content::ServiceWorkerCapability::SERVICE_WORKER_WITH_FETCH_HANDLER: | 533 case content::ServiceWorkerCapability::SERVICE_WORKER_WITH_FETCH_HANDLER: |
| 509 installable_->installable = true; | 534 worker_->has_worker = true; |
| 510 break; | 535 break; |
| 511 case content::ServiceWorkerCapability::SERVICE_WORKER_NO_FETCH_HANDLER: | 536 case content::ServiceWorkerCapability::SERVICE_WORKER_NO_FETCH_HANDLER: |
| 512 installable_->installable = false; | 537 worker_->has_worker = false; |
| 513 installable_->error = NOT_OFFLINE_CAPABLE; | 538 worker_->error = NOT_OFFLINE_CAPABLE; |
| 514 break; | 539 break; |
| 515 case content::ServiceWorkerCapability::NO_SERVICE_WORKER: | 540 case content::ServiceWorkerCapability::NO_SERVICE_WORKER: |
| 516 installable_->installable = false; | 541 InstallableParams& params = tasks_[0].first; |
| 517 installable_->error = NO_MATCHING_SERVICE_WORKER; | 542 if (params.wait_for_worker) { |
| 543 // Wait for ServiceWorkerContextObserver::OnRegistrationStored. Set the |
| 544 // param |wait_for_worker| to false so we only wait once per task. |
| 545 params.wait_for_worker = false; |
| 546 worker_->is_waiting = true; |
| 547 return; |
| 548 } |
| 549 worker_->has_worker = false; |
| 550 worker_->error = NO_MATCHING_SERVICE_WORKER; |
| 518 break; | 551 break; |
| 519 } | 552 } |
| 520 | 553 |
| 521 installable_->fetched = true; | 554 worker_->fetched = true; |
| 522 WorkOnTask(); | 555 WorkOnTask(); |
| 523 } | 556 } |
| 524 | 557 |
| 525 void InstallableManager::CheckAndFetchBestIcon(const IconParams& params) { | 558 void InstallableManager::CheckAndFetchBestIcon(const IconParams& params) { |
| 526 DCHECK(!manifest().IsEmpty()); | 559 DCHECK(!manifest().IsEmpty()); |
| 527 | 560 |
| 528 int ideal_icon_size_in_px = std::get<0>(params); | 561 int ideal_icon_size_in_px = std::get<0>(params); |
| 529 int minimum_icon_size_in_px = std::get<1>(params); | 562 int minimum_icon_size_in_px = std::get<1>(params); |
| 530 IconPurpose icon_purpose = std::get<2>(params); | 563 IconPurpose icon_purpose = std::get<2>(params); |
| 531 | 564 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 562 if (bitmap.drawsNothing()) { | 595 if (bitmap.drawsNothing()) { |
| 563 icon.error = NO_ICON_AVAILABLE; | 596 icon.error = NO_ICON_AVAILABLE; |
| 564 } else { | 597 } else { |
| 565 icon.url = icon_url; | 598 icon.url = icon_url; |
| 566 icon.icon.reset(new SkBitmap(bitmap)); | 599 icon.icon.reset(new SkBitmap(bitmap)); |
| 567 } | 600 } |
| 568 | 601 |
| 569 WorkOnTask(); | 602 WorkOnTask(); |
| 570 } | 603 } |
| 571 | 604 |
| 605 void InstallableManager::OnRegistrationStored(const GURL& pattern) { |
| 606 // We aren't currently waiting, so either: |
| 607 // a) we've already failed the check, or |
| 608 // b) we haven't yet called CheckHasServiceWorker. |
| 609 if (!worker_->is_waiting || !content::ServiceWorkerContext::ScopeMatches( |
| 610 pattern, manifest().start_url)) { |
| 611 return; |
| 612 } |
| 613 |
| 614 // This will call CheckHasServiceWorker to check whether the service worker |
| 615 // controls the start_url and if it has a fetch handler. |
| 616 worker_->is_waiting = false; |
| 617 WorkOnTask(); |
| 618 } |
| 619 |
| 572 void InstallableManager::DidFinishNavigation( | 620 void InstallableManager::DidFinishNavigation( |
| 573 content::NavigationHandle* handle) { | 621 content::NavigationHandle* handle) { |
| 574 if (handle->IsInMainFrame() && handle->HasCommitted() && | 622 if (handle->IsInMainFrame() && handle->HasCommitted() && |
| 575 !handle->IsSameDocument()) { | 623 !handle->IsSameDocument()) { |
| 576 Reset(); | 624 Reset(); |
| 577 } | 625 } |
| 578 } | 626 } |
| 579 | 627 |
| 580 void InstallableManager::WebContentsDestroyed() { | 628 void InstallableManager::WebContentsDestroyed() { |
| 581 Reset(); | 629 Reset(); |
| 582 Observe(nullptr); | 630 Observe(nullptr); |
| 583 } | 631 } |
| 584 | 632 |
| 585 const GURL& InstallableManager::manifest_url() const { | 633 const GURL& InstallableManager::manifest_url() const { |
| 586 return manifest_->url; | 634 return manifest_->url; |
| 587 } | 635 } |
| 588 | 636 |
| 589 const content::Manifest& InstallableManager::manifest() const { | 637 const content::Manifest& InstallableManager::manifest() const { |
| 590 return manifest_->manifest; | 638 return manifest_->manifest; |
| 591 } | 639 } |
| 592 | 640 |
| 593 bool InstallableManager::is_installable() const { | 641 bool InstallableManager::is_installable() const { |
| 594 return installable_->installable; | 642 return valid_manifest_->is_valid && worker_->has_worker; |
| 595 } | 643 } |
| OLD | NEW |