Commit df887034 authored by Gauthier Ambard's avatar Gauthier Ambard Committed by Commit Bot

[iOS] Fix UserAgent restored for preloaded page

When the page is preloaded, a session restoration is done.
But the "visible" page isn't loaded as it would in a normal session
restoration.
This CL makes sure that this page gets the correct UA.

Bug: 1100852
Change-Id: Ia666dd17e512c8d9c7e84e750722dae90f56ca14
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2279757
Commit-Queue: Gauthier Ambard <gambard@chromium.org>
Reviewed-by: default avatarSylvain Defresne <sdefresne@chromium.org>
Reviewed-by: default avatarAli Juma <ajuma@chromium.org>
Cr-Commit-Position: refs/heads/master@{#791785}
parent 1001c66b
......@@ -89,9 +89,12 @@ source_set("eg2_tests") {
testonly = true
sources = [ "prerender_egtest.mm" ]
deps = [
"//components/version_info",
"//ios/chrome/browser/ui/popup_menu:constants",
"//ios/chrome/test/earl_grey:eg_test_support+eg2",
"//ios/testing/earl_grey:eg_test_support+eg2",
"//ios/third_party/earl_grey2:test_lib",
"//ios/web/common:user_agent",
"//net:test_support",
]
frameworks = [ "UIKit.framework" ]
......
......@@ -10,9 +10,13 @@
#include "base/memory/ptr_util.h"
#include "base/strings/sys_string_conversions.h"
#import "base/test/ios/wait_util.h"
#include "components/version_info/version_info.h"
#import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
#import "ios/chrome/test/earl_grey/chrome_matchers.h"
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#include "ios/web/common/user_agent.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
......@@ -25,56 +29,87 @@ using base::test::ios::WaitUntilConditionOrTimeout;
using base::test::ios::kWaitForPageLoadTimeout;
namespace {
const char kPageURL[] = "/test-page.html";
const char kUserAgentPageURL[] = "/user-agent-test-page.html";
const char kPageTitle[] = "Page title!";
const char kPageLoadedString[] = "Page loaded!";
const char kMobileSiteLabel[] = "Mobile";
const char kDesktopSiteLabel[] = "Desktop";
// Provides responses for redirect and changed window location URLs.
std::unique_ptr<net::test_server::HttpResponse> StandardResponse(
int* counter,
const net::test_server::HttpRequest& request) {
if (request.relative_url != kPageURL) {
return nullptr;
}
std::unique_ptr<net::test_server::BasicHttpResponse> http_response =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response->set_code(net::HTTP_OK);
http_response->set_content("<html><head><title>" + std::string(kPageTitle) +
"</title></head><body>" +
std::string(kPageLoadedString) + "</body></html>");
(*counter)++;
return std::move(http_response);
if (request.relative_url == kPageURL) {
http_response->set_content("<html><head><title>" + std::string(kPageTitle) +
"</title></head><body>" +
std::string(kPageLoadedString) +
"</body></html>");
(*counter)++;
return std::move(http_response);
} else if (request.relative_url == kUserAgentPageURL) {
std::string desktop_product =
"CriOS/" + version_info::GetMajorVersionNumber();
std::string desktop_user_agent =
web::BuildDesktopUserAgent(desktop_product);
std::string response_body;
auto user_agent = request.headers.find("User-Agent");
if (user_agent != request.headers.end() &&
user_agent->second == desktop_user_agent) {
response_body = std::string(kDesktopSiteLabel);
} else {
response_body = std::string(kMobileSiteLabel);
}
http_response->set_content("<html><head></head><body>" +
std::string(response_body) + "</body></html>");
return std::move(http_response);
}
return nullptr;
}
// Select the button to request desktop site by scrolling the collection.
// 200 is a reasonable scroll displacement that works for all UI elements, while
// not being too slow.
GREYElementInteraction* RequestDesktopButton() {
return [[EarlGrey
selectElementWithMatcher:grey_allOf(grey_accessibilityID(
kToolsMenuRequestDesktopId),
grey_sufficientlyVisible(), nil)]
usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 200)
onElementWithMatcher:grey_accessibilityID(
kPopupMenuToolsMenuTableViewId)];
}
} // namespace
// Test case for the prerender.
@interface PrerenderTestCase : ChromeTestCase
@interface PrerenderTestCase : ChromeTestCase {
int _visitCounter;
}
@end
@implementation PrerenderTestCase
// Test that tapping the prerendered suggestions opens it.
- (void)testTapPrerenderSuggestions {
// TODO(crbug.com/793306): Re-enable the test on iPad once the alternate
// letters problem is fixed.
if ([ChromeEarlGrey isIPadIdiom]) {
EARL_GREY_TEST_DISABLED(
@"Disabled for iPad due to alternate letters educational screen.");
}
- (void)addURLToHistory {
[ChromeEarlGrey clearBrowsingHistory];
// Set server up.
int visitCounter = 0;
_visitCounter = 0;
self.testServer->RegisterRequestHandler(
base::BindRepeating(&StandardResponse, &visitCounter));
base::BindRepeating(&StandardResponse, &_visitCounter));
GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
const GURL pageURL = self.testServer->GetURL(kPageURL);
NSString* pageString = base::SysUTF8ToNSString(pageURL.GetContent());
// Go to the page a couple of time so it shows as suggestion.
[ChromeEarlGrey loadURL:pageURL];
GREYAssertEqual(1, visitCounter, @"The page should have been loaded once");
GREYAssertEqual(1, _visitCounter, @"The page should have been loaded once");
[ChromeEarlGrey goBack];
[[self class] closeAllTabs];
[ChromeEarlGrey openNewTab];
......@@ -86,9 +121,26 @@ std::unique_ptr<net::test_server::HttpResponse> StandardResponse(
[[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
performAction:grey_typeText([pageString stringByAppendingString:@"\n"])];
[ChromeEarlGrey waitForPageToFinishLoading];
static int visitCountBeforePrerender = visitCounter;
[[self class] closeAllTabs];
[ChromeEarlGrey openNewTab];
}
#pragma mark - Tests
// Test that tapping the prerendered suggestions opens it.
- (void)testTapPrerenderSuggestions {
// TODO(crbug.com/793306): Re-enable the test on iPad once the alternate
// letters problem is fixed.
if ([ChromeEarlGrey isIPadIdiom]) {
EARL_GREY_TEST_DISABLED(
@"Disabled for iPad due to alternate letters educational screen.");
}
[self addURLToHistory];
const GURL pageURL = self.testServer->GetURL(kPageURL);
NSString* pageString = base::SysUTF8ToNSString(pageURL.GetContent());
static int visitCountBeforePrerender = _visitCounter;
// Type the begining of the address to have the autocomplete suggestion.
[[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()]
......@@ -101,7 +153,7 @@ std::unique_ptr<net::test_server::HttpResponse> StandardResponse(
// Wait until prerender request reaches the server.
bool prerendered = WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
return visitCounter == visitCountBeforePrerender + 1;
return _visitCounter == visitCountBeforePrerender + 1;
});
GREYAssertTrue(prerendered, @"Prerender did not happen");
......@@ -125,8 +177,68 @@ std::unique_ptr<net::test_server::HttpResponse> StandardResponse(
performAction:grey_tap()];
[ChromeEarlGrey waitForWebStateContainingText:kPageLoadedString];
GREYAssertEqual(visitCountBeforePrerender + 1, visitCounter,
GREYAssertEqual(visitCountBeforePrerender + 1, _visitCounter,
@"Prerender should have been the last load");
}
// Tests that tapping the prerendered suggestions keeps the UserAgent of the
// previous page.
- (void)testUserAgentTypeInPreviousLoad {
[self addURLToHistory];
const GURL pageURL = self.testServer->GetURL(kPageURL);
NSString* pageString = base::SysUTF8ToNSString(pageURL.GetContent());
static int visitCountBeforePrerender = _visitCounter;
// Load the UserAgent page.
const GURL userAgentPageURL = self.testServer->GetURL(kUserAgentPageURL);
[ChromeEarlGrey loadURL:userAgentPageURL];
[ChromeEarlGrey waitForWebStateContainingText:kMobileSiteLabel];
// Type the begining of the address to have the autocomplete suggestion.
[ChromeEarlGreyUI focusOmnibox];
[[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
performAction:grey_typeText(
[pageString substringToIndex:[pageString length] - 6])];
// Wait until prerender request reaches the server.
bool prerendered = WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
return _visitCounter == visitCountBeforePrerender + 1;
});
GREYAssertTrue(prerendered, @"Prerender did not happen");
// Open the suggestion. The suggestion needs to be the first suggestion to
// have the prerenderer activated.
[[EarlGrey
selectElementWithMatcher:grey_allOf(
grey_accessibilityLabel(pageString),
grey_kindOfClassName(@"FadeTruncatingLabel"),
grey_ancestor(grey_accessibilityID(
@"omnibox suggestion 0")),
grey_sufficientlyVisible(), nil)]
performAction:grey_tap()];
[ChromeEarlGrey waitForWebStateContainingText:kPageLoadedString];
GREYAssertEqual(visitCountBeforePrerender + 1, _visitCounter,
@"Prerender should have been the last load");
// Request the desktop site.
[ChromeEarlGreyUI openToolsMenu];
[RequestDesktopButton() performAction:grey_tap()];
prerendered = WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
return _visitCounter == visitCountBeforePrerender + 2;
});
GREYAssertTrue(prerendered, @"Page wasn't reloaded");
// Verify that going back returns to the mobile site.
[[EarlGrey selectElementWithMatcher:chrome_test_util::BackButton()]
performAction:grey_tap()];
[ChromeEarlGrey waitForWebStateContainingText:kMobileSiteLabel];
// The content of the page can be cached, check the button also.
[ChromeEarlGreyUI openToolsMenu];
[RequestDesktopButton() assertWithMatcher:grey_notNil()];
}
@end
......@@ -109,6 +109,20 @@ void WKBasedNavigationManagerImpl::OnNavigationStarted(const GURL& url) {
restoration_timer_->Elapsed());
restoration_timer_.reset();
}
// Get the last committed item directly because the restoration is in
// progress so the item returned by the last committed item is the
// last_committed_web_view_item_ as the origins mistmatch.
int index = GetLastCommittedItemIndexInCurrentOrRestoredSession();
DCHECK(index != -1 || 0 == GetItemCount());
if (index != -1 &&
restored_visible_item_->GetUserAgentType() != UserAgentType::NONE) {
NavigationItemImpl* last_committed_item =
GetNavigationItemImplAtIndex(static_cast<size_t>(index));
last_committed_item->SetUserAgentType(
restored_visible_item_->GetUserAgentType());
}
FinalizeSessionRestore();
}
}
......@@ -390,6 +404,12 @@ bool WKBasedNavigationManagerImpl::ShouldBlockUrlDuringRestore(
// Abort restore.
DiscardNonCommittedItems();
last_committed_item_index_ = web_view_cache_.GetCurrentItemIndex();
if (restored_visible_item_->GetUserAgentType() != UserAgentType::NONE) {
NavigationItem* last_committed_item =
GetLastCommittedItemInCurrentOrRestoredSession();
last_committed_item->SetUserAgentType(
restored_visible_item_->GetUserAgentType());
}
restored_visible_item_.reset();
FinalizeSessionRestore();
return true;
......
......@@ -28,6 +28,7 @@
#import "ios/web/web_state/user_interaction_state.h"
#import "ios/web/web_state/web_state_impl.h"
#import "net/base/mac/url_conversions.h"
#include "net/base/url_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -324,9 +325,12 @@ enum class BackForwardNavigationType {
// redirects can not change the origin. It is possible to have more than one
// pending navigations, so the redirect does not necesserily belong to the
// pending navigation item.
// Do not do it for localhost address as this is needed to have
// pre-rendering in tests.
if ((base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage) ||
!placeholderNavigation) &&
item->GetURL().GetOrigin() == requestURL.GetOrigin()) {
item->GetURL().GetOrigin() == requestURL.GetOrigin() &&
!net::IsLocalhost(requestURL)) {
self.navigationManagerImpl->UpdatePendingItemUrl(requestURL);
}
} else {
......
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