| 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> |
| 8 |
| 7 #include "base/bind.h" | 9 #include "base/bind.h" |
| 8 #include "base/callback.h" | 10 #include "base/callback.h" |
| 9 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/lazy_instance.h" |
| 10 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 12 #include "chrome/browser/banners/app_banner_metrics.h" | 15 #include "chrome/browser/banners/app_banner_metrics.h" |
| 13 #include "chrome/browser/banners/app_banner_settings_helper.h" | 16 #include "chrome/browser/banners/app_banner_settings_helper.h" |
| 14 #include "chrome/browser/browser_process.h" | 17 #include "chrome/browser/browser_process.h" |
| 15 #include "chrome/browser/engagement/site_engagement_service.h" | 18 #include "chrome/browser/engagement/site_engagement_service.h" |
| 16 #include "chrome/browser/installable/installable_logging.h" | |
| 17 #include "chrome/browser/installable/installable_manager.h" | |
| 18 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
| 19 #include "chrome/common/chrome_switches.h" | 20 #include "chrome/common/chrome_switches.h" |
| 20 #include "chrome/common/render_messages.h" | |
| 21 #include "components/rappor/rappor_utils.h" | 21 #include "components/rappor/rappor_utils.h" |
| 22 #include "content/public/browser/navigation_handle.h" | 22 #include "content/public/browser/navigation_handle.h" |
| 23 #include "content/public/browser/render_frame_host.h" | 23 #include "content/public/browser/render_frame_host.h" |
| 24 #include "content/public/browser/web_contents.h" | 24 #include "content/public/browser/web_contents.h" |
| 25 #include "content/public/common/origin_util.h" | 25 #include "content/public/common/origin_util.h" |
| 26 #include "third_party/WebKit/public/platform/modules/app_banner/WebAppBannerProm
ptReply.h" | 26 #include "mojo/public/cpp/bindings/interface_request.h" |
| 27 #include "services/shell/public/cpp/interface_provider.h" |
| 27 #include "third_party/skia/include/core/SkBitmap.h" | 28 #include "third_party/skia/include/core/SkBitmap.h" |
| 28 #include "ui/display/display.h" | 29 #include "ui/display/display.h" |
| 29 #include "ui/display/screen.h" | 30 #include "ui/display/screen.h" |
| 30 | 31 |
| 31 namespace { | 32 namespace { |
| 32 | 33 |
| 33 bool gDisableSecureCheckForTesting = false; | 34 bool gDisableSecureCheckForTesting = false; |
| 34 int gCurrentRequestID = -1; | 35 int gCurrentRequestID = -1; |
| 35 base::LazyInstance<base::TimeDelta> gTimeDeltaForTesting = | 36 base::LazyInstance<base::TimeDelta> gTimeDeltaForTesting = |
| 36 LAZY_INSTANCE_INITIALIZER; | 37 LAZY_INSTANCE_INITIALIZER; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 | 120 |
| 120 // A secure origin is required to show banners, so exit early if we see the | 121 // A secure origin is required to show banners, so exit early if we see the |
| 121 // URL is invalid. | 122 // URL is invalid. |
| 122 if (!content::IsOriginSecure(validated_url) && | 123 if (!content::IsOriginSecure(validated_url) && |
| 123 !gDisableSecureCheckForTesting) { | 124 !gDisableSecureCheckForTesting) { |
| 124 ReportStatus(contents, NOT_FROM_SECURE_ORIGIN); | 125 ReportStatus(contents, NOT_FROM_SECURE_ORIGIN); |
| 125 Stop(); | 126 Stop(); |
| 126 return; | 127 return; |
| 127 } | 128 } |
| 128 | 129 |
| 130 // Any existing binding is invalid if we re-request the banner. |
| 131 if (binding_.is_bound()) |
| 132 binding_.Close(); |
| 133 |
| 129 manager_->GetData( | 134 manager_->GetData( |
| 130 ParamsToGetManifest(), | 135 ParamsToGetManifest(), |
| 131 base::Bind(&AppBannerManager::OnDidGetManifest, GetWeakPtr())); | 136 base::Bind(&AppBannerManager::OnDidGetManifest, GetWeakPtr())); |
| 132 } | 137 } |
| 133 | 138 |
| 139 void AppBannerManager::SendBannerAccepted(int request_id) { |
| 140 if (request_id != gCurrentRequestID) |
| 141 return; |
| 142 |
| 143 DCHECK(event_.is_bound()); |
| 144 event_->BannerAccepted(GetBannerType()); |
| 145 } |
| 146 |
| 147 void AppBannerManager::SendBannerDismissed(int request_id) { |
| 148 if (request_id != gCurrentRequestID) |
| 149 return; |
| 150 |
| 151 DCHECK(event_.is_bound()); |
| 152 event_->BannerDismissed(); |
| 153 } |
| 154 |
| 134 base::Closure AppBannerManager::FetchWebappSplashScreenImageCallback( | 155 base::Closure AppBannerManager::FetchWebappSplashScreenImageCallback( |
| 135 const std::string& webapp_id) { | 156 const std::string& webapp_id) { |
| 136 return base::Closure(); | 157 return base::Closure(); |
| 137 } | 158 } |
| 138 | 159 |
| 139 AppBannerManager::AppBannerManager(content::WebContents* web_contents) | 160 AppBannerManager::AppBannerManager(content::WebContents* web_contents) |
| 140 : content::WebContentsObserver(web_contents), | 161 : content::WebContentsObserver(web_contents), |
| 141 SiteEngagementObserver(nullptr), | 162 SiteEngagementObserver(nullptr), |
| 142 manager_(nullptr), | 163 manager_(nullptr), |
| 143 event_request_id_(-1), | 164 event_request_id_(-1), |
| 165 binding_(this), |
| 144 is_active_(false), | 166 is_active_(false), |
| 145 banner_request_queued_(false), | 167 banner_request_queued_(false), |
| 146 load_finished_(false), | 168 load_finished_(false), |
| 147 was_canceled_by_page_(false), | 169 was_canceled_by_page_(false), |
| 148 page_requested_prompt_(false), | 170 page_requested_prompt_(false), |
| 149 is_debug_mode_(false), | 171 is_debug_mode_(false), |
| 150 need_to_log_status_(false), | 172 need_to_log_status_(false), |
| 151 weak_factory_(this) { | 173 weak_factory_(this) { |
| 152 // Ensure the InstallableManager exists since we have a hard dependency on it. | 174 // Ensure the InstallableManager exists since we have a hard dependency on it. |
| 153 InstallableManager::CreateForWebContents(web_contents); | 175 InstallableManager::CreateForWebContents(web_contents); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 | 340 |
| 319 // Given all of the other checks that have been made, the only possible reason | 341 // Given all of the other checks that have been made, the only possible reason |
| 320 // for stopping now is that the app has been added to the homescreen. | 342 // for stopping now is that the app has been added to the homescreen. |
| 321 if (!IsDebugMode() && !CheckIfShouldShowBanner()) { | 343 if (!IsDebugMode() && !CheckIfShouldShowBanner()) { |
| 322 Stop(); | 344 Stop(); |
| 323 return; | 345 return; |
| 324 } | 346 } |
| 325 | 347 |
| 326 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_CREATED); | 348 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_CREATED); |
| 327 event_request_id_ = ++gCurrentRequestID; | 349 event_request_id_ = ++gCurrentRequestID; |
| 328 content::RenderFrameHost* frame = web_contents()->GetMainFrame(); | 350 |
| 329 frame->Send(new ChromeViewMsg_AppBannerPromptRequest( | 351 web_contents()->GetMainFrame()->GetRemoteInterfaces()->GetInterface( |
| 330 frame->GetRoutingID(), event_request_id_, GetBannerType())); | 352 mojo::GetProxy(&client_)); |
| 353 |
| 354 client_->BannerPromptRequest( |
| 355 binding_.CreateInterfacePtrAndBind(), mojo::GetProxy(&event_), |
| 356 GetBannerType(), |
| 357 base::Bind(&AppBannerManager::OnBannerPromptReply, GetWeakPtr())); |
| 331 } | 358 } |
| 332 | 359 |
| 333 void AppBannerManager::DidStartNavigation(content::NavigationHandle* handle) { | 360 void AppBannerManager::DidStartNavigation(content::NavigationHandle* handle) { |
| 334 if (!handle->IsInMainFrame()) | 361 if (!handle->IsInMainFrame()) |
| 335 return; | 362 return; |
| 336 | 363 |
| 337 load_finished_ = false; | 364 load_finished_ = false; |
| 338 if (AppBannerSettingsHelper::ShouldUseSiteEngagementScore() && | 365 if (AppBannerSettingsHelper::ShouldUseSiteEngagementScore() && |
| 339 GetSiteEngagementService() == nullptr) { | 366 GetSiteEngagementService() == nullptr) { |
| 340 // Ensure that we are observing the site engagement service on navigation | 367 // Ensure that we are observing the site engagement service on navigation |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 } | 476 } |
| 450 | 477 |
| 451 // If we are in debug mode, AppBannerSettingsHelper::ShouldShowBanner must | 478 // If we are in debug mode, AppBannerSettingsHelper::ShouldShowBanner must |
| 452 // return NO_ERROR_DETECTED (bypass flag is set) or we must not have entered | 479 // return NO_ERROR_DETECTED (bypass flag is set) or we must not have entered |
| 453 // this method. | 480 // this method. |
| 454 DCHECK(!IsDebugMode()); | 481 DCHECK(!IsDebugMode()); |
| 455 ReportStatus(web_contents(), code); | 482 ReportStatus(web_contents(), code); |
| 456 return false; | 483 return false; |
| 457 } | 484 } |
| 458 | 485 |
| 459 bool AppBannerManager::OnMessageReceived( | |
| 460 const IPC::Message& message, | |
| 461 content::RenderFrameHost* render_frame_host) { | |
| 462 bool handled = true; | |
| 463 | |
| 464 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(AppBannerManager, message, render_frame_host) | |
| 465 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_AppBannerPromptReply, | |
| 466 OnBannerPromptReply) | |
| 467 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RequestShowAppBanner, | |
| 468 OnRequestShowAppBanner) | |
| 469 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 470 IPC_END_MESSAGE_MAP() | |
| 471 | |
| 472 return handled; | |
| 473 } | |
| 474 | |
| 475 void AppBannerManager::OnBannerPromptReply( | 486 void AppBannerManager::OnBannerPromptReply( |
| 476 content::RenderFrameHost* render_frame_host, | 487 blink::mojom::AppBannerPromptReply reply, |
| 477 int request_id, | 488 const std::string& referrer) { |
| 478 blink::WebAppBannerPromptReply reply, | |
| 479 std::string referrer) { | |
| 480 content::WebContents* contents = web_contents(); | 489 content::WebContents* contents = web_contents(); |
| 481 if (request_id != event_request_id_) | |
| 482 return; | |
| 483 | |
| 484 // The renderer might have requested the prompt to be canceled. | 490 // The renderer might have requested the prompt to be canceled. |
| 485 // They may request that it is redisplayed later, so don't Stop() here. | 491 // They may request that it is redisplayed later, so don't Stop() here. |
| 486 // However, log that the cancelation was requested, so Stop() can be | 492 // However, log that the cancelation was requested, so Stop() can be |
| 487 // called if a redisplay isn't asked for. | 493 // called if a redisplay isn't asked for. |
| 488 // | 494 // |
| 489 // We use the additional page_requested_prompt_ variable because the redisplay | 495 // We use the additional page_requested_prompt_ variable because the redisplay |
| 490 // request may be received *before* the Cancel prompt reply (e.g. if redisplay | 496 // request may be received *before* the Cancel prompt reply (e.g. if redisplay |
| 491 // is requested in the beforeinstallprompt event handler). | 497 // is requested in the beforeinstallprompt event handler). |
| 492 referrer_ = referrer; | 498 referrer_ = referrer; |
| 493 if (reply == blink::WebAppBannerPromptReply::Cancel && | 499 if (reply == blink::mojom::AppBannerPromptReply::CANCEL && |
| 494 !page_requested_prompt_) { | 500 !page_requested_prompt_) { |
| 495 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_PREVENT_DEFAULT_CALLED); | 501 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_PREVENT_DEFAULT_CALLED); |
| 496 was_canceled_by_page_ = true; | 502 was_canceled_by_page_ = true; |
| 497 return; | 503 return; |
| 498 } | 504 } |
| 499 | 505 |
| 500 // If we haven't yet returned, but either of |was_canceled_by_page_| or | 506 // If we haven't yet returned, but either of |was_canceled_by_page_| or |
| 501 // |page_requested_prompt_| is true, the page has requested a delayed showing | 507 // |page_requested_prompt_| is true, the page has requested a delayed showing |
| 502 // of the prompt. Otherwise, the prompt was never canceled by the page. | 508 // of the prompt. Otherwise, the prompt was never canceled by the page. |
| 503 if (was_canceled_by_page_ || page_requested_prompt_) { | 509 if (was_canceled_by_page_ || page_requested_prompt_) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 514 DCHECK(!manifest_url_.is_empty()); | 520 DCHECK(!manifest_url_.is_empty()); |
| 515 DCHECK(!manifest_.IsEmpty()); | 521 DCHECK(!manifest_.IsEmpty()); |
| 516 DCHECK(!icon_url_.is_empty()); | 522 DCHECK(!icon_url_.is_empty()); |
| 517 DCHECK(icon_.get()); | 523 DCHECK(icon_.get()); |
| 518 | 524 |
| 519 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_COMPLETE); | 525 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_COMPLETE); |
| 520 ShowBanner(); | 526 ShowBanner(); |
| 521 is_active_ = false; | 527 is_active_ = false; |
| 522 } | 528 } |
| 523 | 529 |
| 524 void AppBannerManager::OnRequestShowAppBanner( | 530 void AppBannerManager::DisplayAppBanner() { |
| 525 content::RenderFrameHost* render_frame_host, | |
| 526 int request_id) { | |
| 527 if (was_canceled_by_page_) { | 531 if (was_canceled_by_page_) { |
| 528 // Simulate a non-canceled OnBannerPromptReply to show the delayed banner. | 532 // Simulate a non-canceled OnBannerPromptReply to show the delayed banner. |
| 529 // Don't reset |was_canceled_by_page_| yet for metrics purposes. | 533 // Don't reset |was_canceled_by_page_| yet for metrics purposes. |
| 530 OnBannerPromptReply(render_frame_host, request_id, | 534 OnBannerPromptReply(blink::mojom::AppBannerPromptReply::NONE, referrer_); |
| 531 blink::WebAppBannerPromptReply::None, referrer_); | |
| 532 } else { | 535 } else { |
| 533 // Log that the prompt request was made for when we get the prompt reply. | 536 // Log that the prompt request was made for when we get the prompt reply. |
| 534 page_requested_prompt_ = true; | 537 page_requested_prompt_ = true; |
| 535 } | 538 } |
| 536 } | 539 } |
| 537 | 540 |
| 538 } // namespace banners | 541 } // namespace banners |
| OLD | NEW |