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_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 Loading... |
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 event_request_id_(-1) { | 86 event_request_id_(-1), |
| 87 is_debug_mode_(is_debug_mode) { |
87 DCHECK(minimum_icon_size_in_dp <= ideal_icon_size_in_dp); | 88 DCHECK(minimum_icon_size_in_dp <= ideal_icon_size_in_dp); |
88 } | 89 } |
89 | 90 |
90 void AppBannerDataFetcher::Start(const GURL& validated_url, | 91 void AppBannerDataFetcher::Start(const GURL& validated_url, |
91 ui::PageTransition transition_type) { | 92 ui::PageTransition transition_type) { |
92 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 93 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
93 | 94 |
94 content::WebContents* web_contents = GetWebContents(); | 95 content::WebContents* web_contents = GetWebContents(); |
95 DCHECK(web_contents); | 96 DCHECK(web_contents); |
96 | 97 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 // The redisplay request may be received before the Cancel prompt reply | 178 // The redisplay request may be received before the Cancel prompt reply |
178 // *after* if it is made before the beforeinstallprompt event handler | 179 // *after* if it is made before the beforeinstallprompt event handler |
179 // concludes (e.g. in the event handler itself), so allow the pipeline | 180 // concludes (e.g. in the event handler itself), so allow the pipeline |
180 // to continue in this case. | 181 // to continue in this case. |
181 // | 182 // |
182 // Stash the referrer for the case where the banner is redisplayed. | 183 // Stash the referrer for the case where the banner is redisplayed. |
183 if (reply == blink::WebAppBannerPromptReply::Cancel && | 184 if (reply == blink::WebAppBannerPromptReply::Cancel && |
184 !page_requested_prompt_) { | 185 !page_requested_prompt_) { |
185 was_canceled_by_page_ = true; | 186 was_canceled_by_page_ = true; |
186 referrer_ = referrer; | 187 referrer_ = referrer; |
187 OutputDeveloperNotShownMessage(web_contents, kRendererRequestCancel); | 188 OutputDeveloperNotShownMessage(web_contents, kRendererRequestCancel, |
| 189 is_debug_mode_); |
188 return; | 190 return; |
189 } | 191 } |
190 | 192 |
191 // Definitely going to show the banner now. | 193 // Definitely going to show the banner now. |
192 FOR_EACH_OBSERVER(Observer, observer_list_, | 194 FOR_EACH_OBSERVER(Observer, observer_list_, |
193 OnDecidedWhetherToShow(this, true)); | 195 OnDecidedWhetherToShow(this, true)); |
194 | 196 |
195 ShowBanner(app_icon_.get(), app_title_, referrer); | 197 ShowBanner(app_icon_.get(), app_title_, referrer); |
196 is_active_ = false; | 198 is_active_ = false; |
197 } | 199 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(), | 242 rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(), |
241 event_name, | 243 event_name, |
242 web_contents->GetURL()); | 244 web_contents->GetURL()); |
243 } | 245 } |
244 | 246 |
245 void AppBannerDataFetcher::OnDidHasManifest(bool has_manifest) { | 247 void AppBannerDataFetcher::OnDidHasManifest(bool has_manifest) { |
246 content::WebContents* web_contents = GetWebContents(); | 248 content::WebContents* web_contents = GetWebContents(); |
247 | 249 |
248 if (!CheckFetcherIsStillAlive(web_contents) || !has_manifest) { | 250 if (!CheckFetcherIsStillAlive(web_contents) || !has_manifest) { |
249 if (!has_manifest) | 251 if (!has_manifest) |
250 OutputDeveloperNotShownMessage(web_contents, kNoManifest); | 252 OutputDeveloperNotShownMessage(web_contents, kNoManifest, is_debug_mode_); |
251 | 253 |
252 Cancel(); | 254 Cancel(); |
253 return; | 255 return; |
254 } | 256 } |
255 | 257 |
256 web_contents->GetManifest( | 258 web_contents->GetManifest( |
257 base::Bind(&AppBannerDataFetcher::OnDidGetManifest, this)); | 259 base::Bind(&AppBannerDataFetcher::OnDidGetManifest, this)); |
258 } | 260 } |
259 | 261 |
260 void AppBannerDataFetcher::OnDidGetManifest( | 262 void AppBannerDataFetcher::OnDidGetManifest( |
261 const content::Manifest& manifest) { | 263 const content::Manifest& manifest) { |
262 content::WebContents* web_contents = GetWebContents(); | 264 content::WebContents* web_contents = GetWebContents(); |
263 if (!CheckFetcherIsStillAlive(web_contents)) { | 265 if (!CheckFetcherIsStillAlive(web_contents)) { |
264 Cancel(); | 266 Cancel(); |
265 return; | 267 return; |
266 } | 268 } |
267 if (manifest.IsEmpty()) { | 269 if (manifest.IsEmpty()) { |
268 OutputDeveloperNotShownMessage(web_contents, kManifestEmpty); | 270 OutputDeveloperNotShownMessage(web_contents, kManifestEmpty, |
| 271 is_debug_mode_); |
269 Cancel(); | 272 Cancel(); |
270 return; | 273 return; |
271 } | 274 } |
272 | 275 |
273 if (manifest.prefer_related_applications && | 276 if (manifest.prefer_related_applications && |
274 manifest.related_applications.size()) { | 277 manifest.related_applications.size()) { |
275 for (const auto& application : manifest.related_applications) { | 278 for (const auto& application : manifest.related_applications) { |
276 std::string platform = base::UTF16ToUTF8(application.platform.string()); | 279 std::string platform = base::UTF16ToUTF8(application.platform.string()); |
277 std::string id = base::UTF16ToUTF8(application.id.string()); | 280 std::string id = base::UTF16ToUTF8(application.id.string()); |
278 if (weak_delegate_->HandleNonWebApp(platform, application.url, id)) | 281 if (weak_delegate_->HandleNonWebApp(platform, application.url, id)) |
279 return; | 282 return; |
280 } | 283 } |
281 } | 284 } |
282 | 285 |
283 if (!IsManifestValidForWebApp(manifest, web_contents)) { | 286 if (!IsManifestValidForWebApp(manifest, web_contents, is_debug_mode_)) { |
284 Cancel(); | 287 Cancel(); |
285 return; | 288 return; |
286 } | 289 } |
287 | 290 |
288 web_app_data_ = manifest; | 291 web_app_data_ = manifest; |
289 app_title_ = web_app_data_.name.string(); | 292 app_title_ = web_app_data_.name.string(); |
290 | 293 |
291 if (IsWebAppInstalled(web_contents->GetBrowserContext(), | 294 if (IsWebAppInstalled(web_contents->GetBrowserContext(), |
292 manifest.start_url) && | 295 manifest.start_url) && |
293 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 296 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
294 switches::kBypassAppBannerEngagementChecks)) { | 297 switches::kBypassAppBannerEngagementChecks)) { |
295 OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded); | 298 OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded, |
| 299 is_debug_mode_); |
296 Cancel(); | 300 Cancel(); |
297 return; | 301 return; |
298 } | 302 } |
299 | 303 |
300 banners::TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_REQUESTED); | 304 banners::TrackDisplayEvent(DISPLAY_EVENT_WEB_APP_BANNER_REQUESTED); |
301 | 305 |
302 // Check to see if there is a single service worker controlling this page | 306 // Check to see if there is a single service worker controlling this page |
303 // and the manifest's start url. | 307 // and the manifest's start url. |
304 Profile* profile = | 308 Profile* profile = |
305 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 309 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
(...skipping 11 matching lines...) Expand all Loading... |
317 void AppBannerDataFetcher::OnDidCheckHasServiceWorker( | 321 void AppBannerDataFetcher::OnDidCheckHasServiceWorker( |
318 bool has_service_worker) { | 322 bool has_service_worker) { |
319 content::WebContents* web_contents = GetWebContents(); | 323 content::WebContents* web_contents = GetWebContents(); |
320 if (!CheckFetcherIsStillAlive(web_contents)) { | 324 if (!CheckFetcherIsStillAlive(web_contents)) { |
321 Cancel(); | 325 Cancel(); |
322 return; | 326 return; |
323 } | 327 } |
324 | 328 |
325 if (!has_service_worker) { | 329 if (!has_service_worker) { |
326 TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER); | 330 TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER); |
327 OutputDeveloperNotShownMessage(web_contents, kNoMatchingServiceWorker); | 331 OutputDeveloperNotShownMessage(web_contents, kNoMatchingServiceWorker, |
| 332 is_debug_mode_); |
328 Cancel(); | 333 Cancel(); |
329 return; | 334 return; |
330 } | 335 } |
331 | 336 |
332 OnHasServiceWorker(web_contents); | 337 OnHasServiceWorker(web_contents); |
333 } | 338 } |
334 | 339 |
335 void AppBannerDataFetcher::OnHasServiceWorker( | 340 void AppBannerDataFetcher::OnHasServiceWorker( |
336 content::WebContents* web_contents) { | 341 content::WebContents* web_contents) { |
337 GURL icon_url = | 342 GURL icon_url = |
338 ManifestIconSelector::FindBestMatchingIcon( | 343 ManifestIconSelector::FindBestMatchingIcon( |
339 web_app_data_.icons, | 344 web_app_data_.icons, |
340 ideal_icon_size_in_dp_, | 345 ideal_icon_size_in_dp_, |
341 minimum_icon_size_in_dp_, | 346 minimum_icon_size_in_dp_, |
342 gfx::Screen::GetScreenFor(web_contents->GetNativeView())); | 347 gfx::Screen::GetScreenFor(web_contents->GetNativeView())); |
343 | 348 |
344 if (!FetchAppIcon(web_contents, icon_url)) { | 349 if (!FetchAppIcon(web_contents, icon_url)) { |
345 OutputDeveloperNotShownMessage(web_contents, kCannotDetermineBestIcon); | 350 OutputDeveloperNotShownMessage(web_contents, kCannotDetermineBestIcon, |
| 351 is_debug_mode_); |
346 Cancel(); | 352 Cancel(); |
347 } | 353 } |
348 } | 354 } |
349 | 355 |
350 bool AppBannerDataFetcher::FetchAppIcon(content::WebContents* web_contents, | 356 bool AppBannerDataFetcher::FetchAppIcon(content::WebContents* web_contents, |
351 const GURL& icon_url) { | 357 const GURL& icon_url) { |
352 return ManifestIconDownloader::Download( | 358 return ManifestIconDownloader::Download( |
353 web_contents, | 359 web_contents, |
354 icon_url, | 360 icon_url, |
355 ideal_icon_size_in_dp_, | 361 ideal_icon_size_in_dp_, |
356 minimum_icon_size_in_dp_, | 362 minimum_icon_size_in_dp_, |
357 base::Bind(&AppBannerDataFetcher::OnAppIconFetched, | 363 base::Bind(&AppBannerDataFetcher::OnAppIconFetched, |
358 this)); | 364 this)); |
359 } | 365 } |
360 | 366 |
361 void AppBannerDataFetcher::OnAppIconFetched(const SkBitmap& bitmap) { | 367 void AppBannerDataFetcher::OnAppIconFetched(const SkBitmap& bitmap) { |
362 if (!is_active_) return; | 368 if (!is_active_) return; |
363 | 369 |
364 content::WebContents* web_contents = GetWebContents(); | 370 content::WebContents* web_contents = GetWebContents(); |
365 if (!CheckFetcherIsStillAlive(web_contents)) { | 371 if (!CheckFetcherIsStillAlive(web_contents)) { |
366 Cancel(); | 372 Cancel(); |
367 return; | 373 return; |
368 } | 374 } |
369 if (bitmap.drawsNothing()) { | 375 if (bitmap.drawsNothing()) { |
370 OutputDeveloperNotShownMessage(web_contents, kNoIconAvailable); | 376 OutputDeveloperNotShownMessage(web_contents, kNoIconAvailable, |
| 377 is_debug_mode_); |
371 Cancel(); | 378 Cancel(); |
372 return; | 379 return; |
373 } | 380 } |
374 | 381 |
375 RecordCouldShowBanner(); | 382 RecordCouldShowBanner(); |
376 if (!CheckIfShouldShowBanner()) { | 383 if (!is_debug_mode_ && !CheckIfShouldShowBanner()) { |
377 // At this point, the only possible case is that the banner has been added | 384 // At this point, the only possible case is that the banner has been added |
378 // to the homescreen, given all of the other checks that have been made. | 385 // to the homescreen, given all of the other checks that have been made. |
379 OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded); | 386 OutputDeveloperNotShownMessage(web_contents, kBannerAlreadyAdded, |
| 387 is_debug_mode_); |
380 Cancel(); | 388 Cancel(); |
381 return; | 389 return; |
382 } | 390 } |
383 | 391 |
384 app_icon_.reset(new SkBitmap(bitmap)); | 392 app_icon_.reset(new SkBitmap(bitmap)); |
385 event_request_id_ = ++gCurrentRequestID; | 393 event_request_id_ = ++gCurrentRequestID; |
386 web_contents->GetMainFrame()->Send( | 394 web_contents->GetMainFrame()->Send( |
387 new ChromeViewMsg_AppBannerPromptRequest( | 395 new ChromeViewMsg_AppBannerPromptRequest( |
388 web_contents->GetMainFrame()->GetRoutingID(), | 396 web_contents->GetMainFrame()->GetRoutingID(), |
389 event_request_id_, | 397 event_request_id_, |
(...skipping 19 matching lines...) Expand all Loading... |
409 content::WebContents* web_contents = GetWebContents(); | 417 content::WebContents* web_contents = GetWebContents(); |
410 DCHECK(web_contents); | 418 DCHECK(web_contents); |
411 | 419 |
412 return AppBannerSettingsHelper::ShouldShowBanner( | 420 return AppBannerSettingsHelper::ShouldShowBanner( |
413 web_contents, validated_url_, GetAppIdentifier(), GetCurrentTime()); | 421 web_contents, validated_url_, GetAppIdentifier(), GetCurrentTime()); |
414 } | 422 } |
415 | 423 |
416 bool AppBannerDataFetcher::CheckFetcherIsStillAlive( | 424 bool AppBannerDataFetcher::CheckFetcherIsStillAlive( |
417 content::WebContents* web_contents) { | 425 content::WebContents* web_contents) { |
418 if (!is_active_) { | 426 if (!is_active_) { |
419 OutputDeveloperNotShownMessage(web_contents, | 427 OutputDeveloperNotShownMessage( |
420 kUserNavigatedBeforeBannerShown); | 428 web_contents, kUserNavigatedBeforeBannerShown, is_debug_mode_); |
421 return false; | 429 return false; |
422 } | 430 } |
423 if (!web_contents) { | 431 if (!web_contents) { |
424 return false; // We cannot show a message if |web_contents| is null | 432 return false; // We cannot show a message if |web_contents| is null |
425 } | 433 } |
426 return true; | 434 return true; |
427 } | 435 } |
428 | 436 |
429 // static | 437 // static |
430 bool AppBannerDataFetcher::IsManifestValidForWebApp( | 438 bool AppBannerDataFetcher::IsManifestValidForWebApp( |
431 const content::Manifest& manifest, | 439 const content::Manifest& manifest, |
432 content::WebContents* web_contents) { | 440 content::WebContents* web_contents, |
| 441 bool is_debug_mode) { |
433 if (manifest.IsEmpty()) { | 442 if (manifest.IsEmpty()) { |
434 OutputDeveloperNotShownMessage(web_contents, kManifestEmpty); | 443 OutputDeveloperNotShownMessage(web_contents, kManifestEmpty, is_debug_mode); |
435 return false; | 444 return false; |
436 } | 445 } |
437 if (!manifest.start_url.is_valid()) { | 446 if (!manifest.start_url.is_valid()) { |
438 OutputDeveloperNotShownMessage(web_contents, kStartURLNotValid); | 447 OutputDeveloperNotShownMessage(web_contents, kStartURLNotValid, |
| 448 is_debug_mode); |
439 return false; | 449 return false; |
440 } | 450 } |
441 if (manifest.name.is_null() && manifest.short_name.is_null()) { | 451 if (manifest.name.is_null() && manifest.short_name.is_null()) { |
442 OutputDeveloperNotShownMessage(web_contents, | 452 OutputDeveloperNotShownMessage( |
443 kManifestMissingNameOrShortName); | 453 web_contents, kManifestMissingNameOrShortName, is_debug_mode); |
444 return false; | 454 return false; |
445 } | 455 } |
446 if (!DoesManifestContainRequiredIcon(manifest)) { | 456 if (!DoesManifestContainRequiredIcon(manifest)) { |
447 OutputDeveloperNotShownMessage(web_contents, kManifestMissingSuitableIcon); | 457 OutputDeveloperNotShownMessage(web_contents, kManifestMissingSuitableIcon, |
| 458 is_debug_mode); |
448 return false; | 459 return false; |
449 } | 460 } |
450 return true; | 461 return true; |
451 } | 462 } |
452 | 463 |
453 } // namespace banners | 464 } // namespace banners |
OLD | NEW |