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

Side by Side Diff: ios/chrome/browser/ui/preload_controller.mm

Issue 2775623002: [ios] WebStateList owns all WebState it manages. (Closed)
Patch Set: Fix ios_chrome_unittests. Created 3 years, 9 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 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 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 #import <UIKit/UIKit.h> 5 #import <UIKit/UIKit.h>
6 6
7 #include "ios/chrome/browser/ui/preload_controller.h" 7 #include "ios/chrome/browser/ui/preload_controller.h"
8 8
9 #include "base/ios/device_util.h" 9 #include "base/ios/device_util.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/mac/scoped_nsobject.h"
11 #include "base/metrics/field_trial.h" 12 #include "base/metrics/field_trial.h"
12 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
13 #include "base/strings/sys_string_conversions.h" 14 #include "base/strings/sys_string_conversions.h"
14 #include "components/prefs/pref_service.h" 15 #include "components/prefs/pref_service.h"
15 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" 16 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
16 #include "ios/chrome/browser/pref_names.h" 17 #include "ios/chrome/browser/pref_names.h"
18 #import "ios/chrome/browser/tabs/legacy_tab_helper.h"
17 #import "ios/chrome/browser/tabs/tab.h" 19 #import "ios/chrome/browser/tabs/tab.h"
20 #import "ios/chrome/browser/tabs/tab_helper_util.h"
18 #include "ios/chrome/browser/ui/preload_controller_delegate.h" 21 #include "ios/chrome/browser/ui/preload_controller_delegate.h"
19 #include "ios/chrome/browser/ui/prerender_final_status.h" 22 #include "ios/chrome/browser/ui/prerender_final_status.h"
20 #import "ios/web/public/web_state/ui/crw_native_content.h" 23 #import "ios/web/public/web_state/ui/crw_native_content.h"
21 #include "ios/web/public/web_thread.h" 24 #include "ios/web/public/web_thread.h"
22 #import "ios/web/web_state/ui/crw_web_controller.h" 25 #import "ios/web/web_state/ui/crw_web_controller.h"
23 #import "net/base/mac/url_conversions.h" 26 #import "net/base/mac/url_conversions.h"
24 #include "net/url_request/url_fetcher.h" 27 #include "net/url_request/url_fetcher.h"
25 #include "net/url_request/url_fetcher_delegate.h" 28 #include "net/url_request/url_fetcher_delegate.h"
26 #include "ui/base/page_transition_types.h" 29 #include "ui/base/page_transition_types.h"
27 30
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 public: 97 public:
95 explicit PrefetchDelegate(PreloadController* owner) : owner_(owner) {} 98 explicit PrefetchDelegate(PreloadController* owner) : owner_(owner) {}
96 void OnURLFetchComplete(const net::URLFetcher* source) override { 99 void OnURLFetchComplete(const net::URLFetcher* source) override {
97 [owner_ prefetchDidComplete:source]; 100 [owner_ prefetchDidComplete:source];
98 } 101 }
99 102
100 private: 103 private:
101 PreloadController* owner_; // weak 104 PreloadController* owner_; // weak
102 }; 105 };
103 106
104 @implementation PreloadController 107 @implementation PreloadController {
108 ios::ChromeBrowserState* browserState_; // Weak.
109
110 // The WebState used for prerendering.
111 std::unique_ptr<web::WebState> webState_;
112
113 // The URL that is prerendered in |webState_|. This can be different from
114 // the value returned by WebState last committed navigation item, for example
115 // in cases where there was a redirect.
116 //
117 // When choosing whether or not to use a prerendered Tab,
118 // BrowserViewController compares the URL being loaded by the omnibox with the
119 // URL of the prerendered Tab. Comparing against the Tab's currently URL
120 // could return false negatives in cases of redirect, hence the need to store
121 // the originally prerendered URL.
122 GURL prerenderedURL_;
123
124 // The URL that is scheduled to be prerendered, its associated transition and
125 // referrer. |scheduledTransition_| and |scheduledReferrer_| are not valid
126 // when |scheduledURL_| is empty.
127 GURL scheduledURL_;
128 ui::PageTransition scheduledTransition_;
129 web::Referrer scheduledReferrer_;
130
131 // The most-recently prefetched URL, or nil if there have been no prefetched
132 // URLs.
133 GURL prefetchedURL_;
134
135 // The URLFetcher and associated delegate used to prefetch URLs. The delegate
136 // simply forwards callbacks from URLFetcher back to the PrerenderController.
137 std::unique_ptr<PrefetchDelegate> prefetcherDelegate_;
138 std::unique_ptr<net::URLFetcher> prefetcher_;
139
140 // Bridge to listen to pref changes.
141 std::unique_ptr<PrefObserverBridge> observerBridge_;
142 // Registrar for pref changes notifications.
143 PrefChangeRegistrar prefChangeRegistrar_;
144 // Observer for the WWAN setting. Contains a valid object only if the
145 // instant setting is set to wifi-only.
146 std::unique_ptr<ConnectionTypeObserverBridge> connectionTypeObserverBridge_;
147
148 // Whether or not the preference is enabled.
149 BOOL enabled_;
150 // Whether or not prerendering is only when on wifi.
151 BOOL wifiOnly_;
152 // Whether or not the current connection is using WWAN.
153 BOOL usingWWAN_;
154
155 // Number of successful prerenders (i.e. the user viewed the prerendered page)
156 // during the lifetime of this controller.
157 int successfulPrerendersPerSessionCount_;
158
159 id<PreloadControllerDelegate> delegate_; // weak
160 }
105 161
106 @synthesize prerenderedURL = prerenderedURL_; 162 @synthesize prerenderedURL = prerenderedURL_;
107 @synthesize prefetchedURL = prefetchedURL_; 163 @synthesize prefetchedURL = prefetchedURL_;
108 @synthesize delegate = delegate_; 164 @synthesize delegate = delegate_;
109 165
110 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState { 166 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState {
111 DCHECK(browserState); 167 DCHECK(browserState);
112 DCHECK_CURRENTLY_ON(web::WebThread::UI); 168 DCHECK_CURRENTLY_ON(web::WebThread::UI);
113 if ((self = [super init])) { 169 if ((self = [super init])) {
114 browserState_ = browserState; 170 browserState_ = browserState;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 264
209 - (void)cancelPrerender { 265 - (void)cancelPrerender {
210 [self cancelPrerenderForReason:PRERENDER_FINAL_STATUS_CANCELLED]; 266 [self cancelPrerenderForReason:PRERENDER_FINAL_STATUS_CANCELLED];
211 } 267 }
212 268
213 - (void)cancelPrerenderForReason:(PrerenderFinalStatus)reason { 269 - (void)cancelPrerenderForReason:(PrerenderFinalStatus)reason {
214 [self removeScheduledPrerenderRequests]; 270 [self removeScheduledPrerenderRequests];
215 [self destroyPreviewContentsForReason:reason]; 271 [self destroyPreviewContentsForReason:reason];
216 } 272 }
217 273
218 - (Tab*)releasePrerenderContents { 274 - (std::unique_ptr<web::WebState>)releasePrerenderContents {
219 successfulPrerendersPerSessionCount_++; 275 successfulPrerendersPerSessionCount_++;
220 UMA_HISTOGRAM_ENUMERATION(kPrerenderFinalStatusHistogramName, 276 UMA_HISTOGRAM_ENUMERATION(kPrerenderFinalStatusHistogramName,
221 PRERENDER_FINAL_STATUS_USED, 277 PRERENDER_FINAL_STATUS_USED,
222 PRERENDER_FINAL_STATUS_MAX); 278 PRERENDER_FINAL_STATUS_MAX);
223 [self removeScheduledPrerenderRequests]; 279 [self removeScheduledPrerenderRequests];
224 prerenderedURL_ = GURL(); 280 prerenderedURL_ = GURL();
225 [[tab_ webController] setNativeProvider:nil]; 281
226 [tab_ setDelegate:nil]; 282 if (webState_) {
227 return [tab_.release() autorelease]; 283 Tab* tab = LegacyTabHelper::GetTabForWebState(webState_.get());
284 [[tab webController] setNativeProvider:nil];
285 [tab setDelegate:nil];
286 }
287
288 return std::move(webState_);
228 } 289 }
229 290
230 - (void)connectionTypeChanged:(net::NetworkChangeNotifier::ConnectionType)type { 291 - (void)connectionTypeChanged:(net::NetworkChangeNotifier::ConnectionType)type {
231 DCHECK_CURRENTLY_ON(web::WebThread::UI); 292 DCHECK_CURRENTLY_ON(web::WebThread::UI);
232 usingWWAN_ = net::NetworkChangeNotifier::IsConnectionCellular(type); 293 usingWWAN_ = net::NetworkChangeNotifier::IsConnectionCellular(type);
233 if (wifiOnly_ && usingWWAN_) 294 if (wifiOnly_ && usingWWAN_)
234 [self cancelPrerender]; 295 [self cancelPrerender];
235 } 296 }
236 297
237 - (void)onPreferenceChanged:(const std::string&)preferenceName { 298 - (void)onPreferenceChanged:(const std::string&)preferenceName {
(...skipping 27 matching lines...) Expand all
265 326
266 - (void)didReceiveMemoryWarning { 327 - (void)didReceiveMemoryWarning {
267 [self cancelPrerenderForReason:PRERENDER_FINAL_STATUS_MEMORY_LIMIT_EXCEEDED]; 328 [self cancelPrerenderForReason:PRERENDER_FINAL_STATUS_MEMORY_LIMIT_EXCEEDED];
268 } 329 }
269 330
270 #pragma mark - 331 #pragma mark -
271 #pragma mark CRWNativeContentProvider implementation 332 #pragma mark CRWNativeContentProvider implementation
272 333
273 // Delegate the call to the original native provider. 334 // Delegate the call to the original native provider.
274 - (BOOL)hasControllerForURL:(const GURL&)url { 335 - (BOOL)hasControllerForURL:(const GURL&)url {
275 return [[tab_ webController].nativeProvider hasControllerForURL:url]; 336 if (!webState_)
337 return NO;
338 Tab* tab = LegacyTabHelper::GetTabForWebState(webState_.get());
339 return [[tab webController].nativeProvider hasControllerForURL:url];
276 } 340 }
277 341
278 // Override the CRWNativeContentProvider methods to cancel any prerenders that 342 // Override the CRWNativeContentProvider methods to cancel any prerenders that
279 // require native content. 343 // require native content.
280 - (id<CRWNativeContent>)controllerForURL:(const GURL&)url 344 - (id<CRWNativeContent>)controllerForURL:(const GURL&)url
281 webState:(web::WebState*)webState { 345 webState:(web::WebState*)webState {
282 [self schedulePrerenderCancel]; 346 [self schedulePrerenderCancel];
283 return nil; 347 return nil;
284 } 348 }
285 349
(...skipping 30 matching lines...) Expand all
316 [self destroyPreviewContents]; 380 [self destroyPreviewContents];
317 prerenderedURL_ = scheduledURL_; 381 prerenderedURL_ = scheduledURL_;
318 scheduledURL_ = GURL(); 382 scheduledURL_ = GURL();
319 383
320 DCHECK(prerenderedURL_.is_valid()); 384 DCHECK(prerenderedURL_.is_valid());
321 if (!prerenderedURL_.is_valid()) { 385 if (!prerenderedURL_.is_valid()) {
322 [self destroyPreviewContents]; 386 [self destroyPreviewContents];
323 return; 387 return;
324 } 388 }
325 389
326 Tab* tab = 390 web::WebState::CreateParams createParams(browserState_);
327 [Tab preloadingTabWithBrowserState:browserState_ 391 webState_ = web::WebState::Create(createParams);
328 url:prerenderedURL_ 392 AttachTabHelpers(webState_.get());
329 referrer:scheduledReferrer_
330 transition:scheduledTransition_
331 provider:self
332 opener:nil
333 desktopUserAgent:[delegate_ shouldUseDesktopUserAgent]
334 configuration:^(Tab* tab) {
335 [tab setIsPrerenderTab:YES];
336 [tab setDelegate:self];
337 }];
338 393
339 // Create and set up the prerender. 394 Tab* tab = LegacyTabHelper::GetTabForWebState(webState_.get());
340 tab_.reset([tab retain]); 395 DCHECK(tab);
396
397 if ([delegate_ shouldUseDesktopUserAgent])
398 [tab enableDesktopUserAgent];
399
400 [[tab webController] setNativeProvider:self];
401 [[tab webController] setWebUsageEnabled:YES];
402 [tab setIsPrerenderTab:YES];
403 [tab setDelegate:self];
404
405 web::NavigationManager::WebLoadParams loadParams(prerenderedURL_);
406 loadParams.referrer = scheduledReferrer_;
407 loadParams.transition_type = scheduledTransition_;
408 [[tab webController] loadWithParams:loadParams];
341 409
342 // Trigger the page to start loading. 410 // Trigger the page to start loading.
343 [tab_ view]; 411 [tab view];
344 } 412 }
345 413
346 - (const GURL)urlToPrefetchURL:(const GURL&)url { 414 - (const GURL)urlToPrefetchURL:(const GURL&)url {
347 GURL::Replacements replacements; 415 GURL::Replacements replacements;
348 416
349 // Add prefetch indicator to query params. 417 // Add prefetch indicator to query params.
350 std::string query = url.query(); 418 std::string query = url.query();
351 if (!query.empty()) { 419 if (!query.empty()) {
352 query.append("&"); 420 query.append("&");
353 } 421 }
(...skipping 18 matching lines...) Expand all
372 << "Prefetching URL got response code " << source->GetResponseCode(); 440 << "Prefetching URL got response code " << source->GetResponseCode();
373 } 441 }
374 prefetcher_.reset(); 442 prefetcher_.reset();
375 } 443 }
376 444
377 - (void)destroyPreviewContents { 445 - (void)destroyPreviewContents {
378 [self destroyPreviewContentsForReason:PRERENDER_FINAL_STATUS_CANCELLED]; 446 [self destroyPreviewContentsForReason:PRERENDER_FINAL_STATUS_CANCELLED];
379 } 447 }
380 448
381 - (void)destroyPreviewContentsForReason:(PrerenderFinalStatus)reason { 449 - (void)destroyPreviewContentsForReason:(PrerenderFinalStatus)reason {
382 if (!tab_.get()) 450 if (!webState_)
383 return; 451 return;
384 452
385 UMA_HISTOGRAM_ENUMERATION(kPrerenderFinalStatusHistogramName, reason, 453 UMA_HISTOGRAM_ENUMERATION(kPrerenderFinalStatusHistogramName, reason,
386 PRERENDER_FINAL_STATUS_MAX); 454 PRERENDER_FINAL_STATUS_MAX);
387 [[tab_ webController] setNativeProvider:nil]; 455
388 [tab_ setDelegate:nil]; 456 Tab* tab = LegacyTabHelper::GetTabForWebState(webState_.get());
389 [tab_ close]; 457 [[tab webController] setNativeProvider:nil];
390 tab_.reset(); 458 [tab setDelegate:nil];
459 webState_.reset();
460
391 prerenderedURL_ = GURL(); 461 prerenderedURL_ = GURL();
392 } 462 }
393 463
394 - (void)schedulePrerenderCancel { 464 - (void)schedulePrerenderCancel {
395 // TODO(rohitrao): Instead of cancelling the prerender, should we mark it as 465 // TODO(rohitrao): Instead of cancelling the prerender, should we mark it as
396 // failed instead? That way, subsequent prerender requests for the same URL 466 // failed instead? That way, subsequent prerender requests for the same URL
397 // will not kick off new prerenders. b/5944421 467 // will not kick off new prerenders. b/5944421
398 [self removeScheduledPrerenderRequests]; 468 [self removeScheduledPrerenderRequests];
399 [self performSelector:@selector(cancelPrerender) withObject:nil afterDelay:0]; 469 [self performSelector:@selector(cancelPrerender) withObject:nil afterDelay:0];
400 } 470 }
401 471
402 - (void)removeScheduledPrerenderRequests { 472 - (void)removeScheduledPrerenderRequests {
403 [NSObject cancelPreviousPerformRequestsWithTarget:self]; 473 [NSObject cancelPreviousPerformRequestsWithTarget:self];
404 scheduledURL_ = GURL(); 474 scheduledURL_ = GURL();
405 } 475 }
406 476
407 #pragma mark - TabDelegate 477 #pragma mark - TabDelegate
408 478
409 - (void)discardPrerender { 479 - (void)discardPrerender {
410 [self schedulePrerenderCancel]; 480 [self schedulePrerenderCancel];
411 } 481 }
412 482
413 @end 483 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698