Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / webui / net_internals / net_internals_ui.cc
blobc80cfbece0a88a8f3366ec3c3052902ce5a99818
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/values.h"
30 #include "chrome/browser/browser_process.h"
31 #include "chrome/browser/browsing_data/browsing_data_helper.h"
32 #include "chrome/browser/browsing_data/browsing_data_remover.h"
33 #include "chrome/browser/chrome_notification_types.h"
34 #include "chrome/browser/download/download_prefs.h"
35 #include "chrome/browser/io_thread.h"
36 #include "chrome/browser/net/chrome_net_log.h"
37 #include "chrome/browser/net/chrome_network_delegate.h"
38 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
39 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.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/url_constants.h"
46 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
47 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h"
48 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h"
49 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h"
50 #include "components/onc/onc_constants.h"
51 #include "components/url_fixer/url_fixer.h"
52 #include "content/public/browser/browser_thread.h"
53 #include "content/public/browser/notification_details.h"
54 #include "content/public/browser/resource_dispatcher_host.h"
55 #include "content/public/browser/web_contents.h"
56 #include "content/public/browser/web_ui.h"
57 #include "content/public/browser/web_ui_data_source.h"
58 #include "content/public/browser/web_ui_message_handler.h"
59 #include "grit/net_internals_resources.h"
60 #include "net/base/net_errors.h"
61 #include "net/base/net_util.h"
62 #include "net/disk_cache/disk_cache.h"
63 #include "net/dns/host_cache.h"
64 #include "net/dns/host_resolver.h"
65 #include "net/http/http_cache.h"
66 #include "net/http/http_network_layer.h"
67 #include "net/http/http_network_session.h"
68 #include "net/http/http_server_properties.h"
69 #include "net/http/http_stream_factory.h"
70 #include "net/http/transport_security_state.h"
71 #include "net/log/net_log_util.h"
72 #include "net/log/write_to_file_net_log_observer.h"
73 #include "net/proxy/proxy_service.h"
74 #include "net/url_request/url_request_context.h"
75 #include "net/url_request/url_request_context_getter.h"
77 #if defined(OS_CHROMEOS)
78 #include "chrome/browser/chromeos/file_manager/filesystem_api_util.h"
79 #include "chrome/browser/chromeos/net/onc_utils.h"
80 #include "chrome/browser/chromeos/profiles/profile_helper.h"
81 #include "chrome/browser/chromeos/system_logs/debug_log_writer.h"
82 #include "chrome/browser/net/nss_context.h"
83 #include "chromeos/dbus/dbus_thread_manager.h"
84 #include "chromeos/dbus/debug_daemon_client.h"
85 #include "chromeos/network/onc/onc_certificate_importer_impl.h"
86 #include "chromeos/network/onc/onc_utils.h"
87 #include "components/user_manager/user.h"
88 #endif
90 #if defined(OS_WIN)
91 #include "chrome/browser/net/service_providers_win.h"
92 #endif
94 #if defined(ENABLE_EXTENSIONS)
95 #include "chrome/browser/extensions/extension_service.h"
96 #include "chrome/browser/ui/webui/extensions/extension_basic_info.h"
97 #include "extensions/browser/extension_registry.h"
98 #include "extensions/browser/extension_system.h"
99 #include "extensions/common/extension_set.h"
100 #endif
102 using base::StringValue;
103 using content::BrowserThread;
104 using content::WebContents;
105 using content::WebUIMessageHandler;
107 namespace {
109 // Delay between when an event occurs and when it is passed to the Javascript
110 // page. All events that occur during this period are grouped together and
111 // sent to the page at once, which reduces context switching and CPU usage.
112 const int kNetLogEventDelayMilliseconds = 100;
114 // Returns the HostCache for |context|'s primary HostResolver, or NULL if
115 // there is none.
116 net::HostCache* GetHostResolverCache(net::URLRequestContext* context) {
117 return context->host_resolver()->GetHostCache();
120 std::string HashesToBase64String(const net::HashValueVector& hashes) {
121 std::string str;
122 for (size_t i = 0; i != hashes.size(); ++i) {
123 if (i != 0)
124 str += ",";
125 str += hashes[i].ToString();
127 return str;
130 bool Base64StringToHashes(const std::string& hashes_str,
131 net::HashValueVector* hashes) {
132 hashes->clear();
133 std::vector<std::string> vector_hash_str;
134 base::SplitString(hashes_str, ',', &vector_hash_str);
136 for (size_t i = 0; i != vector_hash_str.size(); ++i) {
137 std::string hash_str;
138 base::RemoveChars(vector_hash_str[i], " \t\r\n", &hash_str);
139 net::HashValue hash;
140 // Skip past unrecognized hash algos
141 // But return false on malformatted input
142 if (hash_str.empty())
143 return false;
144 if (hash_str.compare(0, 5, "sha1/") != 0 &&
145 hash_str.compare(0, 7, "sha256/") != 0) {
146 continue;
148 if (!hash.FromString(hash_str))
149 return false;
150 hashes->push_back(hash);
152 return true;
155 // Returns the http network session for |context| if there is one.
156 // Otherwise, returns NULL.
157 net::HttpNetworkSession* GetHttpNetworkSession(
158 net::URLRequestContext* context) {
159 if (!context->http_transaction_factory())
160 return NULL;
162 return context->http_transaction_factory()->GetSession();
165 content::WebUIDataSource* CreateNetInternalsHTMLSource() {
166 content::WebUIDataSource* source =
167 content::WebUIDataSource::Create(chrome::kChromeUINetInternalsHost);
169 source->SetDefaultResource(IDR_NET_INTERNALS_INDEX_HTML);
170 source->AddResourcePath("index.js", IDR_NET_INTERNALS_INDEX_JS);
171 source->SetJsonPath("strings.js");
172 return source;
175 // This class receives javascript messages from the renderer.
176 // Note that the WebUI infrastructure runs on the UI thread, therefore all of
177 // this class's methods are expected to run on the UI thread.
179 // Since the network code we want to run lives on the IO thread, we proxy
180 // almost everything over to NetInternalsMessageHandler::IOThreadImpl, which
181 // runs on the IO thread.
183 // TODO(eroman): Can we start on the IO thread to begin with?
184 class NetInternalsMessageHandler
185 : public WebUIMessageHandler,
186 public base::SupportsWeakPtr<NetInternalsMessageHandler> {
187 public:
188 NetInternalsMessageHandler();
189 ~NetInternalsMessageHandler() override;
191 // WebUIMessageHandler implementation.
192 void RegisterMessages() override;
194 // Calls g_browser.receive in the renderer, passing in |command| and |arg|.
195 // Takes ownership of |arg|. If the renderer is displaying a log file, the
196 // message will be ignored.
197 void SendJavascriptCommand(const std::string& command, base::Value* arg);
199 // Javascript message handlers.
200 void OnRendererReady(const base::ListValue* list);
201 void OnClearBrowserCache(const base::ListValue* list);
202 void OnGetPrerenderInfo(const base::ListValue* list);
203 void OnGetHistoricNetworkStats(const base::ListValue* list);
204 void OnGetExtensionInfo(const base::ListValue* list);
205 void OnGetDataReductionProxyInfo(const base::ListValue* list);
206 #if defined(OS_CHROMEOS)
207 void OnImportONCFile(const base::ListValue* list);
208 void OnStoreDebugLogs(const base::ListValue* list);
209 void OnStoreDebugLogsCompleted(const base::FilePath& log_path,
210 bool succeeded);
211 void OnSetNetworkDebugMode(const base::ListValue* list);
212 void OnSetNetworkDebugModeCompleted(const std::string& subsystem,
213 bool succeeded);
215 // Callback to |GetNSSCertDatabaseForProfile| used to retrieve the database
216 // to which user's ONC defined certificates should be imported.
217 // It parses and imports |onc_blob|.
218 void ImportONCFileToNSSDB(const std::string& onc_blob,
219 const std::string& passcode,
220 net::NSSCertDatabase* nssdb);
222 // Called back by the CertificateImporter when a certificate import finished.
223 // |previous_error| contains earlier errors during this import.
224 void OnCertificatesImported(
225 const std::string& previous_error,
226 bool success,
227 const net::CertificateList& onc_trusted_certificates);
228 #endif
230 private:
231 class IOThreadImpl;
233 // This is the "real" message handler, which lives on the IO thread.
234 scoped_refptr<IOThreadImpl> proxy_;
236 base::WeakPtr<prerender::PrerenderManager> prerender_manager_;
238 DISALLOW_COPY_AND_ASSIGN(NetInternalsMessageHandler);
241 // This class is the "real" message handler. It is allocated and destroyed on
242 // the UI thread. With the exception of OnAddEntry, OnWebUIDeleted, and
243 // SendJavascriptCommand, its methods are all expected to be called from the IO
244 // thread. OnAddEntry and SendJavascriptCommand can be called from any thread,
245 // and OnWebUIDeleted can only be called from the UI thread.
246 class NetInternalsMessageHandler::IOThreadImpl
247 : public base::RefCountedThreadSafe<
248 NetInternalsMessageHandler::IOThreadImpl,
249 BrowserThread::DeleteOnUIThread>,
250 public net::NetLog::ThreadSafeObserver {
251 public:
252 // Type for methods that can be used as MessageHandler callbacks.
253 typedef void (IOThreadImpl::*MessageHandler)(const base::ListValue*);
255 // Creates a proxy for |handler| that will live on the IO thread.
256 // |handler| is a weak pointer, since it is possible for the
257 // WebUIMessageHandler to be deleted on the UI thread while we were executing
258 // on the IO thread. |io_thread| is the global IOThread (it is passed in as
259 // an argument since we need to grab it from the UI thread).
260 IOThreadImpl(
261 const base::WeakPtr<NetInternalsMessageHandler>& handler,
262 IOThread* io_thread,
263 net::URLRequestContextGetter* main_context_getter);
265 // Called on UI thread just after creation, to add a ContextGetter to
266 // |context_getters_|.
267 void AddRequestContextGetter(net::URLRequestContextGetter* context_getter);
269 // Helper method to enable a callback that will be executed on the IO thread.
270 static void CallbackHelper(MessageHandler method,
271 scoped_refptr<IOThreadImpl> io_thread,
272 const base::ListValue* list);
274 // Called once the WebUI has been deleted (i.e. renderer went away), on the
275 // IO thread.
276 void Detach();
278 // Called when the WebUI is deleted. Prevents calling Javascript functions
279 // afterwards. Called on UI thread.
280 void OnWebUIDeleted();
282 //--------------------------------
283 // Javascript message handlers:
284 //--------------------------------
286 void OnRendererReady(const base::ListValue* list);
288 void OnGetNetInfo(const base::ListValue* list);
289 void OnReloadProxySettings(const base::ListValue* list);
290 void OnClearBadProxies(const base::ListValue* list);
291 void OnClearHostResolverCache(const base::ListValue* list);
292 void OnEnableIPv6(const base::ListValue* list);
293 void OnHSTSQuery(const base::ListValue* list);
294 void OnHSTSAdd(const base::ListValue* list);
295 void OnHSTSDelete(const base::ListValue* list);
296 void OnGetSessionNetworkStats(const base::ListValue* list);
297 void OnCloseIdleSockets(const base::ListValue* list);
298 void OnFlushSocketPools(const base::ListValue* list);
299 #if defined(OS_WIN)
300 void OnGetServiceProviders(const base::ListValue* list);
301 #endif
302 void OnSetCaptureMode(const base::ListValue* list);
304 // ChromeNetLog::ThreadSafeObserver implementation:
305 void OnAddEntry(const net::NetLog::Entry& entry) override;
307 // Helper that calls g_browser.receive in the renderer, passing in |command|
308 // and |arg|. Takes ownership of |arg|. If the renderer is displaying a log
309 // file, the message will be ignored. Note that this can be called from any
310 // thread.
311 void SendJavascriptCommand(const std::string& command, base::Value* arg);
313 private:
314 friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
315 friend class base::DeleteHelper<IOThreadImpl>;
317 typedef std::list<scoped_refptr<net::URLRequestContextGetter> >
318 ContextGetterList;
320 ~IOThreadImpl() override;
322 // Adds |entry| to the queue of pending log entries to be sent to the page via
323 // Javascript. Must be called on the IO Thread. Also creates a delayed task
324 // that will call PostPendingEntries, if there isn't one already.
325 void AddEntryToQueue(base::Value* entry);
327 // Sends all pending entries to the page via Javascript, and clears the list
328 // of pending entries. Sending multiple entries at once results in a
329 // significant reduction of CPU usage when a lot of events are happening.
330 // Must be called on the IO Thread.
331 void PostPendingEntries();
333 // Adds entries with the states of ongoing URL requests.
334 void PrePopulateEventList();
336 net::URLRequestContext* GetMainContext() {
337 return main_context_getter_->GetURLRequestContext();
340 // |info_sources| is an or'd together list of the net::NetInfoSources to
341 // send information about. Information is sent to Javascript in the form of
342 // a single dictionary with information about all requests sources.
343 void SendNetInfo(int info_sources);
345 // Pointer to the UI-thread message handler. Only access this from
346 // the UI thread.
347 base::WeakPtr<NetInternalsMessageHandler> handler_;
349 // The global IOThread, which contains the global NetLog to observer.
350 IOThread* io_thread_;
352 // The main URLRequestContextGetter for the tab's profile.
353 scoped_refptr<net::URLRequestContextGetter> main_context_getter_;
355 // True if the Web UI has been deleted. This is used to prevent calling
356 // Javascript functions after the Web UI is destroyed. On refresh, the
357 // messages can end up being sent to the refreshed page, causing duplicate
358 // or partial entries.
360 // This is only read and written to on the UI thread.
361 bool was_webui_deleted_;
363 // Log entries that have yet to be passed along to Javascript page. Non-NULL
364 // when and only when there is a pending delayed task to call
365 // PostPendingEntries. Read and written to exclusively on the IO Thread.
366 scoped_ptr<base::ListValue> pending_entries_;
368 // Used for getting current status of URLRequests when net-internals is
369 // opened. |main_context_getter_| is automatically added on construction.
370 // Duplicates are allowed.
371 ContextGetterList context_getters_;
373 DISALLOW_COPY_AND_ASSIGN(IOThreadImpl);
376 ////////////////////////////////////////////////////////////////////////////////
378 // NetInternalsMessageHandler
380 ////////////////////////////////////////////////////////////////////////////////
382 NetInternalsMessageHandler::NetInternalsMessageHandler() {}
384 NetInternalsMessageHandler::~NetInternalsMessageHandler() {
385 if (proxy_.get()) {
386 proxy_.get()->OnWebUIDeleted();
387 // Notify the handler on the IO thread that the renderer is gone.
388 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
389 base::Bind(&IOThreadImpl::Detach, proxy_.get()));
393 void NetInternalsMessageHandler::RegisterMessages() {
394 DCHECK_CURRENTLY_ON(BrowserThread::UI);
396 Profile* profile = Profile::FromWebUI(web_ui());
398 proxy_ = new IOThreadImpl(this->AsWeakPtr(), g_browser_process->io_thread(),
399 profile->GetRequestContext());
400 proxy_->AddRequestContextGetter(profile->GetMediaRequestContext());
401 #if defined(ENABLE_EXTENSIONS)
402 proxy_->AddRequestContextGetter(profile->GetRequestContextForExtensions());
403 #endif
405 prerender::PrerenderManager* prerender_manager =
406 prerender::PrerenderManagerFactory::GetForProfile(profile);
407 if (prerender_manager) {
408 prerender_manager_ = prerender_manager->AsWeakPtr();
409 } else {
410 prerender_manager_ = base::WeakPtr<prerender::PrerenderManager>();
413 web_ui()->RegisterMessageCallback(
414 "notifyReady",
415 base::Bind(&NetInternalsMessageHandler::OnRendererReady,
416 base::Unretained(this)));
417 web_ui()->RegisterMessageCallback(
418 "getNetInfo",
419 base::Bind(&IOThreadImpl::CallbackHelper,
420 &IOThreadImpl::OnGetNetInfo, proxy_));
421 web_ui()->RegisterMessageCallback(
422 "reloadProxySettings",
423 base::Bind(&IOThreadImpl::CallbackHelper,
424 &IOThreadImpl::OnReloadProxySettings, proxy_));
425 web_ui()->RegisterMessageCallback(
426 "clearBadProxies",
427 base::Bind(&IOThreadImpl::CallbackHelper,
428 &IOThreadImpl::OnClearBadProxies, proxy_));
429 web_ui()->RegisterMessageCallback(
430 "clearHostResolverCache",
431 base::Bind(&IOThreadImpl::CallbackHelper,
432 &IOThreadImpl::OnClearHostResolverCache, proxy_));
433 web_ui()->RegisterMessageCallback(
434 "enableIPv6",
435 base::Bind(&IOThreadImpl::CallbackHelper,
436 &IOThreadImpl::OnEnableIPv6, proxy_));
437 web_ui()->RegisterMessageCallback(
438 "hstsQuery",
439 base::Bind(&IOThreadImpl::CallbackHelper,
440 &IOThreadImpl::OnHSTSQuery, proxy_));
441 web_ui()->RegisterMessageCallback(
442 "hstsAdd",
443 base::Bind(&IOThreadImpl::CallbackHelper,
444 &IOThreadImpl::OnHSTSAdd, proxy_));
445 web_ui()->RegisterMessageCallback(
446 "hstsDelete",
447 base::Bind(&IOThreadImpl::CallbackHelper,
448 &IOThreadImpl::OnHSTSDelete, proxy_));
449 web_ui()->RegisterMessageCallback(
450 "getSessionNetworkStats",
451 base::Bind(&IOThreadImpl::CallbackHelper,
452 &IOThreadImpl::OnGetSessionNetworkStats, proxy_));
453 web_ui()->RegisterMessageCallback(
454 "closeIdleSockets",
455 base::Bind(&IOThreadImpl::CallbackHelper,
456 &IOThreadImpl::OnCloseIdleSockets, proxy_));
457 web_ui()->RegisterMessageCallback(
458 "flushSocketPools",
459 base::Bind(&IOThreadImpl::CallbackHelper,
460 &IOThreadImpl::OnFlushSocketPools, proxy_));
461 #if defined(OS_WIN)
462 web_ui()->RegisterMessageCallback(
463 "getServiceProviders",
464 base::Bind(&IOThreadImpl::CallbackHelper,
465 &IOThreadImpl::OnGetServiceProviders, proxy_));
466 #endif
468 web_ui()->RegisterMessageCallback(
469 "setCaptureMode", base::Bind(&IOThreadImpl::CallbackHelper,
470 &IOThreadImpl::OnSetCaptureMode, proxy_));
471 web_ui()->RegisterMessageCallback(
472 "clearBrowserCache",
473 base::Bind(&NetInternalsMessageHandler::OnClearBrowserCache,
474 base::Unretained(this)));
475 web_ui()->RegisterMessageCallback(
476 "getPrerenderInfo",
477 base::Bind(&NetInternalsMessageHandler::OnGetPrerenderInfo,
478 base::Unretained(this)));
479 web_ui()->RegisterMessageCallback(
480 "getHistoricNetworkStats",
481 base::Bind(&NetInternalsMessageHandler::OnGetHistoricNetworkStats,
482 base::Unretained(this)));
483 web_ui()->RegisterMessageCallback(
484 "getExtensionInfo",
485 base::Bind(&NetInternalsMessageHandler::OnGetExtensionInfo,
486 base::Unretained(this)));
487 web_ui()->RegisterMessageCallback(
488 "getDataReductionProxyInfo",
489 base::Bind(&NetInternalsMessageHandler::OnGetDataReductionProxyInfo,
490 base::Unretained(this)));
491 #if defined(OS_CHROMEOS)
492 web_ui()->RegisterMessageCallback(
493 "importONCFile",
494 base::Bind(&NetInternalsMessageHandler::OnImportONCFile,
495 base::Unretained(this)));
496 web_ui()->RegisterMessageCallback(
497 "storeDebugLogs",
498 base::Bind(&NetInternalsMessageHandler::OnStoreDebugLogs,
499 base::Unretained(this)));
500 web_ui()->RegisterMessageCallback(
501 "setNetworkDebugMode",
502 base::Bind(&NetInternalsMessageHandler::OnSetNetworkDebugMode,
503 base::Unretained(this)));
504 #endif
507 void NetInternalsMessageHandler::SendJavascriptCommand(
508 const std::string& command,
509 base::Value* arg) {
510 scoped_ptr<base::Value> command_value(new base::StringValue(command));
511 scoped_ptr<base::Value> value(arg);
512 DCHECK_CURRENTLY_ON(BrowserThread::UI);
513 if (value.get()) {
514 web_ui()->CallJavascriptFunction("g_browser.receive",
515 *command_value.get(),
516 *value.get());
517 } else {
518 web_ui()->CallJavascriptFunction("g_browser.receive",
519 *command_value.get());
523 void NetInternalsMessageHandler::OnRendererReady(const base::ListValue* list) {
524 IOThreadImpl::CallbackHelper(&IOThreadImpl::OnRendererReady, proxy_, list);
527 void NetInternalsMessageHandler::OnClearBrowserCache(
528 const base::ListValue* list) {
529 BrowsingDataRemover* remover = BrowsingDataRemover::CreateForUnboundedRange(
530 Profile::FromWebUI(web_ui()));
531 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
532 BrowsingDataHelper::UNPROTECTED_WEB);
533 // BrowsingDataRemover deletes itself.
536 void NetInternalsMessageHandler::OnGetPrerenderInfo(
537 const base::ListValue* list) {
538 DCHECK_CURRENTLY_ON(BrowserThread::UI);
540 base::DictionaryValue* value = NULL;
541 prerender::PrerenderManager* prerender_manager = prerender_manager_.get();
542 if (!prerender_manager) {
543 value = new base::DictionaryValue();
544 value->SetBoolean("enabled", false);
545 value->SetBoolean("omnibox_enabled", false);
546 } else {
547 value = prerender_manager->GetAsValue();
549 SendJavascriptCommand("receivedPrerenderInfo", value);
552 void NetInternalsMessageHandler::OnGetHistoricNetworkStats(
553 const base::ListValue* list) {
554 DCHECK_CURRENTLY_ON(BrowserThread::UI);
555 base::Value* historic_network_info = NULL;
556 Profile* profile = Profile::FromWebUI(web_ui());
557 DataReductionProxyChromeSettings* data_reduction_proxy_settings =
558 DataReductionProxyChromeSettingsFactory::GetForBrowserContext(profile);
559 if (data_reduction_proxy_settings) {
560 data_reduction_proxy::DataReductionProxyCompressionStats*
561 compression_stats =
562 data_reduction_proxy_settings->data_reduction_proxy_service()
563 ->compression_stats();
564 historic_network_info =
565 compression_stats->HistoricNetworkStatsInfoToValue();
567 SendJavascriptCommand("receivedHistoricNetworkStats", historic_network_info);
570 void NetInternalsMessageHandler::OnGetExtensionInfo(
571 const base::ListValue* list) {
572 DCHECK_CURRENTLY_ON(BrowserThread::UI);
573 base::ListValue* extension_list = new base::ListValue();
574 #if defined(ENABLE_EXTENSIONS)
575 Profile* profile = Profile::FromWebUI(web_ui());
576 extensions::ExtensionSystem* extension_system =
577 extensions::ExtensionSystem::Get(profile);
578 if (extension_system) {
579 ExtensionService* extension_service = extension_system->extension_service();
580 if (extension_service) {
581 scoped_ptr<const extensions::ExtensionSet> extensions(
582 extensions::ExtensionRegistry::Get(profile)
583 ->GenerateInstalledExtensionsSet());
584 for (extensions::ExtensionSet::const_iterator it = extensions->begin();
585 it != extensions->end(); ++it) {
586 base::DictionaryValue* extension_info = new base::DictionaryValue();
587 bool enabled = extension_service->IsExtensionEnabled((*it)->id());
588 extensions::GetExtensionBasicInfo(it->get(), enabled, extension_info);
589 extension_list->Append(extension_info);
593 #endif
594 SendJavascriptCommand("receivedExtensionInfo", extension_list);
597 void NetInternalsMessageHandler::OnGetDataReductionProxyInfo(
598 const base::ListValue* list) {
599 DCHECK_CURRENTLY_ON(BrowserThread::UI);
600 Profile* profile = Profile::FromWebUI(web_ui());
601 DataReductionProxyChromeSettings* data_reduction_proxy_settings =
602 DataReductionProxyChromeSettingsFactory::GetForBrowserContext(profile);
603 data_reduction_proxy::DataReductionProxyEventStore* event_store =
604 (data_reduction_proxy_settings == nullptr) ? nullptr :
605 data_reduction_proxy_settings->GetEventStore();
606 SendJavascriptCommand(
607 "receivedDataReductionProxyInfo",
608 (event_store == nullptr) ? nullptr : event_store->GetSummaryValue());
611 ////////////////////////////////////////////////////////////////////////////////
613 // NetInternalsMessageHandler::IOThreadImpl
615 ////////////////////////////////////////////////////////////////////////////////
617 NetInternalsMessageHandler::IOThreadImpl::IOThreadImpl(
618 const base::WeakPtr<NetInternalsMessageHandler>& handler,
619 IOThread* io_thread,
620 net::URLRequestContextGetter* main_context_getter)
621 : handler_(handler),
622 io_thread_(io_thread),
623 main_context_getter_(main_context_getter),
624 was_webui_deleted_(false) {
625 DCHECK_CURRENTLY_ON(BrowserThread::UI);
626 AddRequestContextGetter(main_context_getter);
629 NetInternalsMessageHandler::IOThreadImpl::~IOThreadImpl() {
630 DCHECK_CURRENTLY_ON(BrowserThread::UI);
633 void NetInternalsMessageHandler::IOThreadImpl::AddRequestContextGetter(
634 net::URLRequestContextGetter* context_getter) {
635 DCHECK_CURRENTLY_ON(BrowserThread::UI);
636 context_getters_.push_back(context_getter);
639 void NetInternalsMessageHandler::IOThreadImpl::CallbackHelper(
640 MessageHandler method,
641 scoped_refptr<IOThreadImpl> io_thread,
642 const base::ListValue* list) {
643 DCHECK_CURRENTLY_ON(BrowserThread::UI);
645 // We need to make a copy of the value in order to pass it over to the IO
646 // thread. |list_copy| will be deleted when the task is destroyed. The called
647 // |method| cannot take ownership of |list_copy|.
648 base::ListValue* list_copy =
649 (list && list->GetSize()) ? list->DeepCopy() : NULL;
651 BrowserThread::PostTask(
652 BrowserThread::IO, FROM_HERE,
653 base::Bind(method, io_thread, base::Owned(list_copy)));
656 void NetInternalsMessageHandler::IOThreadImpl::Detach() {
657 DCHECK_CURRENTLY_ON(BrowserThread::IO);
658 // Unregister with network stack to observe events.
659 if (net_log())
660 net_log()->DeprecatedRemoveObserver(this);
663 void NetInternalsMessageHandler::IOThreadImpl::OnWebUIDeleted() {
664 DCHECK_CURRENTLY_ON(BrowserThread::UI);
665 was_webui_deleted_ = true;
668 void NetInternalsMessageHandler::IOThreadImpl::OnRendererReady(
669 const base::ListValue* list) {
670 DCHECK_CURRENTLY_ON(BrowserThread::IO);
672 // If currently watching the NetLog, temporarily stop watching it and flush
673 // pending events, so they won't appear before the status events created for
674 // currently active network objects below.
675 if (net_log()) {
676 net_log()->DeprecatedRemoveObserver(this);
677 PostPendingEntries();
680 SendJavascriptCommand("receivedConstants", NetInternalsUI::GetConstants());
682 PrePopulateEventList();
684 // Register with network stack to observe events.
685 io_thread_->net_log()->DeprecatedAddObserver(
686 this, net::NetLogCaptureMode::IncludeCookiesAndCredentials());
689 void NetInternalsMessageHandler::IOThreadImpl::OnGetNetInfo(
690 const base::ListValue* list) {
691 DCHECK(list);
692 int info_sources;
693 if (!list->GetInteger(0, &info_sources))
694 return;
695 SendNetInfo(info_sources);
698 void NetInternalsMessageHandler::IOThreadImpl::OnReloadProxySettings(
699 const base::ListValue* list) {
700 DCHECK(!list);
701 GetMainContext()->proxy_service()->ForceReloadProxyConfig();
703 // Cause the renderer to be notified of the new values.
704 SendNetInfo(net::NET_INFO_PROXY_SETTINGS);
707 void NetInternalsMessageHandler::IOThreadImpl::OnClearBadProxies(
708 const base::ListValue* list) {
709 DCHECK(!list);
710 GetMainContext()->proxy_service()->ClearBadProxiesCache();
712 // Cause the renderer to be notified of the new values.
713 SendNetInfo(net::NET_INFO_BAD_PROXIES);
716 void NetInternalsMessageHandler::IOThreadImpl::OnClearHostResolverCache(
717 const base::ListValue* list) {
718 DCHECK(!list);
719 net::HostCache* cache = GetHostResolverCache(GetMainContext());
721 if (cache)
722 cache->clear();
724 // Cause the renderer to be notified of the new values.
725 SendNetInfo(net::NET_INFO_HOST_RESOLVER);
728 void NetInternalsMessageHandler::IOThreadImpl::OnEnableIPv6(
729 const base::ListValue* list) {
730 DCHECK(!list);
731 net::HostResolver* host_resolver = GetMainContext()->host_resolver();
733 host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_UNSPECIFIED);
735 // Cause the renderer to be notified of the new value.
736 SendNetInfo(net::NET_INFO_HOST_RESOLVER);
739 void NetInternalsMessageHandler::IOThreadImpl::OnHSTSQuery(
740 const base::ListValue* list) {
741 // |list| should be: [<domain to query>].
742 std::string domain;
743 CHECK(list->GetString(0, &domain));
744 base::DictionaryValue* result = new base::DictionaryValue();
746 if (!base::IsStringASCII(domain)) {
747 result->SetString("error", "non-ASCII domain name");
748 } else {
749 net::TransportSecurityState* transport_security_state =
750 GetMainContext()->transport_security_state();
751 if (!transport_security_state) {
752 result->SetString("error", "no TransportSecurityState active");
753 } else {
754 net::TransportSecurityState::DomainState static_state;
755 const bool found_static = transport_security_state->GetStaticDomainState(
756 domain, &static_state);
757 if (found_static) {
758 result->SetBoolean("has_static_sts",
759 found_static && static_state.ShouldUpgradeToSSL());
760 result->SetInteger("static_upgrade_mode",
761 static_cast<int>(static_state.sts.upgrade_mode));
762 result->SetBoolean("static_sts_include_subdomains",
763 static_state.sts.include_subdomains);
764 result->SetDouble("static_sts_observed",
765 static_state.sts.last_observed.ToDoubleT());
766 result->SetDouble("static_sts_expiry",
767 static_state.sts.expiry.ToDoubleT());
768 result->SetBoolean("has_static_pkp",
769 found_static && static_state.HasPublicKeyPins());
770 result->SetBoolean("static_pkp_include_subdomains",
771 static_state.pkp.include_subdomains);
772 result->SetDouble("static_pkp_observed",
773 static_state.pkp.last_observed.ToDoubleT());
774 result->SetDouble("static_pkp_expiry",
775 static_state.pkp.expiry.ToDoubleT());
776 result->SetString("static_spki_hashes",
777 HashesToBase64String(static_state.pkp.spki_hashes));
778 result->SetString("static_sts_domain", static_state.sts.domain);
779 result->SetString("static_pkp_domain", static_state.pkp.domain);
782 net::TransportSecurityState::DomainState dynamic_state;
783 const bool found_dynamic =
784 transport_security_state->GetDynamicDomainState(domain,
785 &dynamic_state);
786 if (found_dynamic) {
787 result->SetInteger("dynamic_upgrade_mode",
788 static_cast<int>(dynamic_state.sts.upgrade_mode));
789 result->SetBoolean("dynamic_sts_include_subdomains",
790 dynamic_state.sts.include_subdomains);
791 result->SetBoolean("dynamic_pkp_include_subdomains",
792 dynamic_state.pkp.include_subdomains);
793 result->SetDouble("dynamic_sts_observed",
794 dynamic_state.sts.last_observed.ToDoubleT());
795 result->SetDouble("dynamic_pkp_observed",
796 dynamic_state.pkp.last_observed.ToDoubleT());
797 result->SetDouble("dynamic_sts_expiry",
798 dynamic_state.sts.expiry.ToDoubleT());
799 result->SetDouble("dynamic_pkp_expiry",
800 dynamic_state.pkp.expiry.ToDoubleT());
801 result->SetString("dynamic_spki_hashes",
802 HashesToBase64String(dynamic_state.pkp.spki_hashes));
803 result->SetString("dynamic_sts_domain", dynamic_state.sts.domain);
804 result->SetString("dynamic_pkp_domain", dynamic_state.pkp.domain);
807 result->SetBoolean("result", found_static || found_dynamic);
811 SendJavascriptCommand("receivedHSTSResult", result);
814 void NetInternalsMessageHandler::IOThreadImpl::OnHSTSAdd(
815 const base::ListValue* list) {
816 // |list| should be: [<domain to query>, <STS include subdomains>, <PKP
817 // include subdomains>, <key pins>].
818 std::string domain;
819 CHECK(list->GetString(0, &domain));
820 if (!base::IsStringASCII(domain)) {
821 // Silently fail. The user will get a helpful error if they query for the
822 // name.
823 return;
825 bool sts_include_subdomains;
826 CHECK(list->GetBoolean(1, &sts_include_subdomains));
827 bool pkp_include_subdomains;
828 CHECK(list->GetBoolean(2, &pkp_include_subdomains));
829 std::string hashes_str;
830 CHECK(list->GetString(3, &hashes_str));
832 net::TransportSecurityState* transport_security_state =
833 GetMainContext()->transport_security_state();
834 if (!transport_security_state)
835 return;
837 base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
838 net::HashValueVector hashes;
839 if (!hashes_str.empty()) {
840 if (!Base64StringToHashes(hashes_str, &hashes))
841 return;
844 transport_security_state->AddHSTS(domain, expiry, sts_include_subdomains);
845 transport_security_state->AddHPKP(domain, expiry, pkp_include_subdomains,
846 hashes);
849 void NetInternalsMessageHandler::IOThreadImpl::OnHSTSDelete(
850 const base::ListValue* list) {
851 // |list| should be: [<domain to query>].
852 std::string domain;
853 CHECK(list->GetString(0, &domain));
854 if (!base::IsStringASCII(domain)) {
855 // There cannot be a unicode entry in the HSTS set.
856 return;
858 net::TransportSecurityState* transport_security_state =
859 GetMainContext()->transport_security_state();
860 if (!transport_security_state)
861 return;
863 transport_security_state->DeleteDynamicDataForHost(domain);
866 void NetInternalsMessageHandler::IOThreadImpl::OnGetSessionNetworkStats(
867 const base::ListValue* list) {
868 DCHECK(!list);
869 net::HttpNetworkSession* http_network_session =
870 GetHttpNetworkSession(main_context_getter_->GetURLRequestContext());
872 base::Value* network_info = NULL;
873 if (http_network_session) {
874 data_reduction_proxy::DataReductionProxyNetworkDelegate* net_delegate =
875 static_cast<data_reduction_proxy::DataReductionProxyNetworkDelegate*>(
876 http_network_session->network_delegate());
877 if (net_delegate) {
878 network_info = net_delegate->SessionNetworkStatsInfoToValue();
881 SendJavascriptCommand("receivedSessionNetworkStats", network_info);
884 void NetInternalsMessageHandler::IOThreadImpl::OnFlushSocketPools(
885 const base::ListValue* list) {
886 DCHECK(!list);
887 net::HttpNetworkSession* http_network_session =
888 GetHttpNetworkSession(GetMainContext());
890 if (http_network_session)
891 http_network_session->CloseAllConnections();
894 void NetInternalsMessageHandler::IOThreadImpl::OnCloseIdleSockets(
895 const base::ListValue* list) {
896 DCHECK(!list);
897 net::HttpNetworkSession* http_network_session =
898 GetHttpNetworkSession(GetMainContext());
900 if (http_network_session)
901 http_network_session->CloseIdleConnections();
904 #if defined(OS_WIN)
905 void NetInternalsMessageHandler::IOThreadImpl::OnGetServiceProviders(
906 const base::ListValue* list) {
907 DCHECK(!list);
909 base::DictionaryValue* service_providers = new base::DictionaryValue();
911 WinsockLayeredServiceProviderList layered_providers;
912 GetWinsockLayeredServiceProviders(&layered_providers);
913 base::ListValue* layered_provider_list = new base::ListValue();
914 for (size_t i = 0; i < layered_providers.size(); ++i) {
915 base::DictionaryValue* service_dict = new base::DictionaryValue();
916 service_dict->SetString("name", layered_providers[i].name);
917 service_dict->SetInteger("version", layered_providers[i].version);
918 service_dict->SetInteger("chain_length", layered_providers[i].chain_length);
919 service_dict->SetInteger("socket_type", layered_providers[i].socket_type);
920 service_dict->SetInteger("socket_protocol",
921 layered_providers[i].socket_protocol);
922 service_dict->SetString("path", layered_providers[i].path);
924 layered_provider_list->Append(service_dict);
926 service_providers->Set("service_providers", layered_provider_list);
928 WinsockNamespaceProviderList namespace_providers;
929 GetWinsockNamespaceProviders(&namespace_providers);
930 base::ListValue* namespace_list = new base::ListValue;
931 for (size_t i = 0; i < namespace_providers.size(); ++i) {
932 base::DictionaryValue* namespace_dict = new base::DictionaryValue();
933 namespace_dict->SetString("name", namespace_providers[i].name);
934 namespace_dict->SetBoolean("active", namespace_providers[i].active);
935 namespace_dict->SetInteger("version", namespace_providers[i].version);
936 namespace_dict->SetInteger("type", namespace_providers[i].type);
938 namespace_list->Append(namespace_dict);
940 service_providers->Set("namespace_providers", namespace_list);
942 SendJavascriptCommand("receivedServiceProviders", service_providers);
944 #endif
946 #if defined(OS_CHROMEOS)
947 void NetInternalsMessageHandler::ImportONCFileToNSSDB(
948 const std::string& onc_blob,
949 const std::string& passcode,
950 net::NSSCertDatabase* nssdb) {
951 const user_manager::User* user =
952 chromeos::ProfileHelper::Get()->GetUserByProfile(
953 Profile::FromWebUI(web_ui()));
955 if (!user) {
956 std::string error = "User not found.";
957 SendJavascriptCommand("receivedONCFileParse", new base::StringValue(error));
958 return;
961 std::string error;
962 onc::ONCSource onc_source = onc::ONC_SOURCE_USER_IMPORT;
963 base::ListValue network_configs;
964 base::DictionaryValue global_network_config;
965 base::ListValue certificates;
966 if (!chromeos::onc::ParseAndValidateOncForImport(onc_blob,
967 onc_source,
968 passcode,
969 &network_configs,
970 &global_network_config,
971 &certificates)) {
972 error = "Errors occurred during the ONC parsing. ";
975 std::string network_error;
976 chromeos::onc::ImportNetworksForUser(user, network_configs, &network_error);
977 if (!network_error.empty())
978 error += network_error;
980 chromeos::onc::CertificateImporterImpl cert_importer(
981 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), nssdb);
982 cert_importer.ImportCertificates(
983 certificates,
984 onc_source,
985 base::Bind(&NetInternalsMessageHandler::OnCertificatesImported,
986 AsWeakPtr(),
987 error));
990 void NetInternalsMessageHandler::OnCertificatesImported(
991 const std::string& previous_error,
992 bool success,
993 const net::CertificateList& /* unused onc_trusted_certificates */) {
994 std::string error = previous_error;
995 if (!success)
996 error += "Some certificates couldn't be imported. ";
998 SendJavascriptCommand("receivedONCFileParse", new base::StringValue(error));
1001 void NetInternalsMessageHandler::OnImportONCFile(
1002 const base::ListValue* list) {
1003 std::string onc_blob;
1004 std::string passcode;
1005 if (list->GetSize() != 2 ||
1006 !list->GetString(0, &onc_blob) ||
1007 !list->GetString(1, &passcode)) {
1008 NOTREACHED();
1011 GetNSSCertDatabaseForProfile(
1012 Profile::FromWebUI(web_ui()),
1013 base::Bind(&NetInternalsMessageHandler::ImportONCFileToNSSDB, AsWeakPtr(),
1014 onc_blob, passcode));
1017 void NetInternalsMessageHandler::OnStoreDebugLogs(const base::ListValue* list) {
1018 DCHECK(list);
1020 SendJavascriptCommand("receivedStoreDebugLogs",
1021 new base::StringValue("Creating log file..."));
1022 Profile* profile = Profile::FromWebUI(web_ui());
1023 const DownloadPrefs* const prefs = DownloadPrefs::FromBrowserContext(profile);
1024 base::FilePath path = prefs->DownloadPath();
1025 if (file_manager::util::IsUnderNonNativeLocalPath(profile, path))
1026 path = prefs->GetDefaultDownloadDirectoryForProfile();
1027 chromeos::DebugLogWriter::StoreLogs(
1028 path,
1029 true, // should_compress
1030 base::Bind(&NetInternalsMessageHandler::OnStoreDebugLogsCompleted,
1031 AsWeakPtr()));
1034 void NetInternalsMessageHandler::OnStoreDebugLogsCompleted(
1035 const base::FilePath& log_path, bool succeeded) {
1036 std::string status;
1037 if (succeeded)
1038 status = "Created log file: " + log_path.BaseName().AsUTF8Unsafe();
1039 else
1040 status = "Failed to create log file";
1041 SendJavascriptCommand("receivedStoreDebugLogs",
1042 new base::StringValue(status));
1045 void NetInternalsMessageHandler::OnSetNetworkDebugMode(
1046 const base::ListValue* list) {
1047 std::string subsystem;
1048 if (list->GetSize() != 1 || !list->GetString(0, &subsystem))
1049 NOTREACHED();
1050 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
1051 SetDebugMode(
1052 subsystem,
1053 base::Bind(
1054 &NetInternalsMessageHandler::OnSetNetworkDebugModeCompleted,
1055 AsWeakPtr(),
1056 subsystem));
1059 void NetInternalsMessageHandler::OnSetNetworkDebugModeCompleted(
1060 const std::string& subsystem,
1061 bool succeeded) {
1062 std::string status;
1063 if (succeeded)
1064 status = "Debug mode is changed to " + subsystem;
1065 else
1066 status = "Failed to change debug mode to " + subsystem;
1067 SendJavascriptCommand("receivedSetNetworkDebugMode",
1068 new base::StringValue(status));
1070 #endif // defined(OS_CHROMEOS)
1072 void NetInternalsMessageHandler::IOThreadImpl::OnSetCaptureMode(
1073 const base::ListValue* list) {
1074 std::string capture_mode_string;
1075 if (!list->GetString(0, &capture_mode_string)) {
1076 NOTREACHED();
1077 return;
1080 // Convert the string to a NetLogCaptureMode.
1081 net::NetLogCaptureMode mode;
1082 if (capture_mode_string == "IncludeSocketBytes") {
1083 mode = net::NetLogCaptureMode::IncludeSocketBytes();
1084 } else if (capture_mode_string == "IncludeCookiesAndCredentials") {
1085 mode = net::NetLogCaptureMode::IncludeCookiesAndCredentials();
1086 } else {
1087 NOTREACHED();
1090 net_log()->SetObserverCaptureMode(this, mode);
1093 // Note that unlike other methods of IOThreadImpl, this function
1094 // can be called from ANY THREAD.
1095 void NetInternalsMessageHandler::IOThreadImpl::OnAddEntry(
1096 const net::NetLog::Entry& entry) {
1097 BrowserThread::PostTask(
1098 BrowserThread::IO, FROM_HERE,
1099 base::Bind(&IOThreadImpl::AddEntryToQueue, this, entry.ToValue()));
1102 // Note that this can be called from ANY THREAD.
1103 void NetInternalsMessageHandler::IOThreadImpl::SendJavascriptCommand(
1104 const std::string& command,
1105 base::Value* arg) {
1106 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
1107 if (handler_.get() && !was_webui_deleted_) {
1108 // We check |handler_| in case it was deleted on the UI thread earlier
1109 // while we were running on the IO thread.
1110 handler_->SendJavascriptCommand(command, arg);
1111 } else {
1112 delete arg;
1114 return;
1117 if (!BrowserThread::PostTask(
1118 BrowserThread::UI, FROM_HERE,
1119 base::Bind(&IOThreadImpl::SendJavascriptCommand, this, command, arg))) {
1120 // Failed posting the task, avoid leaking.
1121 delete arg;
1125 void NetInternalsMessageHandler::IOThreadImpl::AddEntryToQueue(
1126 base::Value* entry) {
1127 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1128 if (!pending_entries_.get()) {
1129 pending_entries_.reset(new base::ListValue());
1130 BrowserThread::PostDelayedTask(
1131 BrowserThread::IO, FROM_HERE,
1132 base::Bind(&IOThreadImpl::PostPendingEntries, this),
1133 base::TimeDelta::FromMilliseconds(kNetLogEventDelayMilliseconds));
1135 pending_entries_->Append(entry);
1138 void NetInternalsMessageHandler::IOThreadImpl::PostPendingEntries() {
1139 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1140 if (pending_entries_.get())
1141 SendJavascriptCommand("receivedLogEntries", pending_entries_.release());
1144 void NetInternalsMessageHandler::IOThreadImpl::PrePopulateEventList() {
1145 // Using a set removes any duplicates.
1146 std::set<net::URLRequestContext*> contexts;
1147 for (ContextGetterList::const_iterator getter = context_getters_.begin();
1148 getter != context_getters_.end(); ++getter) {
1149 contexts.insert((*getter)->GetURLRequestContext());
1151 contexts.insert(io_thread_->globals()->proxy_script_fetcher_context.get());
1152 contexts.insert(io_thread_->globals()->system_request_context.get());
1154 // Add entries for ongoing network objects.
1155 CreateNetLogEntriesForActiveObjects(contexts, this);
1158 void NetInternalsMessageHandler::IOThreadImpl::SendNetInfo(int info_sources) {
1159 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1160 SendJavascriptCommand(
1161 "receivedNetInfo",
1162 net::GetNetInfo(GetMainContext(), info_sources).release());
1165 } // namespace
1168 ////////////////////////////////////////////////////////////////////////////////
1170 // NetInternalsUI
1172 ////////////////////////////////////////////////////////////////////////////////
1174 // static
1175 base::Value* NetInternalsUI::GetConstants() {
1176 scoped_ptr<base::DictionaryValue> constants_dict = net::GetNetConstants();
1177 DCHECK(constants_dict);
1179 // Add a dictionary with the version of the client and its command line
1180 // arguments.
1182 base::DictionaryValue* dict = new base::DictionaryValue();
1184 chrome::VersionInfo version_info;
1186 // We have everything we need to send the right values.
1187 dict->SetString("name", version_info.Name());
1188 dict->SetString("version", version_info.Version());
1189 dict->SetString("cl", version_info.LastChange());
1190 dict->SetString("version_mod",
1191 chrome::VersionInfo::GetVersionStringModifier());
1192 dict->SetString("official",
1193 version_info.IsOfficialBuild() ? "official" : "unofficial");
1194 dict->SetString("os_type", version_info.OSType());
1195 dict->SetString(
1196 "command_line",
1197 base::CommandLine::ForCurrentProcess()->GetCommandLineString());
1199 constants_dict->Set("clientInfo", dict);
1201 data_reduction_proxy::DataReductionProxyEventStore::AddConstants(
1202 constants_dict.get());
1205 return constants_dict.release();
1208 NetInternalsUI::NetInternalsUI(content::WebUI* web_ui)
1209 : WebUIController(web_ui) {
1210 web_ui->AddMessageHandler(new NetInternalsMessageHandler());
1212 // Set up the chrome://net-internals/ source.
1213 Profile* profile = Profile::FromWebUI(web_ui);
1214 content::WebUIDataSource::Add(profile, CreateNetInternalsHTMLSource());