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" | |
benwells
2015/05/11 08:08:40
I don't think this include is needed now.
dominickn (DO NOT USE)
2015/05/12 07:41:31
Done.
| |
8 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
9 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
11 #include "chrome/browser/banners/app_banner_debug_log.h" | |
10 #include "chrome/browser/banners/app_banner_metrics.h" | 12 #include "chrome/browser/banners/app_banner_metrics.h" |
11 #include "chrome/browser/banners/app_banner_settings_helper.h" | 13 #include "chrome/browser/banners/app_banner_settings_helper.h" |
12 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" | 14 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" |
13 #include "chrome/browser/browser_process.h" | 15 #include "chrome/browser/browser_process.h" |
14 #include "chrome/browser/infobars/infobar_service.h" | 16 #include "chrome/browser/infobars/infobar_service.h" |
15 #include "chrome/browser/manifest/manifest_icon_selector.h" | 17 #include "chrome/browser/manifest/manifest_icon_selector.h" |
16 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
19 #include "chrome/common/chrome_switches.h" | |
benwells
2015/05/11 08:08:40
This too.
dominickn (DO NOT USE)
2015/05/12 07:41:31
Done.
| |
17 #include "chrome/common/render_messages.h" | 20 #include "chrome/common/render_messages.h" |
18 #include "components/infobars/core/infobar.h" | 21 #include "components/infobars/core/infobar.h" |
19 #include "components/rappor/rappor_utils.h" | 22 #include "components/rappor/rappor_utils.h" |
20 #include "content/public/browser/browser_context.h" | 23 #include "content/public/browser/browser_context.h" |
21 #include "content/public/browser/browser_thread.h" | 24 #include "content/public/browser/browser_thread.h" |
22 #include "content/public/browser/navigation_details.h" | 25 #include "content/public/browser/navigation_details.h" |
23 #include "content/public/browser/render_frame_host.h" | 26 #include "content/public/browser/render_frame_host.h" |
24 #include "content/public/browser/service_worker_context.h" | 27 #include "content/public/browser/service_worker_context.h" |
25 #include "content/public/browser/storage_partition.h" | 28 #include "content/public/browser/storage_partition.h" |
26 #include "net/base/load_flags.h" | 29 #include "net/base/load_flags.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 } | 68 } |
66 | 69 |
67 AppBannerDataFetcher::AppBannerDataFetcher( | 70 AppBannerDataFetcher::AppBannerDataFetcher( |
68 content::WebContents* web_contents, | 71 content::WebContents* web_contents, |
69 base::WeakPtr<Delegate> delegate, | 72 base::WeakPtr<Delegate> delegate, |
70 int ideal_icon_size) | 73 int ideal_icon_size) |
71 : WebContentsObserver(web_contents), | 74 : WebContentsObserver(web_contents), |
72 ideal_icon_size_(ideal_icon_size), | 75 ideal_icon_size_(ideal_icon_size), |
73 weak_delegate_(delegate), | 76 weak_delegate_(delegate), |
74 is_active_(false), | 77 is_active_(false), |
78 log_err_(false), | |
75 event_request_id_(-1) { | 79 event_request_id_(-1) { |
76 } | 80 } |
77 | 81 |
78 void AppBannerDataFetcher::Start(const GURL& validated_url) { | 82 void AppBannerDataFetcher::Start(const GURL& validated_url) { |
79 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 83 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
80 | 84 |
81 content::WebContents* web_contents = GetWebContents(); | 85 content::WebContents* web_contents = GetWebContents(); |
82 DCHECK(web_contents); | 86 DCHECK(web_contents); |
83 | 87 |
84 is_active_ = true; | 88 is_active_ = true; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 IPC_END_MESSAGE_MAP() | 137 IPC_END_MESSAGE_MAP() |
134 | 138 |
135 return handled; | 139 return handled; |
136 } | 140 } |
137 | 141 |
138 void AppBannerDataFetcher::OnBannerPromptReply( | 142 void AppBannerDataFetcher::OnBannerPromptReply( |
139 content::RenderFrameHost* render_frame_host, | 143 content::RenderFrameHost* render_frame_host, |
140 int request_id, | 144 int request_id, |
141 blink::WebAppBannerPromptReply reply) { | 145 blink::WebAppBannerPromptReply reply) { |
142 content::WebContents* web_contents = GetWebContents(); | 146 content::WebContents* web_contents = GetWebContents(); |
143 if (!is_active_ || !web_contents || request_id != event_request_id_) { | 147 if (!CheckFetcherIsStillAlive(web_contents, "user navigated") || |
148 request_id != event_request_id_) { | |
144 Cancel(); | 149 Cancel(); |
145 return; | 150 return; |
146 } | 151 } |
147 | 152 |
148 // The renderer might have requested the prompt to be canceled. | 153 // The renderer might have requested the prompt to be canceled. |
149 if (reply == blink::WebAppBannerPromptReply::Cancel) { | 154 if (reply == blink::WebAppBannerPromptReply::Cancel) { |
155 // TODO(mlamouri,benwells): we should probably record that to behave | |
benwells
2015/05/11 08:08:40
This TODO has been removed, it must have come back
dominickn (DO NOT USE)
2015/05/12 07:41:31
Done.
| |
156 // differently with regard to showing the banner. | |
157 SendDebugMessage(web_contents, | |
158 "not shown: renderer has requested the banner prompt be cancelled"); | |
150 Cancel(); | 159 Cancel(); |
151 return; | 160 return; |
152 } | 161 } |
153 | 162 |
154 // Definitely going to show the banner now. | 163 // Definitely going to show the banner now. |
155 FOR_EACH_OBSERVER(Observer, observer_list_, | 164 FOR_EACH_OBSERVER(Observer, observer_list_, |
156 OnDecidedWhetherToShow(this, true)); | 165 OnDecidedWhetherToShow(this, true)); |
157 | 166 |
158 infobars::InfoBar* infobar = CreateBanner(app_icon_.get(), app_title_); | 167 infobars::InfoBar* infobar = CreateBanner(app_icon_.get(), app_title_); |
159 if (infobar) { | 168 if (infobar) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
224 GetCurrentTime()); | 233 GetCurrentTime()); |
225 rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(), | 234 rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(), |
226 event_name, | 235 event_name, |
227 web_contents->GetURL()); | 236 web_contents->GetURL()); |
228 banners::TrackDisplayEvent(DISPLAY_EVENT_CREATED); | 237 banners::TrackDisplayEvent(DISPLAY_EVENT_CREATED); |
229 } | 238 } |
230 | 239 |
231 void AppBannerDataFetcher::OnDidGetManifest( | 240 void AppBannerDataFetcher::OnDidGetManifest( |
232 const content::Manifest& manifest) { | 241 const content::Manifest& manifest) { |
233 content::WebContents* web_contents = GetWebContents(); | 242 content::WebContents* web_contents = GetWebContents(); |
234 if (!is_active_ || !web_contents || manifest.IsEmpty()) { | 243 if (!CheckFetcherIsStillAlive(web_contents, "manifest checking") || |
244 manifest.IsEmpty()) { | |
245 if (manifest.IsEmpty()) | |
benwells
2015/05/11 08:08:40
This is a little convoluted. It would probably be
dominickn (DO NOT USE)
2015/05/12 07:41:31
Done.
| |
246 SendDebugMessage(web_contents, "not shown: manifest is empty"); | |
235 Cancel(); | 247 Cancel(); |
236 return; | 248 return; |
237 } | 249 } |
238 | 250 |
239 if (manifest.prefer_related_applications && | 251 if (manifest.prefer_related_applications && |
240 manifest.related_applications.size()) { | 252 manifest.related_applications.size()) { |
241 for (const auto& application : manifest.related_applications) { | 253 for (const auto& application : manifest.related_applications) { |
242 std::string platform = base::UTF16ToUTF8(application.platform.string()); | 254 std::string platform = base::UTF16ToUTF8(application.platform.string()); |
243 std::string id = base::UTF16ToUTF8(application.id.string()); | 255 std::string id = base::UTF16ToUTF8(application.id.string()); |
244 if (weak_delegate_->HandleNonWebApp(platform, application.url, id)) | 256 if (weak_delegate_->HandleNonWebApp(platform, application.url, id)) |
245 return; | 257 return; |
246 } | 258 } |
247 } | 259 } |
248 | 260 |
249 if (!IsManifestValidForWebApp(manifest)) { | 261 if (!IsManifestValidForWebApp(manifest, web_contents)) { |
250 Cancel(); | 262 Cancel(); |
251 return; | 263 return; |
252 } | 264 } |
253 | 265 |
254 banners::TrackDisplayEvent(DISPLAY_EVENT_BANNER_REQUESTED); | 266 banners::TrackDisplayEvent(DISPLAY_EVENT_BANNER_REQUESTED); |
255 | 267 |
256 web_app_data_ = manifest; | 268 web_app_data_ = manifest; |
257 app_title_ = web_app_data_.name.string(); | 269 app_title_ = web_app_data_.name.string(); |
258 | 270 |
259 // Check to see if there is a single service worker controlling this page | 271 // Check to see if there is a single service worker controlling this page |
260 // and the manifest's start url. | 272 // and the manifest's start url. |
261 Profile* profile = | 273 Profile* profile = |
262 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 274 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
263 content::StoragePartition* storage_partition = | 275 content::StoragePartition* storage_partition = |
264 content::BrowserContext::GetStoragePartition( | 276 content::BrowserContext::GetStoragePartition( |
265 profile, web_contents->GetSiteInstance()); | 277 profile, web_contents->GetSiteInstance()); |
266 DCHECK(storage_partition); | 278 DCHECK(storage_partition); |
267 | 279 |
268 storage_partition->GetServiceWorkerContext()->CheckHasServiceWorker( | 280 storage_partition->GetServiceWorkerContext()->CheckHasServiceWorker( |
269 validated_url_, manifest.start_url, | 281 validated_url_, manifest.start_url, |
270 base::Bind(&AppBannerDataFetcher::OnDidCheckHasServiceWorker, | 282 base::Bind(&AppBannerDataFetcher::OnDidCheckHasServiceWorker, |
271 this)); | 283 this)); |
272 } | 284 } |
273 | 285 |
274 void AppBannerDataFetcher::OnDidCheckHasServiceWorker( | 286 void AppBannerDataFetcher::OnDidCheckHasServiceWorker( |
275 bool has_service_worker) { | 287 bool has_service_worker) { |
276 content::WebContents* web_contents = GetWebContents(); | 288 content::WebContents* web_contents = GetWebContents(); |
277 if (!is_active_ || !web_contents) { | 289 if (!CheckFetcherIsStillAlive(web_contents, "service worker checking")) { |
278 Cancel(); | 290 Cancel(); |
279 return; | 291 return; |
280 } | 292 } |
281 | 293 |
282 if (has_service_worker) { | 294 if (has_service_worker) { |
283 // Create an infobar to promote the manifest's app. | 295 // Create an infobar to promote the manifest's app. |
284 GURL icon_url = | 296 GURL icon_url = |
285 ManifestIconSelector::FindBestMatchingIcon( | 297 ManifestIconSelector::FindBestMatchingIcon( |
286 web_app_data_.icons, | 298 web_app_data_.icons, |
287 ideal_icon_size_, | 299 ideal_icon_size_, |
288 gfx::Screen::GetScreenFor(web_contents->GetNativeView())); | 300 gfx::Screen::GetScreenFor(web_contents->GetNativeView())); |
289 if (!icon_url.is_empty()) { | 301 if (!icon_url.is_empty()) { |
290 FetchIcon(icon_url); | 302 FetchIcon(icon_url); |
291 return; | 303 return; |
292 } | 304 } |
305 SendDebugMessage(web_contents, | |
306 "not shown: could not find icon specified in manifest"); | |
benwells
2015/05/11 08:08:40
I don't really understand how this could happen as
dominickn (DO NOT USE)
2015/05/12 07:41:30
Done.
| |
293 } else { | 307 } else { |
294 TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER); | 308 TrackDisplayEvent(DISPLAY_EVENT_LACKS_SERVICE_WORKER); |
309 SendDebugMessage(web_contents, | |
310 "not shown: no service worker detected. You may need to " | |
311 "reload the page, or check that the manifest URL matches " | |
312 "the page URL"); | |
benwells
2015/05/11 08:08:40
This error is great but could still be improved. T
dominickn (DO NOT USE)
2015/05/12 07:41:31
Done.
dominickn (DO NOT USE)
2015/05/12 07:41:31
Done.
| |
295 } | 313 } |
296 | 314 |
297 Cancel(); | 315 Cancel(); |
298 } | 316 } |
299 | 317 |
300 void AppBannerDataFetcher::OnFetchComplete(const GURL& url, | 318 void AppBannerDataFetcher::OnFetchComplete(const GURL& url, |
301 const SkBitmap* icon) { | 319 const SkBitmap* icon) { |
302 if (is_active_) | 320 if (is_active_) |
303 ShowBanner(icon); | 321 ShowBanner(icon); |
304 | 322 |
305 Release(); | 323 Release(); |
306 } | 324 } |
307 | 325 |
308 void AppBannerDataFetcher::ShowBanner(const SkBitmap* icon) { | 326 void AppBannerDataFetcher::ShowBanner(const SkBitmap* icon) { |
309 content::WebContents* web_contents = GetWebContents(); | 327 content::WebContents* web_contents = GetWebContents(); |
310 if (!is_active_ || !web_contents || !icon) { | 328 if (!CheckFetcherIsStillAlive(web_contents, "banner display") || !icon) { |
329 if (!icon) | |
330 SendDebugMessage(web_contents, "not shown: no icon available to display"); | |
benwells
2015/05/11 08:08:40
Ditto about separating into two ifs.
dominickn (DO NOT USE)
2015/05/12 07:41:31
Done.
| |
311 Cancel(); | 331 Cancel(); |
312 return; | 332 return; |
313 } | 333 } |
314 | 334 |
315 RecordCouldShowBanner(); | 335 RecordCouldShowBanner(); |
316 if (!CheckIfShouldShowBanner()) { | 336 if (!CheckIfShouldShowBanner()) { |
337 SendDebugMessage(web_contents, "not shown: engagement checks failed"); | |
benwells
2015/05/11 08:08:40
This one is tricky. The only way a message will ge
dominickn (DO NOT USE)
2015/05/12 07:41:30
Done.
| |
317 Cancel(); | 338 Cancel(); |
318 return; | 339 return; |
319 } | 340 } |
320 | 341 |
342 SendDebugMessage(web_contents, "shown"); | |
benwells
2015/05/11 08:08:40
I don't think it is necessary to output this. This
dominickn (DO NOT USE)
2015/05/12 07:41:31
Done.
| |
321 app_icon_.reset(new SkBitmap(*icon)); | 343 app_icon_.reset(new SkBitmap(*icon)); |
322 event_request_id_ = ++gCurrentRequestID; | 344 event_request_id_ = ++gCurrentRequestID; |
323 web_contents->GetMainFrame()->Send( | 345 web_contents->GetMainFrame()->Send( |
324 new ChromeViewMsg_AppBannerPromptRequest( | 346 new ChromeViewMsg_AppBannerPromptRequest( |
325 web_contents->GetMainFrame()->GetRoutingID(), | 347 web_contents->GetMainFrame()->GetRoutingID(), |
326 event_request_id_, | 348 event_request_id_, |
327 GetBannerType())); | 349 GetBannerType())); |
328 } | 350 } |
329 | 351 |
330 void AppBannerDataFetcher::RecordCouldShowBanner() { | 352 void AppBannerDataFetcher::RecordCouldShowBanner() { |
331 content::WebContents* web_contents = GetWebContents(); | 353 content::WebContents* web_contents = GetWebContents(); |
332 DCHECK(web_contents); | 354 DCHECK(web_contents); |
333 | 355 |
334 AppBannerSettingsHelper::RecordBannerEvent( | 356 AppBannerSettingsHelper::RecordBannerEvent( |
335 web_contents, validated_url_, GetAppIdentifier(), | 357 web_contents, validated_url_, GetAppIdentifier(), |
336 AppBannerSettingsHelper::APP_BANNER_EVENT_COULD_SHOW, | 358 AppBannerSettingsHelper::APP_BANNER_EVENT_COULD_SHOW, |
337 GetCurrentTime()); | 359 GetCurrentTime()); |
338 } | 360 } |
339 | 361 |
340 bool AppBannerDataFetcher::CheckIfShouldShowBanner() { | 362 bool AppBannerDataFetcher::CheckIfShouldShowBanner() { |
341 content::WebContents* web_contents = GetWebContents(); | 363 content::WebContents* web_contents = GetWebContents(); |
342 DCHECK(web_contents); | 364 DCHECK(web_contents); |
343 | 365 |
344 return AppBannerSettingsHelper::ShouldShowBanner( | 366 return AppBannerSettingsHelper::ShouldShowBanner( |
345 web_contents, validated_url_, GetAppIdentifier(), GetCurrentTime()); | 367 web_contents, validated_url_, GetAppIdentifier(), GetCurrentTime()); |
346 } | 368 } |
347 | 369 |
370 bool AppBannerDataFetcher::CheckFetcherIsStillAlive( | |
371 content::WebContents* web_contents, | |
372 const std::string& section) { | |
373 if (!is_active_) { | |
374 SendDebugMessage(web_contents, | |
375 "not shown: display pipeline halted before " + section); | |
benwells
2015/05/11 08:08:40
This message is too detailed. Please update to som
dominickn (DO NOT USE)
2015/05/12 07:41:30
Done.
| |
376 return false; | |
377 } | |
378 if (!web_contents) | |
379 return false; | |
benwells
2015/05/11 08:08:40
For completeness a message here would be good, lik
dominickn (DO NOT USE)
2015/05/12 07:41:31
But if the web_contents pointer doesn't exist, we
| |
380 return true; | |
381 } | |
382 | |
348 // static | 383 // static |
349 bool AppBannerDataFetcher::IsManifestValidForWebApp( | 384 bool AppBannerDataFetcher::IsManifestValidForWebApp( |
350 const content::Manifest& manifest) { | 385 const content::Manifest& manifest, |
351 if (manifest.IsEmpty()) | 386 content::WebContents* web_contents) { |
387 if (manifest.IsEmpty()) { | |
388 SendDebugMessage(web_contents, "not shown: manifest is empty"); | |
352 return false; | 389 return false; |
353 if (!manifest.start_url.is_valid()) | 390 } |
391 if (!manifest.start_url.is_valid()) { | |
392 SendDebugMessage(web_contents, | |
393 "not shown: start URL in manifest is not valid"); | |
354 return false; | 394 return false; |
355 if (manifest.name.is_null() && manifest.short_name.is_null()) | 395 } |
396 if (manifest.name.is_null() && manifest.short_name.is_null()) { | |
397 SendDebugMessage(web_contents, | |
398 "not shown: manifest name and short name are missing"); | |
benwells
2015/05/11 08:08:40
It would be good to capture in the error that only
dominickn (DO NOT USE)
2015/05/12 07:41:31
Done.
| |
356 return false; | 399 return false; |
357 if (!DoesManifestContainRequiredIcon(manifest)) | 400 } |
401 if (!DoesManifestContainRequiredIcon(manifest)) { | |
402 SendDebugMessage(web_contents, | |
403 "not shown: manifest does not contain a suitable icon"); | |
benwells
2015/05/11 08:08:40
It would be good to capture more details about wha
dominickn (DO NOT USE)
2015/05/12 07:41:31
Done.
| |
358 return false; | 404 return false; |
405 } | |
359 return true; | 406 return true; |
360 } | 407 } |
361 | 408 |
362 } // namespace banners | 409 } // namespace banners |
OLD | NEW |