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

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

Issue 2156113002: Replace AppBannerDataFetcher with InstallableManager. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@banner-refactor
Patch Set: Rebase Created 4 years, 5 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 "chrome/browser/banners/app_banner_data_fetcher.h" 7 #include "base/bind.h"
8 #include "chrome/browser/banners/app_banner_debug_log.h" 8 #include "base/callback.h"
9 #include "base/command_line.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/time/time.h"
12 #include "chrome/browser/banners/app_banner_metrics.h"
9 #include "chrome/browser/banners/app_banner_settings_helper.h" 13 #include "chrome/browser/banners/app_banner_settings_helper.h"
14 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/engagement/site_engagement_service.h" 15 #include "chrome/browser/engagement/site_engagement_service.h"
16 #include "chrome/browser/installable/installable_checker.h"
17 #include "chrome/browser/installable/installable_logging.h"
11 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/render_messages.h"
21 #include "components/rappor/rappor_utils.h"
12 #include "content/public/browser/navigation_handle.h" 22 #include "content/public/browser/navigation_handle.h"
13 #include "content/public/browser/render_frame_host.h" 23 #include "content/public/browser/render_frame_host.h"
14 #include "content/public/browser/web_contents.h" 24 #include "content/public/browser/web_contents.h"
15 #include "content/public/common/frame_navigate_params.h"
16 #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"
27 #include "third_party/skia/include/core/SkBitmap.h"
28 #include "ui/display/display.h"
29 #include "ui/display/screen.h"
17 30
18 namespace { 31 namespace {
32
19 bool gDisableSecureCheckForTesting = false; 33 bool gDisableSecureCheckForTesting = false;
34 int gCurrentRequestID = -1;
35 base::LazyInstance<base::TimeDelta> gTimeDeltaForTesting =
36 LAZY_INSTANCE_INITIALIZER;
37
38 // Returns |size_in_px| in dp, i.e. divided by the current device scale factor.
39 int ConvertIconSizeFromPxToDp(int size_in_px) {
40 return size_in_px /
41 display::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
42 }
43
44 // Returns an InstallableParams object that requests all checks necessary for
45 // a web app banner.
46 installable::InstallableParams GetWebAppParams(int ideal_icon_size_in_dp,
47 int minimum_icon_size_in_dp) {
48 installable::InstallableParams params;
49 params.ideal_icon_size_in_dp = ideal_icon_size_in_dp;
50 params.minimum_icon_size_in_dp = minimum_icon_size_in_dp;
51 params.check_valid_webapp_manifest = true;
52 params.check_service_worker = true;
53 params.check_valid_icon = true;
54
55 return params;
56 }
57
20 } // anonymous namespace 58 } // anonymous namespace
21 59
22 namespace banners { 60 namespace banners {
23 61
62 // static
24 void AppBannerManager::DisableSecureSchemeCheckForTesting() { 63 void AppBannerManager::DisableSecureSchemeCheckForTesting() {
25 gDisableSecureCheckForTesting = true; 64 gDisableSecureCheckForTesting = true;
26 } 65 }
27 66
67 // static
68 base::Time AppBannerManager::GetCurrentTime() {
69 return base::Time::Now() + gTimeDeltaForTesting.Get();
70 }
71
72 // static
73 void AppBannerManager::SetTimeDeltaForTesting(int days) {
74 gTimeDeltaForTesting.Get() = base::TimeDelta::FromDays(days);
75 }
76
77 // static
28 void AppBannerManager::SetEngagementWeights(double direct_engagement, 78 void AppBannerManager::SetEngagementWeights(double direct_engagement,
29 double indirect_engagement) { 79 double indirect_engagement) {
30 AppBannerSettingsHelper::SetEngagementWeights(direct_engagement, 80 AppBannerSettingsHelper::SetEngagementWeights(direct_engagement,
31 indirect_engagement); 81 indirect_engagement);
32 } 82 }
33 83
84 // static
34 bool AppBannerManager::URLsAreForTheSamePage(const GURL& first, 85 bool AppBannerManager::URLsAreForTheSamePage(const GURL& first,
35 const GURL& second) { 86 const GURL& second) {
36 return first.GetWithEmptyPath() == second.GetWithEmptyPath() && 87 return first.GetWithEmptyPath() == second.GetWithEmptyPath() &&
37 first.path() == second.path() && first.query() == second.query(); 88 first.path() == second.path() && first.query() == second.query();
38 } 89 }
39 90
40 AppBannerManager::AppBannerManager(content::WebContents* web_contents)
41 : content::WebContentsObserver(web_contents),
42 SiteEngagementObserver(nullptr),
43 data_fetcher_(nullptr),
44 banner_request_queued_(false),
45 load_finished_(false),
46 weak_factory_(this) {
47 AppBannerSettingsHelper::UpdateFromFieldTrial();
48 }
49
50 AppBannerManager::~AppBannerManager() {
51 CancelActiveFetcher();
52 }
53
54 void AppBannerManager::ReplaceWebContents(content::WebContents* web_contents) {
55 content::WebContentsObserver::Observe(web_contents);
56 if (data_fetcher_.get())
57 data_fetcher_.get()->ReplaceWebContents(web_contents);
58 }
59
60 bool AppBannerManager::IsFetcherActive() {
61 return data_fetcher_ && data_fetcher_->is_active();
62 }
63
64 void AppBannerManager::RequestAppBanner(const GURL& validated_url, 91 void AppBannerManager::RequestAppBanner(const GURL& validated_url,
65 bool is_debug_mode) { 92 bool is_debug_mode) {
66 content::WebContents* contents = web_contents(); 93 content::WebContents* contents = web_contents();
67 if (contents->GetMainFrame()->GetParent()) { 94 if (contents->GetMainFrame()->GetParent()) {
68 OutputDeveloperNotShownMessage(contents, kNotLoadedInMainFrame, 95 ReportError(contents, installable::NOT_IN_MAIN_FRAME);
69 is_debug_mode); 96 return;
70 return; 97 }
71 } 98
72 99 // Don't start a redundant banner request.
73 if (data_fetcher_.get() && data_fetcher_->is_active() && 100 if (is_active_ &&
74 URLsAreForTheSamePage(data_fetcher_->validated_url(), validated_url) && 101 URLsAreForTheSamePage(validated_url, contents->GetLastCommittedURL())) {
75 !is_debug_mode) {
76 return; 102 return;
77 } 103 }
78 104
79 // A secure origin is required to show banners, so exit early if we see the 105 // A secure origin is required to show banners, so exit early if we see the
80 // URL is invalid. 106 // URL is invalid.
81 if (!content::IsOriginSecure(validated_url) && 107 if (!content::IsOriginSecure(validated_url) &&
82 !gDisableSecureCheckForTesting) { 108 !gDisableSecureCheckForTesting) {
83 OutputDeveloperNotShownMessage(contents, kNotServedFromSecureOrigin, 109 ReportError(contents, installable::NOT_FROM_SECURE_ORIGIN);
84 is_debug_mode); 110 return;
85 return; 111 }
86 } 112
87 113 is_debug_mode_ = is_debug_mode;
88 // Kick off the data retrieval pipeline. 114 is_active_ = true;
89 data_fetcher_ = 115
90 CreateAppBannerDataFetcher(weak_factory_.GetWeakPtr(), is_debug_mode); 116 // We start by requesting the manifest from the InstallableChecker. The
91 data_fetcher_->Start(validated_url, last_transition_type_); 117 // default-constructed params will have all other fields as false.
92 } 118 installable::InstallableParams params;
93 119 checker_->Start(
94 void AppBannerManager::DidStartNavigation( 120 params, base::Bind(&AppBannerManager::OnDidGetManifest, GetWeakPtr()));
95 content::NavigationHandle* navigation_handle) { 121 }
96 if (!navigation_handle->IsInMainFrame()) 122
123 base::Closure AppBannerManager::FetchWebappSplashScreenImageCallback(
124 const std::string& webapp_id) {
125 return base::Closure();
126 }
127
128 AppBannerManager::AppBannerManager(content::WebContents* web_contents)
129 : content::WebContentsObserver(web_contents),
130 SiteEngagementObserver(nullptr),
131 checker_(nullptr),
132 event_request_id_(-1),
133 is_active_(false),
134 banner_request_queued_(false),
135 load_finished_(false),
136 was_canceled_by_page_(false),
137 page_requested_prompt_(false),
138 is_debug_mode_(false),
139 weak_factory_(this) {
140 // Ensure the InstallableChecker exists since we have a hard dependency on it.
141 installable::InstallableChecker::CreateForWebContents(web_contents);
142 checker_ = installable::InstallableChecker::FromWebContents(web_contents);
143 DCHECK(checker_);
144
145 AppBannerSettingsHelper::UpdateFromFieldTrial();
146 }
147
148 AppBannerManager::~AppBannerManager() { }
149
150 std::string AppBannerManager::GetAppIdentifier() {
151 DCHECK(!manifest_.IsEmpty());
152 return manifest_.start_url.spec();
153 }
154
155 std::string AppBannerManager::GetBannerType() {
156 return "web";
157 }
158
159 std::string AppBannerManager::GetErrorParam(installable::ErrorCode code) {
160 if (code == installable::NO_ACCEPTABLE_ICON ||
161 code == installable::MANIFEST_MISSING_SUITABLE_ICON) {
162 return base::IntToString(
163 installable::InstallableChecker::GetMinimumIconSizeInPx());
164 }
165
166 return "";
gone 2016/07/23 23:39:23 Is the standard thing to do to use std::string()?
dominickn 2016/07/25 00:23:51 Done.
167 }
168
169 int AppBannerManager::GetIdealIconSizeInDp() {
170 return ConvertIconSizeFromPxToDp(
171 installable::InstallableChecker::GetMinimumIconSizeInPx());
172 }
173
174 int AppBannerManager::GetMinimumIconSizeInDp() {
175 return ConvertIconSizeFromPxToDp(
176 installable::InstallableChecker::GetMinimumIconSizeInPx());
177 }
178
179 base::WeakPtr<AppBannerManager> AppBannerManager::GetWeakPtr() {
180 return weak_factory_.GetWeakPtr();
181 }
182
183 bool AppBannerManager::IsDebugMode() const {
184 return is_debug_mode_ ||
185 base::CommandLine::ForCurrentProcess()->HasSwitch(
186 switches::kBypassAppBannerEngagementChecks);
187 }
188
189 bool AppBannerManager::IsWebAppInstalled(
190 content::BrowserContext* browser_context,
191 const GURL& start_url) {
192 return false;
193 }
194
195 void AppBannerManager::OnDidGetManifest(
196 const installable::InstallableResult& result) {
197 if (result.error_code != installable::NO_ERROR_DETECTED) {
198 ReportError(web_contents(), result.error_code);
199 Stop();
200 }
201
202 if (!is_active_)
203 return;
204
205 DCHECK(!result.manifest_url.is_empty());
206 DCHECK(!result.manifest.IsEmpty());
207
208 manifest_url_ = result.manifest_url;
209 manifest_ = result.manifest;
210 app_title_ = (manifest_.name.is_null()) ? manifest_.short_name.string()
211 : manifest_.name.string();
212
213 ContinueInstallableCheck();
214 }
215
216 void AppBannerManager::ContinueInstallableCheck() {
217 if (IsWebAppInstalled(web_contents()->GetBrowserContext(),
218 manifest_.start_url) &&
219 !IsDebugMode()) {
220 Stop();
221 }
222
223 if (!is_active_)
224 return;
225
226 // Fetch and verify the other required information.
227 checker_->Start(
228 GetWebAppParams(GetIdealIconSizeInDp(), GetMinimumIconSizeInDp()),
229 base::Bind(&AppBannerManager::OnDidFinishInstallableCheck, GetWeakPtr()));
230 }
231
232 void AppBannerManager::OnDidFinishInstallableCheck(
233 const installable::InstallableResult& result) {
234 if (result.has_valid_webapp_manifest)
235 banners::TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_REQUESTED);
236
237 if (result.error_code != installable::NO_ERROR_DETECTED) {
238 if (!result.has_service_worker)
239 TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER);
240
241 ReportError(web_contents(), result.error_code);
242 Stop();
243 }
244
245 if (!is_active_)
246 return;
247
248 DCHECK(result.has_valid_webapp_manifest);
249 DCHECK(result.has_service_worker);
250 DCHECK(!result.icon_url.is_empty());
251 DCHECK(result.icon);
252
253 icon_url_ = result.icon_url;
254 icon_.reset(new SkBitmap(*result.icon));
255
256 SendBannerPromptRequest();
257 }
258
259 void AppBannerManager::RecordDidShowBanner(const std::string& event_name) {
260 content::WebContents* contents = web_contents();
261 DCHECK(contents);
262
263 AppBannerSettingsHelper::RecordBannerEvent(
264 contents, validated_url_, GetAppIdentifier(),
265 AppBannerSettingsHelper::APP_BANNER_EVENT_DID_SHOW,
266 GetCurrentTime());
267 rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(),
268 event_name,
269 contents->GetLastCommittedURL());
270 }
271
272 void AppBannerManager::ReportError(content::WebContents* web_contents,
273 installable::ErrorCode code) {
274 if (IsDebugMode())
275 installable::LogErrorToConsole(web_contents, code, GetErrorParam(code));
276 }
277
278 void AppBannerManager::Stop() {
279 if (was_canceled_by_page_ && !page_requested_prompt_) {
280 TrackBeforeInstallEvent(
281 BEFORE_INSTALL_EVENT_PROMPT_NOT_CALLED_AFTER_PREVENT_DEFAULT);
282 }
283
284 is_active_ = false;
285 was_canceled_by_page_ = false;
286 page_requested_prompt_ = false;
287 referrer_.erase();
288 }
289
290 void AppBannerManager::SendBannerPromptRequest() {
291 RecordCouldShowBanner();
292
293 // Given all of the other checks that have been made, the only possible reason
294 // for stopping now is that the banner has been added to the homescreen.
295 if (!IsDebugMode() && !CheckIfShouldShowBanner())
296 Stop();
297
298 if (!is_active_)
299 return;
300
301 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_CREATED);
302 event_request_id_ = ++gCurrentRequestID;
303 content::RenderFrameHost* frame = web_contents()->GetMainFrame();
304 frame->Send(new ChromeViewMsg_AppBannerPromptRequest(
305 frame->GetRoutingID(), event_request_id_, GetBannerType()));
306 }
307
308 void AppBannerManager::DidStartNavigation(content::NavigationHandle* handle) {
309 if (!handle->IsInMainFrame())
97 return; 310 return;
98 311
99 load_finished_ = false; 312 load_finished_ = false;
100 if (AppBannerSettingsHelper::ShouldUseSiteEngagementScore() && 313 if (AppBannerSettingsHelper::ShouldUseSiteEngagementScore() &&
101 GetSiteEngagementService() == nullptr) { 314 GetSiteEngagementService() == nullptr) {
102 // Ensure that we are observing the site engagement service on navigation 315 // Ensure that we are observing the site engagement service on navigation
103 // start. This may be the first navigation, or we may have stopped 316 // start. This may be the first navigation, or we may have stopped
104 // observing if the banner flow was triggered on the previous page. 317 // observing if the banner flow was triggered on the previous page.
105 SiteEngagementObserver::Observe(SiteEngagementService::Get( 318 SiteEngagementObserver::Observe(SiteEngagementService::Get(
106 Profile::FromBrowserContext(web_contents()->GetBrowserContext()))); 319 Profile::FromBrowserContext(web_contents()->GetBrowserContext())));
107 } 320 }
108 } 321 }
109 322
110 void AppBannerManager::DidFinishNavigation( 323 void AppBannerManager::DidFinishNavigation(content::NavigationHandle* handle) {
111 content::NavigationHandle* navigation_handle) { 324 if (handle->IsInMainFrame() && handle->HasCommitted()) {
112 if (navigation_handle->HasCommitted()) 325 last_transition_type_ = handle->GetPageTransition();
113 last_transition_type_ = navigation_handle->GetPageTransition(); 326 active_media_players_.clear();
327 if (is_active_)
328 Stop();
329 }
114 } 330 }
115 331
116 void AppBannerManager::DidFinishLoad( 332 void AppBannerManager::DidFinishLoad(
117 content::RenderFrameHost* render_frame_host, 333 content::RenderFrameHost* render_frame_host,
118 const GURL& validated_url) { 334 const GURL& validated_url) {
119 // Don't start the banner flow unless the main frame has finished loading. 335 // Don't start the banner flow unless the main frame has finished loading.
120 if (render_frame_host->GetParent()) 336 if (render_frame_host->GetParent())
121 return; 337 return;
122 338
123 load_finished_ = true; 339 load_finished_ = true;
340 validated_url_ = validated_url;
124 if (!AppBannerSettingsHelper::ShouldUseSiteEngagementScore() || 341 if (!AppBannerSettingsHelper::ShouldUseSiteEngagementScore() ||
125 banner_request_queued_) { 342 banner_request_queued_) {
126 banner_request_queued_ = false; 343 banner_request_queued_ = false;
127 344
128 // The third argument is the is_debug_mode boolean value, which is true only
129 // when it is triggered by the developer's action in DevTools.
130 RequestAppBanner(validated_url, false /* is_debug_mode */); 345 RequestAppBanner(validated_url, false /* is_debug_mode */);
131 } 346 }
132 } 347 }
133 348
134 void AppBannerManager::MediaStartedPlaying(const MediaPlayerId& id) { 349 void AppBannerManager::MediaStartedPlaying(const MediaPlayerId& id) {
135 active_media_players_.push_back(id); 350 active_media_players_.push_back(id);
gone 2016/07/23 23:39:23 Eh, why do app banners care if media started playi
dominickn 2016/07/25 00:23:51 Yes, this is to prevent banners from appearing whi
136 } 351 }
137 352
138 void AppBannerManager::MediaStoppedPlaying(const MediaPlayerId& id) { 353 void AppBannerManager::MediaStoppedPlaying(const MediaPlayerId& id) {
139 active_media_players_.erase(std::remove(active_media_players_.begin(), 354 active_media_players_.erase(std::remove(active_media_players_.begin(),
140 active_media_players_.end(), id), 355 active_media_players_.end(), id),
141 active_media_players_.end()); 356 active_media_players_.end());
142 } 357 }
143 358
144 bool AppBannerManager::HandleNonWebApp(const std::string& platform, 359 void AppBannerManager::WebContentsDestroyed() {
145 const GURL& url, 360 Stop();
146 const std::string& id,
147 bool is_debug_mode) {
148 return false;
149 } 361 }
150 362
151 void AppBannerManager::OnEngagementIncreased(content::WebContents* contents, 363 void AppBannerManager::OnEngagementIncreased(content::WebContents* contents,
152 const GURL& url, 364 const GURL& url,
153 double score) { 365 double score) {
154 // Only trigger a banner using site engagement if: 366 // Only trigger a banner using site engagement if:
155 // 1. engagement increased for the web contents which we are attached to; and 367 // 1. engagement increased for the web contents which we are attached to; and
156 // 2. there are no currently active media players; and 368 // 2. there are no currently active media players; and
157 // 3. we have accumulated sufficient engagement. 369 // 3. we have accumulated sufficient engagement.
158 if (web_contents() == contents && active_media_players_.empty() && 370 if (web_contents() == contents && active_media_players_.empty() &&
159 AppBannerSettingsHelper::HasSufficientEngagement(score)) { 371 AppBannerSettingsHelper::HasSufficientEngagement(score)) {
160 // Stop observing so we don't double-trigger the banner. 372 // Stop observing so we don't double-trigger the banner.
161 SiteEngagementObserver::Observe(nullptr); 373 SiteEngagementObserver::Observe(nullptr);
162 374
163 if (!load_finished_) { 375 if (!load_finished_) {
164 // Wait until the main frame finishes loading before requesting a banner. 376 // Wait until the main frame finishes loading before requesting a banner.
165 banner_request_queued_ = true; 377 banner_request_queued_ = true;
166 } else { 378 } else {
167 // Requesting a banner performs some simple tests, creates a data fetcher, 379 // Requesting a banner performs some simple tests, creates a data fetcher,
168 // and starts some asynchronous checks to test installability. It should 380 // and starts some asynchronous checks to test installability. It should
169 // be safe to start this in response to user input. 381 // be safe to start this in response to user input.
170 RequestAppBanner(url, false /* is_debug_mode */); 382 RequestAppBanner(url, false /* is_debug_mode */);
171 } 383 }
172 } 384 }
173 } 385 }
174 386
175 void AppBannerManager::CancelActiveFetcher() { 387 void AppBannerManager::RecordCouldShowBanner() {
176 if (data_fetcher_) { 388 content::WebContents* contents = web_contents();
177 data_fetcher_->Cancel(); 389 DCHECK(contents);
178 data_fetcher_ = nullptr; 390
391 AppBannerSettingsHelper::RecordBannerCouldShowEvent(
392 contents, validated_url_, GetAppIdentifier(),
393 GetCurrentTime(), last_transition_type_);
394 }
395
396 bool AppBannerManager::CheckIfShouldShowBanner() {
397 content::WebContents* contents = web_contents();
398 DCHECK(contents);
399
400 return AppBannerSettingsHelper::ShouldShowBanner(
401 contents, validated_url_, GetAppIdentifier(), GetCurrentTime());
402 }
403
404 bool AppBannerManager::OnMessageReceived(
405 const IPC::Message& message,
406 content::RenderFrameHost* render_frame_host) {
407 bool handled = true;
408
409 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(AppBannerManager, message, render_frame_host)
410 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_AppBannerPromptReply,
411 OnBannerPromptReply)
412 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RequestShowAppBanner,
413 OnRequestShowAppBanner)
414 IPC_MESSAGE_UNHANDLED(handled = false)
415 IPC_END_MESSAGE_MAP()
416
417 return handled;
418 }
419
420 void AppBannerManager::OnBannerPromptReply(
421 content::RenderFrameHost* render_frame_host,
422 int request_id,
423 blink::WebAppBannerPromptReply reply,
424 std::string referrer) {
425 content::WebContents* contents = web_contents();
426 if (request_id != event_request_id_)
427 return;
428
429 // The renderer might have requested the prompt to be canceled.
430 // They may request that it is redisplayed later, so don't Cancel() here.
431 // However, log that the cancelation was requested, so Cancel() can be
432 // called if a redisplay isn't asked for.
433 //
434 // The redisplay request may be received before the Cancel prompt reply
435 // *after* if it is made before the beforeinstallprompt event handler
436 // concludes (e.g. in the event handler itself), so allow the pipeline
437 // to continue in this case.
438 referrer_ = referrer;
439 if (reply == blink::WebAppBannerPromptReply::Cancel &&
440 !page_requested_prompt_) {
441 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_PREVENT_DEFAULT_CALLED);
442 was_canceled_by_page_ = true;
443 ReportError(contents, installable::RENDERER_CANCELLED);
444 return;
445 }
446
447 // If we haven't yet returned, but either of |was_canceled_by_page_| or
448 // |page_requested_prompt_| is true, the page has requested a delayed showing
449 // of the prompt. Otherwise, the prompt was never canceled by the page.
450 if (was_canceled_by_page_ || page_requested_prompt_) {
451 TrackBeforeInstallEvent(
452 BEFORE_INSTALL_EVENT_PROMPT_CALLED_AFTER_PREVENT_DEFAULT);
453 was_canceled_by_page_ = false;
454 } else {
455 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_NO_ACTION);
456 }
457
458 AppBannerSettingsHelper::RecordMinutesFromFirstVisitToShow(
459 contents, validated_url_, GetAppIdentifier(), GetCurrentTime());
460
461 DCHECK(!manifest_url_.is_empty());
462 DCHECK(!manifest_.IsEmpty());
463 DCHECK(!icon_url_.is_empty());
464 DCHECK(icon_.get());
465 TrackBeforeInstallEvent(BEFORE_INSTALL_EVENT_COMPLETE);
466 ShowBanner();
467 is_active_ = false;
468 }
469
470 void AppBannerManager::OnRequestShowAppBanner(
471 content::RenderFrameHost* render_frame_host,
472 int request_id) {
473 if (was_canceled_by_page_) {
474 // Simulate a non-canceled OnBannerPromptReply to show the delayed banner.
475 // Don't reset |was_canceled_by_page_| yet for metrics purposes.
476 OnBannerPromptReply(render_frame_host, request_id,
477 blink::WebAppBannerPromptReply::None, referrer_);
478 } else {
479 // Log that the prompt request was made for when we get the prompt reply.
480 page_requested_prompt_ = true;
179 } 481 }
180 } 482 }
181 483
182 } // namespace banners 484 } // namespace banners
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698