Home | History | Annotate | Download | only in net_internals
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
      6 
      7 #include <algorithm>
      8 #include <list>
      9 #include <string>
     10 #include <utility>
     11 #include <vector>
     12 
     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"
     72 
     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
     86 
     87 #if defined(OS_WIN)
     88 #include "chrome/browser/net/service_providers_win.h"
     89 #endif
     90 
     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
     98 
     99 using base::StringValue;
    100 using content::BrowserThread;
    101 using content::WebContents;
    102 using content::WebUIMessageHandler;
    103 
    104 namespace {
    105 
    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;
    110 
    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();
    115 }
    116 
    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();
    123   }
    124   return str;
    125 }
    126 
    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);
    132 
    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;
    144     }
    145     if (!hash.FromString(hash_str))
    146       return false;
    147     hashes->push_back(hash);
    148   }
    149   return true;
    150 }
    151 
    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();
    157 }
    158 
    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();
    163 }
    164 
    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;
    169 
    170   net::HttpCache* http_cache = context->http_transaction_factory()->GetCache();
    171   if (!http_cache)
    172     return NULL;
    173 
    174   return http_cache->GetCurrentBackend();
    175 }
    176 
    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;
    183 
    184   return context->http_transaction_factory()->GetSession();
    185 }
    186 
    187 base::Value* ExperimentToValue(const ConnectionTester::Experiment& experiment) {
    188   base::DictionaryValue* dict = new base::DictionaryValue();
    189 
    190   if (experiment.url.is_valid())
    191     dict->SetString("url", experiment.url.spec());
    192 
    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;
    200 }
    201 
    202 content::WebUIDataSource* CreateNetInternalsHTMLSource() {
    203   content::WebUIDataSource* source =
    204       content::WebUIDataSource::Create(chrome::kChromeUINetInternalsHost);
    205 
    206   source->SetUseJsonJSFormatV2();
    207   source->SetDefaultResource(IDR_NET_INTERNALS_INDEX_HTML);
    208   source->AddResourcePath("index.js", IDR_NET_INTERNALS_INDEX_JS);
    209   source->SetJsonPath("strings.js");
    210   return source;
    211 }
    212 
    213 // This class receives javascript messages from the renderer.
    214 // Note that the WebUI infrastructure runs on the UI thread, therefore all of
    215 // this class's methods are expected to run on the UI thread.
    216 //
    217 // Since the network code we want to run lives on the IO thread, we proxy
    218 // almost everything over to NetInternalsMessageHandler::IOThreadImpl, which
    219 // runs on the IO thread.
    220 //
    221 // TODO(eroman): Can we start on the IO thread to begin with?
    222 class NetInternalsMessageHandler
    223     : public WebUIMessageHandler,
    224       public base::SupportsWeakPtr<NetInternalsMessageHandler> {
    225  public:
    226   NetInternalsMessageHandler();
    227   virtual ~NetInternalsMessageHandler();
    228 
    229   // WebUIMessageHandler implementation.
    230   virtual void RegisterMessages() OVERRIDE;
    231 
    232   // Calls g_browser.receive in the renderer, passing in |command| and |arg|.
    233   // Takes ownership of |arg|.  If the renderer is displaying a log file, the
    234   // message will be ignored.
    235   void SendJavascriptCommand(const std::string& command, base::Value* arg);
    236 
    237   // Javascript message handlers.
    238   void OnRendererReady(const base::ListValue* list);
    239   void OnClearBrowserCache(const base::ListValue* list);
    240   void OnGetPrerenderInfo(const base::ListValue* list);
    241   void OnGetHistoricNetworkStats(const base::ListValue* list);
    242   void OnGetExtensionInfo(const base::ListValue* list);
    243 #if defined(OS_CHROMEOS)
    244   void OnRefreshSystemLogs(const base::ListValue* list);
    245   void OnGetSystemLog(const base::ListValue* list);
    246   void OnImportONCFile(const base::ListValue* list);
    247   void OnStoreDebugLogs(const base::ListValue* list);
    248   void OnStoreDebugLogsCompleted(const base::FilePath& log_path,
    249                                  bool succeeded);
    250   void OnSetNetworkDebugMode(const base::ListValue* list);
    251   void OnSetNetworkDebugModeCompleted(const std::string& subsystem,
    252                                       bool succeeded);
    253 
    254   // Callback to |GetNSSCertDatabaseForProfile| used to retrieve the database
    255   // to which user's ONC defined certificates should be imported.
    256   // It parses and imports |onc_blob|.
    257   void ImportONCFileToNSSDB(const std::string& onc_blob,
    258                             const std::string& passcode,
    259                             net::NSSCertDatabase* nssdb);
    260 
    261   // Called back by the CertificateImporter when a certificate import finished.
    262   // |previous_error| contains earlier errors during this import.
    263   void OnCertificatesImported(
    264       const std::string& previous_error,
    265       bool success,
    266       const net::CertificateList& onc_trusted_certificates);
    267 #endif
    268 
    269  private:
    270   class IOThreadImpl;
    271 
    272 #if defined(OS_CHROMEOS)
    273   // Class that is used for getting network related ChromeOS logs.
    274   // Logs are fetched from ChromeOS libcros on user request, and only when we
    275   // don't yet have a copy of logs. If a copy is present, we send back data from
    276   // it, else we save request and answer to it when we get logs from libcros.
    277   // If needed, we also send request for system logs to libcros.
    278   // Logs refresh has to be done explicitly, by deleting old logs and then
    279   // loading them again.
    280   class SystemLogsGetter {
    281    public:
    282     SystemLogsGetter(NetInternalsMessageHandler* handler,
    283                      chromeos::system::SyslogsProvider* syslogs_provider);
    284     ~SystemLogsGetter();
    285 
    286     // Deletes logs copy we currently have, and resets logs_requested and
    287     // logs_received flags.
    288     void DeleteSystemLogs();
    289     // Starts log fetching. If logs copy is present, requested logs are sent
    290     // back.
    291     // If syslogs load request hasn't been sent to libcros yet, we do that now,
    292     // and postpone sending response.
    293     // Request data is specified by args:
    294     //   $1 : key of the log we are interested in.
    295     //   $2 : string used to identify request.
    296     void RequestSystemLog(const base::ListValue* args);
    297     // Requests logs from libcros, but only if we don't have a copy.
    298     void LoadSystemLogs();
    299     // Processes callback from libcros containing system logs. Postponed
    300     // request responses are sent.
    301     void OnSystemLogsLoaded(chromeos::system::LogDictionaryType* sys_info,
    302                             std::string* ignored_content);
    303 
    304    private:
    305     // Struct we save postponed log request in.
    306     struct SystemLogRequest {
    307       std::string log_key;
    308       std::string cell_id;
    309     };
    310 
    311     // Processes request.
    312     void SendLogs(const SystemLogRequest& request);
    313 
    314     NetInternalsMessageHandler* handler_;
    315     chromeos::system::SyslogsProvider* syslogs_provider_;
    316     // List of postponed requests.
    317     std::list<SystemLogRequest> requests_;
    318     scoped_ptr<chromeos::system::LogDictionaryType> logs_;
    319     bool logs_received_;
    320     bool logs_requested_;
    321     base::CancelableTaskTracker tracker_;
    322     // Libcros request task ID.
    323     base::CancelableTaskTracker::TaskId syslogs_task_id_;
    324   };
    325 #endif  // defined(OS_CHROMEOS)
    326 
    327   // This is the "real" message handler, which lives on the IO thread.
    328   scoped_refptr<IOThreadImpl> proxy_;
    329 
    330   base::WeakPtr<prerender::PrerenderManager> prerender_manager_;
    331 
    332 #if defined(OS_CHROMEOS)
    333   // Class that handles getting and filtering system logs.
    334   scoped_ptr<SystemLogsGetter> syslogs_getter_;
    335 #endif
    336 
    337   DISALLOW_COPY_AND_ASSIGN(NetInternalsMessageHandler);
    338 };
    339 
    340 // This class is the "real" message handler. It is allocated and destroyed on
    341 // the UI thread.  With the exception of OnAddEntry, OnWebUIDeleted, and
    342 // SendJavascriptCommand, its methods are all expected to be called from the IO
    343 // thread.  OnAddEntry and SendJavascriptCommand can be called from any thread,
    344 // and OnWebUIDeleted can only be called from the UI thread.
    345 class NetInternalsMessageHandler::IOThreadImpl
    346     : public base::RefCountedThreadSafe<
    347           NetInternalsMessageHandler::IOThreadImpl,
    348           BrowserThread::DeleteOnUIThread>,
    349       public net::NetLog::ThreadSafeObserver,
    350       public ConnectionTester::Delegate {
    351  public:
    352   // Type for methods that can be used as MessageHandler callbacks.
    353   typedef void (IOThreadImpl::*MessageHandler)(const base::ListValue*);
    354 
    355   // Creates a proxy for |handler| that will live on the IO thread.
    356   // |handler| is a weak pointer, since it is possible for the
    357   // WebUIMessageHandler to be deleted on the UI thread while we were executing
    358   // on the IO thread. |io_thread| is the global IOThread (it is passed in as
    359   // an argument since we need to grab it from the UI thread).
    360   IOThreadImpl(
    361       const base::WeakPtr<NetInternalsMessageHandler>& handler,
    362       IOThread* io_thread,
    363       net::URLRequestContextGetter* main_context_getter);
    364 
    365   // Called on UI thread just after creation, to add a ContextGetter to
    366   // |context_getters_|.
    367   void AddRequestContextGetter(net::URLRequestContextGetter* context_getter);
    368 
    369   // Helper method to enable a callback that will be executed on the IO thread.
    370   static void CallbackHelper(MessageHandler method,
    371                              scoped_refptr<IOThreadImpl> io_thread,
    372                              const base::ListValue* list);
    373 
    374   // Called once the WebUI has been deleted (i.e. renderer went away), on the
    375   // IO thread.
    376   void Detach();
    377 
    378   // Called when the WebUI is deleted.  Prevents calling Javascript functions
    379   // afterwards.  Called on UI thread.
    380   void OnWebUIDeleted();
    381 
    382   //--------------------------------
    383   // Javascript message handlers:
    384   //--------------------------------
    385 
    386   void OnRendererReady(const base::ListValue* list);
    387 
    388   void OnGetProxySettings(const base::ListValue* list);
    389   void OnReloadProxySettings(const base::ListValue* list);
    390   void OnGetBadProxies(const base::ListValue* list);
    391   void OnClearBadProxies(const base::ListValue* list);
    392   void OnGetHostResolverInfo(const base::ListValue* list);
    393   void OnClearHostResolverCache(const base::ListValue* list);
    394   void OnEnableIPv6(const base::ListValue* list);
    395   void OnStartConnectionTests(const base::ListValue* list);
    396   void OnHSTSQuery(const base::ListValue* list);
    397   void OnHSTSAdd(const base::ListValue* list);
    398   void OnHSTSDelete(const base::ListValue* list);
    399   void OnGetHttpCacheInfo(const base::ListValue* list);
    400   void OnGetSocketPoolInfo(const base::ListValue* list);
    401   void OnGetSessionNetworkStats(const base::ListValue* list);
    402   void OnCloseIdleSockets(const base::ListValue* list);
    403   void OnFlushSocketPools(const base::ListValue* list);
    404   void OnGetSpdySessionInfo(const base::ListValue* list);
    405   void OnGetSpdyStatus(const base::ListValue* list);
    406   void OnGetSpdyAlternateProtocolMappings(const base::ListValue* list);
    407   void OnGetQuicInfo(const base::ListValue* list);
    408 #if defined(OS_WIN)
    409   void OnGetServiceProviders(const base::ListValue* list);
    410 #endif
    411   void OnSetLogLevel(const base::ListValue* list);
    412 
    413   // ChromeNetLog::ThreadSafeObserver implementation:
    414   virtual void OnAddEntry(const net::NetLog::Entry& entry) OVERRIDE;
    415 
    416   // ConnectionTester::Delegate implementation:
    417   virtual void OnStartConnectionTestSuite() OVERRIDE;
    418   virtual void OnStartConnectionTestExperiment(
    419       const ConnectionTester::Experiment& experiment) OVERRIDE;
    420   virtual void OnCompletedConnectionTestExperiment(
    421       const ConnectionTester::Experiment& experiment,
    422       int result) OVERRIDE;
    423   virtual void OnCompletedConnectionTestSuite() OVERRIDE;
    424 
    425   // Helper that calls g_browser.receive in the renderer, passing in |command|
    426   // and |arg|.  Takes ownership of |arg|.  If the renderer is displaying a log
    427   // file, the message will be ignored.  Note that this can be called from any
    428   // thread.
    429   void SendJavascriptCommand(const std::string& command, base::Value* arg);
    430 
    431  private:
    432   friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
    433   friend class base::DeleteHelper<IOThreadImpl>;
    434 
    435   typedef std::list<scoped_refptr<net::URLRequestContextGetter> >
    436       ContextGetterList;
    437 
    438   virtual ~IOThreadImpl();
    439 
    440   // Adds |entry| to the queue of pending log entries to be sent to the page via
    441   // Javascript.  Must be called on the IO Thread.  Also creates a delayed task
    442   // that will call PostPendingEntries, if there isn't one already.
    443   void AddEntryToQueue(base::Value* entry);
    444 
    445   // Sends all pending entries to the page via Javascript, and clears the list
    446   // of pending entries.  Sending multiple entries at once results in a
    447   // significant reduction of CPU usage when a lot of events are happening.
    448   // Must be called on the IO Thread.
    449   void PostPendingEntries();
    450 
    451   // Adds entries with the states of ongoing URL requests.
    452   void PrePopulateEventList();
    453 
    454   net::URLRequestContext* GetMainContext() {
    455     return main_context_getter_->GetURLRequestContext();
    456   }
    457 
    458   // Pointer to the UI-thread message handler. Only access this from
    459   // the UI thread.
    460   base::WeakPtr<NetInternalsMessageHandler> handler_;
    461 
    462   // The global IOThread, which contains the global NetLog to observer.
    463   IOThread* io_thread_;
    464 
    465   // The main URLRequestContextGetter for the tab's profile.
    466   scoped_refptr<net::URLRequestContextGetter> main_context_getter_;
    467 
    468   // Helper that runs the suite of connection tests.
    469   scoped_ptr<ConnectionTester> connection_tester_;
    470 
    471   // True if the Web UI has been deleted.  This is used to prevent calling
    472   // Javascript functions after the Web UI is destroyed.  On refresh, the
    473   // messages can end up being sent to the refreshed page, causing duplicate
    474   // or partial entries.
    475   //
    476   // This is only read and written to on the UI thread.
    477   bool was_webui_deleted_;
    478 
    479   // Log entries that have yet to be passed along to Javascript page.  Non-NULL
    480   // when and only when there is a pending delayed task to call
    481   // PostPendingEntries.  Read and written to exclusively on the IO Thread.
    482   scoped_ptr<base::ListValue> pending_entries_;
    483 
    484   // Used for getting current status of URLRequests when net-internals is
    485   // opened.  |main_context_getter_| is automatically added on construction.
    486   // Duplicates are allowed.
    487   ContextGetterList context_getters_;
    488 
    489   DISALLOW_COPY_AND_ASSIGN(IOThreadImpl);
    490 };
    491 
    492 ////////////////////////////////////////////////////////////////////////////////
    493 //
    494 // NetInternalsMessageHandler
    495 //
    496 ////////////////////////////////////////////////////////////////////////////////
    497 
    498 NetInternalsMessageHandler::NetInternalsMessageHandler() {}
    499 
    500 NetInternalsMessageHandler::~NetInternalsMessageHandler() {
    501   if (proxy_.get()) {
    502     proxy_.get()->OnWebUIDeleted();
    503     // Notify the handler on the IO thread that the renderer is gone.
    504     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
    505                             base::Bind(&IOThreadImpl::Detach, proxy_.get()));
    506   }
    507 }
    508 
    509 void NetInternalsMessageHandler::RegisterMessages() {
    510   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    511 
    512   Profile* profile = Profile::FromWebUI(web_ui());
    513 
    514   proxy_ = new IOThreadImpl(this->AsWeakPtr(), g_browser_process->io_thread(),
    515                             profile->GetRequestContext());
    516   proxy_->AddRequestContextGetter(profile->GetMediaRequestContext());
    517   proxy_->AddRequestContextGetter(profile->GetRequestContextForExtensions());
    518 #if defined(OS_CHROMEOS)
    519   syslogs_getter_.reset(new SystemLogsGetter(this,
    520       chromeos::system::SyslogsProvider::GetInstance()));
    521 #endif
    522 
    523   prerender::PrerenderManager* prerender_manager =
    524       prerender::PrerenderManagerFactory::GetForProfile(profile);
    525   if (prerender_manager) {
    526     prerender_manager_ = prerender_manager->AsWeakPtr();
    527   } else {
    528     prerender_manager_ = base::WeakPtr<prerender::PrerenderManager>();
    529   }
    530 
    531   web_ui()->RegisterMessageCallback(
    532       "notifyReady",
    533       base::Bind(&NetInternalsMessageHandler::OnRendererReady,
    534                  base::Unretained(this)));
    535   web_ui()->RegisterMessageCallback(
    536       "getProxySettings",
    537       base::Bind(&IOThreadImpl::CallbackHelper,
    538                  &IOThreadImpl::OnGetProxySettings, proxy_));
    539   web_ui()->RegisterMessageCallback(
    540       "reloadProxySettings",
    541       base::Bind(&IOThreadImpl::CallbackHelper,
    542                  &IOThreadImpl::OnReloadProxySettings, proxy_));
    543   web_ui()->RegisterMessageCallback(
    544       "getBadProxies",
    545       base::Bind(&IOThreadImpl::CallbackHelper,
    546                  &IOThreadImpl::OnGetBadProxies, proxy_));
    547   web_ui()->RegisterMessageCallback(
    548       "clearBadProxies",
    549       base::Bind(&IOThreadImpl::CallbackHelper,
    550                  &IOThreadImpl::OnClearBadProxies, proxy_));
    551   web_ui()->RegisterMessageCallback(
    552       "getHostResolverInfo",
    553       base::Bind(&IOThreadImpl::CallbackHelper,
    554                  &IOThreadImpl::OnGetHostResolverInfo, proxy_));
    555   web_ui()->RegisterMessageCallback(
    556       "clearHostResolverCache",
    557       base::Bind(&IOThreadImpl::CallbackHelper,
    558                  &IOThreadImpl::OnClearHostResolverCache, proxy_));
    559   web_ui()->RegisterMessageCallback(
    560       "enableIPv6",
    561       base::Bind(&IOThreadImpl::CallbackHelper,
    562                  &IOThreadImpl::OnEnableIPv6, proxy_));
    563   web_ui()->RegisterMessageCallback(
    564       "startConnectionTests",
    565       base::Bind(&IOThreadImpl::CallbackHelper,
    566                  &IOThreadImpl::OnStartConnectionTests, proxy_));
    567   web_ui()->RegisterMessageCallback(
    568       "hstsQuery",
    569       base::Bind(&IOThreadImpl::CallbackHelper,
    570                  &IOThreadImpl::OnHSTSQuery, proxy_));
    571   web_ui()->RegisterMessageCallback(
    572       "hstsAdd",
    573       base::Bind(&IOThreadImpl::CallbackHelper,
    574                  &IOThreadImpl::OnHSTSAdd, proxy_));
    575   web_ui()->RegisterMessageCallback(
    576       "hstsDelete",
    577       base::Bind(&IOThreadImpl::CallbackHelper,
    578                  &IOThreadImpl::OnHSTSDelete, proxy_));
    579   web_ui()->RegisterMessageCallback(
    580       "getHttpCacheInfo",
    581       base::Bind(&IOThreadImpl::CallbackHelper,
    582                  &IOThreadImpl::OnGetHttpCacheInfo, proxy_));
    583   web_ui()->RegisterMessageCallback(
    584       "getSocketPoolInfo",
    585       base::Bind(&IOThreadImpl::CallbackHelper,
    586                  &IOThreadImpl::OnGetSocketPoolInfo, proxy_));
    587   web_ui()->RegisterMessageCallback(
    588       "getSessionNetworkStats",
    589       base::Bind(&IOThreadImpl::CallbackHelper,
    590                  &IOThreadImpl::OnGetSessionNetworkStats, proxy_));
    591   web_ui()->RegisterMessageCallback(
    592       "closeIdleSockets",
    593       base::Bind(&IOThreadImpl::CallbackHelper,
    594                  &IOThreadImpl::OnCloseIdleSockets, proxy_));
    595   web_ui()->RegisterMessageCallback(
    596       "flushSocketPools",
    597       base::Bind(&IOThreadImpl::CallbackHelper,
    598                  &IOThreadImpl::OnFlushSocketPools, proxy_));
    599   web_ui()->RegisterMessageCallback(
    600       "getSpdySessionInfo",
    601       base::Bind(&IOThreadImpl::CallbackHelper,
    602                  &IOThreadImpl::OnGetSpdySessionInfo, proxy_));
    603   web_ui()->RegisterMessageCallback(
    604       "getSpdyStatus",
    605       base::Bind(&IOThreadImpl::CallbackHelper,
    606                  &IOThreadImpl::OnGetSpdyStatus, proxy_));
    607   web_ui()->RegisterMessageCallback(
    608       "getSpdyAlternateProtocolMappings",
    609       base::Bind(&IOThreadImpl::CallbackHelper,
    610                  &IOThreadImpl::OnGetSpdyAlternateProtocolMappings, proxy_));
    611   web_ui()->RegisterMessageCallback(
    612       "getQuicInfo",
    613       base::Bind(&IOThreadImpl::CallbackHelper,
    614                  &IOThreadImpl::OnGetQuicInfo, proxy_));
    615 #if defined(OS_WIN)
    616   web_ui()->RegisterMessageCallback(
    617       "getServiceProviders",
    618       base::Bind(&IOThreadImpl::CallbackHelper,
    619                  &IOThreadImpl::OnGetServiceProviders, proxy_));
    620 #endif
    621 
    622   web_ui()->RegisterMessageCallback(
    623       "setLogLevel",
    624       base::Bind(&IOThreadImpl::CallbackHelper,
    625                  &IOThreadImpl::OnSetLogLevel, proxy_));
    626   web_ui()->RegisterMessageCallback(
    627       "clearBrowserCache",
    628       base::Bind(&NetInternalsMessageHandler::OnClearBrowserCache,
    629                  base::Unretained(this)));
    630   web_ui()->RegisterMessageCallback(
    631       "getPrerenderInfo",
    632       base::Bind(&NetInternalsMessageHandler::OnGetPrerenderInfo,
    633                  base::Unretained(this)));
    634   web_ui()->RegisterMessageCallback(
    635       "getHistoricNetworkStats",
    636       base::Bind(&NetInternalsMessageHandler::OnGetHistoricNetworkStats,
    637                  base::Unretained(this)));
    638   web_ui()->RegisterMessageCallback(
    639       "getExtensionInfo",
    640       base::Bind(&NetInternalsMessageHandler::OnGetExtensionInfo,
    641                  base::Unretained(this)));
    642 #if defined(OS_CHROMEOS)
    643   web_ui()->RegisterMessageCallback(
    644       "refreshSystemLogs",
    645       base::Bind(&NetInternalsMessageHandler::OnRefreshSystemLogs,
    646                  base::Unretained(this)));
    647   web_ui()->RegisterMessageCallback(
    648       "getSystemLog",
    649       base::Bind(&NetInternalsMessageHandler::OnGetSystemLog,
    650                  base::Unretained(this)));
    651   web_ui()->RegisterMessageCallback(
    652       "importONCFile",
    653       base::Bind(&NetInternalsMessageHandler::OnImportONCFile,
    654                  base::Unretained(this)));
    655   web_ui()->RegisterMessageCallback(
    656       "storeDebugLogs",
    657       base::Bind(&NetInternalsMessageHandler::OnStoreDebugLogs,
    658                  base::Unretained(this)));
    659   web_ui()->RegisterMessageCallback(
    660       "setNetworkDebugMode",
    661       base::Bind(&NetInternalsMessageHandler::OnSetNetworkDebugMode,
    662                  base::Unretained(this)));
    663 #endif
    664 }
    665 
    666 void NetInternalsMessageHandler::SendJavascriptCommand(
    667     const std::string& command,
    668     base::Value* arg) {
    669   scoped_ptr<base::Value> command_value(new base::StringValue(command));
    670   scoped_ptr<base::Value> value(arg);
    671   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    672   if (value.get()) {
    673     web_ui()->CallJavascriptFunction("g_browser.receive",
    674                                      *command_value.get(),
    675                                      *value.get());
    676   } else {
    677     web_ui()->CallJavascriptFunction("g_browser.receive",
    678                                      *command_value.get());
    679   }
    680 }
    681 
    682 void NetInternalsMessageHandler::OnRendererReady(const base::ListValue* list) {
    683   IOThreadImpl::CallbackHelper(&IOThreadImpl::OnRendererReady, proxy_, list);
    684 }
    685 
    686 void NetInternalsMessageHandler::OnClearBrowserCache(
    687     const base::ListValue* list) {
    688   BrowsingDataRemover* remover = BrowsingDataRemover::CreateForUnboundedRange(
    689       Profile::FromWebUI(web_ui()));
    690   remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
    691                   BrowsingDataHelper::UNPROTECTED_WEB);
    692   // BrowsingDataRemover deletes itself.
    693 }
    694 
    695 void NetInternalsMessageHandler::OnGetPrerenderInfo(
    696     const base::ListValue* list) {
    697   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    698 
    699   base::DictionaryValue* value = NULL;
    700   prerender::PrerenderManager* prerender_manager = prerender_manager_.get();
    701   if (!prerender_manager) {
    702     value = new base::DictionaryValue();
    703     value->SetBoolean("enabled", false);
    704     value->SetBoolean("omnibox_enabled", false);
    705   } else {
    706     value = prerender_manager->GetAsValue();
    707   }
    708   SendJavascriptCommand("receivedPrerenderInfo", value);
    709 }
    710 
    711 void NetInternalsMessageHandler::OnGetHistoricNetworkStats(
    712     const base::ListValue* list) {
    713   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    714   base::Value* historic_network_info =
    715       ChromeNetworkDelegate::HistoricNetworkStatsInfoToValue();
    716   SendJavascriptCommand("receivedHistoricNetworkStats", historic_network_info);
    717 }
    718 
    719 void NetInternalsMessageHandler::OnGetExtensionInfo(
    720     const base::ListValue* list) {
    721   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    722   base::ListValue* extension_list = new base::ListValue();
    723 #if defined(ENABLE_EXTENSIONS)
    724   Profile* profile = Profile::FromWebUI(web_ui());
    725   extensions::ExtensionSystem* extension_system =
    726       extensions::ExtensionSystem::Get(profile);
    727   if (extension_system) {
    728     ExtensionService* extension_service = extension_system->extension_service();
    729     if (extension_service) {
    730       scoped_ptr<const extensions::ExtensionSet> extensions(
    731           extensions::ExtensionRegistry::Get(profile)
    732               ->GenerateInstalledExtensionsSet());
    733       for (extensions::ExtensionSet::const_iterator it = extensions->begin();
    734            it != extensions->end(); ++it) {
    735         base::DictionaryValue* extension_info = new base::DictionaryValue();
    736         bool enabled = extension_service->IsExtensionEnabled((*it)->id());
    737         extensions::GetExtensionBasicInfo(it->get(), enabled, extension_info);
    738         extension_list->Append(extension_info);
    739       }
    740     }
    741   }
    742 #endif
    743   SendJavascriptCommand("receivedExtensionInfo", extension_list);
    744 }
    745 
    746 #if defined(OS_CHROMEOS)
    747 ////////////////////////////////////////////////////////////////////////////////
    748 //
    749 // NetInternalsMessageHandler::SystemLogsGetter
    750 //
    751 ////////////////////////////////////////////////////////////////////////////////
    752 
    753 NetInternalsMessageHandler::SystemLogsGetter::SystemLogsGetter(
    754     NetInternalsMessageHandler* handler,
    755     chromeos::system::SyslogsProvider* syslogs_provider)
    756     : handler_(handler),
    757       syslogs_provider_(syslogs_provider),
    758       logs_received_(false),
    759       logs_requested_(false) {
    760   if (!syslogs_provider_)
    761     LOG(ERROR) << "System access library not loaded";
    762 }
    763 
    764 NetInternalsMessageHandler::SystemLogsGetter::~SystemLogsGetter() {
    765   DeleteSystemLogs();
    766 }
    767 
    768 void NetInternalsMessageHandler::SystemLogsGetter::DeleteSystemLogs() {
    769   if (syslogs_provider_ && logs_requested_ && !logs_received_) {
    770     tracker_.TryCancel(syslogs_task_id_);
    771   }
    772   logs_requested_ = false;
    773   logs_received_ = false;
    774   logs_.reset();
    775 }
    776 
    777 void NetInternalsMessageHandler::SystemLogsGetter::RequestSystemLog(
    778     const base::ListValue* args) {
    779   if (!logs_requested_) {
    780     DCHECK(!logs_received_);
    781     LoadSystemLogs();
    782   }
    783   SystemLogRequest log_request;
    784   args->GetString(0, &log_request.log_key);
    785   args->GetString(1, &log_request.cell_id);
    786 
    787   if (logs_received_) {
    788     SendLogs(log_request);
    789   } else {
    790     requests_.push_back(log_request);
    791   }
    792 }
    793 
    794 void NetInternalsMessageHandler::SystemLogsGetter::LoadSystemLogs() {
    795   if (logs_requested_ || !syslogs_provider_)
    796     return;
    797   logs_requested_ = true;
    798   syslogs_task_id_ = syslogs_provider_->RequestSyslogs(
    799       false,  // compress logs.
    800       chromeos::system::SyslogsProvider::SYSLOGS_NETWORK,
    801       base::Bind(
    802           &NetInternalsMessageHandler::SystemLogsGetter::OnSystemLogsLoaded,
    803           base::Unretained(this)),
    804       &tracker_);
    805 }
    806 
    807 void NetInternalsMessageHandler::SystemLogsGetter::OnSystemLogsLoaded(
    808     chromeos::system::LogDictionaryType* sys_info,
    809     std::string* ignored_content) {
    810   DCHECK(!ignored_content);
    811   logs_.reset(sys_info);
    812   logs_received_ = true;
    813   for (std::list<SystemLogRequest>::iterator request_it = requests_.begin();
    814        request_it != requests_.end();
    815        ++request_it) {
    816     SendLogs(*request_it);
    817   }
    818   requests_.clear();
    819 }
    820 
    821 void NetInternalsMessageHandler::SystemLogsGetter::SendLogs(
    822     const SystemLogRequest& request) {
    823   base::DictionaryValue* result = new base::DictionaryValue();
    824   chromeos::system::LogDictionaryType::iterator log_it =
    825       logs_->find(request.log_key);
    826   if (log_it != logs_->end()) {
    827     if (!log_it->second.empty()) {
    828       result->SetString("log", log_it->second);
    829     } else {
    830       result->SetString("log", "<no relevant lines found>");
    831     }
    832   } else {
    833     result->SetString("log", "<invalid log name>");
    834   }
    835   result->SetString("cellId", request.cell_id);
    836 
    837   handler_->SendJavascriptCommand("getSystemLogCallback", result);
    838 }
    839 #endif  // defined(OS_CHROMEOS)
    840 
    841 ////////////////////////////////////////////////////////////////////////////////
    842 //
    843 // NetInternalsMessageHandler::IOThreadImpl
    844 //
    845 ////////////////////////////////////////////////////////////////////////////////
    846 
    847 NetInternalsMessageHandler::IOThreadImpl::IOThreadImpl(
    848     const base::WeakPtr<NetInternalsMessageHandler>& handler,
    849     IOThread* io_thread,
    850     net::URLRequestContextGetter* main_context_getter)
    851     : handler_(handler),
    852       io_thread_(io_thread),
    853       main_context_getter_(main_context_getter),
    854       was_webui_deleted_(false) {
    855   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    856   AddRequestContextGetter(main_context_getter);
    857 }
    858 
    859 NetInternalsMessageHandler::IOThreadImpl::~IOThreadImpl() {
    860   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    861 }
    862 
    863 void NetInternalsMessageHandler::IOThreadImpl::AddRequestContextGetter(
    864     net::URLRequestContextGetter* context_getter) {
    865   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    866   context_getters_.push_back(context_getter);
    867 }
    868 
    869 void NetInternalsMessageHandler::IOThreadImpl::CallbackHelper(
    870     MessageHandler method,
    871     scoped_refptr<IOThreadImpl> io_thread,
    872     const base::ListValue* list) {
    873   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    874 
    875   // We need to make a copy of the value in order to pass it over to the IO
    876   // thread. |list_copy| will be deleted when the task is destroyed. The called
    877   // |method| cannot take ownership of |list_copy|.
    878   base::ListValue* list_copy =
    879       (list && list->GetSize()) ? list->DeepCopy() : NULL;
    880 
    881   BrowserThread::PostTask(
    882       BrowserThread::IO, FROM_HERE,
    883       base::Bind(method, io_thread, base::Owned(list_copy)));
    884 }
    885 
    886 void NetInternalsMessageHandler::IOThreadImpl::Detach() {
    887   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    888   // Unregister with network stack to observe events.
    889   if (net_log())
    890     net_log()->RemoveThreadSafeObserver(this);
    891 
    892   // Cancel any in-progress connection tests.
    893   connection_tester_.reset();
    894 }
    895 
    896 void NetInternalsMessageHandler::IOThreadImpl::OnWebUIDeleted() {
    897   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    898   was_webui_deleted_ = true;
    899 }
    900 
    901 void NetInternalsMessageHandler::IOThreadImpl::OnRendererReady(
    902     const base::ListValue* list) {
    903   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    904 
    905   // If we have any pending entries, go ahead and get rid of them, so they won't
    906   // appear before the REQUEST_ALIVE events we add for currently active
    907   // URLRequests.
    908   PostPendingEntries();
    909 
    910   SendJavascriptCommand("receivedConstants", NetInternalsUI::GetConstants());
    911 
    912   // Add entries for ongoing URL requests.
    913   PrePopulateEventList();
    914 
    915   if (!net_log()) {
    916     // Register with network stack to observe events.
    917     io_thread_->net_log()->AddThreadSafeObserver(this,
    918         net::NetLog::LOG_ALL_BUT_BYTES);
    919   }
    920 }
    921 
    922 void NetInternalsMessageHandler::IOThreadImpl::OnGetProxySettings(
    923     const base::ListValue* list) {
    924   DCHECK(!list);
    925   net::ProxyService* proxy_service = GetMainContext()->proxy_service();
    926 
    927   base::DictionaryValue* dict = new base::DictionaryValue();
    928   if (proxy_service->fetched_config().is_valid())
    929     dict->Set("original", proxy_service->fetched_config().ToValue());
    930   if (proxy_service->config().is_valid())
    931     dict->Set("effective", proxy_service->config().ToValue());
    932 
    933   SendJavascriptCommand("receivedProxySettings", dict);
    934 }
    935 
    936 void NetInternalsMessageHandler::IOThreadImpl::OnReloadProxySettings(
    937     const base::ListValue* list) {
    938   DCHECK(!list);
    939   GetMainContext()->proxy_service()->ForceReloadProxyConfig();
    940 
    941   // Cause the renderer to be notified of the new values.
    942   OnGetProxySettings(NULL);
    943 }
    944 
    945 void NetInternalsMessageHandler::IOThreadImpl::OnGetBadProxies(
    946     const base::ListValue* list) {
    947   DCHECK(!list);
    948 
    949   const net::ProxyRetryInfoMap& bad_proxies_map =
    950       GetMainContext()->proxy_service()->proxy_retry_info();
    951 
    952   base::ListValue* dict_list = new base::ListValue();
    953 
    954   for (net::ProxyRetryInfoMap::const_iterator it = bad_proxies_map.begin();
    955        it != bad_proxies_map.end(); ++it) {
    956     const std::string& proxy_uri = it->first;
    957     const net::ProxyRetryInfo& retry_info = it->second;
    958 
    959     base::DictionaryValue* dict = new base::DictionaryValue();
    960     dict->SetString("proxy_uri", proxy_uri);
    961     dict->SetString("bad_until",
    962                     net::NetLog::TickCountToString(retry_info.bad_until));
    963 
    964     dict_list->Append(dict);
    965   }
    966 
    967   SendJavascriptCommand("receivedBadProxies", dict_list);
    968 }
    969 
    970 void NetInternalsMessageHandler::IOThreadImpl::OnClearBadProxies(
    971     const base::ListValue* list) {
    972   DCHECK(!list);
    973   GetMainContext()->proxy_service()->ClearBadProxiesCache();
    974 
    975   // Cause the renderer to be notified of the new values.
    976   OnGetBadProxies(NULL);
    977 }
    978 
    979 void NetInternalsMessageHandler::IOThreadImpl::OnGetHostResolverInfo(
    980     const base::ListValue* list) {
    981   DCHECK(!list);
    982   net::URLRequestContext* context = GetMainContext();
    983   net::HostCache* cache = GetHostResolverCache(context);
    984 
    985   if (!cache) {
    986     SendJavascriptCommand("receivedHostResolverInfo", NULL);
    987     return;
    988   }
    989 
    990   base::DictionaryValue* dict = new base::DictionaryValue();
    991 
    992   base::Value* dns_config = context->host_resolver()->GetDnsConfigAsValue();
    993   if (dns_config)
    994     dict->Set("dns_config", dns_config);
    995 
    996   dict->SetInteger(
    997       "default_address_family",
    998       static_cast<int>(context->host_resolver()->GetDefaultAddressFamily()));
    999 
   1000   base::DictionaryValue* cache_info_dict = new base::DictionaryValue();
   1001 
   1002   cache_info_dict->SetInteger(
   1003       "capacity",
   1004       static_cast<int>(cache->max_entries()));
   1005 
   1006   base::ListValue* entry_list = new base::ListValue();
   1007 
   1008   net::HostCache::EntryMap::Iterator it(cache->entries());
   1009   for (; it.HasNext(); it.Advance()) {
   1010     const net::HostCache::Key& key = it.key();
   1011     const net::HostCache::Entry& entry = it.value();
   1012 
   1013     base::DictionaryValue* entry_dict = new base::DictionaryValue();
   1014 
   1015     entry_dict->SetString("hostname", key.hostname);
   1016     entry_dict->SetInteger("address_family",
   1017         static_cast<int>(key.address_family));
   1018     entry_dict->SetString("expiration",
   1019                           net::NetLog::TickCountToString(it.expiration()));
   1020 
   1021     if (entry.error != net::OK) {
   1022       entry_dict->SetInteger("error", entry.error);
   1023     } else {
   1024       // Append all of the resolved addresses.
   1025       base::ListValue* address_list = new base::ListValue();
   1026       for (size_t i = 0; i < entry.addrlist.size(); ++i) {
   1027         address_list->AppendString(entry.addrlist[i].ToStringWithoutPort());
   1028       }
   1029       entry_dict->Set("addresses", address_list);
   1030     }
   1031 
   1032     entry_list->Append(entry_dict);
   1033   }
   1034 
   1035   cache_info_dict->Set("entries", entry_list);
   1036   dict->Set("cache", cache_info_dict);
   1037 
   1038   SendJavascriptCommand("receivedHostResolverInfo", dict);
   1039 }
   1040 
   1041 void NetInternalsMessageHandler::IOThreadImpl::OnClearHostResolverCache(
   1042     const base::ListValue* list) {
   1043   DCHECK(!list);
   1044   net::HostCache* cache = GetHostResolverCache(GetMainContext());
   1045 
   1046   if (cache)
   1047     cache->clear();
   1048 
   1049   // Cause the renderer to be notified of the new values.
   1050   OnGetHostResolverInfo(NULL);
   1051 }
   1052 
   1053 void NetInternalsMessageHandler::IOThreadImpl::OnEnableIPv6(
   1054     const base::ListValue* list) {
   1055   DCHECK(!list);
   1056   net::HostResolver* host_resolver = GetMainContext()->host_resolver();
   1057 
   1058   host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_UNSPECIFIED);
   1059 
   1060   // Cause the renderer to be notified of the new value.
   1061   OnGetHostResolverInfo(NULL);
   1062 }
   1063 
   1064 void NetInternalsMessageHandler::IOThreadImpl::OnStartConnectionTests(
   1065     const base::ListValue* list) {
   1066   // |value| should be: [<URL to test>].
   1067   base::string16 url_str;
   1068   CHECK(list->GetString(0, &url_str));
   1069 
   1070   // Try to fix-up the user provided URL into something valid.
   1071   // For example, turn "www.google.com" into "http://www.google.com".
   1072   GURL url(url_fixer::FixupURL(base::UTF16ToUTF8(url_str), std::string()));
   1073 
   1074   connection_tester_.reset(new ConnectionTester(
   1075       this,
   1076       io_thread_->globals()->proxy_script_fetcher_context.get(),
   1077       net_log()));
   1078   connection_tester_->RunAllTests(url);
   1079 }
   1080 
   1081 void NetInternalsMessageHandler::IOThreadImpl::OnHSTSQuery(
   1082     const base::ListValue* list) {
   1083   // |list| should be: [<domain to query>].
   1084   std::string domain;
   1085   CHECK(list->GetString(0, &domain));
   1086   base::DictionaryValue* result = new base::DictionaryValue();
   1087 
   1088   if (!base::IsStringASCII(domain)) {
   1089     result->SetString("error", "non-ASCII domain name");
   1090   } else {
   1091     net::TransportSecurityState* transport_security_state =
   1092         GetMainContext()->transport_security_state();
   1093     if (!transport_security_state) {
   1094       result->SetString("error", "no TransportSecurityState active");
   1095     } else {
   1096       net::TransportSecurityState::DomainState static_state;
   1097       const bool found_static = transport_security_state->GetStaticDomainState(
   1098           domain, &static_state);
   1099       if (found_static) {
   1100         result->SetBoolean("has_static_sts",
   1101                            found_static && static_state.ShouldUpgradeToSSL());
   1102         result->SetInteger("static_upgrade_mode",
   1103                            static_cast<int>(static_state.sts.upgrade_mode));
   1104         result->SetBoolean("static_sts_include_subdomains",
   1105                            static_state.sts.include_subdomains);
   1106         result->SetDouble("static_sts_observed",
   1107                           static_state.sts.last_observed.ToDoubleT());
   1108         result->SetDouble("static_sts_expiry",
   1109                           static_state.sts.expiry.ToDoubleT());
   1110         result->SetBoolean("has_static_pkp",
   1111                            found_static && static_state.HasPublicKeyPins());
   1112         result->SetBoolean("static_pkp_include_subdomains",
   1113                            static_state.pkp.include_subdomains);
   1114         result->SetDouble("static_pkp_observed",
   1115                           static_state.pkp.last_observed.ToDoubleT());
   1116         result->SetDouble("static_pkp_expiry",
   1117                           static_state.pkp.expiry.ToDoubleT());
   1118         result->SetString("static_spki_hashes",
   1119                           HashesToBase64String(static_state.pkp.spki_hashes));
   1120       }
   1121 
   1122       net::TransportSecurityState::DomainState dynamic_state;
   1123       const bool found_dynamic =
   1124           transport_security_state->GetDynamicDomainState(domain,
   1125                                                           &dynamic_state);
   1126       if (found_dynamic) {
   1127         result->SetInteger("dynamic_upgrade_mode",
   1128                            static_cast<int>(dynamic_state.sts.upgrade_mode));
   1129         result->SetBoolean("dynamic_sts_include_subdomains",
   1130                            dynamic_state.sts.include_subdomains);
   1131         result->SetBoolean("dynamic_pkp_include_subdomains",
   1132                            dynamic_state.pkp.include_subdomains);
   1133         result->SetDouble("dynamic_sts_observed",
   1134                           dynamic_state.sts.last_observed.ToDoubleT());
   1135         result->SetDouble("dynamic_pkp_observed",
   1136                           dynamic_state.pkp.last_observed.ToDoubleT());
   1137         result->SetDouble("dynamic_sts_expiry",
   1138                           dynamic_state.sts.expiry.ToDoubleT());
   1139         result->SetDouble("dynamic_pkp_expiry",
   1140                           dynamic_state.pkp.expiry.ToDoubleT());
   1141         result->SetString("dynamic_spki_hashes",
   1142                           HashesToBase64String(dynamic_state.pkp.spki_hashes));
   1143       }
   1144 
   1145       result->SetBoolean("result", found_static || found_dynamic);
   1146       if (found_static) {
   1147         result->SetString("domain", static_state.domain);
   1148       } else if (found_dynamic) {
   1149         result->SetString("domain", dynamic_state.domain);
   1150       } else {
   1151         result->SetString("domain", domain);
   1152       }
   1153     }
   1154   }
   1155 
   1156   SendJavascriptCommand("receivedHSTSResult", result);
   1157 }
   1158 
   1159 void NetInternalsMessageHandler::IOThreadImpl::OnHSTSAdd(
   1160     const base::ListValue* list) {
   1161   // |list| should be: [<domain to query>, <STS include subdomains>, <PKP
   1162   // include subdomains>, <key pins>].
   1163   std::string domain;
   1164   CHECK(list->GetString(0, &domain));
   1165   if (!base::IsStringASCII(domain)) {
   1166     // Silently fail. The user will get a helpful error if they query for the
   1167     // name.
   1168     return;
   1169   }
   1170   bool sts_include_subdomains;
   1171   CHECK(list->GetBoolean(1, &sts_include_subdomains));
   1172   bool pkp_include_subdomains;
   1173   CHECK(list->GetBoolean(2, &pkp_include_subdomains));
   1174   std::string hashes_str;
   1175   CHECK(list->GetString(3, &hashes_str));
   1176 
   1177   net::TransportSecurityState* transport_security_state =
   1178       GetMainContext()->transport_security_state();
   1179   if (!transport_security_state)
   1180     return;
   1181 
   1182   base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
   1183   net::HashValueVector hashes;
   1184   if (!hashes_str.empty()) {
   1185     if (!Base64StringToHashes(hashes_str, &hashes))
   1186       return;
   1187   }
   1188 
   1189   transport_security_state->AddHSTS(domain, expiry, sts_include_subdomains);
   1190   transport_security_state->AddHPKP(domain, expiry, pkp_include_subdomains,
   1191                                     hashes);
   1192 }
   1193 
   1194 void NetInternalsMessageHandler::IOThreadImpl::OnHSTSDelete(
   1195     const base::ListValue* list) {
   1196   // |list| should be: [<domain to query>].
   1197   std::string domain;
   1198   CHECK(list->GetString(0, &domain));
   1199   if (!base::IsStringASCII(domain)) {
   1200     // There cannot be a unicode entry in the HSTS set.
   1201     return;
   1202   }
   1203   net::TransportSecurityState* transport_security_state =
   1204       GetMainContext()->transport_security_state();
   1205   if (!transport_security_state)
   1206     return;
   1207 
   1208   transport_security_state->DeleteDynamicDataForHost(domain);
   1209 }
   1210 
   1211 void NetInternalsMessageHandler::IOThreadImpl::OnGetHttpCacheInfo(
   1212     const base::ListValue* list) {
   1213   DCHECK(!list);
   1214   base::DictionaryValue* info_dict = new base::DictionaryValue();
   1215   base::DictionaryValue* stats_dict = new base::DictionaryValue();
   1216 
   1217   disk_cache::Backend* disk_cache = GetDiskCacheBackend(GetMainContext());
   1218 
   1219   if (disk_cache) {
   1220     // Extract the statistics key/value pairs from the backend.
   1221     base::StringPairs stats;
   1222     disk_cache->GetStats(&stats);
   1223     for (size_t i = 0; i < stats.size(); ++i) {
   1224       stats_dict->SetStringWithoutPathExpansion(
   1225           stats[i].first, stats[i].second);
   1226     }
   1227   }
   1228 
   1229   info_dict->Set("stats", stats_dict);
   1230 
   1231   SendJavascriptCommand("receivedHttpCacheInfo", info_dict);
   1232 }
   1233 
   1234 void NetInternalsMessageHandler::IOThreadImpl::OnGetSocketPoolInfo(
   1235     const base::ListValue* list) {
   1236   DCHECK(!list);
   1237   net::HttpNetworkSession* http_network_session =
   1238       GetHttpNetworkSession(GetMainContext());
   1239 
   1240   base::Value* socket_pool_info = NULL;
   1241   if (http_network_session)
   1242     socket_pool_info = http_network_session->SocketPoolInfoToValue();
   1243 
   1244   SendJavascriptCommand("receivedSocketPoolInfo", socket_pool_info);
   1245 }
   1246 
   1247 void NetInternalsMessageHandler::IOThreadImpl::OnGetSessionNetworkStats(
   1248     const base::ListValue* list) {
   1249   DCHECK(!list);
   1250   net::HttpNetworkSession* http_network_session =
   1251       GetHttpNetworkSession(main_context_getter_->GetURLRequestContext());
   1252 
   1253   base::Value* network_info = NULL;
   1254   if (http_network_session) {
   1255     ChromeNetworkDelegate* net_delegate =
   1256         static_cast<ChromeNetworkDelegate*>(
   1257             http_network_session->network_delegate());
   1258     if (net_delegate) {
   1259       network_info = net_delegate->SessionNetworkStatsInfoToValue();
   1260     }
   1261   }
   1262   SendJavascriptCommand("receivedSessionNetworkStats", network_info);
   1263 }
   1264 
   1265 void NetInternalsMessageHandler::IOThreadImpl::OnFlushSocketPools(
   1266     const base::ListValue* list) {
   1267   DCHECK(!list);
   1268   net::HttpNetworkSession* http_network_session =
   1269       GetHttpNetworkSession(GetMainContext());
   1270 
   1271   if (http_network_session)
   1272     http_network_session->CloseAllConnections();
   1273 }
   1274 
   1275 void NetInternalsMessageHandler::IOThreadImpl::OnCloseIdleSockets(
   1276     const base::ListValue* list) {
   1277   DCHECK(!list);
   1278   net::HttpNetworkSession* http_network_session =
   1279       GetHttpNetworkSession(GetMainContext());
   1280 
   1281   if (http_network_session)
   1282     http_network_session->CloseIdleConnections();
   1283 }
   1284 
   1285 void NetInternalsMessageHandler::IOThreadImpl::OnGetSpdySessionInfo(
   1286     const base::ListValue* list) {
   1287   DCHECK(!list);
   1288   net::HttpNetworkSession* http_network_session =
   1289       GetHttpNetworkSession(GetMainContext());
   1290 
   1291   base::Value* spdy_info = http_network_session ?
   1292       http_network_session->SpdySessionPoolInfoToValue() : NULL;
   1293   SendJavascriptCommand("receivedSpdySessionInfo", spdy_info);
   1294 }
   1295 
   1296 void NetInternalsMessageHandler::IOThreadImpl::OnGetSpdyStatus(
   1297     const base::ListValue* list) {
   1298   DCHECK(!list);
   1299   base::DictionaryValue* status_dict = new base::DictionaryValue();
   1300 
   1301   net::HttpNetworkSession* http_network_session =
   1302       GetHttpNetworkSession(GetMainContext());
   1303 
   1304   status_dict->SetBoolean("spdy_enabled",
   1305                           net::HttpStreamFactory::spdy_enabled());
   1306   status_dict->SetBoolean(
   1307       "use_alternate_protocols",
   1308       http_network_session->params().use_alternate_protocols);
   1309   status_dict->SetBoolean("force_spdy_over_ssl",
   1310                           http_network_session->params().force_spdy_over_ssl);
   1311   status_dict->SetBoolean("force_spdy_always",
   1312                           http_network_session->params().force_spdy_always);
   1313 
   1314   std::vector<std::string> next_protos;
   1315   http_network_session->GetNextProtos(&next_protos);
   1316   std::string next_protos_string = JoinString(next_protos, ',');
   1317   status_dict->SetString("next_protos", next_protos_string);
   1318 
   1319   SendJavascriptCommand("receivedSpdyStatus", status_dict);
   1320 }
   1321 
   1322 void
   1323 NetInternalsMessageHandler::IOThreadImpl::OnGetSpdyAlternateProtocolMappings(
   1324     const base::ListValue* list) {
   1325   DCHECK(!list);
   1326   base::ListValue* dict_list = new base::ListValue();
   1327 
   1328   const net::HttpServerProperties& http_server_properties =
   1329       *GetMainContext()->http_server_properties();
   1330 
   1331   const net::AlternateProtocolMap& map =
   1332       http_server_properties.alternate_protocol_map();
   1333 
   1334   for (net::AlternateProtocolMap::const_iterator it = map.begin();
   1335        it != map.end(); ++it) {
   1336     base::DictionaryValue* dict = new base::DictionaryValue();
   1337     dict->SetString("host_port_pair", it->first.ToString());
   1338     dict->SetString("alternate_protocol", it->second.ToString());
   1339     dict_list->Append(dict);
   1340   }
   1341 
   1342   SendJavascriptCommand("receivedSpdyAlternateProtocolMappings", dict_list);
   1343 }
   1344 
   1345 void NetInternalsMessageHandler::IOThreadImpl::OnGetQuicInfo(
   1346     const base::ListValue* list) {
   1347   DCHECK(!list);
   1348   net::HttpNetworkSession* http_network_session =
   1349       GetHttpNetworkSession(GetMainContext());
   1350 
   1351   base::Value* quic_info = http_network_session ?
   1352       http_network_session->QuicInfoToValue() : NULL;
   1353   SendJavascriptCommand("receivedQuicInfo", quic_info);
   1354 }
   1355 
   1356 #if defined(OS_WIN)
   1357 void NetInternalsMessageHandler::IOThreadImpl::OnGetServiceProviders(
   1358     const base::ListValue* list) {
   1359   DCHECK(!list);
   1360 
   1361   base::DictionaryValue* service_providers = new base::DictionaryValue();
   1362 
   1363   WinsockLayeredServiceProviderList layered_providers;
   1364   GetWinsockLayeredServiceProviders(&layered_providers);
   1365   base::ListValue* layered_provider_list = new base::ListValue();
   1366   for (size_t i = 0; i < layered_providers.size(); ++i) {
   1367     base::DictionaryValue* service_dict = new base::DictionaryValue();
   1368     service_dict->SetString("name", layered_providers[i].name);
   1369     service_dict->SetInteger("version", layered_providers[i].version);
   1370     service_dict->SetInteger("chain_length", layered_providers[i].chain_length);
   1371     service_dict->SetInteger("socket_type", layered_providers[i].socket_type);
   1372     service_dict->SetInteger("socket_protocol",
   1373         layered_providers[i].socket_protocol);
   1374     service_dict->SetString("path", layered_providers[i].path);
   1375 
   1376     layered_provider_list->Append(service_dict);
   1377   }
   1378   service_providers->Set("service_providers", layered_provider_list);
   1379 
   1380   WinsockNamespaceProviderList namespace_providers;
   1381   GetWinsockNamespaceProviders(&namespace_providers);
   1382   base::ListValue* namespace_list = new base::ListValue;
   1383   for (size_t i = 0; i < namespace_providers.size(); ++i) {
   1384     base::DictionaryValue* namespace_dict = new base::DictionaryValue();
   1385     namespace_dict->SetString("name", namespace_providers[i].name);
   1386     namespace_dict->SetBoolean("active", namespace_providers[i].active);
   1387     namespace_dict->SetInteger("version", namespace_providers[i].version);
   1388     namespace_dict->SetInteger("type", namespace_providers[i].type);
   1389 
   1390     namespace_list->Append(namespace_dict);
   1391   }
   1392   service_providers->Set("namespace_providers", namespace_list);
   1393 
   1394   SendJavascriptCommand("receivedServiceProviders", service_providers);
   1395 }
   1396 #endif
   1397 
   1398 #if defined(OS_CHROMEOS)
   1399 void NetInternalsMessageHandler::OnRefreshSystemLogs(
   1400     const base::ListValue* list) {
   1401   DCHECK(!list);
   1402   DCHECK(syslogs_getter_.get());
   1403   syslogs_getter_->DeleteSystemLogs();
   1404   syslogs_getter_->LoadSystemLogs();
   1405 }
   1406 
   1407 void NetInternalsMessageHandler::OnGetSystemLog(
   1408     const base::ListValue* list) {
   1409   DCHECK(syslogs_getter_.get());
   1410   syslogs_getter_->RequestSystemLog(list);
   1411 }
   1412 
   1413 void NetInternalsMessageHandler::ImportONCFileToNSSDB(
   1414     const std::string& onc_blob,
   1415     const std::string& passcode,
   1416     net::NSSCertDatabase* nssdb) {
   1417   user_manager::User* user = chromeos::ProfileHelper::Get()->GetUserByProfile(
   1418       Profile::FromWebUI(web_ui()));
   1419 
   1420   if (!user) {
   1421     std::string error = "User not found.";
   1422     SendJavascriptCommand("receivedONCFileParse", new base::StringValue(error));
   1423     return;
   1424   }
   1425 
   1426   std::string error;
   1427   onc::ONCSource onc_source = onc::ONC_SOURCE_USER_IMPORT;
   1428   base::ListValue network_configs;
   1429   base::DictionaryValue global_network_config;
   1430   base::ListValue certificates;
   1431   if (!chromeos::onc::ParseAndValidateOncForImport(onc_blob,
   1432                                                    onc_source,
   1433                                                    passcode,
   1434                                                    &network_configs,
   1435                                                    &global_network_config,
   1436                                                    &certificates)) {
   1437     error = "Errors occurred during the ONC parsing. ";
   1438   }
   1439 
   1440   std::string network_error;
   1441   chromeos::onc::ImportNetworksForUser(user, network_configs, &network_error);
   1442   if (!network_error.empty())
   1443     error += network_error;
   1444 
   1445   chromeos::onc::CertificateImporterImpl cert_importer(
   1446       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), nssdb);
   1447   cert_importer.ImportCertificates(
   1448       certificates,
   1449       onc_source,
   1450       base::Bind(&NetInternalsMessageHandler::OnCertificatesImported,
   1451                  AsWeakPtr(),
   1452                  error));
   1453 }
   1454 
   1455 void NetInternalsMessageHandler::OnCertificatesImported(
   1456     const std::string& previous_error,
   1457     bool success,
   1458     const net::CertificateList& /* unused onc_trusted_certificates */) {
   1459   std::string error = previous_error;
   1460   if (!success)
   1461     error += "Some certificates couldn't be imported. ";
   1462 
   1463   SendJavascriptCommand("receivedONCFileParse", new base::StringValue(error));
   1464 }
   1465 
   1466 void NetInternalsMessageHandler::OnImportONCFile(
   1467     const base::ListValue* list) {
   1468   std::string onc_blob;
   1469   std::string passcode;
   1470   if (list->GetSize() != 2 ||
   1471       !list->GetString(0, &onc_blob) ||
   1472       !list->GetString(1, &passcode)) {
   1473     NOTREACHED();
   1474   }
   1475 
   1476   GetNSSCertDatabaseForProfile(
   1477       Profile::FromWebUI(web_ui()),
   1478       base::Bind(&NetInternalsMessageHandler::ImportONCFileToNSSDB, AsWeakPtr(),
   1479                  onc_blob, passcode));
   1480 }
   1481 
   1482 void NetInternalsMessageHandler::OnStoreDebugLogs(const base::ListValue* list) {
   1483   DCHECK(list);
   1484 
   1485   SendJavascriptCommand("receivedStoreDebugLogs",
   1486                         new base::StringValue("Creating log file..."));
   1487   Profile* profile = Profile::FromWebUI(web_ui());
   1488   const DownloadPrefs* const prefs = DownloadPrefs::FromBrowserContext(profile);
   1489   base::FilePath path = prefs->DownloadPath();
   1490   if (file_manager::util::IsUnderNonNativeLocalPath(profile, path))
   1491     path = prefs->GetDefaultDownloadDirectoryForProfile();
   1492   chromeos::DebugLogWriter::StoreLogs(
   1493       path,
   1494       true,  // should_compress
   1495       base::Bind(&NetInternalsMessageHandler::OnStoreDebugLogsCompleted,
   1496                  AsWeakPtr()));
   1497 }
   1498 
   1499 void NetInternalsMessageHandler::OnStoreDebugLogsCompleted(
   1500     const base::FilePath& log_path, bool succeeded) {
   1501   std::string status;
   1502   if (succeeded)
   1503     status = "Created log file: " + log_path.BaseName().AsUTF8Unsafe();
   1504   else
   1505     status = "Failed to create log file";
   1506   SendJavascriptCommand("receivedStoreDebugLogs",
   1507                         new base::StringValue(status));
   1508 }
   1509 
   1510 void NetInternalsMessageHandler::OnSetNetworkDebugMode(
   1511     const base::ListValue* list) {
   1512   std::string subsystem;
   1513   if (list->GetSize() != 1 || !list->GetString(0, &subsystem))
   1514     NOTREACHED();
   1515   chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
   1516       SetDebugMode(
   1517           subsystem,
   1518           base::Bind(
   1519               &NetInternalsMessageHandler::OnSetNetworkDebugModeCompleted,
   1520               AsWeakPtr(),
   1521               subsystem));
   1522 }
   1523 
   1524 void NetInternalsMessageHandler::OnSetNetworkDebugModeCompleted(
   1525     const std::string& subsystem,
   1526     bool succeeded) {
   1527   std::string status;
   1528   if (succeeded)
   1529     status = "Debug mode is changed to " + subsystem;
   1530   else
   1531     status = "Failed to change debug mode to " + subsystem;
   1532   SendJavascriptCommand("receivedSetNetworkDebugMode",
   1533                         new base::StringValue(status));
   1534 }
   1535 #endif  // defined(OS_CHROMEOS)
   1536 
   1537 void NetInternalsMessageHandler::IOThreadImpl::OnSetLogLevel(
   1538     const base::ListValue* list) {
   1539   int log_level;
   1540   std::string log_level_string;
   1541   if (!list->GetString(0, &log_level_string) ||
   1542       !base::StringToInt(log_level_string, &log_level)) {
   1543     NOTREACHED();
   1544     return;
   1545   }
   1546 
   1547   DCHECK_GE(log_level, net::NetLog::LOG_ALL);
   1548   DCHECK_LT(log_level, net::NetLog::LOG_NONE);
   1549   net_log()->SetObserverLogLevel(
   1550       this, static_cast<net::NetLog::LogLevel>(log_level));
   1551 }
   1552 
   1553 // Note that unlike other methods of IOThreadImpl, this function
   1554 // can be called from ANY THREAD.
   1555 void NetInternalsMessageHandler::IOThreadImpl::OnAddEntry(
   1556     const net::NetLog::Entry& entry) {
   1557   BrowserThread::PostTask(
   1558       BrowserThread::IO, FROM_HERE,
   1559       base::Bind(&IOThreadImpl::AddEntryToQueue, this, entry.ToValue()));
   1560 }
   1561 
   1562 void NetInternalsMessageHandler::IOThreadImpl::OnStartConnectionTestSuite() {
   1563   SendJavascriptCommand("receivedStartConnectionTestSuite", NULL);
   1564 }
   1565 
   1566 void NetInternalsMessageHandler::IOThreadImpl::OnStartConnectionTestExperiment(
   1567     const ConnectionTester::Experiment& experiment) {
   1568   SendJavascriptCommand(
   1569       "receivedStartConnectionTestExperiment",
   1570       ExperimentToValue(experiment));
   1571 }
   1572 
   1573 void
   1574 NetInternalsMessageHandler::IOThreadImpl::OnCompletedConnectionTestExperiment(
   1575     const ConnectionTester::Experiment& experiment,
   1576     int result) {
   1577   base::DictionaryValue* dict = new base::DictionaryValue();
   1578 
   1579   dict->Set("experiment", ExperimentToValue(experiment));
   1580   dict->SetInteger("result", result);
   1581 
   1582   SendJavascriptCommand(
   1583       "receivedCompletedConnectionTestExperiment",
   1584       dict);
   1585 }
   1586 
   1587 void
   1588 NetInternalsMessageHandler::IOThreadImpl::OnCompletedConnectionTestSuite() {
   1589   SendJavascriptCommand(
   1590       "receivedCompletedConnectionTestSuite",
   1591       NULL);
   1592 }
   1593 
   1594 // Note that this can be called from ANY THREAD.
   1595 void NetInternalsMessageHandler::IOThreadImpl::SendJavascriptCommand(
   1596     const std::string& command,
   1597     base::Value* arg) {
   1598   if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
   1599     if (handler_.get() && !was_webui_deleted_) {
   1600       // We check |handler_| in case it was deleted on the UI thread earlier
   1601       // while we were running on the IO thread.
   1602       handler_->SendJavascriptCommand(command, arg);
   1603     } else {
   1604       delete arg;
   1605     }
   1606     return;
   1607   }
   1608 
   1609   if (!BrowserThread::PostTask(
   1610       BrowserThread::UI, FROM_HERE,
   1611       base::Bind(&IOThreadImpl::SendJavascriptCommand, this, command, arg))) {
   1612     // Failed posting the task, avoid leaking.
   1613     delete arg;
   1614   }
   1615 }
   1616 
   1617 void NetInternalsMessageHandler::IOThreadImpl::AddEntryToQueue(
   1618     base::Value* entry) {
   1619   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   1620   if (!pending_entries_.get()) {
   1621     pending_entries_.reset(new base::ListValue());
   1622     BrowserThread::PostDelayedTask(
   1623         BrowserThread::IO, FROM_HERE,
   1624         base::Bind(&IOThreadImpl::PostPendingEntries, this),
   1625         base::TimeDelta::FromMilliseconds(kNetLogEventDelayMilliseconds));
   1626   }
   1627   pending_entries_->Append(entry);
   1628 }
   1629 
   1630 void NetInternalsMessageHandler::IOThreadImpl::PostPendingEntries() {
   1631   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   1632   if (pending_entries_.get())
   1633     SendJavascriptCommand("receivedLogEntries", pending_entries_.release());
   1634 }
   1635 
   1636 void NetInternalsMessageHandler::IOThreadImpl::PrePopulateEventList() {
   1637   // Use a set to prevent duplicates.
   1638   std::set<net::URLRequestContext*> contexts;
   1639   for (ContextGetterList::const_iterator getter = context_getters_.begin();
   1640        getter != context_getters_.end(); ++getter) {
   1641     contexts.insert((*getter)->GetURLRequestContext());
   1642   }
   1643   contexts.insert(io_thread_->globals()->proxy_script_fetcher_context.get());
   1644   contexts.insert(io_thread_->globals()->system_request_context.get());
   1645 
   1646   // Put together the list of all requests.
   1647   std::vector<const net::URLRequest*> requests;
   1648   for (std::set<net::URLRequestContext*>::const_iterator context =
   1649            contexts.begin();
   1650        context != contexts.end(); ++context) {
   1651     std::set<const net::URLRequest*>* context_requests =
   1652         (*context)->url_requests();
   1653     for (std::set<const net::URLRequest*>::const_iterator request_it =
   1654              context_requests->begin();
   1655          request_it != context_requests->end(); ++request_it) {
   1656       DCHECK_EQ(io_thread_->net_log(), (*request_it)->net_log().net_log());
   1657       requests.push_back(*request_it);
   1658     }
   1659   }
   1660 
   1661   // Sort by creation time.
   1662   std::sort(requests.begin(), requests.end(), RequestCreatedBefore);
   1663 
   1664   // Create fake events.
   1665   for (std::vector<const net::URLRequest*>::const_iterator request_it =
   1666            requests.begin();
   1667        request_it != requests.end(); ++request_it) {
   1668     const net::URLRequest* request = *request_it;
   1669     net::NetLog::ParametersCallback callback =
   1670         base::Bind(&GetRequestStateAsValue, base::Unretained(request));
   1671 
   1672     // Create and add the entry directly, to avoid sending it to any other
   1673     // NetLog observers.
   1674     net::NetLog::EntryData entry_data(net::NetLog::TYPE_REQUEST_ALIVE,
   1675                                       request->net_log().source(),
   1676                                       net::NetLog::PHASE_BEGIN,
   1677                                       request->creation_time(),
   1678                                       &callback);
   1679     net::NetLog::Entry entry(&entry_data, request->net_log().GetLogLevel());
   1680 
   1681     // Have to add |entry| to the queue synchronously, as there may already
   1682     // be posted tasks queued up to add other events for |request|, which we
   1683     // want |entry| to precede.
   1684     AddEntryToQueue(entry.ToValue());
   1685   }
   1686 }
   1687 
   1688 }  // namespace
   1689 
   1690 
   1691 ////////////////////////////////////////////////////////////////////////////////
   1692 //
   1693 // NetInternalsUI
   1694 //
   1695 ////////////////////////////////////////////////////////////////////////////////
   1696 
   1697 // static
   1698 base::Value* NetInternalsUI::GetConstants() {
   1699   base::DictionaryValue* constants_dict = net::NetLogLogger::GetConstants();
   1700   DCHECK(constants_dict);
   1701 
   1702   // Add a dictionary with the version of the client and its command line
   1703   // arguments.
   1704   {
   1705     base::DictionaryValue* dict = new base::DictionaryValue();
   1706 
   1707     chrome::VersionInfo version_info;
   1708 
   1709     if (!version_info.is_valid()) {
   1710       DLOG(ERROR) << "Unable to create chrome::VersionInfo";
   1711     } else {
   1712       // We have everything we need to send the right values.
   1713       dict->SetString("name", version_info.Name());
   1714       dict->SetString("version", version_info.Version());
   1715       dict->SetString("cl", version_info.LastChange());
   1716       dict->SetString("version_mod",
   1717                       chrome::VersionInfo::GetVersionStringModifier());
   1718       dict->SetString("official",
   1719                       version_info.IsOfficialBuild() ? "official" :
   1720                                                        "unofficial");
   1721       dict->SetString("os_type", version_info.OSType());
   1722       dict->SetString("command_line",
   1723                       CommandLine::ForCurrentProcess()->GetCommandLineString());
   1724     }
   1725 
   1726     constants_dict->Set("clientInfo", dict);
   1727   }
   1728 
   1729   return constants_dict;
   1730 }
   1731 
   1732 NetInternalsUI::NetInternalsUI(content::WebUI* web_ui)
   1733     : WebUIController(web_ui) {
   1734   web_ui->AddMessageHandler(new NetInternalsMessageHandler());
   1735 
   1736   // Set up the chrome://net-internals/ source.
   1737   Profile* profile = Profile::FromWebUI(web_ui);
   1738   content::WebUIDataSource::Add(profile, CreateNetInternalsHTMLSource());
   1739 }
   1740