Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: chrome/browser/banners/app_banner_manager.cc

Issue 2778983005: Allow the app banner installability check to run on page load. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "base/feature_list.h"
11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
12 #include "base/time/time.h" 13 #include "base/time/time.h"
13 #include "chrome/browser/banners/app_banner_metrics.h" 14 #include "chrome/browser/banners/app_banner_metrics.h"
14 #include "chrome/browser/banners/app_banner_settings_helper.h" 15 #include "chrome/browser/banners/app_banner_settings_helper.h"
15 #include "chrome/browser/browser_process.h" 16 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/engagement/site_engagement_service.h" 17 #include "chrome/browser/engagement/site_engagement_service.h"
17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/chrome_features.h"
18 #include "chrome/common/chrome_switches.h" 20 #include "chrome/common/chrome_switches.h"
19 #include "components/rappor/public/rappor_utils.h" 21 #include "components/rappor/public/rappor_utils.h"
20 #include "components/rappor/rappor_service_impl.h" 22 #include "components/rappor/rappor_service_impl.h"
21 #include "content/public/browser/navigation_handle.h" 23 #include "content/public/browser/navigation_handle.h"
22 #include "content/public/browser/render_frame_host.h" 24 #include "content/public/browser/render_frame_host.h"
23 #include "content/public/browser/web_contents.h" 25 #include "content/public/browser/web_contents.h"
24 #include "mojo/public/cpp/bindings/interface_request.h" 26 #include "mojo/public/cpp/bindings/interface_request.h"
25 #include "services/service_manager/public/cpp/interface_provider.h" 27 #include "services/service_manager/public/cpp/interface_provider.h"
26 #include "third_party/WebKit/public/platform/modules/installation/installation.m ojom.h" 28 #include "third_party/WebKit/public/platform/modules/installation/installation.m ojom.h"
27 #include "third_party/skia/include/core/SkBitmap.h" 29 #include "third_party/skia/include/core/SkBitmap.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 first.path_piece() == second.path_piece() && 64 first.path_piece() == second.path_piece() &&
63 first.query_piece() == second.query_piece(); 65 first.query_piece() == second.query_piece();
64 } 66 }
65 67
66 void AppBannerManager::RequestAppBanner(const GURL& validated_url, 68 void AppBannerManager::RequestAppBanner(const GURL& validated_url,
67 bool is_debug_mode) { 69 bool is_debug_mode) {
68 content::WebContents* contents = web_contents(); 70 content::WebContents* contents = web_contents();
69 71
70 // Don't start a redundant banner request. Otherwise, if one is running, 72 // Don't start a redundant banner request. Otherwise, if one is running,
71 // invalidate our weak pointers so it terminates. 73 // invalidate our weak pointers so it terminates.
72 if (is_active_) { 74 if (IsActive()) {
benwells 2017/03/30 08:22:37 My initial comment: Is this right? Should it be !I
dominickn 2017/03/30 23:42:52 The main case this is catching is if we've trigger
benwells 2017/03/31 04:00:35 OK. This logic is really complicated, but right no
dominickn 2017/03/31 04:59:17 Yep, I think we can remove the retrigger stuff her
73 if (URLsAreForTheSamePage(validated_url, contents->GetLastCommittedURL())) 75 if (URLsAreForTheSamePage(validated_url, contents->GetLastCommittedURL()))
74 return; 76 return;
75 else 77 else
76 weak_factory_.InvalidateWeakPtrs(); 78 weak_factory_.InvalidateWeakPtrs();
77 } 79 }
78 80
79 is_active_ = true; 81 UpdateState(State::ACTIVE);
80 is_debug_mode_ = is_debug_mode; 82 is_debug_mode_ = is_debug_mode;
81 was_canceled_by_page_ = false;
82 page_requested_prompt_ = false; 83 page_requested_prompt_ = false;
83 84
84 // We only need to call ReportStatus if we aren't in debug mode (this avoids 85 // We only need to call ReportStatus if we aren't in debug mode (this avoids
85 // skew from testing). 86 // skew from testing).
86 DCHECK(!need_to_log_status_); 87 DCHECK(!need_to_log_status_);
87 need_to_log_status_ = !IsDebugMode(); 88 need_to_log_status_ = !IsDebugMode();
88 89
89 // Exit if this is an incognito window, non-main frame, or insecure context. 90 // Exit if this is an incognito window, non-main frame, or insecure context.
90 InstallableStatusCode code = NO_ERROR_DETECTED; 91 InstallableStatusCode code = NO_ERROR_DETECTED;
91 if (Profile::FromBrowserContext(contents->GetBrowserContext()) 92 if (Profile::FromBrowserContext(contents->GetBrowserContext())
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 void AppBannerManager::SendBannerDismissed(int request_id) { 135 void AppBannerManager::SendBannerDismissed(int request_id) {
135 if (request_id != gCurrentRequestID) 136 if (request_id != gCurrentRequestID)
136 return; 137 return;
137 138
138 DCHECK(event_.is_bound()); 139 DCHECK(event_.is_bound());
139 event_->BannerDismissed(); 140 event_->BannerDismissed();
140 } 141 }
141 142
142 AppBannerManager::AppBannerManager(content::WebContents* web_contents) 143 AppBannerManager::AppBannerManager(content::WebContents* web_contents)
143 : content::WebContentsObserver(web_contents), 144 : content::WebContentsObserver(web_contents),
144 SiteEngagementObserver(nullptr), 145 SiteEngagementObserver(SiteEngagementService::Get(
146 Profile::FromBrowserContext(web_contents->GetBrowserContext()))),
147 state_(State::INACTIVE),
145 manager_(nullptr), 148 manager_(nullptr),
146 event_request_id_(-1), 149 event_request_id_(-1),
147 binding_(this), 150 binding_(this),
148 is_active_(false), 151 has_sufficient_engagement_(false),
149 banner_request_queued_(false),
150 load_finished_(false), 152 load_finished_(false),
151 was_canceled_by_page_(false),
152 page_requested_prompt_(false), 153 page_requested_prompt_(false),
153 is_debug_mode_(false), 154 is_debug_mode_(false),
154 need_to_log_status_(false), 155 need_to_log_status_(false),
155 weak_factory_(this) { 156 weak_factory_(this) {
156 // Ensure the InstallableManager exists since we have a hard dependency on it. 157 // Ensure the InstallableManager exists since we have a hard dependency on it.
157 InstallableManager::CreateForWebContents(web_contents); 158 InstallableManager::CreateForWebContents(web_contents);
158 manager_ = InstallableManager::FromWebContents(web_contents); 159 manager_ = InstallableManager::FromWebContents(web_contents);
159 DCHECK(manager_); 160 DCHECK(manager_);
160 161
161 AppBannerSettingsHelper::UpdateFromFieldTrial(); 162 AppBannerSettingsHelper::UpdateFromFieldTrial();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 const GURL& manifest_url) { 205 const GURL& manifest_url) {
205 return false; 206 return false;
206 } 207 }
207 208
208 void AppBannerManager::OnDidGetManifest(const InstallableData& data) { 209 void AppBannerManager::OnDidGetManifest(const InstallableData& data) {
209 if (data.error_code != NO_ERROR_DETECTED) { 210 if (data.error_code != NO_ERROR_DETECTED) {
210 ReportStatus(web_contents(), data.error_code); 211 ReportStatus(web_contents(), data.error_code);
211 Stop(); 212 Stop();
212 } 213 }
213 214
214 if (!is_active_) 215 if (!IsActive())
215 return; 216 return;
216 217
217 DCHECK(!data.manifest_url.is_empty()); 218 DCHECK(!data.manifest_url.is_empty());
218 DCHECK(!data.manifest.IsEmpty()); 219 DCHECK(!data.manifest.IsEmpty());
219 220
220 manifest_url_ = data.manifest_url; 221 manifest_url_ = data.manifest_url;
221 manifest_ = data.manifest; 222 manifest_ = data.manifest;
222 app_title_ = (manifest_.name.is_null()) ? manifest_.short_name.string() 223 app_title_ = (manifest_.name.is_null()) ? manifest_.short_name.string()
223 : manifest_.name.string(); 224 : manifest_.name.string();
224 225
(...skipping 26 matching lines...) Expand all
251 TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_REQUESTED); 252 TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_REQUESTED);
252 253
253 if (data.error_code != NO_ERROR_DETECTED) { 254 if (data.error_code != NO_ERROR_DETECTED) {
254 if (data.error_code == NO_MATCHING_SERVICE_WORKER) 255 if (data.error_code == NO_MATCHING_SERVICE_WORKER)
255 TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER); 256 TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER);
256 257
257 ReportStatus(web_contents(), data.error_code); 258 ReportStatus(web_contents(), data.error_code);
258 Stop(); 259 Stop();
259 } 260 }
260 261
261 if (!is_active_) 262 if (!IsActive())
262 return; 263 return;
263 264
264 DCHECK(data.is_installable); 265 DCHECK(data.is_installable);
265 DCHECK(!data.primary_icon_url.is_empty()); 266 DCHECK(!data.primary_icon_url.is_empty());
266 DCHECK(data.primary_icon); 267 DCHECK(data.primary_icon);
267 268
268 primary_icon_url_ = data.primary_icon_url; 269 primary_icon_url_ = data.primary_icon_url;
269 primary_icon_.reset(new SkBitmap(*data.primary_icon)); 270 primary_icon_.reset(new SkBitmap(*data.primary_icon));
270 271
272 // If we triggered the installability check on page load, then it's possible
273 // we don't have enough engagement yet. If that's the case, return here but
274 // don't call Stop(). We wait for OnEngagementIncreased to tell us that we
275 // should trigger.
276 if (!has_sufficient_engagement_) {
277 UpdateState(State::PENDING_ENGAGEMENT);
278 return;
279 }
280
271 SendBannerPromptRequest(); 281 SendBannerPromptRequest();
272 } 282 }
273 283
274 void AppBannerManager::RecordDidShowBanner(const std::string& event_name) { 284 void AppBannerManager::RecordDidShowBanner(const std::string& event_name) {
275 content::WebContents* contents = web_contents(); 285 content::WebContents* contents = web_contents();
276 DCHECK(contents); 286 DCHECK(contents);
277 287
278 AppBannerSettingsHelper::RecordBannerEvent( 288 AppBannerSettingsHelper::RecordBannerEvent(
279 contents, validated_url_, GetAppIdentifier(), 289 contents, validated_url_, GetAppIdentifier(),
280 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_SHOW, 290 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_SHOW,
(...skipping 17 matching lines...) Expand all
298 308
299 void AppBannerManager::ResetCurrentPageData() { 309 void AppBannerManager::ResetCurrentPageData() {
300 active_media_players_.clear(); 310 active_media_players_.clear();
301 manifest_ = content::Manifest(); 311 manifest_ = content::Manifest();
302 manifest_url_ = GURL(); 312 manifest_url_ = GURL();
303 validated_url_ = GURL(); 313 validated_url_ = GURL();
304 referrer_.erase(); 314 referrer_.erase();
305 } 315 }
306 316
307 void AppBannerManager::Stop() { 317 void AppBannerManager::Stop() {
308 if (was_canceled_by_page_ && !page_requested_prompt_) { 318 if (state_ == State::PENDING_EVENT && !page_requested_prompt_) {
309 TrackBeforeInstallEvent( 319 TrackBeforeInstallEvent(
310 BEFORE_INSTALL_EVENT_PROMPT_NOT_CALLED_AFTER_PREVENT_DEFAULT); 320 BEFORE_INSTALL_EVENT_PROMPT_NOT_CALLED_AFTER_PREVENT_DEFAULT);
311 ReportStatus(web_contents(), RENDERER_CANCELLED); 321 ReportStatus(web_contents(), RENDERER_CANCELLED);
322 } else if (state_ == State::PENDING_ENGAGEMENT &&
323 !has_sufficient_engagement_) {
324 TrackDisplayEvent(DISPLAY_EVENT_NOT_VISITED_ENOUGH);
325 ReportStatus(web_contents(), INSUFFICIENT_ENGAGEMENT);
312 } 326 }
313 327
314 // In every non-debug run through the banner pipeline, we should have called 328 // In every non-debug run through the banner pipeline, we should have called
315 // ReportStatus() and set need_to_log_status_ to false. The only case where 329 // ReportStatus() and set need_to_log_status_ to false. The only case where
316 // we don't is if we're still active and waiting for a callback from the 330 // we don't is if we're still active and waiting for a callback from the
317 // InstallableManager (e.g. the renderer crashes or the browser is shutting 331 // InstallableManager (e.g. the renderer crashes or the browser is shutting
318 // down). These situations are explicitly not logged. 332 // down). These situations are explicitly not logged.
319 DCHECK(!need_to_log_status_ || is_active_); 333 DCHECK(!need_to_log_status_ || IsActive());
320 334
321 weak_factory_.InvalidateWeakPtrs(); 335 weak_factory_.InvalidateWeakPtrs();
322 binding_.Close(); 336 binding_.Close();
323 controller_.reset(); 337 controller_.reset();
324 event_.reset(); 338 event_.reset();
325 339
326 is_active_ = false; 340 UpdateState(State::COMPLETE);
327 need_to_log_status_ = false; 341 need_to_log_status_ = false;
342 has_sufficient_engagement_ = false;
benwells 2017/03/30 08:22:37 Why do you set this false? and why COMPLETE?
dominickn 2017/03/30 23:42:52 COMPLETE means that we're not going to do anything
328 } 343 }
329 344
330 void AppBannerManager::SendBannerPromptRequest() { 345 void AppBannerManager::SendBannerPromptRequest() {
331 RecordCouldShowBanner(); 346 RecordCouldShowBanner();
332 347
333 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_CREATED); 348 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_CREATED);
334 event_request_id_ = ++gCurrentRequestID; 349 event_request_id_ = ++gCurrentRequestID;
335 350
336 web_contents()->GetMainFrame()->GetRemoteInterfaces()->GetInterface( 351 web_contents()->GetMainFrame()->GetRemoteInterfaces()->GetInterface(
337 mojo::MakeRequest(&controller_)); 352 mojo::MakeRequest(&controller_));
338 353
339 controller_->BannerPromptRequest( 354 controller_->BannerPromptRequest(
340 binding_.CreateInterfacePtrAndBind(), mojo::MakeRequest(&event_), 355 binding_.CreateInterfacePtrAndBind(), mojo::MakeRequest(&event_),
341 {GetBannerType()}, 356 {GetBannerType()},
342 base::Bind(&AppBannerManager::OnBannerPromptReply, GetWeakPtr())); 357 base::Bind(&AppBannerManager::OnBannerPromptReply, GetWeakPtr()));
343 } 358 }
344 359
360 void AppBannerManager::UpdateState(State state) {
361 state_ = state;
benwells 2017/03/30 08:22:36 Is it worth setting more state here (e.g. if inact
dominickn 2017/03/30 23:42:52 I added the pending event DCHECK, but I can't thin
362 }
363
345 void AppBannerManager::DidStartNavigation(content::NavigationHandle* handle) { 364 void AppBannerManager::DidStartNavigation(content::NavigationHandle* handle) {
346 if (!handle->IsInMainFrame() || handle->IsSameDocument()) 365 if (!handle->IsInMainFrame() || handle->IsSameDocument())
347 return; 366 return;
348 367
368 if (IsActiveOrPending())
369 Stop();
370 UpdateState(State::INACTIVE);
349 load_finished_ = false; 371 load_finished_ = false;
350 if (GetSiteEngagementService() == nullptr) { 372 has_sufficient_engagement_ = false;
351 // Ensure that we are observing the site engagement service on navigation 373 page_requested_prompt_ = false;
352 // start. This may be the first navigation, or we may have stopped
353 // observing if the banner flow was triggered on the previous page.
354 SiteEngagementObserver::Observe(SiteEngagementService::Get(
355 Profile::FromBrowserContext(web_contents()->GetBrowserContext())));
356 }
357 } 374 }
358 375
359 void AppBannerManager::DidFinishNavigation(content::NavigationHandle* handle) { 376 void AppBannerManager::DidFinishNavigation(content::NavigationHandle* handle) {
360 if (handle->IsInMainFrame() && handle->HasCommitted() && 377 if (handle->IsInMainFrame() && handle->HasCommitted() &&
361 !handle->IsSameDocument()) { 378 !handle->IsSameDocument()) {
362 ResetCurrentPageData(); 379 ResetCurrentPageData();
363 if (is_active_)
364 Stop();
365 } 380 }
366 } 381 }
367 382
368 void AppBannerManager::DidFinishLoad( 383 void AppBannerManager::DidFinishLoad(
369 content::RenderFrameHost* render_frame_host, 384 content::RenderFrameHost* render_frame_host,
370 const GURL& validated_url) { 385 const GURL& validated_url) {
371 // Don't start the banner flow unless the main frame has finished loading. 386 // Don't start the banner flow unless the main frame has finished loading.
372 if (render_frame_host->GetParent()) 387 if (render_frame_host->GetParent())
373 return; 388 return;
374 389
375 load_finished_ = true; 390 load_finished_ = true;
376 validated_url_ = validated_url; 391 validated_url_ = validated_url;
377 // Start the pipeline immediately if 0 engagement is required or if we've 392 // Start the pipeline immediately if:
378 // queued a banner request. 393 // 1. we have sufficient engagement, or
379 if (banner_request_queued_ || 394 // 2. 0 engagement is required, or
380 AppBannerSettingsHelper::HasSufficientEngagement(0)) { 395 // 3. the feature to start the installability check in load is enabled
381 SiteEngagementObserver::Observe(nullptr); 396 if (has_sufficient_engagement_ ||
382 banner_request_queued_ = false; 397 AppBannerSettingsHelper::HasSufficientEngagement(0) ||
383 398 base::FeatureList::IsEnabled(
399 features::kCheckInstallabilityForBannerOnLoad)) {
384 RequestAppBanner(validated_url, false /* is_debug_mode */); 400 RequestAppBanner(validated_url, false /* is_debug_mode */);
385 } 401 }
386 } 402 }
387 403
388 void AppBannerManager::MediaStartedPlaying(const MediaPlayerInfo& media_info, 404 void AppBannerManager::MediaStartedPlaying(const MediaPlayerInfo& media_info,
389 const MediaPlayerId& id) { 405 const MediaPlayerId& id) {
390 active_media_players_.push_back(id); 406 active_media_players_.push_back(id);
391 } 407 }
392 408
393 void AppBannerManager::MediaStoppedPlaying(const MediaPlayerInfo& media_info, 409 void AppBannerManager::MediaStoppedPlaying(const MediaPlayerInfo& media_info,
394 const MediaPlayerId& id) { 410 const MediaPlayerId& id) {
395 active_media_players_.erase(std::remove(active_media_players_.begin(), 411 active_media_players_.erase(std::remove(active_media_players_.begin(),
396 active_media_players_.end(), id), 412 active_media_players_.end(), id),
397 active_media_players_.end()); 413 active_media_players_.end());
398 } 414 }
399 415
400 void AppBannerManager::WebContentsDestroyed() { 416 void AppBannerManager::WebContentsDestroyed() {
401 Stop(); 417 Stop();
402 } 418 }
403 419
404 void AppBannerManager::OnEngagementIncreased(content::WebContents* contents, 420 void AppBannerManager::OnEngagementIncreased(content::WebContents* contents,
405 const GURL& url, 421 const GURL& url,
406 double score) { 422 double score) {
423 // In the ACTIVE state, we may have triggered the installability check, but
424 // not checked engagement yet. In the INACTIVE or PENDING_ENGAGEMENT states,
425 // we are waiting for an engagement signal to trigger the pipeline.
426 if (IsComplete() || IsPendingEvent())
427 return;
428
407 // Only trigger a banner using site engagement if: 429 // Only trigger a banner using site engagement if:
408 // 1. engagement increased for the web contents which we are attached to; and 430 // 1. engagement increased for the web contents which we are attached to; and
409 // 2. there are no currently active media players; and 431 // 2. there are no currently active media players; and
410 // 3. we have accumulated sufficient engagement. 432 // 3. we have accumulated sufficient engagement.
411 if (web_contents() == contents && active_media_players_.empty() && 433 if (web_contents() == contents && active_media_players_.empty() &&
412 AppBannerSettingsHelper::HasSufficientEngagement(score)) { 434 AppBannerSettingsHelper::HasSufficientEngagement(score)) {
413 // Stop observing so we don't double-trigger the banner. 435 has_sufficient_engagement_ = true;
414 SiteEngagementObserver::Observe(nullptr);
415 436
416 if (!load_finished_) { 437 if (IsPendingEngagement()) {
417 // Queue the banner request until the main frame finishes loading. 438 // We have already finished the installability eligibility checks. Proceed
418 banner_request_queued_ = true; 439 // directly to sending the banner prompt request.
419 } else { 440 UpdateState(State::ACTIVE);
420 // A banner request performs some simple tests, creates a data fetcher, 441 SendBannerPromptRequest();
421 // and starts some asynchronous checks to test installability. It should 442 } else if (load_finished_) {
422 // be safe to start this in response to user input. 443 // This performs some simple tests and starts async checks to test
444 // installability. It should be safe to start in response to user input.
423 RequestAppBanner(url, false /* is_debug_mode */); 445 RequestAppBanner(url, false /* is_debug_mode */);
424 } 446 }
425 } 447 }
426 } 448 }
427 449
428 void AppBannerManager::RecordCouldShowBanner() { 450 void AppBannerManager::RecordCouldShowBanner() {
429 content::WebContents* contents = web_contents(); 451 content::WebContents* contents = web_contents();
430 DCHECK(contents); 452 DCHECK(contents);
431 453
432 AppBannerSettingsHelper::RecordBannerEvent( 454 AppBannerSettingsHelper::RecordBannerEvent(
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 } 497 }
476 498
477 void AppBannerManager::OnBannerPromptReply( 499 void AppBannerManager::OnBannerPromptReply(
478 blink::mojom::AppBannerPromptReply reply, 500 blink::mojom::AppBannerPromptReply reply,
479 const std::string& referrer) { 501 const std::string& referrer) {
480 // We don't need the controller any more, so reset it so the Blink-side object 502 // We don't need the controller any more, so reset it so the Blink-side object
481 // is destroyed. 503 // is destroyed.
482 controller_.reset(); 504 controller_.reset();
483 content::WebContents* contents = web_contents(); 505 content::WebContents* contents = web_contents();
484 506
485 // The renderer might have requested the prompt to be canceled. 507 // The renderer might have requested the prompt to be canceled. They may
486 // They may request that it is redisplayed later, so don't Stop() here. 508 // request that it is redisplayed later, so don't Stop() here. However, log
487 // However, log that the cancelation was requested, so Stop() can be 509 // that the cancelation was requested, so Stop() can be called if a redisplay
488 // called if a redisplay isn't asked for. 510 // isn't asked for.
489 // 511 //
490 // We use the additional page_requested_prompt_ variable because the redisplay 512 // We use the additional page_requested_prompt_ variable because the redisplay
491 // request may be received *before* the Cancel prompt reply (e.g. if redisplay 513 // request may be received *before* the Cancel prompt reply (e.g. if redisplay
492 // is requested in the beforeinstallprompt event handler). 514 // is requested in the beforeinstallprompt event handler).
493 referrer_ = referrer; 515 referrer_ = referrer;
494 if (reply == blink::mojom::AppBannerPromptReply::CANCEL && 516 if (reply == blink::mojom::AppBannerPromptReply::CANCEL) {
495 !page_requested_prompt_) { 517 UpdateState(State::PENDING_EVENT);
benwells 2017/03/30 08:22:36 How come you don't have to check page_requested_pr
dominickn 2017/03/30 23:42:52 We still do to return (see line 519). The key thin
496 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_PREVENT_DEFAULT_CALLED); 518 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_PREVENT_DEFAULT_CALLED);
497 was_canceled_by_page_ = true; 519 if (!page_requested_prompt_)
498 return; 520 return;
499 } 521 }
500 522
501 // If we haven't yet returned, but either of |was_canceled_by_page_| or 523 // If we haven't yet returned, but we're in the PENDING_EVENT state or
502 // |page_requested_prompt_| is true, the page has requested a delayed showing 524 // |page_requested_prompt_| is true, the page has requested a delayed showing
503 // of the prompt. Otherwise, the prompt was never canceled by the page. 525 // of the prompt. Otherwise, the prompt was never canceled by the page.
504 if (was_canceled_by_page_ || page_requested_prompt_) { 526 if (IsPendingEvent()) {
505 TrackBeforeInstallEvent( 527 TrackBeforeInstallEvent(
506 BEFORE_INSTALL_EVENT_PROMPT_CALLED_AFTER_PREVENT_DEFAULT); 528 BEFORE_INSTALL_EVENT_PROMPT_CALLED_AFTER_PREVENT_DEFAULT);
507 was_canceled_by_page_ = false; 529 UpdateState(State::ACTIVE);
benwells 2017/03/30 08:22:36 This is weird - why go back to ACTIVE?
dominickn 2017/03/30 23:42:52 This is analogous to the case where we didn't have
benwells 2017/03/31 04:00:35 Ah ... I think so.
508 } else { 530 } else {
509 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_NO_ACTION); 531 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_NO_ACTION);
510 } 532 }
511 533
512 AppBannerSettingsHelper::RecordMinutesFromFirstVisitToShow( 534 AppBannerSettingsHelper::RecordMinutesFromFirstVisitToShow(
513 contents, validated_url_, GetAppIdentifier(), GetCurrentTime()); 535 contents, validated_url_, GetAppIdentifier(), GetCurrentTime());
514 536
515 DCHECK(!manifest_url_.is_empty()); 537 DCHECK(!manifest_url_.is_empty());
516 DCHECK(!manifest_.IsEmpty()); 538 DCHECK(!manifest_.IsEmpty());
517 DCHECK(!primary_icon_url_.is_empty()); 539 DCHECK(!primary_icon_url_.is_empty());
518 DCHECK(primary_icon_.get()); 540 DCHECK(primary_icon_.get());
519 541
520 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_COMPLETE); 542 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_COMPLETE);
521 ShowBanner(); 543 ShowBanner();
522 is_active_ = false; 544 UpdateState(State::COMPLETE);
523 } 545 }
524 546
525 void AppBannerManager::DisplayAppBanner() { 547 void AppBannerManager::DisplayAppBanner() {
526 if (was_canceled_by_page_) { 548 if (IsPendingEvent()) {
527 // Simulate a non-canceled OnBannerPromptReply to show the delayed banner. 549 // Simulate a non-canceled OnBannerPromptReply to show the delayed banner.
528 // Don't reset |was_canceled_by_page_| yet for metrics purposes.
529 OnBannerPromptReply(blink::mojom::AppBannerPromptReply::NONE, referrer_); 550 OnBannerPromptReply(blink::mojom::AppBannerPromptReply::NONE, referrer_);
530 } else { 551 } else {
531 // Log that the prompt request was made for when we get the prompt reply. 552 // Log that the prompt request was made for when we get the prompt reply.
532 page_requested_prompt_ = true; 553 page_requested_prompt_ = true;
533 } 554 }
534 } 555 }
535 556
536 } // namespace banners 557 } // namespace banners
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698