1 // Copyright (c) 2012 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 #include "chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/files/scoped_file.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/values.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/io_thread.h"
19 #include "chrome/browser/net/chrome_net_log.h"
20 #include "chrome/browser/prerender/prerender_manager.h"
21 #include "chrome/browser/prerender/prerender_manager_factory.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/test/base/ui_test_utils.h"
28 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
29 #include "content/public/browser/render_frame_host.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/browser/web_ui_message_handler.h"
32 #include "net/base/address_list.h"
33 #include "net/base/net_errors.h"
34 #include "net/dns/host_cache.h"
35 #include "net/dns/host_resolver.h"
36 #include "net/dns/mock_host_resolver.h"
37 #include "net/http/http_network_session.h"
38 #include "net/http/http_transaction_factory.h"
39 #include "net/log/net_log.h"
40 #include "net/log/write_to_file_net_log_observer.h"
41 #include "net/url_request/url_request_context.h"
42 #include "net/url_request/url_request_context_getter.h"
43 #include "testing/gtest/include/gtest/gtest.h"
46 using content::BrowserThread
;
47 using content::WebUIMessageHandler
;
51 // Called on IO thread. Adds an entry to the cache for the specified hostname.
52 // Either |net_error| must be net::OK, or |address| must be NULL.
53 void AddCacheEntryOnIOThread(net::URLRequestContextGetter
* context_getter
,
54 const std::string
& hostname
,
55 const std::string
& ip_literal
,
57 int expire_days_from_now
) {
58 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO
));
59 net::URLRequestContext
* context
= context_getter
->GetURLRequestContext();
60 net::HostCache
* cache
= context
->host_resolver()->GetHostCache();
63 net::HostCache::Key
key(hostname
, net::ADDRESS_FAMILY_UNSPECIFIED
, 0);
64 base::TimeDelta ttl
= base::TimeDelta::FromDays(expire_days_from_now
);
66 net::AddressList address_list
;
67 if (net_error
== net::OK
) {
68 // If |net_error| does not indicate an error, convert |ip_literal| to a
69 // net::AddressList, so it can be used with the cache.
70 int rv
= net::ParseAddressList(ip_literal
, hostname
, &address_list
);
71 ASSERT_EQ(net::OK
, rv
);
73 ASSERT_TRUE(ip_literal
.empty());
76 // Add entry to the cache.
77 cache
->Set(net::HostCache::Key(hostname
, net::ADDRESS_FAMILY_UNSPECIFIED
, 0),
78 net::HostCache::Entry(net_error
, address_list
),
79 base::TimeTicks::Now(),
85 ////////////////////////////////////////////////////////////////////////////////
86 // NetInternalsTest::MessageHandler
87 ////////////////////////////////////////////////////////////////////////////////
89 // Class to handle messages from the renderer needed by certain tests.
90 class NetInternalsTest::MessageHandler
: public content::WebUIMessageHandler
{
92 explicit MessageHandler(NetInternalsTest
* net_internals_test
);
95 void RegisterMessages() override
;
97 // Runs NetInternalsTest.callback with the given value.
98 void RunJavascriptCallback(base::Value
* value
);
100 // Takes a string and provides the corresponding URL from the test server,
101 // which must already have been started.
102 void GetTestServerURL(const base::ListValue
* list_value
);
104 // Called on UI thread. Adds an entry to the cache for the specified
105 // hostname by posting a task to the IO thread. Takes the host name,
106 // ip address, net error code, and expiration time in days from now
107 // as parameters. If the error code indicates failure, the ip address
108 // must be an empty string.
109 void AddCacheEntry(const base::ListValue
* list_value
);
111 // Opens the given URL in a new tab.
112 void LoadPage(const base::ListValue
* list_value
);
114 // Opens a page in a new tab that prerenders the given URL.
115 void PrerenderPage(const base::ListValue
* list_value
);
117 // Navigates to the prerender in the background tab. This assumes that
118 // there is a "Click()" function in the background tab which will navigate
119 // there, and that the background tab exists at slot 1.
120 void NavigateToPrerender(const base::ListValue
* list_value
);
122 // Creates an incognito browser. Once creation is complete, passes a
123 // message to the Javascript test harness.
124 void CreateIncognitoBrowser(const base::ListValue
* list_value
);
126 // Closes an incognito browser created with CreateIncognitoBrowser.
127 void CloseIncognitoBrowser(const base::ListValue
* list_value
);
129 // Creates a simple log using WriteToFileNetLogObserver, and returns it to
130 // the Javascript callback.
131 void GetNetLogFileContents(const base::ListValue
* list_value
);
133 // Changes the data reduction proxy mode. A boolean is assumed to exist at
134 // index 0 which enables the proxy is set to true.
135 void EnableDataReductionProxy(const base::ListValue
* list_value
);
137 Browser
* browser() { return net_internals_test_
->browser(); }
139 NetInternalsTest
* net_internals_test_
;
140 Browser
* incognito_browser_
;
142 DISALLOW_COPY_AND_ASSIGN(MessageHandler
);
145 NetInternalsTest::MessageHandler::MessageHandler(
146 NetInternalsTest
* net_internals_test
)
147 : net_internals_test_(net_internals_test
),
148 incognito_browser_(NULL
) {
151 void NetInternalsTest::MessageHandler::RegisterMessages() {
152 web_ui()->RegisterMessageCallback("getTestServerURL",
153 base::Bind(&NetInternalsTest::MessageHandler::GetTestServerURL
,
154 base::Unretained(this)));
155 web_ui()->RegisterMessageCallback("addCacheEntry",
156 base::Bind(&NetInternalsTest::MessageHandler::AddCacheEntry
,
157 base::Unretained(this)));
158 web_ui()->RegisterMessageCallback("loadPage",
159 base::Bind(&NetInternalsTest::MessageHandler::LoadPage
,
160 base::Unretained(this)));
161 web_ui()->RegisterMessageCallback("prerenderPage",
162 base::Bind(&NetInternalsTest::MessageHandler::PrerenderPage
,
163 base::Unretained(this)));
164 web_ui()->RegisterMessageCallback("navigateToPrerender",
165 base::Bind(&NetInternalsTest::MessageHandler::NavigateToPrerender
,
166 base::Unretained(this)));
167 web_ui()->RegisterMessageCallback("createIncognitoBrowser",
168 base::Bind(&NetInternalsTest::MessageHandler::CreateIncognitoBrowser
,
169 base::Unretained(this)));
170 web_ui()->RegisterMessageCallback("closeIncognitoBrowser",
171 base::Bind(&NetInternalsTest::MessageHandler::CloseIncognitoBrowser
,
172 base::Unretained(this)));
173 web_ui()->RegisterMessageCallback("getNetLogFileContents",
175 &NetInternalsTest::MessageHandler::GetNetLogFileContents
,
176 base::Unretained(this)));
177 web_ui()->RegisterMessageCallback("enableDataReductionProxy",
179 &NetInternalsTest::MessageHandler::EnableDataReductionProxy
,
180 base::Unretained(this)));
183 void NetInternalsTest::MessageHandler::RunJavascriptCallback(
184 base::Value
* value
) {
185 web_ui()->CallJavascriptFunction("NetInternalsTest.callback", *value
);
188 void NetInternalsTest::MessageHandler::GetTestServerURL(
189 const base::ListValue
* list_value
) {
190 ASSERT_TRUE(net_internals_test_
->StartTestServer());
192 ASSERT_TRUE(list_value
->GetString(0, &path
));
193 GURL url
= net_internals_test_
->test_server()->GetURL(path
);
194 scoped_ptr
<base::Value
> url_value(new base::StringValue(url
.spec()));
195 RunJavascriptCallback(url_value
.get());
198 void NetInternalsTest::MessageHandler::AddCacheEntry(
199 const base::ListValue
* list_value
) {
200 std::string hostname
;
201 std::string ip_literal
;
203 double expire_days_from_now
;
204 ASSERT_TRUE(list_value
->GetString(0, &hostname
));
205 ASSERT_TRUE(list_value
->GetString(1, &ip_literal
));
206 ASSERT_TRUE(list_value
->GetDouble(2, &net_error
));
207 ASSERT_TRUE(list_value
->GetDouble(3, &expire_days_from_now
));
208 ASSERT_TRUE(browser());
210 BrowserThread::PostTask(
211 BrowserThread::IO
, FROM_HERE
,
212 base::Bind(&AddCacheEntryOnIOThread
,
213 make_scoped_refptr(browser()->profile()->GetRequestContext()),
216 static_cast<int>(net_error
),
217 static_cast<int>(expire_days_from_now
)));
220 void NetInternalsTest::MessageHandler::LoadPage(
221 const base::ListValue
* list_value
) {
223 ASSERT_TRUE(list_value
->GetString(0, &url
));
224 LOG(WARNING
) << "url: [" << url
<< "]";
225 ui_test_utils::NavigateToURLWithDisposition(
229 ui_test_utils::BROWSER_TEST_NONE
);
232 void NetInternalsTest::MessageHandler::PrerenderPage(
233 const base::ListValue
* list_value
) {
234 std::string prerender_url
;
235 ASSERT_TRUE(list_value
->GetString(0, &prerender_url
));
237 net_internals_test_
->CreatePrerenderLoaderUrl(GURL(prerender_url
));
238 ui_test_utils::NavigateToURLWithDisposition(
242 ui_test_utils::BROWSER_TEST_NONE
);
245 void NetInternalsTest::MessageHandler::NavigateToPrerender(
246 const base::ListValue
* list_value
) {
248 ASSERT_TRUE(list_value
->GetString(0, &url
));
249 content::RenderFrameHost
* frame
=
250 browser()->tab_strip_model()->GetWebContentsAt(1)->GetMainFrame();
251 frame
->ExecuteJavaScript(
252 base::ASCIIToUTF16(base::StringPrintf("Click('%s')", url
.c_str())));
255 void NetInternalsTest::MessageHandler::CreateIncognitoBrowser(
256 const base::ListValue
* list_value
) {
257 ASSERT_FALSE(incognito_browser_
);
258 incognito_browser_
= net_internals_test_
->CreateIncognitoBrowser();
260 // Tell the test harness that creation is complete.
261 base::StringValue
command_value("onIncognitoBrowserCreatedForTest");
262 web_ui()->CallJavascriptFunction("g_browser.receive", command_value
);
265 void NetInternalsTest::MessageHandler::CloseIncognitoBrowser(
266 const base::ListValue
* list_value
) {
267 ASSERT_TRUE(incognito_browser_
);
268 incognito_browser_
->tab_strip_model()->CloseAllTabs();
269 // Closing all a Browser's tabs will ultimately result in its destruction,
270 // thought it may not have been destroyed yet.
271 incognito_browser_
= NULL
;
274 void NetInternalsTest::MessageHandler::GetNetLogFileContents(
275 const base::ListValue
* list_value
) {
276 base::ScopedTempDir temp_directory
;
277 ASSERT_TRUE(temp_directory
.CreateUniqueTempDir());
278 base::FilePath temp_file
;
279 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_directory
.path(),
281 base::ScopedFILE
temp_file_handle(base::OpenFile(temp_file
, "w"));
282 ASSERT_TRUE(temp_file_handle
);
284 scoped_ptr
<base::Value
> constants(NetInternalsUI::GetConstants());
285 scoped_ptr
<net::WriteToFileNetLogObserver
> net_log_logger(
286 new net::WriteToFileNetLogObserver());
287 net_log_logger
->StartObserving(
288 g_browser_process
->net_log(), temp_file_handle
.Pass(), constants
.get(),
290 g_browser_process
->net_log()->AddGlobalEntry(
291 net::NetLog::TYPE_NETWORK_IP_ADDRESSES_CHANGED
);
292 net::BoundNetLog bound_net_log
= net::BoundNetLog::Make(
293 g_browser_process
->net_log(),
294 net::NetLog::SOURCE_URL_REQUEST
);
295 bound_net_log
.BeginEvent(net::NetLog::TYPE_REQUEST_ALIVE
);
296 net_log_logger
->StopObserving(nullptr);
297 net_log_logger
.reset();
299 std::string log_contents
;
300 ASSERT_TRUE(base::ReadFileToString(temp_file
, &log_contents
));
301 ASSERT_GT(log_contents
.length(), 0u);
303 scoped_ptr
<base::Value
> log_contents_value(
304 new base::StringValue(log_contents
));
305 RunJavascriptCallback(log_contents_value
.get());
308 void NetInternalsTest::MessageHandler::EnableDataReductionProxy(
309 const base::ListValue
* list_value
) {
311 ASSERT_TRUE(list_value
->GetBoolean(0, &enable
));
312 browser()->profile()->GetPrefs()->SetBoolean(
313 data_reduction_proxy::prefs::kDataReductionProxyEnabled
, enable
);
316 ////////////////////////////////////////////////////////////////////////////////
318 ////////////////////////////////////////////////////////////////////////////////
320 NetInternalsTest::NetInternalsTest()
321 : test_server_started_(false) {
322 message_handler_
.reset(new MessageHandler(this));
325 NetInternalsTest::~NetInternalsTest() {
328 void NetInternalsTest::SetUpCommandLine(base::CommandLine
* command_line
) {
329 WebUIBrowserTest::SetUpCommandLine(command_line
);
330 // Needed to test the prerender view.
331 command_line
->AppendSwitchASCII(switches::kPrerenderMode
,
332 switches::kPrerenderModeSwitchValueEnabled
);
335 void NetInternalsTest::SetUpOnMainThread() {
336 WebUIBrowserTest::SetUpOnMainThread();
337 // Increase the memory allowed in a prerendered page above normal settings,
338 // as debug builds use more memory and often go over the usual limit.
339 Profile
* profile
= browser()->profile();
340 prerender::PrerenderManager
* prerender_manager
=
341 prerender::PrerenderManagerFactory::GetForProfile(profile
);
342 prerender_manager
->mutable_config().max_bytes
= 1000 * 1024 * 1024;
345 content::WebUIMessageHandler
* NetInternalsTest::GetMockMessageHandler() {
346 return message_handler_
.get();
349 GURL
NetInternalsTest::CreatePrerenderLoaderUrl(
350 const GURL
& prerender_url
) {
351 EXPECT_TRUE(StartTestServer());
352 std::vector
<net::SpawnedTestServer::StringPair
> replacement_text
;
353 replacement_text
.push_back(
354 make_pair("REPLACE_WITH_PRERENDER_URL", prerender_url
.spec()));
355 std::string replacement_path
;
356 EXPECT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
357 "files/prerender/prerender_loader.html",
360 GURL url_loader
= test_server()->GetURL(replacement_path
);
364 bool NetInternalsTest::StartTestServer() {
365 if (test_server_started_
)
367 test_server_started_
= test_server()->Start();
369 // Sample domain for SDCH-view test. Dictionaries for localhost/127.0.0.1
371 host_resolver()->AddRule("testdomain.com", "127.0.0.1");
372 host_resolver()->AddRule("sub.testdomain.com", "127.0.0.1");
373 return test_server_started_
;