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

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

Issue 1569893003: Add "Request app banner" context menu in DevTools (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: incorporated dominickn's comment Created 4 years, 11 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_data_fetcher.h" 5 #include "chrome/browser/banners/app_banner_data_fetcher.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 // static 64 // static
65 base::Time AppBannerDataFetcher::GetCurrentTime() { 65 base::Time AppBannerDataFetcher::GetCurrentTime() {
66 return base::Time::Now() + gTimeDeltaForTesting; 66 return base::Time::Now() + gTimeDeltaForTesting;
67 } 67 }
68 68
69 // static 69 // static
70 void AppBannerDataFetcher::SetTimeDeltaForTesting(int days) { 70 void AppBannerDataFetcher::SetTimeDeltaForTesting(int days) {
71 gTimeDeltaForTesting = base::TimeDelta::FromDays(days); 71 gTimeDeltaForTesting = base::TimeDelta::FromDays(days);
72 } 72 }
73 73
74 AppBannerDataFetcher::AppBannerDataFetcher( 74 AppBannerDataFetcher::AppBannerDataFetcher(content::WebContents* web_contents,
75 content::WebContents* web_contents, 75 base::WeakPtr<Delegate> delegate,
76 base::WeakPtr<Delegate> delegate, 76 int ideal_icon_size_in_dp,
77 int ideal_icon_size_in_dp, 77 int minimum_icon_size_in_dp,
78 int minimum_icon_size_in_dp) 78 bool is_debug_mode)
79 : WebContentsObserver(web_contents), 79 : WebContentsObserver(web_contents),
80 weak_delegate_(delegate), 80 weak_delegate_(delegate),
81 ideal_icon_size_in_dp_(ideal_icon_size_in_dp), 81 ideal_icon_size_in_dp_(ideal_icon_size_in_dp),
82 minimum_icon_size_in_dp_(minimum_icon_size_in_dp), 82 minimum_icon_size_in_dp_(minimum_icon_size_in_dp),
83 is_active_(false), 83 is_active_(false),
84 was_canceled_by_page_(false), 84 was_canceled_by_page_(false),
85 page_requested_prompt_(false), 85 page_requested_prompt_(false),
86 is_debug_mode_(is_debug_mode ||
87 base::CommandLine::ForCurrentProcess()->HasSwitch(
88 switches::kBypassAppBannerEngagementChecks)),
86 event_request_id_(-1) { 89 event_request_id_(-1) {
87 DCHECK(minimum_icon_size_in_dp <= ideal_icon_size_in_dp); 90 DCHECK(minimum_icon_size_in_dp <= ideal_icon_size_in_dp);
88 } 91 }
89 92
90 void AppBannerDataFetcher::Start(const GURL& validated_url, 93 void AppBannerDataFetcher::Start(const GURL& validated_url,
91 ui::PageTransition transition_type) { 94 ui::PageTransition transition_type) {
92 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 95 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
93 96
94 content::WebContents* web_contents = GetWebContents(); 97 content::WebContents* web_contents = GetWebContents();
95 DCHECK(web_contents); 98 DCHECK(web_contents);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 // The redisplay request may be received before the Cancel prompt reply 180 // The redisplay request may be received before the Cancel prompt reply
178 // *after* if it is made before the beforeinstallprompt event handler 181 // *after* if it is made before the beforeinstallprompt event handler
179 // concludes (e.g. in the event handler itself), so allow the pipeline 182 // concludes (e.g. in the event handler itself), so allow the pipeline
180 // to continue in this case. 183 // to continue in this case.
181 // 184 //
182 // Stash the referrer for the case where the banner is redisplayed. 185 // Stash the referrer for the case where the banner is redisplayed.
183 if (reply == blink::WebAppBannerPromptReply::Cancel && 186 if (reply == blink::WebAppBannerPromptReply::Cancel &&
184 !page_requested_prompt_) { 187 !page_requested_prompt_) {
185 was_canceled_by_page_ = true; 188 was_canceled_by_page_ = true;
186 referrer_ = referrer; 189 referrer_ = referrer;
187 OutputDeveloperNotShownMessage(web_contents, kRendererRequestCancel); 190 OutputDeveloperNotShownMessage(web_contents, kRendererRequestCancel,
191 is_debug_mode_);
188 return; 192 return;
189 } 193 }
190 194
191 AppBannerSettingsHelper::RecordMinutesFromFirstVisitToShow( 195 AppBannerSettingsHelper::RecordMinutesFromFirstVisitToShow(
192 web_contents, validated_url_, GetAppIdentifier(), GetCurrentTime()); 196 web_contents, validated_url_, GetAppIdentifier(), GetCurrentTime());
193 197
194 // Definitely going to show the banner now. 198 // Definitely going to show the banner now.
195 FOR_EACH_OBSERVER(Observer, observer_list_, 199 FOR_EACH_OBSERVER(Observer, observer_list_,
196 OnDecidedWhetherToShow(this, true)); 200 OnDecidedWhetherToShow(this, true));
197 201
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(), 247 rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(),
244 event_name, 248 event_name,
245 web_contents->GetURL()); 249 web_contents->GetURL());
246 } 250 }
247 251
248 void AppBannerDataFetcher::OnDidHasManifest(bool has_manifest) { 252 void AppBannerDataFetcher::OnDidHasManifest(bool has_manifest) {
249 content::WebContents* web_contents = GetWebContents(); 253 content::WebContents* web_contents = GetWebContents();
250 254
251 if (!CheckFetcherIsStillAlive(web_contents) || !has_manifest) { 255 if (!CheckFetcherIsStillAlive(web_contents) || !has_manifest) {
252 if (!has_manifest) 256 if (!has_manifest)
253 OutputDeveloperNotShownMessage(web_contents, kNoManifest); 257 OutputDeveloperNotShownMessage(web_contents, kNoManifest, is_debug_mode_);
254 258
255 Cancel(); 259 Cancel();
256 return; 260 return;
257 } 261 }
258 262
259 web_contents->GetManifest( 263 web_contents->GetManifest(
260 base::Bind(&AppBannerDataFetcher::OnDidGetManifest, this)); 264 base::Bind(&AppBannerDataFetcher::OnDidGetManifest, this));
261 } 265 }
262 266
263 void AppBannerDataFetcher::OnDidGetManifest( 267 void AppBannerDataFetcher::OnDidGetManifest(
264 const content::Manifest& manifest) { 268 const content::Manifest& manifest) {
265 content::WebContents* web_contents = GetWebContents(); 269 content::WebContents* web_contents = GetWebContents();
266 if (!CheckFetcherIsStillAlive(web_contents)) { 270 if (!CheckFetcherIsStillAlive(web_contents)) {
267 Cancel(); 271 Cancel();
268 return; 272 return;
269 } 273 }
270 if (manifest.IsEmpty()) { 274 if (manifest.IsEmpty()) {
271 OutputDeveloperNotShownMessage(web_contents, kManifestEmpty); 275 OutputDeveloperNotShownMessage(web_contents, kManifestEmpty,
276 is_debug_mode_);
272 Cancel(); 277 Cancel();
273 return; 278 return;
274 } 279 }
275 280
276 if (manifest.prefer_related_applications && 281 if (manifest.prefer_related_applications &&
277 manifest.related_applications.size()) { 282 manifest.related_applications.size()) {
278 for (const auto& application : manifest.related_applications) { 283 for (const auto& application : manifest.related_applications) {
279 std::string platform = base::UTF16ToUTF8(application.platform.string()); 284 std::string platform = base::UTF16ToUTF8(application.platform.string());
280 std::string id = base::UTF16ToUTF8(application.id.string()); 285 std::string id = base::UTF16ToUTF8(application.id.string());
281 if (weak_delegate_->HandleNonWebApp(platform, application.url, id)) 286 if (weak_delegate_->HandleNonWebApp(platform, application.url, id,
287 is_debug_mode_))
282 return; 288 return;
283 } 289 }
284 } 290 }
285 291
286 if (!IsManifestValidForWebApp(manifest, web_contents)) { 292 if (!IsManifestValidForWebApp(manifest, web_contents, is_debug_mode_)) {
287 Cancel(); 293 Cancel();
288 return; 294 return;
289 } 295 }
290 296
291 web_app_data_ = manifest; 297 web_app_data_ = manifest;
292 app_title_ = web_app_data_.name.string(); 298 app_title_ = web_app_data_.name.string();
293 299
294 if (IsWebAppInstalled(web_contents->GetBrowserContext(), 300 if (IsWebAppInstalled(web_contents->GetBrowserContext(),
295 manifest.start_url) && 301 manifest.start_url) &&
296 !base::CommandLine::ForCurrentProcess()->HasSwitch( 302 !is_debug_mode_) {
297 switches::kBypassAppBannerEngagementChecks)) { 303 OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded,
dominickn 2016/01/19 02:25:10 Looking at this again, printing an error message h
298 OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded); 304 is_debug_mode_);
299 Cancel(); 305 Cancel();
300 return; 306 return;
301 } 307 }
302 308
303 banners::TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_REQUESTED); 309 banners::TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_REQUESTED);
304 310
305 // Check to see if there is a single service worker controlling this page 311 // Check to see if there is a single service worker controlling this page
306 // and the manifest's start url. 312 // and the manifest's start url.
307 Profile* profile = 313 Profile* profile =
308 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 314 Profile::FromBrowserContext(web_contents->GetBrowserContext());
(...skipping 11 matching lines...) Expand all
320 void AppBannerDataFetcher::OnDidCheckHasServiceWorker( 326 void AppBannerDataFetcher::OnDidCheckHasServiceWorker(
321 bool has_service_worker) { 327 bool has_service_worker) {
322 content::WebContents* web_contents = GetWebContents(); 328 content::WebContents* web_contents = GetWebContents();
323 if (!CheckFetcherIsStillAlive(web_contents)) { 329 if (!CheckFetcherIsStillAlive(web_contents)) {
324 Cancel(); 330 Cancel();
325 return; 331 return;
326 } 332 }
327 333
328 if (!has_service_worker) { 334 if (!has_service_worker) {
329 TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER); 335 TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER);
330 OutputDeveloperNotShownMessage(web_contents, kNoMatchingServiceWorker); 336 OutputDeveloperNotShownMessage(web_contents, kNoMatchingServiceWorker,
337 is_debug_mode_);
331 Cancel(); 338 Cancel();
332 return; 339 return;
333 } 340 }
334 341
335 OnHasServiceWorker(web_contents); 342 OnHasServiceWorker(web_contents);
336 } 343 }
337 344
338 void AppBannerDataFetcher::OnHasServiceWorker( 345 void AppBannerDataFetcher::OnHasServiceWorker(
339 content::WebContents* web_contents) { 346 content::WebContents* web_contents) {
340 GURL icon_url = 347 GURL icon_url =
341 ManifestIconSelector::FindBestMatchingIcon( 348 ManifestIconSelector::FindBestMatchingIcon(
342 web_app_data_.icons, 349 web_app_data_.icons,
343 ideal_icon_size_in_dp_, 350 ideal_icon_size_in_dp_,
344 minimum_icon_size_in_dp_, 351 minimum_icon_size_in_dp_,
345 gfx::Screen::GetScreenFor(web_contents->GetNativeView())); 352 gfx::Screen::GetScreenFor(web_contents->GetNativeView()));
346 353
347 if (!FetchAppIcon(web_contents, icon_url)) { 354 if (!FetchAppIcon(web_contents, icon_url)) {
348 OutputDeveloperNotShownMessage(web_contents, kCannotDetermineBestIcon); 355 OutputDeveloperNotShownMessage(web_contents, kCannotDetermineBestIcon,
356 is_debug_mode_);
349 Cancel(); 357 Cancel();
350 } 358 }
351 } 359 }
352 360
353 bool AppBannerDataFetcher::FetchAppIcon(content::WebContents* web_contents, 361 bool AppBannerDataFetcher::FetchAppIcon(content::WebContents* web_contents,
354 const GURL& icon_url) { 362 const GURL& icon_url) {
355 return ManifestIconDownloader::Download( 363 return ManifestIconDownloader::Download(
356 web_contents, 364 web_contents,
357 icon_url, 365 icon_url,
358 ideal_icon_size_in_dp_, 366 ideal_icon_size_in_dp_,
359 minimum_icon_size_in_dp_, 367 minimum_icon_size_in_dp_,
360 base::Bind(&AppBannerDataFetcher::OnAppIconFetched, 368 base::Bind(&AppBannerDataFetcher::OnAppIconFetched,
361 this)); 369 this));
362 } 370 }
363 371
364 void AppBannerDataFetcher::OnAppIconFetched(const SkBitmap& bitmap) { 372 void AppBannerDataFetcher::OnAppIconFetched(const SkBitmap& bitmap) {
365 if (!is_active_) return; 373 if (!is_active_) return;
366 374
367 content::WebContents* web_contents = GetWebContents(); 375 content::WebContents* web_contents = GetWebContents();
368 if (!CheckFetcherIsStillAlive(web_contents)) { 376 if (!CheckFetcherIsStillAlive(web_contents)) {
369 Cancel(); 377 Cancel();
370 return; 378 return;
371 } 379 }
372 if (bitmap.drawsNothing()) { 380 if (bitmap.drawsNothing()) {
373 OutputDeveloperNotShownMessage(web_contents, kNoIconAvailable); 381 OutputDeveloperNotShownMessage(web_contents, kNoIconAvailable,
382 is_debug_mode_);
374 Cancel(); 383 Cancel();
375 return; 384 return;
376 } 385 }
377 386
378 RecordCouldShowBanner(); 387 RecordCouldShowBanner();
379 if (!CheckIfShouldShowBanner()) { 388 if (!is_debug_mode_ && !CheckIfShouldShowBanner()) {
380 // At this point, the only possible case is that the banner has been added 389 // At this point, the only possible case is that the banner has been added
381 // to the homescreen, given all of the other checks that have been made. 390 // to the homescreen, given all of the other checks that have been made.
382 OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded); 391 OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded,
392 is_debug_mode_);
383 Cancel(); 393 Cancel();
384 return; 394 return;
385 } 395 }
386 396
387 app_icon_.reset(new SkBitmap(bitmap)); 397 app_icon_.reset(new SkBitmap(bitmap));
388 event_request_id_ = ++gCurrentRequestID; 398 event_request_id_ = ++gCurrentRequestID;
389 web_contents->GetMainFrame()->Send( 399 web_contents->GetMainFrame()->Send(
390 new ChromeViewMsg_AppBannerPromptRequest( 400 new ChromeViewMsg_AppBannerPromptRequest(
391 web_contents->GetMainFrame()->GetRoutingID(), 401 web_contents->GetMainFrame()->GetRoutingID(),
392 event_request_id_, 402 event_request_id_,
(...skipping 19 matching lines...) Expand all
412 content::WebContents* web_contents = GetWebContents(); 422 content::WebContents* web_contents = GetWebContents();
413 DCHECK(web_contents); 423 DCHECK(web_contents);
414 424
415 return AppBannerSettingsHelper::ShouldShowBanner( 425 return AppBannerSettingsHelper::ShouldShowBanner(
416 web_contents, validated_url_, GetAppIdentifier(), GetCurrentTime()); 426 web_contents, validated_url_, GetAppIdentifier(), GetCurrentTime());
417 } 427 }
418 428
419 bool AppBannerDataFetcher::CheckFetcherIsStillAlive( 429 bool AppBannerDataFetcher::CheckFetcherIsStillAlive(
420 content::WebContents* web_contents) { 430 content::WebContents* web_contents) {
421 if (!is_active_) { 431 if (!is_active_) {
422 OutputDeveloperNotShownMessage(web_contents, 432 OutputDeveloperNotShownMessage(
423 kUserNavigatedBeforeBannerShown); 433 web_contents, kUserNavigatedBeforeBannerShown, is_debug_mode_);
424 return false; 434 return false;
425 } 435 }
426 if (!web_contents) { 436 if (!web_contents) {
427 return false; // We cannot show a message if |web_contents| is null 437 return false; // We cannot show a message if |web_contents| is null
428 } 438 }
429 return true; 439 return true;
430 } 440 }
431 441
432 // static 442 // static
433 bool AppBannerDataFetcher::IsManifestValidForWebApp( 443 bool AppBannerDataFetcher::IsManifestValidForWebApp(
434 const content::Manifest& manifest, 444 const content::Manifest& manifest,
435 content::WebContents* web_contents) { 445 content::WebContents* web_contents,
446 bool is_debug_mode) {
436 if (manifest.IsEmpty()) { 447 if (manifest.IsEmpty()) {
437 OutputDeveloperNotShownMessage(web_contents, kManifestEmpty); 448 OutputDeveloperNotShownMessage(web_contents, kManifestEmpty, is_debug_mode);
438 return false; 449 return false;
439 } 450 }
440 if (!manifest.start_url.is_valid()) { 451 if (!manifest.start_url.is_valid()) {
441 OutputDeveloperNotShownMessage(web_contents, kStartURLNotValid); 452 OutputDeveloperNotShownMessage(web_contents, kStartURLNotValid,
453 is_debug_mode);
442 return false; 454 return false;
443 } 455 }
444 if (manifest.name.is_null() && manifest.short_name.is_null()) { 456 if (manifest.name.is_null() && manifest.short_name.is_null()) {
445 OutputDeveloperNotShownMessage(web_contents, 457 OutputDeveloperNotShownMessage(
446 kManifestMissingNameOrShortName); 458 web_contents, kManifestMissingNameOrShortName, is_debug_mode);
447 return false; 459 return false;
448 } 460 }
449 if (!DoesManifestContainRequiredIcon(manifest)) { 461 if (!DoesManifestContainRequiredIcon(manifest)) {
450 OutputDeveloperNotShownMessage(web_contents, kManifestMissingSuitableIcon); 462 OutputDeveloperNotShownMessage(web_contents, kManifestMissingSuitableIcon,
463 is_debug_mode);
451 return false; 464 return false;
452 } 465 }
453 return true; 466 return true;
454 } 467 }
455 468
456 } // namespace banners 469 } // namespace banners
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698