Commit 101b5ae0 authored by Justin Cohen's avatar Justin Cohen Committed by Commit Bot

[ios] Enable preload with slim-navigation-manager.

Previously, preload required CopyStateFromAndPrune and
CanPruneAllButLastCommittedItem within NavigationManager, but those
are not supported with SlimNav. Here, preload is implemented by
creating a preload WebState with navigation history by restoring the
current WebState.

The performance of this implementation depends on Slim
Navigation Manager's session restoration performance which can be
measured with existing kRestoreNavigationTime metric.

Original implementation of this CL was written by eugenebut@,
simply updated in this resurrected CL.

Bug: 834116
Change-Id: I86c9ecf7e3ed213ebaeddce6264dff3bbb8a8c94
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1815702
Commit-Queue: Justin Cohen <justincohen@chromium.org>
Reviewed-by: default avatarRohit Rao <rohitrao@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701228}
parent 176ec0a2
...@@ -71,10 +71,11 @@ class WebState; ...@@ -71,10 +71,11 @@ class WebState;
// Returns whether |webState| is the WebState used for pre-rendering. // Returns whether |webState| is the WebState used for pre-rendering.
- (BOOL)isWebStatePrerendered:(web::WebState*)webState; - (BOOL)isWebStatePrerendered:(web::WebState*)webState;
// Returns the currently prerendered WebState, or nil if none exists. After // Returns the currently prerendered WebState, or nil if it was not created
// this method is called, the PrerenderController reverts to a non-prerendering // while |oldWebState| was active, or nil if none exists. After this method is
// state. // called, the PrerenderController reverts to a non-prerendering state.
- (std::unique_ptr<web::WebState>)releasePrerenderContents; - (std::unique_ptr<web::WebState>)releasePrerenderContentsForWebState:
(web::WebState*)oldWebState;
@end @end
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#import "ios/web/public/navigation/web_state_policy_decider_bridge.h" #import "ios/web/public/navigation/web_state_policy_decider_bridge.h"
#include "ios/web/public/thread/web_thread.h" #include "ios/web/public/thread/web_thread.h"
#import "ios/web/public/ui/java_script_dialog_presenter.h" #import "ios/web/public/ui/java_script_dialog_presenter.h"
#include "ios/web/public/web_client.h"
#import "ios/web/public/web_state.h" #import "ios/web/public/web_state.h"
#import "ios/web/public/web_state_observer_bridge.h" #import "ios/web/public/web_state_observer_bridge.h"
#import "ios/web/web_state/ui/crw_web_controller.h" #import "ios/web/web_state/ui/crw_web_controller.h"
...@@ -186,6 +187,10 @@ class PreloadJavaScriptDialogPresenter : public web::JavaScriptDialogPresenter { ...@@ -186,6 +187,10 @@ class PreloadJavaScriptDialogPresenter : public web::JavaScriptDialogPresenter {
// there is no prerender scheduled. // there is no prerender scheduled.
@property(nonatomic, readonly) const GURL& scheduledURL; @property(nonatomic, readonly) const GURL& scheduledURL;
// Contains the original webState that, for SlimNav, session history will be
// created from.
@property(nonatomic, assign) web::WebState* webStateToReplace;
// Whether or not the preference is enabled. // Whether or not the preference is enabled.
@property(nonatomic, getter=isPreferenceEnabled) BOOL preferenceEnabled; @property(nonatomic, getter=isPreferenceEnabled) BOOL preferenceEnabled;
...@@ -299,6 +304,9 @@ class PreloadJavaScriptDialogPresenter : public web::JavaScriptDialogPresenter { ...@@ -299,6 +304,9 @@ class PreloadJavaScriptDialogPresenter : public web::JavaScriptDialogPresenter {
} }
[self removeScheduledPrerenderRequests]; [self removeScheduledPrerenderRequests];
self.webStateToReplace = [self.delegate webStateToReplace];
_scheduledRequest = _scheduledRequest =
std::make_unique<PrerenderRequest>(url, transition, referrer); std::make_unique<PrerenderRequest>(url, transition, referrer);
...@@ -321,10 +329,13 @@ class PreloadJavaScriptDialogPresenter : public web::JavaScriptDialogPresenter { ...@@ -321,10 +329,13 @@ class PreloadJavaScriptDialogPresenter : public web::JavaScriptDialogPresenter {
return webState && _webState.get() == webState; return webState && _webState.get() == webState;
} }
- (std::unique_ptr<web::WebState>)releasePrerenderContents { - (std::unique_ptr<web::WebState>)releasePrerenderContentsForWebState:
if (!_webState) (web::WebState*)oldWebState {
if (!_webState || oldWebState != self.webStateToReplace ||
_webState->GetNavigationManager()->IsRestoreSessionInProgress())
return nullptr; return nullptr;
self.webStateToReplace = nullptr;
self.successfulPrerendersPerSessionCount++; self.successfulPrerendersPerSessionCount++;
[self recordReleaseMetrics]; [self recordReleaseMetrics];
[self removeScheduledPrerenderRequests]; [self removeScheduledPrerenderRequests];
...@@ -501,7 +512,13 @@ class PreloadJavaScriptDialogPresenter : public web::JavaScriptDialogPresenter { ...@@ -501,7 +512,13 @@ class PreloadJavaScriptDialogPresenter : public web::JavaScriptDialogPresenter {
} }
web::WebState::CreateParams createParams(self.browserState); web::WebState::CreateParams createParams(self.browserState);
_webState = web::WebState::Create(createParams); if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) {
_webState = web::WebState::CreateWithStorageSession(
createParams, self.webStateToReplace->BuildSessionStorage());
} else {
_webState = web::WebState::Create(createParams);
}
// Add the preload controller as a policyDecider before other tab helpers, so // Add the preload controller as a policyDecider before other tab helpers, so
// that it can block the navigation if needed before other policy deciders // that it can block the navigation if needed before other policy deciders
// execute thier side effects (eg. AppLauncherTabHelper launching app). // execute thier side effects (eg. AppLauncherTabHelper launching app).
...@@ -563,6 +580,7 @@ class PreloadJavaScriptDialogPresenter : public web::JavaScriptDialogPresenter { ...@@ -563,6 +580,7 @@ class PreloadJavaScriptDialogPresenter : public web::JavaScriptDialogPresenter {
self.prerenderedURL = GURL(); self.prerenderedURL = GURL();
self.startTime = base::TimeTicks(); self.startTime = base::TimeTicks();
self.webStateToReplace = nullptr;
} }
#pragma mark - Notification Helpers #pragma mark - Notification Helpers
......
...@@ -12,6 +12,10 @@ ...@@ -12,6 +12,10 @@
// A protocol implemented by a delegate of PreloadController // A protocol implemented by a delegate of PreloadController
@protocol PreloadControllerDelegate @protocol PreloadControllerDelegate
// WebState from which preload controller should copy the session history.
// This web state will be replaced on successful preload.
- (web::WebState*)webStateToReplace;
// Should preload controller request a desktop site. // Should preload controller request a desktop site.
- (BOOL)preloadShouldUseDesktopUserAgent; - (BOOL)preloadShouldUseDesktopUserAgent;
......
...@@ -116,7 +116,7 @@ TEST_F(PreloadControllerTest, DontPreloadNonWebURLs) { ...@@ -116,7 +116,7 @@ TEST_F(PreloadControllerTest, DontPreloadNonWebURLs) {
referrer:kReferrer referrer:kReferrer
transition:kTransition transition:kTransition
immediately:YES]; immediately:YES];
EXPECT_FALSE([controller_ releasePrerenderContents]); EXPECT_FALSE([controller_ releasePrerenderContentsForWebState:nil]);
// Attempt to prerender the NTP and verify that no WebState was created // Attempt to prerender the NTP and verify that no WebState was created
// to preload. // to preload.
...@@ -124,7 +124,7 @@ TEST_F(PreloadControllerTest, DontPreloadNonWebURLs) { ...@@ -124,7 +124,7 @@ TEST_F(PreloadControllerTest, DontPreloadNonWebURLs) {
referrer:kReferrer referrer:kReferrer
transition:kTransition transition:kTransition
immediately:YES]; immediately:YES];
EXPECT_FALSE([controller_ releasePrerenderContents]); EXPECT_FALSE([controller_ releasePrerenderContentsForWebState:nil]);
// Attempt to prerender the flags UI and verify that no WebState was created // Attempt to prerender the flags UI and verify that no WebState was created
// to preload. // to preload.
...@@ -132,7 +132,7 @@ TEST_F(PreloadControllerTest, DontPreloadNonWebURLs) { ...@@ -132,7 +132,7 @@ TEST_F(PreloadControllerTest, DontPreloadNonWebURLs) {
referrer:kReferrer referrer:kReferrer
transition:kTransition transition:kTransition
immediately:YES]; immediately:YES];
EXPECT_FALSE([controller_ releasePrerenderContents]); EXPECT_FALSE([controller_ releasePrerenderContentsForWebState:nil]);
} }
TEST_F(PreloadControllerTest, TestIsPrerenderingEnabled_preloadAlways) { TEST_F(PreloadControllerTest, TestIsPrerenderingEnabled_preloadAlways) {
......
...@@ -65,11 +65,6 @@ std::unique_ptr<net::test_server::HttpResponse> StandardResponse( ...@@ -65,11 +65,6 @@ std::unique_ptr<net::test_server::HttpResponse> StandardResponse(
@"Disabled for iPad due to alternate letters educational screen."); @"Disabled for iPad due to alternate letters educational screen.");
} }
if ([ChromeEarlGrey isSlimNavigationManagerEnabled]) {
// TODO(crbug.com/834116): Fix and enable this test.
EARL_GREY_TEST_DISABLED(@"Prerender is not supported by slim-nav yet.");
}
[ChromeEarlGrey clearBrowsingHistory]; [ChromeEarlGrey clearBrowsingHistory];
// Set server up. // Set server up.
int visitCounter = 0; int visitCounter = 0;
......
...@@ -39,13 +39,6 @@ void PrerenderService::StartPrerender(const GURL& url, ...@@ -39,13 +39,6 @@ void PrerenderService::StartPrerender(const GURL& url,
const web::Referrer& referrer, const web::Referrer& referrer,
ui::PageTransition transition, ui::PageTransition transition,
bool immediately) { bool immediately) {
// PrerenderService is not compatible with WKBasedNavigationManager because it
// loads the URL in a new WKWebView, which doesn't have the current session
// history. TODO(crbug.com/814789): decide whether PrerenderService needs to
// be supported after evaluating the performance impact in Finch experiment.
if (web::GetWebClient()->IsSlimNavigationManagerEnabled())
return;
[controller_ prerenderURL:url [controller_ prerenderURL:url
referrer:referrer referrer:referrer
transition:transition transition:transition
...@@ -62,12 +55,18 @@ bool PrerenderService::MaybeLoadPrerenderedURL( ...@@ -62,12 +55,18 @@ bool PrerenderService::MaybeLoadPrerenderedURL(
return false; return false;
} }
web::WebState* web_state = web_state_list->GetActiveWebState();
std::unique_ptr<web::WebState> new_web_state = std::unique_ptr<web::WebState> new_web_state =
[controller_ releasePrerenderContents]; [controller_ releasePrerenderContentsForWebState:web_state];
if (!new_web_state) {
CancelPrerender();
return false;
}
DCHECK_NE(WebStateList::kInvalidIndex, web_state_list->active_index()); DCHECK_NE(WebStateList::kInvalidIndex, web_state_list->active_index());
web::NavigationManager* active_navigation_manager = web::NavigationManager* active_navigation_manager =
web_state_list->GetActiveWebState()->GetNavigationManager(); web_state->GetNavigationManager();
int lastIndex = active_navigation_manager->GetLastCommittedItemIndex(); int lastIndex = active_navigation_manager->GetLastCommittedItemIndex();
UMA_HISTOGRAM_COUNTS_100("Prerender.PrerenderLoadedOnIndex", lastIndex); UMA_HISTOGRAM_COUNTS_100("Prerender.PrerenderLoadedOnIndex", lastIndex);
...@@ -79,8 +78,13 @@ bool PrerenderService::MaybeLoadPrerenderedURL( ...@@ -79,8 +78,13 @@ bool PrerenderService::MaybeLoadPrerenderedURL(
web::NavigationManager* new_navigation_manager = web::NavigationManager* new_navigation_manager =
new_web_state->GetNavigationManager(); new_web_state->GetNavigationManager();
if (new_navigation_manager->CanPruneAllButLastCommittedItem()) { bool slim_navigation_manager_enabled =
new_navigation_manager->CopyStateFromAndPrune(active_navigation_manager); web::GetWebClient()->IsSlimNavigationManagerEnabled();
if (new_navigation_manager->CanPruneAllButLastCommittedItem() ||
slim_navigation_manager_enabled) {
if (!slim_navigation_manager_enabled) {
new_navigation_manager->CopyStateFromAndPrune(active_navigation_manager);
}
loading_prerender_ = true; loading_prerender_ = true;
web_state_list->ReplaceWebStateAt(web_state_list->active_index(), web_state_list->ReplaceWebStateAt(web_state_list->active_index(),
std::move(new_web_state)); std::move(new_web_state));
......
...@@ -4758,6 +4758,10 @@ NSString* const kBrowserViewControllerSnackbarCategory = ...@@ -4758,6 +4758,10 @@ NSString* const kBrowserViewControllerSnackbarCategory =
return [self userAgentType] == web::UserAgentType::DESKTOP; return [self userAgentType] == web::UserAgentType::DESKTOP;
} }
- (web::WebState*)webStateToReplace {
return self.currentWebState;
}
#pragma mark - NetExportTabHelperDelegate #pragma mark - NetExportTabHelperDelegate
- (void)netExportTabHelper:(NetExportTabHelper*)tabHelper - (void)netExportTabHelper:(NetExportTabHelper*)tabHelper
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment