| 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..48c676a2f8f0606188ba6003ee20d2fa0ca382dd 100644
|
| --- a/chrome/browser/banners/app_banner_manager.cc
|
| +++ b/chrome/browser/banners/app_banner_manager.cc
|
| @@ -93,15 +93,27 @@ 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;
|
| +
|
| + // We only need to call ReportStatus if we aren't in debug mode (this avoids
|
| + // skew from testing).
|
| + DCHECK(!need_to_log_status_);
|
| + need_to_log_status_ = !IsDebugMode();
|
| +
|
| + if (contents->GetMainFrame()->GetParent()) {
|
| + ReportStatus(contents, NOT_IN_MAIN_FRAME);
|
| + Stop();
|
| return;
|
| }
|
|
|
| @@ -109,15 +121,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 +147,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 +168,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 +204,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 +226,7 @@ void AppBannerManager::PerformInstallableCheck() {
|
| if (IsWebAppInstalled(web_contents()->GetBrowserContext(),
|
| manifest_.start_url) &&
|
| !IsDebugMode()) {
|
| + ReportStatus(web_contents(), ALREADY_INSTALLED);
|
| Stop();
|
| }
|
|
|
| @@ -239,7 +249,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 +279,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.
|
| + 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);
|
| }
|
|
|
| + // In every non-debug run through the banner pipeline, we should have called
|
| + // ReportStatus() and set need_to_log_status_ to false. The only case where
|
| + // we don't is if we're still active and waiting for a callback from the
|
| + // InstallableManager (e.g. the renderer crashes or the browser is shutting
|
| + // down). These situations are explicitly not logged.
|
| + DCHECK(!need_to_log_status_ || is_active_);
|
| +
|
| + weak_factory_.InvalidateWeakPtrs();
|
| is_active_ = false;
|
| was_canceled_by_page_ = false;
|
| page_requested_prompt_ = false;
|
| + need_to_log_status_ = false;
|
| referrer_.erase();
|
| }
|
|
|
| @@ -292,11 +318,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()) {
|
| Stop();
|
| -
|
| - if (!is_active_)
|
| return;
|
| + }
|
|
|
| TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_CREATED);
|
| event_request_id_ = ++gCurrentRequestID;
|
| @@ -373,10 +398,10 @@ void AppBannerManager::OnEngagementIncreased(content::WebContents* contents,
|
| SiteEngagementObserver::Observe(nullptr);
|
|
|
| if (!load_finished_) {
|
| - // Wait until the main frame finishes loading before requesting a banner.
|
| + // Queue the banner request until the main frame finishes loading.
|
| banner_request_queued_ = true;
|
| } else {
|
| - // Requesting a banner performs some simple tests, creates a data fetcher,
|
| + // 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 +422,17 @@ 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;
|
| +
|
| + // If we are in debug mode, AppBannerSettingsHelper::ShouldShowBanner must
|
| + // return NO_ERROR_DETECTED (bypass flag is set) or we must not have entered
|
| + // this method.
|
| + DCHECK(!IsDebugMode());
|
| + ReportStatus(web_contents(), code);
|
| + return false;
|
| }
|
|
|
| bool AppBannerManager::OnMessageReceived(
|
| @@ -439,7 +473,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 +494,7 @@ void AppBannerManager::OnBannerPromptReply(
|
| DCHECK(!manifest_.IsEmpty());
|
| DCHECK(!icon_url_.is_empty());
|
| DCHECK(icon_.get());
|
| +
|
| TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_COMPLETE);
|
| ShowBanner();
|
| is_active_ = false;
|
|
|