Chromium Code Reviews| Index: chrome/browser/banners/app_banner_manager.cc |
| diff --git a/chrome/browser/banners/app_banner_manager.cc b/chrome/browser/banners/app_banner_manager.cc |
| index 2757f5cb5ac99beb1a0576bea768ebea3d80836d..a55e8e60093a51be621c17ef9a97e1d0c1cc156c 100644 |
| --- a/chrome/browser/banners/app_banner_manager.cc |
| +++ b/chrome/browser/banners/app_banner_manager.cc |
| @@ -93,15 +93,25 @@ bool AppBannerManager::URLsAreForTheSamePage(const GURL& first, |
| void AppBannerManager::RequestAppBanner(const GURL& validated_url, |
| bool is_debug_mode) { |
| + // Don't start a redundant banner request. Otherwise, if one is running, |
| + // invalidate our weak pointers so it terminates. |
| content::WebContents* contents = web_contents(); |
| - if (contents->GetMainFrame()->GetParent()) { |
| - ReportError(contents, NOT_IN_MAIN_FRAME); |
| - return; |
| + if (is_active_) { |
| + if (URLsAreForTheSamePage(validated_url, contents->GetLastCommittedURL())) |
| + return; |
| + else |
| + weak_factory_.InvalidateWeakPtrs(); |
| } |
| - // Don't start a redundant banner request. |
| - if (is_active_ && |
| - URLsAreForTheSamePage(validated_url, contents->GetLastCommittedURL())) { |
| + is_active_ = true; |
| + is_debug_mode_ = is_debug_mode; |
| + |
| + DCHECK(!need_to_log_status_); |
| + need_to_log_status_ = !IsDebugMode(); |
| + |
| + if (contents->GetMainFrame()->GetParent()) { |
| + ReportStatus(contents, NOT_IN_MAIN_FRAME); |
| + Stop(); |
| return; |
| } |
| @@ -109,15 +119,11 @@ void AppBannerManager::RequestAppBanner(const GURL& validated_url, |
| // URL is invalid. |
| if (!content::IsOriginSecure(validated_url) && |
| !gDisableSecureCheckForTesting) { |
| - ReportError(contents, NOT_FROM_SECURE_ORIGIN); |
| + ReportStatus(contents, NOT_FROM_SECURE_ORIGIN); |
| + Stop(); |
| return; |
| } |
| - is_debug_mode_ = is_debug_mode; |
| - is_active_ = true; |
| - |
| - // We start by requesting the manifest from the InstallableManager. The |
| - // default-constructed params will have all other fields as false. |
| manager_->GetData( |
| ParamsToGetManifest(), |
| base::Bind(&AppBannerManager::OnDidGetManifest, GetWeakPtr())); |
| @@ -139,6 +145,7 @@ AppBannerManager::AppBannerManager(content::WebContents* web_contents) |
| was_canceled_by_page_(false), |
| page_requested_prompt_(false), |
| is_debug_mode_(false), |
| + need_to_log_status_(false), |
| weak_factory_(this) { |
| // Ensure the InstallableManager exists since we have a hard dependency on it. |
| InstallableManager::CreateForWebContents(web_contents); |
| @@ -159,7 +166,7 @@ std::string AppBannerManager::GetBannerType() { |
| return "web"; |
| } |
| -std::string AppBannerManager::GetErrorParam(InstallableErrorCode code) { |
| +std::string AppBannerManager::GetStatusParam(InstallableStatusCode code) { |
| if (code == NO_ACCEPTABLE_ICON || code == MANIFEST_MISSING_SUITABLE_ICON) { |
| return base::IntToString(InstallableManager::GetMinimumIconSizeInPx()); |
| } |
| @@ -195,7 +202,7 @@ bool AppBannerManager::IsWebAppInstalled( |
| void AppBannerManager::OnDidGetManifest(const InstallableData& data) { |
| if (data.error_code != NO_ERROR_DETECTED) { |
| - ReportError(web_contents(), data.error_code); |
| + ReportStatus(web_contents(), data.error_code); |
| Stop(); |
| } |
| @@ -217,6 +224,7 @@ void AppBannerManager::PerformInstallableCheck() { |
| if (IsWebAppInstalled(web_contents()->GetBrowserContext(), |
| manifest_.start_url) && |
| !IsDebugMode()) { |
| + ReportStatus(web_contents(), ALREADY_INSTALLED); |
| Stop(); |
| } |
| @@ -239,7 +247,7 @@ void AppBannerManager::OnDidPerformInstallableCheck( |
| if (data.error_code == NO_MATCHING_SERVICE_WORKER) |
| TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER); |
| - ReportError(web_contents(), data.error_code); |
| + ReportStatus(web_contents(), data.error_code); |
| Stop(); |
| } |
| @@ -269,21 +277,37 @@ void AppBannerManager::RecordDidShowBanner(const std::string& event_name) { |
| contents->GetLastCommittedURL()); |
| } |
| -void AppBannerManager::ReportError(content::WebContents* web_contents, |
| - InstallableErrorCode code) { |
| - if (IsDebugMode()) |
| - LogErrorToConsole(web_contents, code, GetErrorParam(code)); |
| +void AppBannerManager::ReportStatus(content::WebContents* web_contents, |
| + InstallableStatusCode code) { |
| + if (IsDebugMode()) { |
| + LogErrorToConsole(web_contents, code, GetStatusParam(code)); |
| + } else { |
| + // Ensure that we haven't yet logged a status code for this page. Only |
| + // log status for pages where we are not in debug mode to avoid skew. |
| + DCHECK(need_to_log_status_); |
| + TrackInstallableStatusCode(code); |
| + need_to_log_status_ = false; |
| + } |
| } |
| void AppBannerManager::Stop() { |
| if (was_canceled_by_page_ && !page_requested_prompt_) { |
| TrackBeforeInstallEvent( |
| BEFORE_INSTALL_EVENT_PROMPT_NOT_CALLED_AFTER_PREVENT_DEFAULT); |
| + ReportStatus(web_contents(), RENDERER_CANCELLED); |
| } |
| + // Ensure that we've either logged an InstallableStatusCode, or that we're |
| + // still active and waiting for a callback, or that we're in debug mode. The |
| + // final time a status is logged is within the platform-specific ShowBanner() |
| + // implementations, and is_active_ is not reset until those have run and |
| + // logged a status. |
| + DCHECK(!need_to_log_status_ || is_active_ || IsDebugMode()); |
| + |
| is_active_ = false; |
| was_canceled_by_page_ = false; |
| page_requested_prompt_ = false; |
| + need_to_log_status_ = false; |
|
benwells
2016/08/11 07:14:23
I don't understand how this works - won't the DCHE
dominickn
2016/08/11 08:13:38
need_to_log_status_ is set to true in RequestAppBa
benwells
2016/08/12 01:34:23
OK, as discussed offline there might be some subtl
|
| referrer_.erase(); |
| } |
| @@ -292,11 +316,10 @@ void AppBannerManager::SendBannerPromptRequest() { |
| // Given all of the other checks that have been made, the only possible reason |
| // for stopping now is that the app has been added to the homescreen. |
| - if (!IsDebugMode() && !CheckIfShouldShowBanner()) |
| + if (!IsDebugMode() && !CheckIfShouldShowBanner()) { |
|
benwells
2016/08/11 07:14:23
Why is this changing?
dominickn
2016/08/11 08:13:38
The only way is_active_ will be false here is if S
|
| Stop(); |
| - |
| - if (!is_active_) |
| return; |
| + } |
| TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_CREATED); |
| event_request_id_ = ++gCurrentRequestID; |
| @@ -367,19 +390,20 @@ void AppBannerManager::OnEngagementIncreased(content::WebContents* contents, |
| // 1. engagement increased for the web contents which we are attached to; and |
| // 2. there are no currently active media players; and |
| // 3. we have accumulated sufficient engagement. |
| - if (web_contents() == contents && active_media_players_.empty() && |
| - AppBannerSettingsHelper::HasSufficientEngagement(score)) { |
| - // Stop observing so we don't double-trigger the banner. |
| - SiteEngagementObserver::Observe(nullptr); |
| - |
| - if (!load_finished_) { |
| - // Wait until the main frame finishes loading before requesting a banner. |
| - banner_request_queued_ = true; |
| - } else { |
| - // Requesting a banner performs some simple tests, creates a data fetcher, |
| - // and starts some asynchronous checks to test installability. It should |
| - // be safe to start this in response to user input. |
| - RequestAppBanner(url, false /* is_debug_mode */); |
| + if (web_contents() == contents && active_media_players_.empty()) { |
| + if (AppBannerSettingsHelper::HasSufficientEngagement(score)) { |
|
benwells
2016/08/11 07:14:23
Why is this changing?
dominickn
2016/08/11 08:13:38
Ah, I had a ReportStatus branch here that was remo
|
| + // Stop observing so we don't double-trigger the banner. |
| + SiteEngagementObserver::Observe(nullptr); |
| + |
| + if (!load_finished_) { |
| + // Queue the banner request until the main frame finishes loading. |
| + banner_request_queued_ = true; |
| + } else { |
| + // A banner request performs some simple tests, creates a data fetcher, |
| + // and starts some asynchronous checks to test installability. It should |
| + // be safe to start this in response to user input. |
| + RequestAppBanner(url, false /* is_debug_mode */); |
| + } |
| } |
| } |
| } |
| @@ -397,8 +421,14 @@ bool AppBannerManager::CheckIfShouldShowBanner() { |
| content::WebContents* contents = web_contents(); |
| DCHECK(contents); |
| - return AppBannerSettingsHelper::ShouldShowBanner( |
| + InstallableStatusCode code = AppBannerSettingsHelper::ShouldShowBanner( |
| contents, validated_url_, GetAppIdentifier(), GetCurrentTime()); |
| + if (code == NO_ERROR_DETECTED) |
| + return true; |
| + |
| + DCHECK(!IsDebugMode()); |
|
benwells
2016/08/11 07:14:23
Could you have a comment explaining why this DCHEC
dominickn
2016/08/11 08:13:38
Done.
|
| + ReportStatus(web_contents(), code); |
| + return false; |
| } |
| bool AppBannerManager::OnMessageReceived( |
| @@ -439,7 +469,6 @@ void AppBannerManager::OnBannerPromptReply( |
| !page_requested_prompt_) { |
| TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_PREVENT_DEFAULT_CALLED); |
| was_canceled_by_page_ = true; |
| - ReportError(contents, RENDERER_CANCELLED); |
| return; |
| } |
| @@ -461,6 +490,7 @@ void AppBannerManager::OnBannerPromptReply( |
| DCHECK(!manifest_.IsEmpty()); |
| DCHECK(!icon_url_.is_empty()); |
| DCHECK(icon_.get()); |
| + |
| TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_COMPLETE); |
| ShowBanner(); |
| is_active_ = false; |