- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / net_internals / net_internals_ui_browsertest.cc
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.
4
5 #include "chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/files/file_path.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/io_thread.h"
16 #include "chrome/browser/net/chrome_net_log.h"
17 #include "chrome/browser/prerender/prerender_manager.h"
18 #include "chrome/browser/prerender/prerender_manager_factory.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/tabs/tab_strip_model.h"
22 #include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/test/base/ui_test_utils.h"
25 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/browser/web_ui_message_handler.h"
28 #include "net/base/address_list.h"
29 #include "net/base/net_errors.h"
30 #include "net/base/net_log.h"
31 #include "net/base/net_log_logger.h"
32 #include "net/dns/host_cache.h"
33 #include "net/dns/host_resolver.h"
34 #include "net/dns/mock_host_resolver.h"
35 #include "net/http/http_network_session.h"
36 #include "net/http/http_pipelined_host_capability.h"
37 #include "net/http/http_transaction_factory.h"
38 #include "net/url_request/url_request_context.h"
39 #include "net/url_request/url_request_context_getter.h"
40 #include "testing/gtest/include/gtest/gtest.h"
41 #include "url/gurl.h"
42
43 using content::BrowserThread;
44 using content::WebUIMessageHandler;
45
46 namespace {
47
48 // Called on IO thread.  Adds an entry to the cache for the specified hostname.
49 // Either |net_error| must be net::OK, or |address| must be NULL.
50 void AddCacheEntryOnIOThread(net::URLRequestContextGetter* context_getter,
51                              const std::string& hostname,
52                              const std::string& ip_literal,
53                              int net_error,
54                              int expire_days_from_now) {
55   ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
56   net::URLRequestContext* context = context_getter->GetURLRequestContext();
57   net::HostCache* cache = context->host_resolver()->GetHostCache();
58   ASSERT_TRUE(cache);
59
60   net::HostCache::Key key(hostname, net::ADDRESS_FAMILY_UNSPECIFIED, 0);
61   base::TimeDelta ttl = base::TimeDelta::FromDays(expire_days_from_now);
62
63   net::AddressList address_list;
64   if (net_error == net::OK) {
65     // If |net_error| does not indicate an error, convert |ip_literal| to a
66     // net::AddressList, so it can be used with the cache.
67     int rv = net::ParseAddressList(ip_literal, hostname, &address_list);
68     ASSERT_EQ(net::OK, rv);
69   } else {
70     ASSERT_TRUE(ip_literal.empty());
71   }
72
73   // Add entry to the cache.
74   cache->Set(net::HostCache::Key(hostname, net::ADDRESS_FAMILY_UNSPECIFIED, 0),
75              net::HostCache::Entry(net_error, address_list),
76              base::TimeTicks::Now(),
77              ttl);
78 }
79
80 // Called on IO thread.  Adds an entry to the list of known HTTP pipelining
81 // hosts.
82 void AddDummyHttpPipelineFeedbackOnIOThread(
83     net::URLRequestContextGetter* context_getter,
84     const std::string& hostname,
85     int port,
86     net::HttpPipelinedHostCapability capability) {
87   ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
88   net::URLRequestContext* context = context_getter->GetURLRequestContext();
89   net::HttpNetworkSession* http_network_session =
90       context->http_transaction_factory()->GetSession();
91   base::WeakPtr<net::HttpServerProperties> http_server_properties =
92       http_network_session->http_server_properties();
93   net::HostPortPair origin(hostname, port);
94   http_server_properties->SetPipelineCapability(origin, capability);
95 }
96
97 // Called on IO thread.  Adds an entry to the list of known HTTP pipelining
98 // hosts.
99 void EnableHttpPipeliningOnIOThread(
100     net::URLRequestContextGetter* context_getter, bool enable) {
101   ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
102   net::URLRequestContext* context = context_getter->GetURLRequestContext();
103   net::HttpNetworkSession* http_network_session =
104       context->http_transaction_factory()->GetSession();
105   http_network_session->set_http_pipelining_enabled(enable);
106 }
107
108 }  // namespace
109
110 ////////////////////////////////////////////////////////////////////////////////
111 // NetInternalsTest::MessageHandler
112 ////////////////////////////////////////////////////////////////////////////////
113
114 // Class to handle messages from the renderer needed by certain tests.
115 class NetInternalsTest::MessageHandler : public content::WebUIMessageHandler {
116  public:
117   explicit MessageHandler(NetInternalsTest* net_internals_test);
118
119  private:
120   virtual void RegisterMessages() OVERRIDE;
121
122   // Runs NetInternalsTest.callback with the given value.
123   void RunJavascriptCallback(base::Value* value);
124
125   // Takes a string and provides the corresponding URL from the test server,
126   // which must already have been started.
127   void GetTestServerURL(const base::ListValue* list_value);
128
129   // Called on UI thread.  Adds an entry to the cache for the specified
130   // hostname by posting a task to the IO thread.  Takes the host name,
131   // ip address, net error code, and expiration time in days from now
132   // as parameters.  If the error code indicates failure, the ip address
133   // must be an empty string.
134   void AddCacheEntry(const base::ListValue* list_value);
135
136   // Opens the given URL in a new tab.
137   void LoadPage(const base::ListValue* list_value);
138
139   // Opens a page in a new tab that prerenders the given URL.
140   void PrerenderPage(const base::ListValue* list_value);
141
142   // Navigates to the prerender in the background tab. This assumes that
143   // there is a "Click()" function in the background tab which will navigate
144   // there, and that the background tab exists at slot 1.
145   void NavigateToPrerender(const base::ListValue* list_value);
146
147   // Creates an incognito browser.  Once creation is complete, passes a
148   // message to the Javascript test harness.
149   void CreateIncognitoBrowser(const base::ListValue* list_value);
150
151   // Closes an incognito browser created with CreateIncognitoBrowser.
152   void CloseIncognitoBrowser(const base::ListValue* list_value);
153
154   // Takes in a boolean and enables/disabled HTTP pipelining accordingly.
155   void EnableHttpPipelining(const base::ListValue* list_value);
156
157   // Called on UI thread. Adds an entry to the list of known HTTP pipelining
158   // hosts.
159   void AddDummyHttpPipelineFeedback(const base::ListValue* list_value);
160
161   // Creates a simple log with a NetLogLogger, and returns it to the
162   // Javascript callback.
163   void GetNetLogLoggerLog(const ListValue* list_value);
164
165   Browser* browser() { return net_internals_test_->browser(); }
166
167   NetInternalsTest* net_internals_test_;
168   Browser* incognito_browser_;
169
170   DISALLOW_COPY_AND_ASSIGN(MessageHandler);
171 };
172
173 NetInternalsTest::MessageHandler::MessageHandler(
174     NetInternalsTest* net_internals_test)
175     : net_internals_test_(net_internals_test),
176       incognito_browser_(NULL) {
177 }
178
179 void NetInternalsTest::MessageHandler::RegisterMessages() {
180   web_ui()->RegisterMessageCallback("getTestServerURL",
181       base::Bind(&NetInternalsTest::MessageHandler::GetTestServerURL,
182                  base::Unretained(this)));
183   web_ui()->RegisterMessageCallback("addCacheEntry",
184       base::Bind(&NetInternalsTest::MessageHandler::AddCacheEntry,
185                  base::Unretained(this)));
186   web_ui()->RegisterMessageCallback("loadPage",
187       base::Bind(&NetInternalsTest::MessageHandler::LoadPage,
188                   base::Unretained(this)));
189   web_ui()->RegisterMessageCallback("prerenderPage",
190       base::Bind(&NetInternalsTest::MessageHandler::PrerenderPage,
191                   base::Unretained(this)));
192   web_ui()->RegisterMessageCallback("navigateToPrerender",
193       base::Bind(&NetInternalsTest::MessageHandler::NavigateToPrerender,
194                  base::Unretained(this)));
195   web_ui()->RegisterMessageCallback("createIncognitoBrowser",
196       base::Bind(&NetInternalsTest::MessageHandler::CreateIncognitoBrowser,
197                  base::Unretained(this)));
198   web_ui()->RegisterMessageCallback("closeIncognitoBrowser",
199       base::Bind(&NetInternalsTest::MessageHandler::CloseIncognitoBrowser,
200                  base::Unretained(this)));
201   web_ui()->RegisterMessageCallback("enableHttpPipelining",
202       base::Bind(&NetInternalsTest::MessageHandler::EnableHttpPipelining,
203                  base::Unretained(this)));
204   web_ui()->RegisterMessageCallback("addDummyHttpPipelineFeedback",
205       base::Bind(
206           &NetInternalsTest::MessageHandler::AddDummyHttpPipelineFeedback,
207           base::Unretained(this)));
208   web_ui()->RegisterMessageCallback("getNetLogLoggerLog",
209       base::Bind(
210           &NetInternalsTest::MessageHandler::GetNetLogLoggerLog,
211           base::Unretained(this)));
212 }
213
214 void NetInternalsTest::MessageHandler::RunJavascriptCallback(
215     Value* value) {
216   web_ui()->CallJavascriptFunction("NetInternalsTest.callback", *value);
217 }
218
219 void NetInternalsTest::MessageHandler::GetTestServerURL(
220     const ListValue* list_value) {
221   ASSERT_TRUE(net_internals_test_->StartTestServer());
222   std::string path;
223   ASSERT_TRUE(list_value->GetString(0, &path));
224   GURL url = net_internals_test_->test_server()->GetURL(path);
225   scoped_ptr<Value> url_value(Value::CreateStringValue(url.spec()));
226   RunJavascriptCallback(url_value.get());
227 }
228
229 void NetInternalsTest::MessageHandler::AddCacheEntry(
230     const ListValue* list_value) {
231   std::string hostname;
232   std::string ip_literal;
233   double net_error;
234   double expire_days_from_now;
235   ASSERT_TRUE(list_value->GetString(0, &hostname));
236   ASSERT_TRUE(list_value->GetString(1, &ip_literal));
237   ASSERT_TRUE(list_value->GetDouble(2, &net_error));
238   ASSERT_TRUE(list_value->GetDouble(3, &expire_days_from_now));
239   ASSERT_TRUE(browser());
240
241   BrowserThread::PostTask(
242       BrowserThread::IO, FROM_HERE,
243       base::Bind(&AddCacheEntryOnIOThread,
244                  make_scoped_refptr(browser()->profile()->GetRequestContext()),
245                  hostname,
246                  ip_literal,
247                  static_cast<int>(net_error),
248                  static_cast<int>(expire_days_from_now)));
249 }
250
251 void NetInternalsTest::MessageHandler::LoadPage(
252     const ListValue* list_value) {
253   std::string url;
254   ASSERT_TRUE(list_value->GetString(0, &url));
255   LOG(WARNING) << "url: [" << url << "]";
256   ui_test_utils::NavigateToURLWithDisposition(
257       browser(),
258       GURL(url),
259       NEW_BACKGROUND_TAB,
260       ui_test_utils::BROWSER_TEST_NONE);
261 }
262
263 void NetInternalsTest::MessageHandler::PrerenderPage(
264     const ListValue* list_value) {
265   std::string prerender_url;
266   ASSERT_TRUE(list_value->GetString(0, &prerender_url));
267   GURL loader_url =
268       net_internals_test_->CreatePrerenderLoaderUrl(GURL(prerender_url));
269   ui_test_utils::NavigateToURLWithDisposition(
270       browser(),
271       GURL(loader_url),
272       NEW_BACKGROUND_TAB,
273       ui_test_utils::BROWSER_TEST_NONE);
274 }
275
276 void NetInternalsTest::MessageHandler::NavigateToPrerender(
277     const ListValue* list_value) {
278   content::RenderViewHost* host =
279       browser()->tab_strip_model()->GetWebContentsAt(1)->GetRenderViewHost();
280   host->ExecuteJavascriptInWebFrame(string16(), ASCIIToUTF16("Click()"));
281 }
282
283 void NetInternalsTest::MessageHandler::CreateIncognitoBrowser(
284     const ListValue* list_value) {
285   ASSERT_FALSE(incognito_browser_);
286   incognito_browser_ = net_internals_test_->CreateIncognitoBrowser();
287
288   // Tell the test harness that creation is complete.
289   StringValue command_value("onIncognitoBrowserCreatedForTest");
290   web_ui()->CallJavascriptFunction("g_browser.receive", command_value);
291 }
292
293 void NetInternalsTest::MessageHandler::CloseIncognitoBrowser(
294     const ListValue* list_value) {
295   ASSERT_TRUE(incognito_browser_);
296   incognito_browser_->tab_strip_model()->CloseAllTabs();
297   // Closing all a Browser's tabs will ultimately result in its destruction,
298   // thought it may not have been destroyed yet.
299   incognito_browser_ = NULL;
300 }
301
302 void NetInternalsTest::MessageHandler::EnableHttpPipelining(
303     const ListValue* list_value) {
304   bool enable;
305   ASSERT_TRUE(list_value->GetBoolean(0, &enable));
306   BrowserThread::PostTask(
307       BrowserThread::IO, FROM_HERE,
308       base::Bind(&EnableHttpPipeliningOnIOThread,
309                  make_scoped_refptr(browser()->profile()->GetRequestContext()),
310                  enable));
311 }
312
313 void NetInternalsTest::MessageHandler::AddDummyHttpPipelineFeedback(
314     const ListValue* list_value) {
315   std::string hostname;
316   double port;
317   std::string raw_capability;
318   net::HttpPipelinedHostCapability capability;
319   ASSERT_TRUE(list_value->GetString(0, &hostname));
320   ASSERT_TRUE(list_value->GetDouble(1, &port));
321   ASSERT_TRUE(list_value->GetString(2, &raw_capability));
322   if (raw_capability == "capable") {
323     capability = net::PIPELINE_CAPABLE;
324   } else if (raw_capability == "incapable") {
325     capability = net::PIPELINE_INCAPABLE;
326   } else {
327     FAIL() << "Unexpected capability string: " << raw_capability;
328   }
329   BrowserThread::PostTask(
330       BrowserThread::IO, FROM_HERE,
331       base::Bind(&AddDummyHttpPipelineFeedbackOnIOThread,
332                  make_scoped_refptr(browser()->profile()->GetRequestContext()),
333                  hostname,
334                  static_cast<int>(port),
335                  capability));
336 }
337
338 void NetInternalsTest::MessageHandler::GetNetLogLoggerLog(
339     const ListValue* list_value) {
340   base::ScopedTempDir temp_directory;
341   ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
342   base::FilePath temp_file;
343   ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_directory.path(),
344                                                   &temp_file));
345   FILE* temp_file_handle = file_util::OpenFile(temp_file, "w");
346   ASSERT_TRUE(temp_file_handle);
347
348   scoped_ptr<base::Value> constants(NetInternalsUI::GetConstants());
349   scoped_ptr<net::NetLogLogger> net_log_logger(new net::NetLogLogger(
350       temp_file_handle, *constants));
351   net_log_logger->StartObserving(g_browser_process->net_log());
352   g_browser_process->net_log()->AddGlobalEntry(
353       net::NetLog::TYPE_NETWORK_IP_ADDRESSES_CHANGED);
354   net::BoundNetLog bound_net_log = net::BoundNetLog::Make(
355       g_browser_process->net_log(),
356       net::NetLog::SOURCE_URL_REQUEST);
357   bound_net_log.BeginEvent(net::NetLog::TYPE_REQUEST_ALIVE);
358   net_log_logger->StopObserving();
359   net_log_logger.reset();
360
361   std::string log_contents;
362   ASSERT_TRUE(base::ReadFileToString(temp_file, &log_contents));
363   ASSERT_GT(log_contents.length(), 0u);
364
365   scoped_ptr<Value> log_contents_value(new base::StringValue(log_contents));
366   RunJavascriptCallback(log_contents_value.get());
367 }
368
369 ////////////////////////////////////////////////////////////////////////////////
370 // NetInternalsTest
371 ////////////////////////////////////////////////////////////////////////////////
372
373 NetInternalsTest::NetInternalsTest()
374     : test_server_started_(false) {
375   message_handler_.reset(new MessageHandler(this));
376 }
377
378 NetInternalsTest::~NetInternalsTest() {
379 }
380
381 void NetInternalsTest::SetUp() {
382 #if defined(OS_WIN) && defined(USE_AURA)
383   // The NetInternalsTest.netInternalsTimelineViewScrollbar test requires real
384   // GL bindings to pass on Win7 Aura.
385   UseRealGLBindings();
386 #endif
387
388   WebUIBrowserTest::SetUp();
389 }
390
391 void NetInternalsTest::SetUpCommandLine(CommandLine* command_line) {
392   WebUIBrowserTest::SetUpCommandLine(command_line);
393   // Needed to test the prerender view.
394   command_line->AppendSwitchASCII(switches::kPrerenderMode,
395                                   switches::kPrerenderModeSwitchValueEnabled);
396 }
397
398 void NetInternalsTest::SetUpOnMainThread() {
399   WebUIBrowserTest::SetUpOnMainThread();
400   // Increase the memory allowed in a prerendered page above normal settings,
401   // as debug builds use more memory and often go over the usual limit.
402   Profile* profile = browser()->profile();
403   prerender::PrerenderManager* prerender_manager =
404       prerender::PrerenderManagerFactory::GetForProfile(profile);
405   prerender_manager->mutable_config().max_bytes = 1000 * 1024 * 1024;
406 }
407
408 content::WebUIMessageHandler* NetInternalsTest::GetMockMessageHandler() {
409   return message_handler_.get();
410 }
411
412 GURL NetInternalsTest::CreatePrerenderLoaderUrl(
413     const GURL& prerender_url) {
414   EXPECT_TRUE(StartTestServer());
415   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
416   replacement_text.push_back(
417       make_pair("REPLACE_WITH_PRERENDER_URL", prerender_url.spec()));
418   replacement_text.push_back(
419       make_pair("REPLACE_WITH_DESTINATION_URL", prerender_url.spec()));
420   std::string replacement_path;
421   EXPECT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
422       "files/prerender/prerender_loader.html",
423       replacement_text,
424       &replacement_path));
425   GURL url_loader = test_server()->GetURL(replacement_path);
426   return url_loader;
427 }
428
429 bool NetInternalsTest::StartTestServer() {
430   if (test_server_started_)
431     return true;
432   test_server_started_ = test_server()->Start();
433   return test_server_started_;
434 }