blob: 463de89e8f93afd0cd18c555c4e327a513b5a98d [file] [log] [blame]
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ios/chrome/browser/web/chrome_web_client.h"
#import <UIKit/UIKit.h>
#include <memory>
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/sys_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
#include "ios/chrome/browser/chrome_url_constants.h"
#include "ios/chrome/browser/passwords/password_manager_features.h"
#import "ios/chrome/browser/web/error_page_util.h"
#import "ios/web/public/test/error_test_util.h"
#import "ios/web/public/test/js_test_util.h"
#include "ios/web/public/test/scoped_testing_web_client.h"
#import "ios/web/public/web_view_creation_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Error used to test PrepareErrorPage method.
NSError* CreateTestError() {
return web::testing::CreateTestNetError([NSError
errorWithDomain:NSURLErrorDomain
code:NSURLErrorNetworkConnectionLost
userInfo:nil]);
}
} // namespace
class ChromeWebClientTest : public PlatformTest {
public:
ChromeWebClientTest() {
browser_state_ = TestChromeBrowserState::Builder().Build();
}
~ChromeWebClientTest() override = default;
ios::ChromeBrowserState* browser_state() { return browser_state_.get(); }
private:
base::test::ScopedTaskEnvironment environment_;
std::unique_ptr<ios::ChromeBrowserState> browser_state_;
DISALLOW_COPY_AND_ASSIGN(ChromeWebClientTest);
};
TEST_F(ChromeWebClientTest, UserAgent) {
std::vector<std::string> pieces;
// Check if the pieces of the user agent string come in the correct order.
ChromeWebClient web_client;
std::string buffer = web_client.GetUserAgent(web::UserAgentType::MOBILE);
pieces = base::SplitStringUsingSubstr(
buffer, "Mozilla/5.0 (", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
ASSERT_EQ(2u, pieces.size());
buffer = pieces[1];
EXPECT_EQ("", pieces[0]);
pieces = base::SplitStringUsingSubstr(
buffer, ") AppleWebKit/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
ASSERT_EQ(2u, pieces.size());
buffer = pieces[1];
std::string os_str = pieces[0];
pieces =
base::SplitStringUsingSubstr(buffer, " (KHTML, like Gecko) ",
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
ASSERT_EQ(2u, pieces.size());
buffer = pieces[1];
std::string webkit_version_str = pieces[0];
pieces = base::SplitStringUsingSubstr(
buffer, " Safari/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
ASSERT_EQ(2u, pieces.size());
std::string product_str = pieces[0];
std::string safari_version_str = pieces[1];
// Not sure what can be done to better check the OS string, since it's highly
// platform-dependent.
EXPECT_FALSE(os_str.empty());
EXPECT_FALSE(webkit_version_str.empty());
EXPECT_FALSE(safari_version_str.empty());
EXPECT_EQ(0u, product_str.find("CriOS/"));
}
// Tests that ChromeWebClient provides accessibility script for WKWebView.
TEST_F(ChromeWebClientTest, WKWebViewEarlyPageScriptAccessibility) {
// Chrome scripts rely on __gCrWeb object presence.
WKWebView* web_view = web::BuildWKWebView(CGRectZero, browser_state());
web::test::ExecuteJavaScript(web_view, @"__gCrWeb = {};");
web::ScopedTestingWebClient web_client(std::make_unique<ChromeWebClient>());
NSString* script =
web_client.Get()->GetDocumentStartScriptForAllFrames(browser_state());
web::test::ExecuteJavaScript(web_view, script);
EXPECT_NSEQ(@"object", web::test::ExecuteJavaScript(
web_view, @"typeof __gCrWeb.accessibility"));
}
// Tests that ChromeWebClient provides print script for WKWebView.
TEST_F(ChromeWebClientTest, WKWebViewEarlyPageScriptPrint) {
// Chrome scripts rely on __gCrWeb object presence.
WKWebView* web_view = web::BuildWKWebView(CGRectZero, browser_state());
web::test::ExecuteJavaScript(web_view, @"__gCrWeb = {};");
web::ScopedTestingWebClient web_client(std::make_unique<ChromeWebClient>());
NSString* script =
web_client.Get()->GetDocumentStartScriptForAllFrames(browser_state());
web::test::ExecuteJavaScript(web_view, script);
EXPECT_NSEQ(@"object",
web::test::ExecuteJavaScript(web_view, @"typeof __gCrWeb.print"));
}
// Tests that ChromeWebClient provides autofill controller script for WKWebView.
TEST_F(ChromeWebClientTest, WKWebViewEarlyPageScriptAutofillController) {
// Chrome scripts rely on __gCrWeb object presence.
WKWebView* web_view = web::BuildWKWebView(CGRectZero, browser_state());
web::test::ExecuteJavaScript(web_view, @"__gCrWeb = {};");
web::ScopedTestingWebClient web_client(std::make_unique<ChromeWebClient>());
NSString* script =
web_client.Get()->GetDocumentStartScriptForAllFrames(browser_state());
web::test::ExecuteJavaScript(web_view, script);
EXPECT_NSEQ(@"object", web::test::ExecuteJavaScript(
web_view, @"typeof __gCrWeb.autofill"));
}
// Tests that ChromeWebClient provides credential manager script for WKWebView
// if and only if the feature is enabled.
TEST_F(ChromeWebClientTest, WKWebViewEarlyPageScriptCredentialManager) {
// Chrome scripts rely on __gCrWeb object presence.
WKWebView* web_view = web::BuildWKWebView(CGRectZero, browser_state());
web::test::ExecuteJavaScript(web_view, @"__gCrWeb = {};");
web::ScopedTestingWebClient web_client(std::make_unique<ChromeWebClient>());
NSString* script =
web_client.Get()->GetDocumentStartScriptForMainFrame(browser_state());
web::test::ExecuteJavaScript(web_view, script);
EXPECT_NSEQ(@"undefined", web::test::ExecuteJavaScript(
web_view, @"typeof navigator.credentials"));
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(features::kCredentialManager);
script =
web_client.Get()->GetDocumentStartScriptForMainFrame(browser_state());
web::test::ExecuteJavaScript(web_view, script);
EXPECT_NSEQ(@"object", web::test::ExecuteJavaScript(
web_view, @"typeof navigator.credentials"));
}
// Tests that ChromeWebClient provides payment request script for WKWebView.
TEST_F(ChromeWebClientTest, WKWebViewEarlyPageScriptPaymentRequest) {
// Chrome scripts rely on __gCrWeb object presence.
WKWebView* web_view = web::BuildWKWebView(CGRectZero, browser_state());
web::test::ExecuteJavaScript(web_view, @"__gCrWeb = {};");
web::ScopedTestingWebClient web_client(std::make_unique<ChromeWebClient>());
NSString* script =
web_client.Get()->GetDocumentStartScriptForMainFrame(browser_state());
web::test::ExecuteJavaScript(web_view, script);
EXPECT_NSEQ(@"function", web::test::ExecuteJavaScript(
web_view, @"typeof window.PaymentRequest"));
}
// Tests PrepareErrorPage wth non-post, not Off The Record error.
TEST_F(ChromeWebClientTest, PrepareErrorPageNonPostNonOtr) {
ChromeWebClient web_client;
NSError* error = CreateTestError();
NSString* page = nil;
web_client.PrepareErrorPage(error, /*is_post=*/false,
/*is_off_the_record=*/false, &page);
EXPECT_NSEQ(
GetErrorPage(error, /*is_post=*/false, /*is_off_the_record=*/false),
page);
}
// Tests PrepareErrorPage with post, not Off The Record error.
TEST_F(ChromeWebClientTest, PrepareErrorPagePostNonOtr) {
ChromeWebClient web_client;
NSError* error = CreateTestError();
NSString* page = nil;
web_client.PrepareErrorPage(error, /*is_post=*/true,
/*is_off_the_record=*/false, &page);
EXPECT_NSEQ(
GetErrorPage(error, /*is_post=*/true, /*is_off_the_record=*/false), page);
}
// Tests PrepareErrorPage with non-post, Off The Record error.
TEST_F(ChromeWebClientTest, PrepareErrorPageNonPostOtr) {
ChromeWebClient web_client;
NSError* error = CreateTestError();
NSString* page = nil;
web_client.PrepareErrorPage(error, /*is_post=*/false,
/*is_off_the_record=*/true, &page);
EXPECT_NSEQ(
GetErrorPage(error, /*is_post=*/false, /*is_off_the_record=*/true), page);
}
// Tests PrepareErrorPage with post, Off The Record error.
TEST_F(ChromeWebClientTest, PrepareErrorPagePostOtr) {
ChromeWebClient web_client;
NSError* error = CreateTestError();
NSString* page = nil;
web_client.PrepareErrorPage(error, /*is_post=*/true,
/*is_off_the_record=*/true, &page);
EXPECT_NSEQ(GetErrorPage(error, /*is_post=*/true, /*is_off_the_record=*/true),
page);
}