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
3 // found in the LICENSE file.
5 #import "ios/web/webui/crw_web_ui_manager.h"
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.h"
9 #include "base/logging.h"
10 #import "base/mac/scoped_nsobject.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/path_service.h"
14 #include "base/strings/stringprintf.h"
15 #import "base/strings/sys_string_conversions.h"
16 #include "base/values.h"
17 #include "ios/web/public/test/test_browser_state.h"
18 #import "ios/web/public/test/test_web_client.h"
19 #include "ios/web/web_state/web_state_impl.h"
20 #import "ios/web/webui/crw_web_ui_page_builder.h"
21 #include "ios/web/webui/url_fetcher_block_adapter.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "testing/gtest_mac.h"
25 #include "testing/platform_test.h"
29 // Path for test favicon file.
30 const char kFaviconPath[] = "ios/web/test/data/testfavicon.png";
31 // URL for mock WebUI page.
32 const char kTestChromeUrl[] = "chrome://test";
33 // URL for mock favicon.
34 const char kFaviconUrl[] = "chrome://favicon";
35 // HTML for mock WebUI page.
36 NSString* kHtml = @"<html>Hello World</html>";
38 // Mock of WebStateImpl to check that LoadHtml and ExecuteJavaScriptAsync are
39 // called as expected.
40 class MockWebStateImpl : public WebStateImpl {
42 MockWebStateImpl(BrowserState* browser_state) : WebStateImpl(browser_state) {}
43 MOCK_METHOD2(LoadWebUIHtml,
44 void(const base::string16& html, const GURL& url));
45 MOCK_METHOD1(ExecuteJavaScriptAsync, void(const base::string16& javascript));
48 // Mock of URLFetcherBlockAdapter to provide mock resources.
49 class MockURLFetcherBlockAdapter : public URLFetcherBlockAdapter {
51 MockURLFetcherBlockAdapter(
53 net::URLRequestContextGetter* request_context,
54 URLFetcherBlockAdapterCompletion completion_handler)
55 : URLFetcherBlockAdapter(url, request_context, completion_handler),
57 completion_handler_(completion_handler) {}
59 void Start() override {
60 if (url_.spec() == kTestChromeUrl) {
61 completion_handler_.get()([kHtml dataUsingEncoding:NSUTF8StringEncoding],
63 } else if (url_.spec() == kFaviconUrl) {
64 base::FilePath favicon_path;
65 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &favicon_path));
66 favicon_path = favicon_path.AppendASCII(kFaviconPath);
67 completion_handler_.get()(
68 [NSData dataWithContentsOfFile:base::SysUTF8ToNSString(
69 favicon_path.value())],
79 // Callback for resource load.
80 base::mac::ScopedBlock<URLFetcherBlockAdapterCompletion> completion_handler_;
83 class AppSpecificTestWebClient : public TestWebClient {
85 bool IsAppSpecificURL(const GURL& url) const override {
86 return url.SchemeIs("chrome");
92 // Subclass of CRWWebUIManager for testing.
93 @interface CRWTestWebUIManager : CRWWebUIManager
94 // Use mock URLFetcherBlockAdapter.
95 - (scoped_ptr<web::URLFetcherBlockAdapter>)
96 fetcherForURL:(const GURL&)URL
97 completionHandler:(web::URLFetcherBlockAdapterCompletion)handler;
100 @implementation CRWTestWebUIManager
101 - (scoped_ptr<web::URLFetcherBlockAdapter>)
102 fetcherForURL:(const GURL&)URL
103 completionHandler:(web::URLFetcherBlockAdapterCompletion)handler {
104 return scoped_ptr<web::URLFetcherBlockAdapter>(
105 new web::MockURLFetcherBlockAdapter(URL, nil, handler));
111 // Test fixture for testing CRWWebUIManager
112 class CRWWebUIManagerTest : public PlatformTest {
114 void SetUp() override {
115 PlatformTest::SetUp();
116 test_web_client_.reset(new web::AppSpecificTestWebClient());
117 web::SetWebClient(test_web_client_.get());
118 test_browser_state_.reset(new TestBrowserState());
119 web_state_impl_.reset(new MockWebStateImpl(test_browser_state_.get()));
120 web_ui_manager_.reset(
121 [[CRWTestWebUIManager alloc] initWithWebState:web_state_impl_.get()]);
124 // TestBrowserState for creation of WebStateImpl.
125 scoped_ptr<TestBrowserState> test_browser_state_;
126 // MockWebStateImpl for detection of LoadHtml and EvaluateJavaScriptAync
128 scoped_ptr<MockWebStateImpl> web_state_impl_;
129 // WebUIManager for testing.
130 base::scoped_nsobject<CRWTestWebUIManager> web_ui_manager_;
131 // The WebClient used in tests.
132 scoped_ptr<AppSpecificTestWebClient> test_web_client_;
135 // Tests that CRWWebUIManager observes provisional navigation and invokes an
136 // HTML load in web state.
137 TEST_F(CRWWebUIManagerTest, LoadWebUI) {
138 base::string16 html(base::SysNSStringToUTF16(kHtml));
139 GURL url(kTestChromeUrl);
140 EXPECT_CALL(*web_state_impl_, LoadWebUIHtml(html, url));
141 web_state_impl_->OnProvisionalNavigationStarted(url);
144 // Tests that CRWWebUIManager responds to OnScriptCommandReceieved call and runs
145 // JavaScript to set favicon background.
146 TEST_F(CRWWebUIManagerTest, HandleFaviconRequest) {
147 GURL test_url(kTestChromeUrl);
148 std::string favicon_url_string(kFaviconUrl);
150 // Create mock JavaScript message to request favicon.
151 base::ListValue* arguments(new base::ListValue());
152 arguments->AppendString(favicon_url_string);
153 scoped_ptr<base::DictionaryValue> message(new base::DictionaryValue());
154 message->SetString("message", "webui.requestFavicon");
155 message->Set("arguments", arguments);
157 // Create expected JavaScript to call.
158 base::FilePath favicon_path;
159 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &favicon_path));
160 favicon_path = favicon_path.AppendASCII(kFaviconPath);
161 NSData* expected_data = [NSData
162 dataWithContentsOfFile:base::SysUTF8ToNSString(favicon_path.value())];
163 base::string16 expected_javascript = base::SysNSStringToUTF16([NSString
165 @"chrome.setFaviconBackground('%s', 'data:image/png;base64,%@');",
166 favicon_url_string.c_str(),
167 [expected_data base64EncodedStringWithOptions:0]]);
169 EXPECT_CALL(*web_state_impl_, ExecuteJavaScriptAsync(expected_javascript));
170 web_state_impl_->OnScriptCommandReceived("webui.requestFavicon", *message,