| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/banners/app_banner_manager.h" | 5 #include "chrome/browser/banners/app_banner_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 namespace { | 31 namespace { |
| 32 | 32 |
| 33 int gCurrentRequestID = -1; | 33 int gCurrentRequestID = -1; |
| 34 int gTimeDeltaInDaysForTesting = 0; | 34 int gTimeDeltaInDaysForTesting = 0; |
| 35 | 35 |
| 36 InstallableParams ParamsToGetManifest() { | 36 InstallableParams ParamsToGetManifest() { |
| 37 return InstallableParams(); | 37 return InstallableParams(); |
| 38 } | 38 } |
| 39 | 39 |
| 40 // Returns whether or not the URLs match for everything except for the ref. | |
| 41 bool URLsAreForTheSamePage(const GURL& first, const GURL& second) { | |
| 42 return first.GetWithEmptyPath() == second.GetWithEmptyPath() && | |
| 43 first.path_piece() == second.path_piece() && | |
| 44 first.query_piece() == second.query_piece(); | |
| 45 } | |
| 46 | |
| 47 } // anonymous namespace | 40 } // anonymous namespace |
| 48 | 41 |
| 49 namespace banners { | 42 namespace banners { |
| 50 | 43 |
| 51 // static | 44 // static |
| 52 base::Time AppBannerManager::GetCurrentTime() { | 45 base::Time AppBannerManager::GetCurrentTime() { |
| 53 return base::Time::Now() + | 46 return base::Time::Now() + |
| 54 base::TimeDelta::FromDays(gTimeDeltaInDaysForTesting); | 47 base::TimeDelta::FromDays(gTimeDeltaInDaysForTesting); |
| 55 } | 48 } |
| 56 | 49 |
| 57 // static | 50 // static |
| 58 void AppBannerManager::SetTimeDeltaForTesting(int days) { | 51 void AppBannerManager::SetTimeDeltaForTesting(int days) { |
| 59 gTimeDeltaInDaysForTesting = days; | 52 gTimeDeltaInDaysForTesting = days; |
| 60 } | 53 } |
| 61 | 54 |
| 62 // static | 55 // static |
| 63 void AppBannerManager::SetTotalEngagementToTrigger(double engagement) { | 56 void AppBannerManager::SetTotalEngagementToTrigger(double engagement) { |
| 64 AppBannerSettingsHelper::SetTotalEngagementToTrigger(engagement); | 57 AppBannerSettingsHelper::SetTotalEngagementToTrigger(engagement); |
| 65 } | 58 } |
| 66 | 59 |
| 67 void AppBannerManager::RequestAppBanner(const GURL& validated_url, | 60 void AppBannerManager::RequestAppBanner(const GURL& validated_url, |
| 68 bool is_debug_mode) { | 61 bool is_debug_mode) { |
| 69 content::WebContents* contents = web_contents(); | 62 content::WebContents* contents = web_contents(); |
| 70 | 63 |
| 71 // Don't start a redundant banner request. Otherwise, if one is running, | 64 // The only time we should start the pipeline while it is already running is |
| 72 // invalidate our weak pointers so it terminates. | 65 // if it's been triggered from devtools. |
| 73 if (is_active()) { | 66 if (is_active_or_pending()) { |
| 74 if (URLsAreForTheSamePage(validated_url, contents->GetLastCommittedURL())) | 67 DCHECK(is_debug_mode); |
| 75 return; | 68 weak_factory_.InvalidateWeakPtrs(); |
| 76 else | |
| 77 weak_factory_.InvalidateWeakPtrs(); | |
| 78 } | 69 } |
| 79 | 70 |
| 80 UpdateState(State::ACTIVE); | 71 UpdateState(State::ACTIVE); |
| 81 triggered_by_devtools_ = is_debug_mode; | 72 triggered_by_devtools_ = is_debug_mode; |
| 82 page_requested_prompt_ = false; | 73 page_requested_prompt_ = false; |
| 83 | 74 |
| 84 // We only need to call ReportStatus if we aren't in debug mode (this avoids | 75 // We only need to call ReportStatus if we aren't in debug mode (this avoids |
| 85 // skew from testing). | 76 // skew from testing). |
| 86 DCHECK(!need_to_log_status_); | 77 DCHECK(!need_to_log_status_); |
| 87 need_to_log_status_ = !IsDebugMode(); | 78 need_to_log_status_ = !IsDebugMode(); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 const GURL& start_url, | 195 const GURL& start_url, |
| 205 const GURL& manifest_url) { | 196 const GURL& manifest_url) { |
| 206 return false; | 197 return false; |
| 207 } | 198 } |
| 208 | 199 |
| 209 void AppBannerManager::OnDidGetManifest(const InstallableData& data) { | 200 void AppBannerManager::OnDidGetManifest(const InstallableData& data) { |
| 210 UpdateState(State::ACTIVE); | 201 UpdateState(State::ACTIVE); |
| 211 if (data.error_code != NO_ERROR_DETECTED) { | 202 if (data.error_code != NO_ERROR_DETECTED) { |
| 212 ReportStatus(web_contents(), data.error_code); | 203 ReportStatus(web_contents(), data.error_code); |
| 213 Stop(); | 204 Stop(); |
| 205 return; |
| 214 } | 206 } |
| 215 | 207 |
| 216 if (!is_active()) | |
| 217 return; | |
| 218 | |
| 219 DCHECK(!data.manifest_url.is_empty()); | 208 DCHECK(!data.manifest_url.is_empty()); |
| 220 DCHECK(!data.manifest.IsEmpty()); | 209 DCHECK(!data.manifest.IsEmpty()); |
| 221 | 210 |
| 222 manifest_url_ = data.manifest_url; | 211 manifest_url_ = data.manifest_url; |
| 223 manifest_ = data.manifest; | 212 manifest_ = data.manifest; |
| 224 | 213 |
| 225 // One of manifest_.name or manifest_.short_name must be non-null and | 214 // One of manifest_.name or manifest_.short_name must be non-null and |
| 226 // non-empty if the error code was NO_ERROR_DETECTED. | 215 // non-empty if the error code was NO_ERROR_DETECTED. |
| 227 if (manifest_.name.is_null() || manifest_.name.string().empty()) | 216 if (manifest_.name.is_null() || manifest_.name.string().empty()) |
| 228 app_title_ = manifest_.short_name.string(); | 217 app_title_ = manifest_.short_name.string(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 UpdateState(State::ACTIVE); | 250 UpdateState(State::ACTIVE); |
| 262 if (data.is_installable) | 251 if (data.is_installable) |
| 263 TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_REQUESTED); | 252 TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_REQUESTED); |
| 264 | 253 |
| 265 if (data.error_code != NO_ERROR_DETECTED) { | 254 if (data.error_code != NO_ERROR_DETECTED) { |
| 266 if (data.error_code == NO_MATCHING_SERVICE_WORKER) | 255 if (data.error_code == NO_MATCHING_SERVICE_WORKER) |
| 267 TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER); | 256 TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER); |
| 268 | 257 |
| 269 ReportStatus(web_contents(), data.error_code); | 258 ReportStatus(web_contents(), data.error_code); |
| 270 Stop(); | 259 Stop(); |
| 260 return; |
| 271 } | 261 } |
| 272 | 262 |
| 273 if (!is_active()) | |
| 274 return; | |
| 275 | |
| 276 DCHECK(data.is_installable); | 263 DCHECK(data.is_installable); |
| 277 DCHECK(!data.primary_icon_url.is_empty()); | 264 DCHECK(!data.primary_icon_url.is_empty()); |
| 278 DCHECK(data.primary_icon); | 265 DCHECK(data.primary_icon); |
| 279 | 266 |
| 280 primary_icon_url_ = data.primary_icon_url; | 267 primary_icon_url_ = data.primary_icon_url; |
| 281 primary_icon_ = *data.primary_icon; | 268 primary_icon_ = *data.primary_icon; |
| 282 | 269 |
| 283 // If we triggered the installability check on page load, then it's possible | 270 // If we triggered the installability check on page load, then it's possible |
| 284 // we don't have enough engagement yet. If that's the case, return here but | 271 // we don't have enough engagement yet. If that's the case, return here but |
| 285 // don't call Stop(). We wait for OnEngagementIncreased to tell us that we | 272 // don't call Stop(). We wait for OnEngagementIncreased to tell us that we |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 validated_url_ = validated_url; | 413 validated_url_ = validated_url; |
| 427 | 414 |
| 428 // If the bypass flag is on, or if we require no engagement to trigger the | 415 // If the bypass flag is on, or if we require no engagement to trigger the |
| 429 // banner, the rest of the banner pipeline should operate as if the engagement | 416 // banner, the rest of the banner pipeline should operate as if the engagement |
| 430 // threshold has been met. | 417 // threshold has been met. |
| 431 if (AppBannerSettingsHelper::HasSufficientEngagement(0)) | 418 if (AppBannerSettingsHelper::HasSufficientEngagement(0)) |
| 432 has_sufficient_engagement_ = true; | 419 has_sufficient_engagement_ = true; |
| 433 | 420 |
| 434 // Start the pipeline immediately if we pass (or bypass) the engagement check, | 421 // Start the pipeline immediately if we pass (or bypass) the engagement check, |
| 435 // or if the feature to run the installability check on page load is enabled. | 422 // or if the feature to run the installability check on page load is enabled. |
| 436 if (has_sufficient_engagement_ || | 423 if (!is_active_or_pending() && |
| 437 base::FeatureList::IsEnabled( | 424 (has_sufficient_engagement_ || |
| 438 features::kCheckInstallabilityForBannerOnLoad)) { | 425 base::FeatureList::IsEnabled( |
| 426 features::kCheckInstallabilityForBannerOnLoad))) { |
| 439 RequestAppBanner(validated_url, false /* is_debug_mode */); | 427 RequestAppBanner(validated_url, false /* is_debug_mode */); |
| 440 } | 428 } |
| 441 } | 429 } |
| 442 | 430 |
| 443 void AppBannerManager::MediaStartedPlaying(const MediaPlayerInfo& media_info, | 431 void AppBannerManager::MediaStartedPlaying(const MediaPlayerInfo& media_info, |
| 444 const MediaPlayerId& id) { | 432 const MediaPlayerId& id) { |
| 445 active_media_players_.push_back(id); | 433 active_media_players_.push_back(id); |
| 446 } | 434 } |
| 447 | 435 |
| 448 void AppBannerManager::MediaStoppedPlaying(const MediaPlayerInfo& media_info, | 436 void AppBannerManager::MediaStoppedPlaying(const MediaPlayerInfo& media_info, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 471 // 3. we have accumulated sufficient engagement. | 459 // 3. we have accumulated sufficient engagement. |
| 472 if (web_contents() == contents && active_media_players_.empty() && | 460 if (web_contents() == contents && active_media_players_.empty() && |
| 473 AppBannerSettingsHelper::HasSufficientEngagement(score)) { | 461 AppBannerSettingsHelper::HasSufficientEngagement(score)) { |
| 474 has_sufficient_engagement_ = true; | 462 has_sufficient_engagement_ = true; |
| 475 | 463 |
| 476 if (is_pending_engagement()) { | 464 if (is_pending_engagement()) { |
| 477 // We have already finished the installability eligibility checks. Proceed | 465 // We have already finished the installability eligibility checks. Proceed |
| 478 // directly to sending the banner prompt request. | 466 // directly to sending the banner prompt request. |
| 479 UpdateState(State::ACTIVE); | 467 UpdateState(State::ACTIVE); |
| 480 SendBannerPromptRequest(); | 468 SendBannerPromptRequest(); |
| 481 } else if (load_finished_) { | 469 } else if (load_finished_ && !is_active_or_pending()) { |
| 482 // This performs some simple tests and starts async checks to test | 470 // This performs some simple tests and starts async checks to test |
| 483 // installability. It should be safe to start in response to user input. | 471 // installability. It should be safe to start in response to user input. |
| 472 // Don't call if we're already working on processing a banner request. |
| 484 RequestAppBanner(url, false /* is_debug_mode */); | 473 RequestAppBanner(url, false /* is_debug_mode */); |
| 485 } | 474 } |
| 486 } | 475 } |
| 487 } | 476 } |
| 488 | 477 |
| 489 void AppBannerManager::RecordCouldShowBanner() { | 478 void AppBannerManager::RecordCouldShowBanner() { |
| 490 content::WebContents* contents = web_contents(); | 479 content::WebContents* contents = web_contents(); |
| 491 DCHECK(contents); | 480 DCHECK(contents); |
| 492 | 481 |
| 493 AppBannerSettingsHelper::RecordBannerEvent( | 482 AppBannerSettingsHelper::RecordBannerEvent( |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 if (is_pending_event()) { | 576 if (is_pending_event()) { |
| 588 // Simulate a non-canceled OnBannerPromptReply to show the delayed banner. | 577 // Simulate a non-canceled OnBannerPromptReply to show the delayed banner. |
| 589 OnBannerPromptReply(blink::mojom::AppBannerPromptReply::NONE, referrer_); | 578 OnBannerPromptReply(blink::mojom::AppBannerPromptReply::NONE, referrer_); |
| 590 } else { | 579 } else { |
| 591 // Log that the prompt request was made for when we get the prompt reply. | 580 // Log that the prompt request was made for when we get the prompt reply. |
| 592 page_requested_prompt_ = true; | 581 page_requested_prompt_ = true; |
| 593 } | 582 } |
| 594 } | 583 } |
| 595 | 584 |
| 596 } // namespace banners | 585 } // namespace banners |
| OLD | NEW |