Standardize usage of virtual/override/final in chrome/browser/ui/
[chromium-blink-merge.git] / chrome / browser / ui / webui / net_internals / net_internals_ui.cc
blobe959c6b367077c716560167499489402c75a0530
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.h"
7 #include <algorithm>
8 #include <list>
9 #include <string>
10 #include <utility>
11 #include <vector>
13 #include "base/base64.h"
14 #include "base/bind.h"
15 #include "base/bind_helpers.h"
16 #include "base/command_line.h"
17 #include "base/files/file.h"
18 #include "base/files/file_path.h"
19 #include "base/files/file_util.h"
20 #include "base/memory/weak_ptr.h"
21 #include "base/message_loop/message_loop.h"
22 #include "base/prefs/pref_member.h"
23 #include "base/sequenced_task_runner_helpers.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_piece.h"
26 #include "base/strings/string_split.h"
27 #include "base/strings/string_util.h"
28 #include "base/strings/utf_string_conversions.h"
29 #include "base/task/cancelable_task_tracker.h"
30 #include "base/values.h"
31 #include "chrome/browser/browser_process.h"
32 #include "chrome/browser/browsing_data/browsing_data_helper.h"
33 #include "chrome/browser/browsing_data/browsing_data_remover.h"
34 #include "chrome/browser/chrome_notification_types.h"
35 #include "chrome/browser/download/download_prefs.h"
36 #include "chrome/browser/io_thread.h"
37 #include "chrome/browser/net/chrome_net_log.h"
38 #include "chrome/browser/net/chrome_network_delegate.h"
39 #include "chrome/browser/net/connection_tester.h"
40 #include "chrome/browser/prerender/prerender_manager.h"
41 #include "chrome/browser/prerender/prerender_manager_factory.h"
42 #include "chrome/browser/profiles/profile.h"
43 #include "chrome/common/chrome_paths.h"
44 #include "chrome/common/chrome_version_info.h"
45 #include "chrome/common/pref_names.h"
46 #include "chrome/common/url_constants.h"
47 #include "components/onc/onc_constants.h"
48 #include "components/url_fixer/url_fixer.h"
49 #include "content/public/browser/browser_thread.h"
50 #include "content/public/browser/notification_details.h"
51 #include "content/public/browser/resource_dispatcher_host.h"
52 #include "content/public/browser/web_contents.h"
53 #include "content/public/browser/web_ui.h"
54 #include "content/public/browser/web_ui_data_source.h"
55 #include "content/public/browser/web_ui_message_handler.h"
56 #include "grit/net_internals_resources.h"
57 #include "net/base/net_errors.h"
58 #include "net/base/net_log_logger.h"
59 #include "net/base/net_util.h"
60 #include "net/disk_cache/disk_cache.h"
61 #include "net/dns/host_cache.h"
62 #include "net/dns/host_resolver.h"
63 #include "net/http/http_cache.h"
64 #include "net/http/http_network_layer.h"
65 #include "net/http/http_network_session.h"
66 #include "net/http/http_server_properties.h"
67 #include "net/http/http_stream_factory.h"
68 #include "net/http/transport_security_state.h"
69 #include "net/proxy/proxy_service.h"
70 #include "net/url_request/url_request_context.h"
71 #include "net/url_request/url_request_context_getter.h"
73 #if defined(OS_CHROMEOS)
74 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
75 #include "chrome/browser/chromeos/net/onc_utils.h"
76 #include "chrome/browser/chromeos/profiles/profile_helper.h"
77 #include "chrome/browser/chromeos/system/syslogs_provider.h"
78 #include "chrome/browser/chromeos/system_logs/debug_log_writer.h"
79 #include "chrome/browser/net/nss_context.h"
80 #include "chromeos/dbus/dbus_thread_manager.h"
81 #include "chromeos/dbus/debug_daemon_client.h"
82 #include "chromeos/network/onc/onc_certificate_importer_impl.h"
83 #include "chromeos/network/onc/onc_utils.h"
84 #include "components/user_manager/user.h"
85 #endif
87 #if defined(OS_WIN)
88 #include "chrome/browser/net/service_providers_win.h"
89 #endif
91 #if defined(ENABLE_EXTENSIONS)
92 #include "chrome/browser/extensions/extension_service.h"
93 #include "chrome/browser/ui/webui/extensions/extension_basic_info.h"
94 #include "extensions/browser/extension_registry.h"
95 #include "extensions/browser/extension_system.h"
96 #include "extensions/common/extension_set.h"
97 #endif
99 using base::StringValue;
100 using content::BrowserThread;
101 using content::WebContents;
102 using content::WebUIMessageHandler;
104 namespace {
106 // Delay between when an event occurs and when it is passed to the Javascript
107 // page. All events that occur during this period are grouped together and
108 // sent to the page at once, which reduces context switching and CPU usage.
109 const int kNetLogEventDelayMilliseconds = 100;
111 // Returns the HostCache for |context|'s primary HostResolver, or NULL if
112 // there is none.
113 net::HostCache* GetHostResolverCache(net::URLRequestContext* context) {
114 return context->host_resolver()->GetHostCache();
117 std::string HashesToBase64String(const net::HashValueVector& hashes) {
118 std::string str;
119 for (size_t i = 0; i != hashes.size(); ++i) {
120 if (i != 0)
121 str += ",";
122 str += hashes[i].ToString();
124 return str;
127 bool Base64StringToHashes(const std::string& hashes_str,
128 net::HashValueVector* hashes) {
129 hashes->clear();
130 std::vector<std::string> vector_hash_str;
131 base::SplitString(hashes_str, ',', &vector_hash_str);
133 for (size_t i = 0; i != vector_hash_str.size(); ++i) {
134 std::string hash_str;
135 base::RemoveChars(vector_hash_str[i], " \t\r\n", &hash_str);
136 net::HashValue hash;
137 // Skip past unrecognized hash algos
138 // But return false on malformatted input
139 if (hash_str.empty())
140 return false;
141 if (hash_str.compare(0, 5, "sha1/") != 0 &&
142 hash_str.compare(0, 7, "sha256/") != 0) {
143 continue;
145 if (!hash.FromString(hash_str))
146 return false;
147 hashes->push_back(hash);
149 return true;
152 // Returns a Value representing the state of a pre-existing URLRequest when
153 // net-internals was opened.
154 base::Value* GetRequestStateAsValue(const net::URLRequest* request,
155 net::NetLog::LogLevel log_level) {
156 return request->GetStateAsValue();
159 // Returns true if |request1| was created before |request2|.
160 bool RequestCreatedBefore(const net::URLRequest* request1,
161 const net::URLRequest* request2) {
162 return request1->creation_time() < request2->creation_time();
165 // Returns the disk cache backend for |context| if there is one, or NULL.
166 disk_cache::Backend* GetDiskCacheBackend(net::URLRequestContext* context) {
167 if (!context->http_transaction_factory())
168 return NULL;
170 net::HttpCache* http_cache = context->http_transaction_factory()->GetCache();
171 if (!http_cache)
172 return NULL;
174 return http_cache->GetCurrentBackend();
177 // Returns the http network session for |context| if there is one.
178 // Otherwise, returns NULL.
179 net::HttpNetworkSession* GetHttpNetworkSession(
180 net::URLRequestContext* context) {
181 if (!context->http_transaction_factory())
182 return NULL;
184 return context->http_transaction_factory()->GetSession();
187 base::Value* ExperimentToValue(const ConnectionTester::Experiment& experiment) {
188 base::DictionaryValue* dict = new base::DictionaryValue();
190 if (experiment.url.is_valid())
191 dict->SetString("url", experiment.url.spec());
193 dict->SetString("proxy_settings_experiment",
194 ConnectionTester::ProxySettingsExperimentDescription(
195 experiment.proxy_settings_experiment));
196 dict->SetString("host_resolver_experiment",
197 ConnectionTester::HostResolverExperimentDescription(
198 experiment.host_resolver_experiment));
199 return dict;
202 content::WebUIDataSource* CreateNetInternalsHTMLSource() {
203 content::WebUIDataSource* source =
204 content::WebUIDataSource::Create(chrome::kChromeUINetInternalsHost);
206 source->SetDefaultResource(IDR_NET_INTERNALS_INDEX_HTML);
207 source->AddResourcePath("index.js", IDR_NET_INTERNALS_INDEX_JS);
208 source->SetJsonPath("strings.js");
209 return source;
212 // This class receives javascript messages from the renderer.
213 // Note that the WebUI infrastructure runs on the UI thread, therefore all of
214 // this class's methods are expected to run on the UI thread.
216 // Since the network code we want to run lives on the IO thread, we proxy
217 // almost everything over to NetInternalsMessageHandler::IOThreadImpl, which
218 // runs on the IO thread.
220 // TODO(eroman): Can we start on the IO thread to begin with?
221 class NetInternalsMessageHandler
222 : public WebUIMessageHandler,
223 public base::SupportsWeakPtr<NetInternalsMessageHandler> {
224 public:
225 NetInternalsMessageHandler();
226 ~NetInternalsMessageHandler() override;
228 // WebUIMessageHandler implementation.
229 void RegisterMessages() override;
231 // Calls g_browser.receive in the renderer, passing in |command| and |arg|.
232 // Takes ownership of |arg|. If the renderer is displaying a log file, the
233 // message will be ignored.
234 void SendJavascriptCommand(const std::string& command, base::Value* arg);
236 // Javascript message handlers.
237 void OnRendererReady(const base::ListValue* list);
238 void OnClearBrowserCache(const base::ListValue* list);
239 void OnGetPrerenderInfo(const base::ListValue* list);
240 void OnGetHistoricNetworkStats(const base::ListValue* list);
241 void OnGetExtensionInfo(const base::ListValue* list);
242 #if defined(OS_CHROMEOS)
243 void OnRefreshSystemLogs(const base::ListValue* list);
244 void OnGetSystemLog(const base::ListValue* list);
245 void OnImportONCFile(const base::ListValue* list);
246 void OnStoreDebugLogs(const base::ListValue* list);
247 void OnStoreDebugLogsCompleted(const base::FilePath& log_path,
248 bool succeeded);
249 void OnSetNetworkDebugMode(const base::ListValue* list);
250 void OnSetNetworkDebugModeCompleted(const std::string& subsystem,
251 bool succeeded);
253 // Callback to |GetNSSCertDatabaseForProfile| used to retrieve the database
254 // to which user's ONC defined certificates should be imported.
255 // It parses and imports |onc_blob|.
256 void ImportONCFileToNSSDB(const std::string& onc_blob,
257 const std::string& passcode,
258 net::NSSCertDatabase* nssdb);
260 // Called back by the CertificateImporter when a certificate import finished.
261 // |previous_error| contains earlier errors during this import.
262 void OnCertificatesImported(
263 const std::string& previous_error,
264 bool success,
265 const net::CertificateList& onc_trusted_certificates);
266 #endif
268 private:
269 class IOThreadImpl;
271 #if defined(OS_CHROMEOS)
272 // Class that is used for getting network related ChromeOS logs.
273 // Logs are fetched from ChromeOS libcros on user request, and only when we
274 // don't yet have a copy of logs. If a copy is present, we send back data from
275 // it, else we save request and answer to it when we get logs from libcros.
276 // If needed, we also send request for system logs to libcros.
277 // Logs refresh has to be done explicitly, by deleting old logs and then
278 // loading them again.
279 class SystemLogsGetter {
280 public:
281 SystemLogsGetter(NetInternalsMessageHandler* handler,
282 chromeos::system::SyslogsProvider* syslogs_provider);
283 ~SystemLogsGetter();
285 // Deletes logs copy we currently have, and resets logs_requested and
286 // logs_received flags.
287 void DeleteSystemLogs();
288 // Starts log fetching. If logs copy is present, requested logs are sent
289 // back.
290 // If syslogs load request hasn't been sent to libcros yet, we do that now,
291 // and postpone sending response.
292 // Request data is specified by args:
293 // $1 : key of the log we are interested in.
294 // $2 : string used to identify request.
295 void RequestSystemLog(const base::ListValue* args);
296 // Requests logs from libcros, but only if we don't have a copy.
297 void LoadSystemLogs();
298 // Processes callback from libcros containing system logs. Postponed
299 // request responses are sent.
300 void OnSystemLogsLoaded(chromeos::system::LogDictionaryType* sys_info,
301 std::string* ignored_content);
303 private:
304 // Struct we save postponed log request in.
305 struct SystemLogRequest {
306 std::string log_key;
307 std::string cell_id;
310 // Processes request.
311 void SendLogs(const SystemLogRequest& request);
313 NetInternalsMessageHandler* handler_;
314 chromeos::system::SyslogsProvider* syslogs_provider_;
315 // List of postponed requests.
316 std::list<SystemLogRequest> requests_;
317 scoped_ptr<chromeos::system::LogDictionaryType> logs_;
318 bool logs_received_;
319 bool logs_requested_;
320 base::CancelableTaskTracker tracker_;
321 // Libcros request task ID.
322 base::CancelableTaskTracker::TaskId syslogs_task_id_;
324 #endif // defined(OS_CHROMEOS)
326 // This is the "real" message handler, which lives on the IO thread.
327 scoped_refptr<IOThreadImpl> proxy_;
329 base::WeakPtr<prerender::PrerenderManager> prerender_manager_;
331 #if defined(OS_CHROMEOS)
332 // Class that handles getting and filtering system logs.
333 scoped_ptr<SystemLogsGetter> syslogs_getter_;
334 #endif
336 DISALLOW_COPY_AND_ASSIGN(NetInternalsMessageHandler);
339 // This class is the "real" message handler. It is allocated and destroyed on
340 // the UI thread. With the exception of OnAddEntry, OnWebUIDeleted, and
341 // SendJavascriptCommand, its methods are all expected to be called from the IO
342 // thread. OnAddEntry and SendJavascriptCommand can be called from any thread,
343 // and OnWebUIDeleted can only be called from the UI thread.
344 class NetInternalsMessageHandler::IOThreadImpl
345 : public base::RefCountedThreadSafe<
346 NetInternalsMessageHandler::IOThreadImpl,
347 BrowserThread::DeleteOnUIThread>,
348 public net::NetLog::ThreadSafeObserver,
349 public ConnectionTester::Delegate {
350 public:
351 // Type for methods that can be used as MessageHandler callbacks.
352 typedef void (IOThreadImpl::*MessageHandler)(const base::ListValue*);
354 // Creates a proxy for |handler| that will live on the IO thread.
355 // |handler| is a weak pointer, since it is possible for the
356 // WebUIMessageHandler to be deleted on the UI thread while we were executing
357 // on the IO thread. |io_thread| is the global IOThread (it is passed in as
358 // an argument since we need to grab it from the UI thread).
359 IOThreadImpl(
360 const base::WeakPtr<NetInternalsMessageHandler>& handler,
361 IOThread* io_thread,
362 net::URLRequestContextGetter* main_context_getter);
364 // Called on UI thread just after creation, to add a ContextGetter to
365 // |context_getters_|.
366 void AddRequestContextGetter(net::URLRequestContextGetter* context_getter);
368 // Helper method to enable a callback that will be executed on the IO thread.
369 static void CallbackHelper(MessageHandler method,
370 scoped_refptr<IOThreadImpl> io_thread,
371 const base::ListValue* list);
373 // Called once the WebUI has been deleted (i.e. renderer went away), on the
374 // IO thread.
375 void Detach();
377 // Called when the WebUI is deleted. Prevents calling Javascript functions
378 // afterwards. Called on UI thread.
379 void OnWebUIDeleted();
381 //--------------------------------
382 // Javascript message handlers:
383 //--------------------------------
385 void OnRendererReady(const base::ListValue* list);
387 void OnGetProxySettings(const base::ListValue* list);
388 void OnReloadProxySettings(const base::ListValue* list);
389 void OnGetBadProxies(const base::ListValue* list);
390 void OnClearBadProxies(const base::ListValue* list);
391 void OnGetHostResolverInfo(const base::ListValue* list);
392 void OnClearHostResolverCache(const base::ListValue* list);
393 void OnEnableIPv6(const base::ListValue* list);
394 void OnStartConnectionTests(const base::ListValue* list);
395 void OnHSTSQuery(const base::ListValue* list);
396 void OnHSTSAdd(const base::ListValue* list);
397 void OnHSTSDelete(const base::ListValue* list);
398 void OnGetHttpCacheInfo(const base::ListValue* list);
399 void OnGetSocketPoolInfo(const base::ListValue* list);
400 void OnGetSessionNetworkStats(const base::ListValue* list);
401 void OnCloseIdleSockets(const base::ListValue* list);
402 void OnFlushSocketPools(const base::ListValue* list);
403 void OnGetSpdySessionInfo(const base::ListValue* list);
404 void OnGetSpdyStatus(const base::ListValue* list);
405 void OnGetSpdyAlternateProtocolMappings(const base::ListValue* list);
406 void OnGetQuicInfo(const base::ListValue* list);
407 #if defined(OS_WIN)
408 void OnGetServiceProviders(const base::ListValue* list);
409 #endif
410 void OnSetLogLevel(const base::ListValue* list);
412 // ChromeNetLog::ThreadSafeObserver implementation:
413 void OnAddEntry(const net::NetLog::Entry& entry) override;
415 // ConnectionTester::Delegate implementation:
416 void OnStartConnectionTestSuite() override;
417 void OnStartConnectionTestExperiment(
418 const ConnectionTester::Experiment& experiment) override;
419 void OnCompletedConnectionTestExperiment(
420 const ConnectionTester::Experiment& experiment,
421 int result) override;
422 void OnCompletedConnectionTestSuite() override;
424 // Helper that calls g_browser.receive in the renderer, passing in |command|
425 // and |arg|. Takes ownership of |arg|. If the renderer is displaying a log
426 // file, the message will be ignored. Note that this can be called from any
427 // thread.
428 void SendJavascriptCommand(const std::string& command, base::Value* arg);
430 private:
431 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
432 friend class base::DeleteHelper<IOThreadImpl>;
434 typedef std::list<scoped_refptr<net::URLRequestContextGetter> >
435 ContextGetterList;
437 ~IOThreadImpl() override;
439 // Adds |entry| to the queue of pending log entries to be sent to the page via
440 // Javascript. Must be called on the IO Thread. Also creates a delayed task
441 // that will call PostPendingEntries, if there isn't one already.
442 void AddEntryToQueue(base::Value* entry);
444 // Sends all pending entries to the page via Javascript, and clears the list
445 // of pending entries. Sending multiple entries at once results in a
446 // significant reduction of CPU usage when a lot of events are happening.
447 // Must be called on the IO Thread.
448 void PostPendingEntries();
450 // Adds entries with the states of ongoing URL requests.
451 void PrePopulateEventList();
453 net::URLRequestContext* GetMainContext() {
454 return main_context_getter_->GetURLRequestContext();
457 // Pointer to the UI-thread message handler. Only access this from
458 // the UI thread.
459 base::WeakPtr<NetInternalsMessageHandler> handler_;
461 // The global IOThread, which contains the global NetLog to observer.
462 IOThread* io_thread_;
464 // The main URLRequestContextGetter for the tab's profile.
465 scoped_refptr<net::URLRequestContextGetter> main_context_getter_;
467 // Helper that runs the suite of connection tests.
468 scoped_ptr<ConnectionTester> connection_tester_;
470 // True if the Web UI has been deleted. This is used to prevent calling
471 // Javascript functions after the Web UI is destroyed. On refresh, the
472 // messages can end up being sent to the refreshed page, causing duplicate
473 // or partial entries.
475 // This is only read and written to on the UI thread.
476 bool was_webui_deleted_;
478 // Log entries that have yet to be passed along to Javascript page. Non-NULL
479 // when and only when there is a pending delayed task to call
480 // PostPendingEntries. Read and written to exclusively on the IO Thread.
481 scoped_ptr<base::ListValue> pending_entries_;
483 // Used for getting current status of URLRequests when net-internals is
484 // opened. |main_context_getter_| is automatically added on construction.
485 // Duplicates are allowed.
486 ContextGetterList context_getters_;
488 DISALLOW_COPY_AND_ASSIGN(IOThreadImpl);
491 ////////////////////////////////////////////////////////////////////////////////
493 // NetInternalsMessageHandler
495 ////////////////////////////////////////////////////////////////////////////////
497 NetInternalsMessageHandler::NetInternalsMessageHandler() {}
499 NetInternalsMessageHandler::~NetInternalsMessageHandler() {
500 if (proxy_.get()) {
501 proxy_.get()->OnWebUIDeleted();
502 // Notify the handler on the IO thread that the renderer is gone.
503 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
504 base::Bind(&IOThreadImpl::Detach, proxy_.get()));
508 void NetInternalsMessageHandler::RegisterMessages() {
509 DCHECK_CURRENTLY_ON(BrowserThread::UI);
511 Profile* profile = Profile::FromWebUI(web_ui());
513 proxy_ = new IOThreadImpl(this->AsWeakPtr(), g_browser_process->io_thread(),
514 profile->GetRequestContext());
515 proxy_->AddRequestContextGetter(profile->GetMediaRequestContext());
516 proxy_->AddRequestContextGetter(profile->GetRequestContextForExtensions());
517 #if defined(OS_CHROMEOS)
518 syslogs_getter_.reset(new SystemLogsGetter(this,
519 chromeos::system::SyslogsProvider::GetInstance()));
520 #endif
522 prerender::PrerenderManager* prerender_manager =
523 prerender::PrerenderManagerFactory::GetForProfile(profile);
524 if (prerender_manager) {
525 prerender_manager_ = prerender_manager->AsWeakPtr();
526 } else {
527 prerender_manager_ = base::WeakPtr<prerender::PrerenderManager>();
530 web_ui()->RegisterMessageCallback(
531 "notifyReady",
532 base::Bind(&NetInternalsMessageHandler::OnRendererReady,
533 base::Unretained(this)));
534 web_ui()->RegisterMessageCallback(
535 "getProxySettings",
536 base::Bind(&IOThreadImpl::CallbackHelper,
537 &IOThreadImpl::OnGetProxySettings, proxy_));
538 web_ui()->RegisterMessageCallback(
539 "reloadProxySettings",
540 base::Bind(&IOThreadImpl::CallbackHelper,
541 &IOThreadImpl::OnReloadProxySettings, proxy_));
542 web_ui()->RegisterMessageCallback(
543 "getBadProxies",
544 base::Bind(&IOThreadImpl::CallbackHelper,
545 &IOThreadImpl::OnGetBadProxies, proxy_));
546 web_ui()->RegisterMessageCallback(
547 "clearBadProxies",
548 base::Bind(&IOThreadImpl::CallbackHelper,
549 &IOThreadImpl::OnClearBadProxies, proxy_));
550 web_ui()->RegisterMessageCallback(
551 "getHostResolverInfo",
552 base::Bind(&IOThreadImpl::CallbackHelper,
553 &IOThreadImpl::OnGetHostResolverInfo, proxy_));
554 web_ui()->RegisterMessageCallback(
555 "clearHostResolverCache",
556 base::Bind(&IOThreadImpl::CallbackHelper,
557 &IOThreadImpl::OnClearHostResolverCache, proxy_));
558 web_ui()->RegisterMessageCallback(
559 "enableIPv6",
560 base::Bind(&IOThreadImpl::CallbackHelper,
561 &IOThreadImpl::OnEnableIPv6, proxy_));
562 web_ui()->RegisterMessageCallback(
563 "startConnectionTests",
564 base::Bind(&IOThreadImpl::CallbackHelper,
565 &IOThreadImpl::OnStartConnectionTests, proxy_));
566 web_ui()->RegisterMessageCallback(
567 "hstsQuery",
568 base::Bind(&IOThreadImpl::CallbackHelper,
569 &IOThreadImpl::OnHSTSQuery, proxy_));
570 web_ui()->RegisterMessageCallback(
571 "hstsAdd",
572 base::Bind(&IOThreadImpl::CallbackHelper,
573 &IOThreadImpl::OnHSTSAdd, proxy_));
574 web_ui()->RegisterMessageCallback(
575 "hstsDelete",
576 base::Bind(&IOThreadImpl::CallbackHelper,
577 &IOThreadImpl::OnHSTSDelete, proxy_));
578 web_ui()->RegisterMessageCallback(
579 "getHttpCacheInfo",
580 base::Bind(&IOThreadImpl::CallbackHelper,
581 &IOThreadImpl::OnGetHttpCacheInfo, proxy_));
582 web_ui()->RegisterMessageCallback(
583 "getSocketPoolInfo",
584 base::Bind(&IOThreadImpl::CallbackHelper,
585 &IOThreadImpl::OnGetSocketPoolInfo, proxy_));
586 web_ui()->RegisterMessageCallback(
587 "getSessionNetworkStats",
588 base::Bind(&IOThreadImpl::CallbackHelper,
589 &IOThreadImpl::OnGetSessionNetworkStats, proxy_));
590 web_ui()->RegisterMessageCallback(
591 "closeIdleSockets",
592 base::Bind(&IOThreadImpl::CallbackHelper,
593 &IOThreadImpl::OnCloseIdleSockets, proxy_));
594 web_ui()->RegisterMessageCallback(
595 "flushSocketPools",
596 base::Bind(&IOThreadImpl::CallbackHelper,
597 &IOThreadImpl::OnFlushSocketPools, proxy_));
598 web_ui()->RegisterMessageCallback(
599 "getSpdySessionInfo",
600 base::Bind(&IOThreadImpl::CallbackHelper,
601 &IOThreadImpl::OnGetSpdySessionInfo, proxy_));
602 web_ui()->RegisterMessageCallback(
603 "getSpdyStatus",
604 base::Bind(&IOThreadImpl::CallbackHelper,
605 &IOThreadImpl::OnGetSpdyStatus, proxy_));
606 web_ui()->RegisterMessageCallback(
607 "getSpdyAlternateProtocolMappings",
608 base::Bind(&IOThreadImpl::CallbackHelper,
609 &IOThreadImpl::OnGetSpdyAlternateProtocolMappings, proxy_));
610 web_ui()->RegisterMessageCallback(
611 "getQuicInfo",
612 base::Bind(&IOThreadImpl::CallbackHelper,
613 &IOThreadImpl::OnGetQuicInfo, proxy_));
614 #if defined(OS_WIN)
615 web_ui()->RegisterMessageCallback(
616 "getServiceProviders",
617 base::Bind(&IOThreadImpl::CallbackHelper,
618 &IOThreadImpl::OnGetServiceProviders, proxy_));
619 #endif
621 web_ui()->RegisterMessageCallback(
622 "setLogLevel",
623 base::Bind(&IOThreadImpl::CallbackHelper,
624 &IOThreadImpl::OnSetLogLevel, proxy_));
625 web_ui()->RegisterMessageCallback(
626 "clearBrowserCache",
627 base::Bind(&NetInternalsMessageHandler::OnClearBrowserCache,
628 base::Unretained(this)));
629 web_ui()->RegisterMessageCallback(
630 "getPrerenderInfo",
631 base::Bind(&NetInternalsMessageHandler::OnGetPrerenderInfo,
632 base::Unretained(this)));
633 web_ui()->RegisterMessageCallback(
634 "getHistoricNetworkStats",
635 base::Bind(&NetInternalsMessageHandler::OnGetHistoricNetworkStats,
636 base::Unretained(this)));
637 web_ui()->RegisterMessageCallback(
638 "getExtensionInfo",
639 base::Bind(&NetInternalsMessageHandler::OnGetExtensionInfo,
640 base::Unretained(this)));
641 #if defined(OS_CHROMEOS)
642 web_ui()->RegisterMessageCallback(
643 "refreshSystemLogs",
644 base::Bind(&NetInternalsMessageHandler::OnRefreshSystemLogs,
645 base::Unretained(this)));
646 web_ui()->RegisterMessageCallback(
647 "getSystemLog",
648 base::Bind(&NetInternalsMessageHandler::OnGetSystemLog,
649 base::Unretained(this)));
650 web_ui()->RegisterMessageCallback(
651 "importONCFile",
652 base::Bind(&NetInternalsMessageHandler::OnImportONCFile,
653 base::Unretained(this)));
654 web_ui()->RegisterMessageCallback(
655 "storeDebugLogs",
656 base::Bind(&NetInternalsMessageHandler::OnStoreDebugLogs,
657 base::Unretained(this)));
658 web_ui()->RegisterMessageCallback(
659 "setNetworkDebugMode",
660 base::Bind(&NetInternalsMessageHandler::OnSetNetworkDebugMode,
661 base::Unretained(this)));
662 #endif
665 void NetInternalsMessageHandler::SendJavascriptCommand(
666 const std::string& command,
667 base::Value* arg) {
668 scoped_ptr<base::Value> command_value(new base::StringValue(command));
669 scoped_ptr<base::Value> value(arg);
670 DCHECK_CURRENTLY_ON(BrowserThread::UI);
671 if (value.get()) {
672 web_ui()->CallJavascriptFunction("g_browser.receive",
673 *command_value.get(),
674 *value.get());
675 } else {
676 web_ui()->CallJavascriptFunction("g_browser.receive",
677 *command_value.get());
681 void NetInternalsMessageHandler::OnRendererReady(const base::ListValue* list) {
682 IOThreadImpl::CallbackHelper(&IOThreadImpl::OnRendererReady, proxy_, list);
685 void NetInternalsMessageHandler::OnClearBrowserCache(
686 const base::ListValue* list) {
687 BrowsingDataRemover* remover = BrowsingDataRemover::CreateForUnboundedRange(
688 Profile::FromWebUI(web_ui()));
689 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
690 BrowsingDataHelper::UNPROTECTED_WEB);
691 // BrowsingDataRemover deletes itself.
694 void NetInternalsMessageHandler::OnGetPrerenderInfo(
695 const base::ListValue* list) {
696 DCHECK_CURRENTLY_ON(BrowserThread::UI);
698 base::DictionaryValue* value = NULL;
699 prerender::PrerenderManager* prerender_manager = prerender_manager_.get();
700 if (!prerender_manager) {
701 value = new base::DictionaryValue();
702 value->SetBoolean("enabled", false);
703 value->SetBoolean("omnibox_enabled", false);
704 } else {
705 value = prerender_manager->GetAsValue();
707 SendJavascriptCommand("receivedPrerenderInfo", value);
710 void NetInternalsMessageHandler::OnGetHistoricNetworkStats(
711 const base::ListValue* list) {
712 DCHECK_CURRENTLY_ON(BrowserThread::UI);
713 base::Value* historic_network_info =
714 ChromeNetworkDelegate::HistoricNetworkStatsInfoToValue();
715 SendJavascriptCommand("receivedHistoricNetworkStats", historic_network_info);
718 void NetInternalsMessageHandler::OnGetExtensionInfo(
719 const base::ListValue* list) {
720 DCHECK_CURRENTLY_ON(BrowserThread::UI);
721 base::ListValue* extension_list = new base::ListValue();
722 #if defined(ENABLE_EXTENSIONS)
723 Profile* profile = Profile::FromWebUI(web_ui());
724 extensions::ExtensionSystem* extension_system =
725 extensions::ExtensionSystem::Get(profile);
726 if (extension_system) {
727 ExtensionService* extension_service = extension_system->extension_service();
728 if (extension_service) {
729 scoped_ptr<const extensions::ExtensionSet> extensions(
730 extensions::ExtensionRegistry::Get(profile)
731 ->GenerateInstalledExtensionsSet());
732 for (extensions::ExtensionSet::const_iterator it = extensions->begin();
733 it != extensions->end(); ++it) {
734 base::DictionaryValue* extension_info = new base::DictionaryValue();
735 bool enabled = extension_service->IsExtensionEnabled((*it)->id());
736 extensions::GetExtensionBasicInfo(it->get(), enabled, extension_info);
737 extension_list->Append(extension_info);
741 #endif
742 SendJavascriptCommand("receivedExtensionInfo", extension_list);
745 #if defined(OS_CHROMEOS)
746 ////////////////////////////////////////////////////////////////////////////////
748 // NetInternalsMessageHandler::SystemLogsGetter
750 ////////////////////////////////////////////////////////////////////////////////
752 NetInternalsMessageHandler::SystemLogsGetter::SystemLogsGetter(
753 NetInternalsMessageHandler* handler,
754 chromeos::system::SyslogsProvider* syslogs_provider)
755 : handler_(handler),
756 syslogs_provider_(syslogs_provider),
757 logs_received_(false),
758 logs_requested_(false) {
759 if (!syslogs_provider_)
760 LOG(ERROR) << "System access library not loaded";
763 NetInternalsMessageHandler::SystemLogsGetter::~SystemLogsGetter() {
764 DeleteSystemLogs();
767 void NetInternalsMessageHandler::SystemLogsGetter::DeleteSystemLogs() {
768 if (syslogs_provider_ && logs_requested_ && !logs_received_) {
769 tracker_.TryCancel(syslogs_task_id_);
771 logs_requested_ = false;
772 logs_received_ = false;
773 logs_.reset();
776 void NetInternalsMessageHandler::SystemLogsGetter::RequestSystemLog(
777 const base::ListValue* args) {
778 if (!logs_requested_) {
779 DCHECK(!logs_received_);
780 LoadSystemLogs();
782 SystemLogRequest log_request;
783 args->GetString(0, &log_request.log_key);
784 args->GetString(1, &log_request.cell_id);
786 if (logs_received_) {
787 SendLogs(log_request);
788 } else {
789 requests_.push_back(log_request);
793 void NetInternalsMessageHandler::SystemLogsGetter::LoadSystemLogs() {
794 if (logs_requested_ || !syslogs_provider_)
795 return;
796 logs_requested_ = true;
797 syslogs_task_id_ = syslogs_provider_->RequestSyslogs(
798 false, // compress logs.
799 chromeos::system::SyslogsProvider::SYSLOGS_NETWORK,
800 base::Bind(
801 &NetInternalsMessageHandler::SystemLogsGetter::OnSystemLogsLoaded,
802 base::Unretained(this)),
803 &tracker_);
806 void NetInternalsMessageHandler::SystemLogsGetter::OnSystemLogsLoaded(
807 chromeos::system::LogDictionaryType* sys_info,
808 std::string* ignored_content) {
809 DCHECK(!ignored_content);
810 logs_.reset(sys_info);
811 logs_received_ = true;
812 for (std::list<SystemLogRequest>::iterator request_it = requests_.begin();
813 request_it != requests_.end();
814 ++request_it) {
815 SendLogs(*request_it);
817 requests_.clear();
820 void NetInternalsMessageHandler::SystemLogsGetter::SendLogs(
821 const SystemLogRequest& request) {
822 base::DictionaryValue* result = new base::DictionaryValue();
823 chromeos::system::LogDictionaryType::iterator log_it =
824 logs_->find(request.log_key);
825 if (log_it != logs_->end()) {
826 if (!log_it->second.empty()) {
827 result->SetString("log", log_it->second);
828 } else {
829 result->SetString("log", "<no relevant lines found>");
831 } else {
832 result->SetString("log", "<invalid log name>");
834 result->SetString("cellId", request.cell_id);
836 handler_->SendJavascriptCommand("getSystemLogCallback", result);
838 #endif // defined(OS_CHROMEOS)
840 ////////////////////////////////////////////////////////////////////////////////
842 // NetInternalsMessageHandler::IOThreadImpl
844 ////////////////////////////////////////////////////////////////////////////////
846 NetInternalsMessageHandler::IOThreadImpl::IOThreadImpl(
847 const base::WeakPtr<NetInternalsMessageHandler>& handler,
848 IOThread* io_thread,
849 net::URLRequestContextGetter* main_context_getter)
850 : handler_(handler),
851 io_thread_(io_thread),
852 main_context_getter_(main_context_getter),
853 was_webui_deleted_(false) {
854 DCHECK_CURRENTLY_ON(BrowserThread::UI);
855 AddRequestContextGetter(main_context_getter);
858 NetInternalsMessageHandler::IOThreadImpl::~IOThreadImpl() {
859 DCHECK_CURRENTLY_ON(BrowserThread::UI);
862 void NetInternalsMessageHandler::IOThreadImpl::AddRequestContextGetter(
863 net::URLRequestContextGetter* context_getter) {
864 DCHECK_CURRENTLY_ON(BrowserThread::UI);
865 context_getters_.push_back(context_getter);
868 void NetInternalsMessageHandler::IOThreadImpl::CallbackHelper(
869 MessageHandler method,
870 scoped_refptr<IOThreadImpl> io_thread,
871 const base::ListValue* list) {
872 DCHECK_CURRENTLY_ON(BrowserThread::UI);
874 // We need to make a copy of the value in order to pass it over to the IO
875 // thread. |list_copy| will be deleted when the task is destroyed. The called
876 // |method| cannot take ownership of |list_copy|.
877 base::ListValue* list_copy =
878 (list && list->GetSize()) ? list->DeepCopy() : NULL;
880 BrowserThread::PostTask(
881 BrowserThread::IO, FROM_HERE,
882 base::Bind(method, io_thread, base::Owned(list_copy)));
885 void NetInternalsMessageHandler::IOThreadImpl::Detach() {
886 DCHECK_CURRENTLY_ON(BrowserThread::IO);
887 // Unregister with network stack to observe events.
888 if (net_log())
889 net_log()->RemoveThreadSafeObserver(this);
891 // Cancel any in-progress connection tests.
892 connection_tester_.reset();
895 void NetInternalsMessageHandler::IOThreadImpl::OnWebUIDeleted() {
896 DCHECK_CURRENTLY_ON(BrowserThread::UI);
897 was_webui_deleted_ = true;
900 void NetInternalsMessageHandler::IOThreadImpl::OnRendererReady(
901 const base::ListValue* list) {
902 DCHECK_CURRENTLY_ON(BrowserThread::IO);
904 // If we have any pending entries, go ahead and get rid of them, so they won't
905 // appear before the REQUEST_ALIVE events we add for currently active
906 // URLRequests.
907 PostPendingEntries();
909 SendJavascriptCommand("receivedConstants", NetInternalsUI::GetConstants());
911 // Add entries for ongoing URL requests.
912 PrePopulateEventList();
914 if (!net_log()) {
915 // Register with network stack to observe events.
916 io_thread_->net_log()->AddThreadSafeObserver(this,
917 net::NetLog::LOG_ALL_BUT_BYTES);
921 void NetInternalsMessageHandler::IOThreadImpl::OnGetProxySettings(
922 const base::ListValue* list) {
923 DCHECK(!list);
924 net::ProxyService* proxy_service = GetMainContext()->proxy_service();
926 base::DictionaryValue* dict = new base::DictionaryValue();
927 if (proxy_service->fetched_config().is_valid())
928 dict->Set("original", proxy_service->fetched_config().ToValue());
929 if (proxy_service->config().is_valid())
930 dict->Set("effective", proxy_service->config().ToValue());
932 SendJavascriptCommand("receivedProxySettings", dict);
935 void NetInternalsMessageHandler::IOThreadImpl::OnReloadProxySettings(
936 const base::ListValue* list) {
937 DCHECK(!list);
938 GetMainContext()->proxy_service()->ForceReloadProxyConfig();
940 // Cause the renderer to be notified of the new values.
941 OnGetProxySettings(NULL);
944 void NetInternalsMessageHandler::IOThreadImpl::OnGetBadProxies(
945 const base::ListValue* list) {
946 DCHECK(!list);
948 const net::ProxyRetryInfoMap& bad_proxies_map =
949 GetMainContext()->proxy_service()->proxy_retry_info();
951 base::ListValue* dict_list = new base::ListValue();
953 for (net::ProxyRetryInfoMap::const_iterator it = bad_proxies_map.begin();
954 it != bad_proxies_map.end(); ++it) {
955 const std::string& proxy_uri = it->first;
956 const net::ProxyRetryInfo& retry_info = it->second;
958 base::DictionaryValue* dict = new base::DictionaryValue();
959 dict->SetString("proxy_uri", proxy_uri);
960 dict->SetString("bad_until",
961 net::NetLog::TickCountToString(retry_info.bad_until));
963 dict_list->Append(dict);
966 SendJavascriptCommand("receivedBadProxies", dict_list);
969 void NetInternalsMessageHandler::IOThreadImpl::OnClearBadProxies(
970 const base::ListValue* list) {
971 DCHECK(!list);
972 GetMainContext()->proxy_service()->ClearBadProxiesCache();
974 // Cause the renderer to be notified of the new values.
975 OnGetBadProxies(NULL);
978 void NetInternalsMessageHandler::IOThreadImpl::OnGetHostResolverInfo(
979 const base::ListValue* list) {
980 DCHECK(!list);
981 net::URLRequestContext* context = GetMainContext();
982 net::HostCache* cache = GetHostResolverCache(context);
984 if (!cache) {
985 SendJavascriptCommand("receivedHostResolverInfo", NULL);
986 return;
989 base::DictionaryValue* dict = new base::DictionaryValue();
991 base::Value* dns_config = context->host_resolver()->GetDnsConfigAsValue();
992 if (dns_config)
993 dict->Set("dns_config", dns_config);
995 dict->SetInteger(
996 "default_address_family",
997 static_cast<int>(context->host_resolver()->GetDefaultAddressFamily()));
999 base::DictionaryValue* cache_info_dict = new base::DictionaryValue();
1001 cache_info_dict->SetInteger(
1002 "capacity",
1003 static_cast<int>(cache->max_entries()));
1005 base::ListValue* entry_list = new base::ListValue();
1007 net::HostCache::EntryMap::Iterator it(cache->entries());
1008 for (; it.HasNext(); it.Advance()) {
1009 const net::HostCache::Key& key = it.key();
1010 const net::HostCache::Entry& entry = it.value();
1012 base::DictionaryValue* entry_dict = new base::DictionaryValue();
1014 entry_dict->SetString("hostname", key.hostname);
1015 entry_dict->SetInteger("address_family",
1016 static_cast<int>(key.address_family));
1017 entry_dict->SetString("expiration",
1018 net::NetLog::TickCountToString(it.expiration()));
1020 if (entry.error != net::OK) {
1021 entry_dict->SetInteger("error", entry.error);
1022 } else {
1023 // Append all of the resolved addresses.
1024 base::ListValue* address_list = new base::ListValue();
1025 for (size_t i = 0; i < entry.addrlist.size(); ++i) {
1026 address_list->AppendString(entry.addrlist[i].ToStringWithoutPort());
1028 entry_dict->Set("addresses", address_list);
1031 entry_list->Append(entry_dict);
1034 cache_info_dict->Set("entries", entry_list);
1035 dict->Set("cache", cache_info_dict);
1037 SendJavascriptCommand("receivedHostResolverInfo", dict);
1040 void NetInternalsMessageHandler::IOThreadImpl::OnClearHostResolverCache(
1041 const base::ListValue* list) {
1042 DCHECK(!list);
1043 net::HostCache* cache = GetHostResolverCache(GetMainContext());
1045 if (cache)
1046 cache->clear();
1048 // Cause the renderer to be notified of the new values.
1049 OnGetHostResolverInfo(NULL);
1052 void NetInternalsMessageHandler::IOThreadImpl::OnEnableIPv6(
1053 const base::ListValue* list) {
1054 DCHECK(!list);
1055 net::HostResolver* host_resolver = GetMainContext()->host_resolver();
1057 host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_UNSPECIFIED);
1059 // Cause the renderer to be notified of the new value.
1060 OnGetHostResolverInfo(NULL);
1063 void NetInternalsMessageHandler::IOThreadImpl::OnStartConnectionTests(
1064 const base::ListValue* list) {
1065 // |value| should be: [<URL to test>].
1066 base::string16 url_str;
1067 CHECK(list->GetString(0, &url_str));
1069 // Try to fix-up the user provided URL into something valid.
1070 // For example, turn "www.google.com" into "http://www.google.com".
1071 GURL url(url_fixer::FixupURL(base::UTF16ToUTF8(url_str), std::string()));
1073 connection_tester_.reset(new ConnectionTester(
1074 this,
1075 io_thread_->globals()->proxy_script_fetcher_context.get(),
1076 net_log()));
1077 connection_tester_->RunAllTests(url);
1080 void NetInternalsMessageHandler::IOThreadImpl::OnHSTSQuery(
1081 const base::ListValue* list) {
1082 // |list| should be: [<domain to query>].
1083 std::string domain;
1084 CHECK(list->GetString(0, &domain));
1085 base::DictionaryValue* result = new base::DictionaryValue();
1087 if (!base::IsStringASCII(domain)) {
1088 result->SetString("error", "non-ASCII domain name");
1089 } else {
1090 net::TransportSecurityState* transport_security_state =
1091 GetMainContext()->transport_security_state();
1092 if (!transport_security_state) {
1093 result->SetString("error", "no TransportSecurityState active");
1094 } else {
1095 net::TransportSecurityState::DomainState static_state;
1096 const bool found_static = transport_security_state->GetStaticDomainState(
1097 domain, &static_state);
1098 if (found_static) {
1099 result->SetBoolean("has_static_sts",
1100 found_static && static_state.ShouldUpgradeToSSL());
1101 result->SetInteger("static_upgrade_mode",
1102 static_cast<int>(static_state.sts.upgrade_mode));
1103 result->SetBoolean("static_sts_include_subdomains",
1104 static_state.sts.include_subdomains);
1105 result->SetDouble("static_sts_observed",
1106 static_state.sts.last_observed.ToDoubleT());
1107 result->SetDouble("static_sts_expiry",
1108 static_state.sts.expiry.ToDoubleT());
1109 result->SetBoolean("has_static_pkp",
1110 found_static && static_state.HasPublicKeyPins());
1111 result->SetBoolean("static_pkp_include_subdomains",
1112 static_state.pkp.include_subdomains);
1113 result->SetDouble("static_pkp_observed",
1114 static_state.pkp.last_observed.ToDoubleT());
1115 result->SetDouble("static_pkp_expiry",
1116 static_state.pkp.expiry.ToDoubleT());
1117 result->SetString("static_spki_hashes",
1118 HashesToBase64String(static_state.pkp.spki_hashes));
1121 net::TransportSecurityState::DomainState dynamic_state;
1122 const bool found_dynamic =
1123 transport_security_state->GetDynamicDomainState(domain,
1124 &dynamic_state);
1125 if (found_dynamic) {
1126 result->SetInteger("dynamic_upgrade_mode",
1127 static_cast<int>(dynamic_state.sts.upgrade_mode));
1128 result->SetBoolean("dynamic_sts_include_subdomains",
1129 dynamic_state.sts.include_subdomains);
1130 result->SetBoolean("dynamic_pkp_include_subdomains",
1131 dynamic_state.pkp.include_subdomains);
1132 result->SetDouble("dynamic_sts_observed",
1133 dynamic_state.sts.last_observed.ToDoubleT());
1134 result->SetDouble("dynamic_pkp_observed",
1135 dynamic_state.pkp.last_observed.ToDoubleT());
1136 result->SetDouble("dynamic_sts_expiry",
1137 dynamic_state.sts.expiry.ToDoubleT());
1138 result->SetDouble("dynamic_pkp_expiry",
1139 dynamic_state.pkp.expiry.ToDoubleT());
1140 result->SetString("dynamic_spki_hashes",
1141 HashesToBase64String(dynamic_state.pkp.spki_hashes));
1144 result->SetBoolean("result", found_static || found_dynamic);
1145 if (found_static) {
1146 result->SetString("domain", static_state.domain);
1147 } else if (found_dynamic) {
1148 result->SetString("domain", dynamic_state.domain);
1149 } else {
1150 result->SetString("domain", domain);
1155 SendJavascriptCommand("receivedHSTSResult", result);
1158 void NetInternalsMessageHandler::IOThreadImpl::OnHSTSAdd(
1159 const base::ListValue* list) {
1160 // |list| should be: [<domain to query>, <STS include subdomains>, <PKP
1161 // include subdomains>, <key pins>].
1162 std::string domain;
1163 CHECK(list->GetString(0, &domain));
1164 if (!base::IsStringASCII(domain)) {
1165 // Silently fail. The user will get a helpful error if they query for the
1166 // name.
1167 return;
1169 bool sts_include_subdomains;
1170 CHECK(list->GetBoolean(1, &sts_include_subdomains));
1171 bool pkp_include_subdomains;
1172 CHECK(list->GetBoolean(2, &pkp_include_subdomains));
1173 std::string hashes_str;
1174 CHECK(list->GetString(3, &hashes_str));
1176 net::TransportSecurityState* transport_security_state =
1177 GetMainContext()->transport_security_state();
1178 if (!transport_security_state)
1179 return;
1181 base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
1182 net::HashValueVector hashes;
1183 if (!hashes_str.empty()) {
1184 if (!Base64StringToHashes(hashes_str, &hashes))
1185 return;
1188 transport_security_state->AddHSTS(domain, expiry, sts_include_subdomains);
1189 transport_security_state->AddHPKP(domain, expiry, pkp_include_subdomains,
1190 hashes);
1193 void NetInternalsMessageHandler::IOThreadImpl::OnHSTSDelete(
1194 const base::ListValue* list) {
1195 // |list| should be: [<domain to query>].
1196 std::string domain;
1197 CHECK(list->GetString(0, &domain));
1198 if (!base::IsStringASCII(domain)) {
1199 // There cannot be a unicode entry in the HSTS set.
1200 return;
1202 net::TransportSecurityState* transport_security_state =
1203 GetMainContext()->transport_security_state();
1204 if (!transport_security_state)
1205 return;
1207 transport_security_state->DeleteDynamicDataForHost(domain);
1210 void NetInternalsMessageHandler::IOThreadImpl::OnGetHttpCacheInfo(
1211 const base::ListValue* list) {
1212 DCHECK(!list);
1213 base::DictionaryValue* info_dict = new base::DictionaryValue();
1214 base::DictionaryValue* stats_dict = new base::DictionaryValue();
1216 disk_cache::Backend* disk_cache = GetDiskCacheBackend(GetMainContext());
1218 if (disk_cache) {
1219 // Extract the statistics key/value pairs from the backend.
1220 base::StringPairs stats;
1221 disk_cache->GetStats(&stats);
1222 for (size_t i = 0; i < stats.size(); ++i) {
1223 stats_dict->SetStringWithoutPathExpansion(
1224 stats[i].first, stats[i].second);
1228 info_dict->Set("stats", stats_dict);
1230 SendJavascriptCommand("receivedHttpCacheInfo", info_dict);
1233 void NetInternalsMessageHandler::IOThreadImpl::OnGetSocketPoolInfo(
1234 const base::ListValue* list) {
1235 DCHECK(!list);
1236 net::HttpNetworkSession* http_network_session =
1237 GetHttpNetworkSession(GetMainContext());
1239 base::Value* socket_pool_info = NULL;
1240 if (http_network_session)
1241 socket_pool_info = http_network_session->SocketPoolInfoToValue();
1243 SendJavascriptCommand("receivedSocketPoolInfo", socket_pool_info);
1246 void NetInternalsMessageHandler::IOThreadImpl::OnGetSessionNetworkStats(
1247 const base::ListValue* list) {
1248 DCHECK(!list);
1249 net::HttpNetworkSession* http_network_session =
1250 GetHttpNetworkSession(main_context_getter_->GetURLRequestContext());
1252 base::Value* network_info = NULL;
1253 if (http_network_session) {
1254 ChromeNetworkDelegate* net_delegate =
1255 static_cast<ChromeNetworkDelegate*>(
1256 http_network_session->network_delegate());
1257 if (net_delegate) {
1258 network_info = net_delegate->SessionNetworkStatsInfoToValue();
1261 SendJavascriptCommand("receivedSessionNetworkStats", network_info);
1264 void NetInternalsMessageHandler::IOThreadImpl::OnFlushSocketPools(
1265 const base::ListValue* list) {
1266 DCHECK(!list);
1267 net::HttpNetworkSession* http_network_session =
1268 GetHttpNetworkSession(GetMainContext());
1270 if (http_network_session)
1271 http_network_session->CloseAllConnections();
1274 void NetInternalsMessageHandler::IOThreadImpl::OnCloseIdleSockets(
1275 const base::ListValue* list) {
1276 DCHECK(!list);
1277 net::HttpNetworkSession* http_network_session =
1278 GetHttpNetworkSession(GetMainContext());
1280 if (http_network_session)
1281 http_network_session->CloseIdleConnections();
1284 void NetInternalsMessageHandler::IOThreadImpl::OnGetSpdySessionInfo(
1285 const base::ListValue* list) {
1286 DCHECK(!list);
1287 net::HttpNetworkSession* http_network_session =
1288 GetHttpNetworkSession(GetMainContext());
1290 base::Value* spdy_info = http_network_session ?
1291 http_network_session->SpdySessionPoolInfoToValue() : NULL;
1292 SendJavascriptCommand("receivedSpdySessionInfo", spdy_info);
1295 void NetInternalsMessageHandler::IOThreadImpl::OnGetSpdyStatus(
1296 const base::ListValue* list) {
1297 DCHECK(!list);
1298 base::DictionaryValue* status_dict = new base::DictionaryValue();
1300 net::HttpNetworkSession* http_network_session =
1301 GetHttpNetworkSession(GetMainContext());
1303 status_dict->SetBoolean("spdy_enabled",
1304 net::HttpStreamFactory::spdy_enabled());
1305 status_dict->SetBoolean(
1306 "use_alternate_protocols",
1307 http_network_session->params().use_alternate_protocols);
1308 status_dict->SetBoolean("force_spdy_over_ssl",
1309 http_network_session->params().force_spdy_over_ssl);
1310 status_dict->SetBoolean("force_spdy_always",
1311 http_network_session->params().force_spdy_always);
1313 std::vector<std::string> next_protos;
1314 http_network_session->GetNextProtos(&next_protos);
1315 std::string next_protos_string = JoinString(next_protos, ',');
1316 status_dict->SetString("next_protos", next_protos_string);
1318 SendJavascriptCommand("receivedSpdyStatus", status_dict);
1321 void
1322 NetInternalsMessageHandler::IOThreadImpl::OnGetSpdyAlternateProtocolMappings(
1323 const base::ListValue* list) {
1324 DCHECK(!list);
1325 base::ListValue* dict_list = new base::ListValue();
1327 const net::HttpServerProperties& http_server_properties =
1328 *GetMainContext()->http_server_properties();
1330 const net::AlternateProtocolMap& map =
1331 http_server_properties.alternate_protocol_map();
1333 for (net::AlternateProtocolMap::const_iterator it = map.begin();
1334 it != map.end(); ++it) {
1335 base::DictionaryValue* dict = new base::DictionaryValue();
1336 dict->SetString("host_port_pair", it->first.ToString());
1337 dict->SetString("alternate_protocol", it->second.ToString());
1338 dict_list->Append(dict);
1341 SendJavascriptCommand("receivedSpdyAlternateProtocolMappings", dict_list);
1344 void NetInternalsMessageHandler::IOThreadImpl::OnGetQuicInfo(
1345 const base::ListValue* list) {
1346 DCHECK(!list);
1347 net::HttpNetworkSession* http_network_session =
1348 GetHttpNetworkSession(GetMainContext());
1350 base::Value* quic_info = http_network_session ?
1351 http_network_session->QuicInfoToValue() : NULL;
1352 SendJavascriptCommand("receivedQuicInfo", quic_info);
1355 #if defined(OS_WIN)
1356 void NetInternalsMessageHandler::IOThreadImpl::OnGetServiceProviders(
1357 const base::ListValue* list) {
1358 DCHECK(!list);
1360 base::DictionaryValue* service_providers = new base::DictionaryValue();
1362 WinsockLayeredServiceProviderList layered_providers;
1363 GetWinsockLayeredServiceProviders(&layered_providers);
1364 base::ListValue* layered_provider_list = new base::ListValue();
1365 for (size_t i = 0; i < layered_providers.size(); ++i) {
1366 base::DictionaryValue* service_dict = new base::DictionaryValue();
1367 service_dict->SetString("name", layered_providers[i].name);
1368 service_dict->SetInteger("version", layered_providers[i].version);
1369 service_dict->SetInteger("chain_length", layered_providers[i].chain_length);
1370 service_dict->SetInteger("socket_type", layered_providers[i].socket_type);
1371 service_dict->SetInteger("socket_protocol",
1372 layered_providers[i].socket_protocol);
1373 service_dict->SetString("path", layered_providers[i].path);
1375 layered_provider_list->Append(service_dict);
1377 service_providers->Set("service_providers", layered_provider_list);
1379 WinsockNamespaceProviderList namespace_providers;
1380 GetWinsockNamespaceProviders(&namespace_providers);
1381 base::ListValue* namespace_list = new base::ListValue;
1382 for (size_t i = 0; i < namespace_providers.size(); ++i) {
1383 base::DictionaryValue* namespace_dict = new base::DictionaryValue();
1384 namespace_dict->SetString("name", namespace_providers[i].name);
1385 namespace_dict->SetBoolean("active", namespace_providers[i].active);
1386 namespace_dict->SetInteger("version", namespace_providers[i].version);
1387 namespace_dict->SetInteger("type", namespace_providers[i].type);
1389 namespace_list->Append(namespace_dict);
1391 service_providers->Set("namespace_providers", namespace_list);
1393 SendJavascriptCommand("receivedServiceProviders", service_providers);
1395 #endif
1397 #if defined(OS_CHROMEOS)
1398 void NetInternalsMessageHandler::OnRefreshSystemLogs(
1399 const base::ListValue* list) {
1400 DCHECK(!list);
1401 DCHECK(syslogs_getter_.get());
1402 syslogs_getter_->DeleteSystemLogs();
1403 syslogs_getter_->LoadSystemLogs();
1406 void NetInternalsMessageHandler::OnGetSystemLog(
1407 const base::ListValue* list) {
1408 DCHECK(syslogs_getter_.get());
1409 syslogs_getter_->RequestSystemLog(list);
1412 void NetInternalsMessageHandler::ImportONCFileToNSSDB(
1413 const std::string& onc_blob,
1414 const std::string& passcode,
1415 net::NSSCertDatabase* nssdb) {
1416 user_manager::User* user = chromeos::ProfileHelper::Get()->GetUserByProfile(
1417 Profile::FromWebUI(web_ui()));
1419 if (!user) {
1420 std::string error = "User not found.";
1421 SendJavascriptCommand("receivedONCFileParse", new base::StringValue(error));
1422 return;
1425 std::string error;
1426 onc::ONCSource onc_source = onc::ONC_SOURCE_USER_IMPORT;
1427 base::ListValue network_configs;
1428 base::DictionaryValue global_network_config;
1429 base::ListValue certificates;
1430 if (!chromeos::onc::ParseAndValidateOncForImport(onc_blob,
1431 onc_source,
1432 passcode,
1433 &network_configs,
1434 &global_network_config,
1435 &certificates)) {
1436 error = "Errors occurred during the ONC parsing. ";
1439 std::string network_error;
1440 chromeos::onc::ImportNetworksForUser(user, network_configs, &network_error);
1441 if (!network_error.empty())
1442 error += network_error;
1444 chromeos::onc::CertificateImporterImpl cert_importer(
1445 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), nssdb);
1446 cert_importer.ImportCertificates(
1447 certificates,
1448 onc_source,
1449 base::Bind(&NetInternalsMessageHandler::OnCertificatesImported,
1450 AsWeakPtr(),
1451 error));
1454 void NetInternalsMessageHandler::OnCertificatesImported(
1455 const std::string& previous_error,
1456 bool success,
1457 const net::CertificateList& /* unused onc_trusted_certificates */) {
1458 std::string error = previous_error;
1459 if (!success)
1460 error += "Some certificates couldn't be imported. ";
1462 SendJavascriptCommand("receivedONCFileParse", new base::StringValue(error));
1465 void NetInternalsMessageHandler::OnImportONCFile(
1466 const base::ListValue* list) {
1467 std::string onc_blob;
1468 std::string passcode;
1469 if (list->GetSize() != 2 ||
1470 !list->GetString(0, &onc_blob) ||
1471 !list->GetString(1, &passcode)) {
1472 NOTREACHED();
1475 GetNSSCertDatabaseForProfile(
1476 Profile::FromWebUI(web_ui()),
1477 base::Bind(&NetInternalsMessageHandler::ImportONCFileToNSSDB, AsWeakPtr(),
1478 onc_blob, passcode));
1481 void NetInternalsMessageHandler::OnStoreDebugLogs(const base::ListValue* list) {
1482 DCHECK(list);
1484 SendJavascriptCommand("receivedStoreDebugLogs",
1485 new base::StringValue("Creating log file..."));
1486 Profile* profile = Profile::FromWebUI(web_ui());
1487 const DownloadPrefs* const prefs = DownloadPrefs::FromBrowserContext(profile);
1488 base::FilePath path = prefs->DownloadPath();
1489 if (file_manager::util::IsUnderNonNativeLocalPath(profile, path))
1490 path = prefs->GetDefaultDownloadDirectoryForProfile();
1491 chromeos::DebugLogWriter::StoreLogs(
1492 path,
1493 true, // should_compress
1494 base::Bind(&NetInternalsMessageHandler::OnStoreDebugLogsCompleted,
1495 AsWeakPtr()));
1498 void NetInternalsMessageHandler::OnStoreDebugLogsCompleted(
1499 const base::FilePath& log_path, bool succeeded) {
1500 std::string status;
1501 if (succeeded)
1502 status = "Created log file: " + log_path.BaseName().AsUTF8Unsafe();
1503 else
1504 status = "Failed to create log file";
1505 SendJavascriptCommand("receivedStoreDebugLogs",
1506 new base::StringValue(status));
1509 void NetInternalsMessageHandler::OnSetNetworkDebugMode(
1510 const base::ListValue* list) {
1511 std::string subsystem;
1512 if (list->GetSize() != 1 || !list->GetString(0, &subsystem))
1513 NOTREACHED();
1514 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
1515 SetDebugMode(
1516 subsystem,
1517 base::Bind(
1518 &NetInternalsMessageHandler::OnSetNetworkDebugModeCompleted,
1519 AsWeakPtr(),
1520 subsystem));
1523 void NetInternalsMessageHandler::OnSetNetworkDebugModeCompleted(
1524 const std::string& subsystem,
1525 bool succeeded) {
1526 std::string status;
1527 if (succeeded)
1528 status = "Debug mode is changed to " + subsystem;
1529 else
1530 status = "Failed to change debug mode to " + subsystem;
1531 SendJavascriptCommand("receivedSetNetworkDebugMode",
1532 new base::StringValue(status));
1534 #endif // defined(OS_CHROMEOS)
1536 void NetInternalsMessageHandler::IOThreadImpl::OnSetLogLevel(
1537 const base::ListValue* list) {
1538 int log_level;
1539 std::string log_level_string;
1540 if (!list->GetString(0, &log_level_string) ||
1541 !base::StringToInt(log_level_string, &log_level)) {
1542 NOTREACHED();
1543 return;
1546 DCHECK_GE(log_level, net::NetLog::LOG_ALL);
1547 DCHECK_LT(log_level, net::NetLog::LOG_NONE);
1548 net_log()->SetObserverLogLevel(
1549 this, static_cast<net::NetLog::LogLevel>(log_level));
1552 // Note that unlike other methods of IOThreadImpl, this function
1553 // can be called from ANY THREAD.
1554 void NetInternalsMessageHandler::IOThreadImpl::OnAddEntry(
1555 const net::NetLog::Entry& entry) {
1556 BrowserThread::PostTask(
1557 BrowserThread::IO, FROM_HERE,
1558 base::Bind(&IOThreadImpl::AddEntryToQueue, this, entry.ToValue()));
1561 void NetInternalsMessageHandler::IOThreadImpl::OnStartConnectionTestSuite() {
1562 SendJavascriptCommand("receivedStartConnectionTestSuite", NULL);
1565 void NetInternalsMessageHandler::IOThreadImpl::OnStartConnectionTestExperiment(
1566 const ConnectionTester::Experiment& experiment) {
1567 SendJavascriptCommand(
1568 "receivedStartConnectionTestExperiment",
1569 ExperimentToValue(experiment));
1572 void
1573 NetInternalsMessageHandler::IOThreadImpl::OnCompletedConnectionTestExperiment(
1574 const ConnectionTester::Experiment& experiment,
1575 int result) {
1576 base::DictionaryValue* dict = new base::DictionaryValue();
1578 dict->Set("experiment", ExperimentToValue(experiment));
1579 dict->SetInteger("result", result);
1581 SendJavascriptCommand(
1582 "receivedCompletedConnectionTestExperiment",
1583 dict);
1586 void
1587 NetInternalsMessageHandler::IOThreadImpl::OnCompletedConnectionTestSuite() {
1588 SendJavascriptCommand(
1589 "receivedCompletedConnectionTestSuite",
1590 NULL);
1593 // Note that this can be called from ANY THREAD.
1594 void NetInternalsMessageHandler::IOThreadImpl::SendJavascriptCommand(
1595 const std::string& command,
1596 base::Value* arg) {
1597 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
1598 if (handler_.get() && !was_webui_deleted_) {
1599 // We check |handler_| in case it was deleted on the UI thread earlier
1600 // while we were running on the IO thread.
1601 handler_->SendJavascriptCommand(command, arg);
1602 } else {
1603 delete arg;
1605 return;
1608 if (!BrowserThread::PostTask(
1609 BrowserThread::UI, FROM_HERE,
1610 base::Bind(&IOThreadImpl::SendJavascriptCommand, this, command, arg))) {
1611 // Failed posting the task, avoid leaking.
1612 delete arg;
1616 void NetInternalsMessageHandler::IOThreadImpl::AddEntryToQueue(
1617 base::Value* entry) {
1618 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1619 if (!pending_entries_.get()) {
1620 pending_entries_.reset(new base::ListValue());
1621 BrowserThread::PostDelayedTask(
1622 BrowserThread::IO, FROM_HERE,
1623 base::Bind(&IOThreadImpl::PostPendingEntries, this),
1624 base::TimeDelta::FromMilliseconds(kNetLogEventDelayMilliseconds));
1626 pending_entries_->Append(entry);
1629 void NetInternalsMessageHandler::IOThreadImpl::PostPendingEntries() {
1630 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1631 if (pending_entries_.get())
1632 SendJavascriptCommand("receivedLogEntries", pending_entries_.release());
1635 void NetInternalsMessageHandler::IOThreadImpl::PrePopulateEventList() {
1636 // Use a set to prevent duplicates.
1637 std::set<net::URLRequestContext*> contexts;
1638 for (ContextGetterList::const_iterator getter = context_getters_.begin();
1639 getter != context_getters_.end(); ++getter) {
1640 contexts.insert((*getter)->GetURLRequestContext());
1642 contexts.insert(io_thread_->globals()->proxy_script_fetcher_context.get());
1643 contexts.insert(io_thread_->globals()->system_request_context.get());
1645 // Put together the list of all requests.
1646 std::vector<const net::URLRequest*> requests;
1647 for (std::set<net::URLRequestContext*>::const_iterator context =
1648 contexts.begin();
1649 context != contexts.end(); ++context) {
1650 std::set<const net::URLRequest*>* context_requests =
1651 (*context)->url_requests();
1652 for (std::set<const net::URLRequest*>::const_iterator request_it =
1653 context_requests->begin();
1654 request_it != context_requests->end(); ++request_it) {
1655 DCHECK_EQ(io_thread_->net_log(), (*request_it)->net_log().net_log());
1656 requests.push_back(*request_it);
1660 // Sort by creation time.
1661 std::sort(requests.begin(), requests.end(), RequestCreatedBefore);
1663 // Create fake events.
1664 for (std::vector<const net::URLRequest*>::const_iterator request_it =
1665 requests.begin();
1666 request_it != requests.end(); ++request_it) {
1667 const net::URLRequest* request = *request_it;
1668 net::NetLog::ParametersCallback callback =
1669 base::Bind(&GetRequestStateAsValue, base::Unretained(request));
1671 // Create and add the entry directly, to avoid sending it to any other
1672 // NetLog observers.
1673 net::NetLog::EntryData entry_data(net::NetLog::TYPE_REQUEST_ALIVE,
1674 request->net_log().source(),
1675 net::NetLog::PHASE_BEGIN,
1676 request->creation_time(),
1677 &callback);
1678 net::NetLog::Entry entry(&entry_data, request->net_log().GetLogLevel());
1680 // Have to add |entry| to the queue synchronously, as there may already
1681 // be posted tasks queued up to add other events for |request|, which we
1682 // want |entry| to precede.
1683 AddEntryToQueue(entry.ToValue());
1687 } // namespace
1690 ////////////////////////////////////////////////////////////////////////////////
1692 // NetInternalsUI
1694 ////////////////////////////////////////////////////////////////////////////////
1696 // static
1697 base::Value* NetInternalsUI::GetConstants() {
1698 base::DictionaryValue* constants_dict = net::NetLogLogger::GetConstants();
1699 DCHECK(constants_dict);
1701 // Add a dictionary with the version of the client and its command line
1702 // arguments.
1704 base::DictionaryValue* dict = new base::DictionaryValue();
1706 chrome::VersionInfo version_info;
1708 // We have everything we need to send the right values.
1709 dict->SetString("name", version_info.Name());
1710 dict->SetString("version", version_info.Version());
1711 dict->SetString("cl", version_info.LastChange());
1712 dict->SetString("version_mod",
1713 chrome::VersionInfo::GetVersionStringModifier());
1714 dict->SetString("official",
1715 version_info.IsOfficialBuild() ? "official" : "unofficial");
1716 dict->SetString("os_type", version_info.OSType());
1717 dict->SetString("command_line",
1718 CommandLine::ForCurrentProcess()->GetCommandLineString());
1720 constants_dict->Set("clientInfo", dict);
1723 return constants_dict;
1726 NetInternalsUI::NetInternalsUI(content::WebUI* web_ui)
1727 : WebUIController(web_ui) {
1728 web_ui->AddMessageHandler(new NetInternalsMessageHandler());
1730 // Set up the chrome://net-internals/ source.
1731 Profile* profile = Profile::FromWebUI(web_ui);
1732 content::WebUIDataSource::Add(profile, CreateNetInternalsHTMLSource());