Bug 1303762 - Add UI to about:networking to turn on logging modules at runtime r=jaws,mcmanus
☠☠ backed out by b9fddae1ada2 ☠ ☠
authorValentin Gosu <valentin.gosu@gmail.com>
Thu, 29 Sep 2016 17:00:21 +0200
changeset 315763 e4508f246a862379bc3e40380f1972fa808fc685
parent 315762 930ead1e6df1dd3e4d75c8fbbfdd83b5b38419c8
child 315764 f325ed1abef16a4090cd6d3fd7a81d245c2de705
push id82263
push uservalentin.gosu@gmail.com
push dateThu, 29 Sep 2016 15:00:34 +0000
treeherdermozilla-inbound@e4508f246a86 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws, mcmanus
bugs1303762
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1303762 - Add UI to about:networking to turn on logging modules at runtime r=jaws,mcmanus
netwerk/base/Dashboard.cpp
netwerk/base/nsIDashboard.idl
toolkit/content/aboutNetworking.js
toolkit/content/aboutNetworking.xhtml
toolkit/locales/en-US/chrome/global/aboutNetworking.dtd
--- a/netwerk/base/Dashboard.cpp
+++ b/netwerk/base/Dashboard.cpp
@@ -13,16 +13,17 @@
 #include "nsIDNSRecord.h"
 #include "nsIInputStream.h"
 #include "nsISocketTransport.h"
 #include "nsIThread.h"
 #include "nsProxyRelease.h"
 #include "nsSocketTransportService2.h"
 #include "nsThreadUtils.h"
 #include "nsURLHelper.h"
+#include "mozilla/Logging.h"
 
 using mozilla::AutoSafeJSContext;
 using mozilla::dom::Sequence;
 using mozilla::dom::ToJSValue;
 
 namespace mozilla {
 namespace net {
 
@@ -777,16 +778,25 @@ HttpConnInfo::SetHTTP1ProtocolVersion(ui
 void
 HttpConnInfo::SetHTTP2ProtocolVersion(uint8_t pv)
 {
     MOZ_ASSERT (pv == HTTP_VERSION_2);
     protocolVersion.Assign(u"h2");
 }
 
 NS_IMETHODIMP
+Dashboard::GetLogPath(nsACString &aLogPath)
+{
+    aLogPath.SetCapacity(2048);
+    uint32_t len = LogModule::GetLogFile(aLogPath.BeginWriting(), 2048);
+    aLogPath.SetLength(len);
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 Dashboard::RequestConnection(const nsACString& aHost, uint32_t aPort,
                              const char *aProtocol, uint32_t aTimeout,
                              NetDashboardCallback *aCallback)
 {
     nsresult rv;
     RefPtr<ConnectionData> connectionData = new ConnectionData(this);
     connectionData->mHost = aHost;
     connectionData->mPort = aPort;
--- a/netwerk/base/nsIDashboard.idl
+++ b/netwerk/base/nsIDashboard.idl
@@ -44,9 +44,11 @@ interface nsIDashboard : nsISupports
                            in NetDashboardCallback cb);
 
     /* When true, the service will log websocket events */
     attribute boolean enableLogging;
 
     /* DNS resolver for host name
      * aHost: host name */
     void requestDNSLookup(in ACString aHost, in NetDashboardCallback cb);
+
+    AUTF8String getLogPath();
 };
--- a/toolkit/content/aboutNetworking.js
+++ b/toolkit/content/aboutNetworking.js
@@ -3,20 +3,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 'use strict';
 
 var Ci = Components.interfaces;
 var Cc = Components.classes;
 var Cu = Components.utils;
 
-const gDashboard = Cc['@mozilla.org/network/dashboard;1'].
-  getService(Ci.nsIDashboard);
-const gPrefs = Cc["@mozilla.org/preferences-service;1"].
-  getService(Ci.nsIPrefService).getBranch("network.");
+Cu.import("resource://gre/modules/Services.jsm");
+const FileUtils = Cu.import("resource://gre/modules/FileUtils.jsm").FileUtils
+const gEnv = Cc["@mozilla.org/process/environment;1"]
+               .getService(Ci.nsIEnvironment);
+const gDashboard = Cc['@mozilla.org/network/dashboard;1']
+                     .getService(Ci.nsIDashboard);
+const gDirServ = Cc["@mozilla.org/file/directory_service;1"]
+                   .getService(Ci.nsIDirectoryServiceProvider);
+
 const gRequestNetworkingData = {
   "http": gDashboard.requestHttpConnections,
   "sockets": gDashboard.requestSockets,
   "dns": gDashboard.requestDNSInfo,
   "websockets": gDashboard.requestWebsocketConnections
 };
 const gDashboardCallbacks = {
   "http": displayHttp,
@@ -125,17 +130,17 @@ function requestAllNetworkingData() {
 }
 
 function requestNetworkingDataForTab(id) {
   gRequestNetworkingData[id](gDashboardCallbacks[id]);
 }
 
 function init() {
   gDashboard.enableLogging = true;
-  if (gPrefs.getBoolPref("warnOnAboutNetworking")) {
+  if (Services.prefs.getBoolPref("network.warnOnAboutNetworking")) {
     let div = document.getElementById("warning_message");
     div.classList.add("active");
     div.hidden = false;
     document.getElementById("confpref").addEventListener("click", confirm);
   }
 
   requestAllNetworkingData();
 
@@ -165,24 +170,155 @@ function init() {
     if (e.target && e.target.parentNode == menu)
       show(e.target);
   });
 
   let dnsLookupButton = document.getElementById("dnsLookupButton");
   dnsLookupButton.addEventListener("click", function() {
     doLookup();
   });
+
+  let setLogButton = document.getElementById("set-log-file-button");
+  setLogButton.addEventListener("click", setLogFile);
+
+  let setModulesButton = document.getElementById("set-log-modules-button");
+  setModulesButton.addEventListener("click", setLogModules);
+
+  try {
+    let file = gDirServ.getFile("TmpD",  {});
+    file.append("log.txt");
+    document.getElementById("log-file").value = file.path;
+  } catch (e) {
+    console.error(e);
+  }
+
+  // Update the value of the log file.
+  updateLogFile();
+
+  // Update the active log modules
+  updateLogModules();
+}
+
+function updateLogFile() {
+  let logPath = "";
+
+  // Try to get the environment variable for the log file
+  logPath = gEnv.get("MOZ_LOG_FILE") || gEnv.get("NSPR_LOG_FILE");
+  let currentLogFile = document.getElementById("current-log-file");
+  let setLogFileButton = document.getElementById("set-log-file-button");
+
+  // If the log file was set from an env var, we disable the ability to set it
+  // at runtime.
+  if (logPath.length > 0) {
+    currentLogFile.innerText = logPath;
+    setLogFileButton.disabled = true;
+  } else {
+    // There may be a value set by a pref.
+    currentLogFile.innerText = gDashboard.getLogPath();
+    setLogFileButton.disabled = false;
+  }
+}
+
+function updateLogModules() {
+  // Try to get the environment variable for the log file
+  let logModules = gEnv.get("MOZ_LOG") ||
+                   gEnv.get("MOZ_LOG_MODULES") ||
+                   gEnv.get("NSPR_LOG_MODULES");
+  let currentLogModules = document.getElementById("current-log-modules");
+  let setLogModulesButton = document.getElementById("set-log-modules-button");
+  if (logModules.length > 0) {
+    currentLogModules.innerText = logModules;
+    // If the log modules are set by an environment variable at startup, do not
+    // allow changing them throught a pref. It would be difficult to figure out
+    // which ones are enabled and which ones are not. The user probably knows
+    // what he they are doing.
+    setLogModulesButton.disabled = true;
+  } else {
+    let activeLogModules = [];
+    try {
+      if (Services.prefs.getBoolPref("logging.config.add_timestamp")) {
+        activeLogModules.push("timestamp");
+      }
+    } catch (e) {}
+    try {
+      if (Services.prefs.getBoolPref("logging.config.sync")) {
+        activeLogModules.push("sync");
+      }
+    } catch (e) {}
+
+    let children = Services.prefs.getBranch("logging.").getChildList("", {});
+
+    for (let pref of children) {
+      if (pref.startsWith("config.")) {
+        continue;
+      }
+
+      try {
+        let value = Services.prefs.getIntPref(`logging.${pref}`);
+        activeLogModules.push(`${pref}:${value}`);
+      } catch (e) {
+        console.error(e);
+      }
+    }
+
+    currentLogModules.innerText = activeLogModules.join(",");
+  }
+}
+
+function setLogFile() {
+  let logFile = document.getElementById("log-file").value.trim();
+  Services.prefs.setCharPref("logging.config.LOG_FILE", logFile);
+  updateLogFile();
+}
+
+function setLogModules() {
+  let modules = document.getElementById("log-modules").value.trim();
+  if (modules.length == 0) {
+    // Turn off all the modules.
+    let children = Services.prefs.getBranch("logging.").getChildList("", {});
+    for (let pref of children) {
+      if (!pref.startsWith("config.")) {
+        Services.prefs.clearUserPref(`logging.${pref}`);
+      }
+    }
+    Services.prefs.clearUserPref("logging.config.add_timestamp");
+    Services.prefs.clearUserPref("logging.config.sync");
+    updateLogModules();
+    return;
+  }
+
+  let logModules = modules.split(",");
+  let isSync = false;
+  let addTimestamp = false;
+  for (let module of logModules) {
+    if (module == "timestamp") {
+      addTimestamp = true;
+    } else if (module == "rotate") {
+      // XXX: rotate is not yet supported.
+    } else if (module == "append") {
+      // XXX: append is not yet supported.
+    } else if (module == "sync") {
+      isSync = true;
+    } else {
+      let [key, value] = module.split(":");
+      Services.prefs.setIntPref(`logging.${key}`, parseInt(value, 10));
+    }
+  }
+  Services.prefs.setBoolPref("logging.config.add_timestamp", addTimestamp);
+  Services.prefs.setBoolPref("logging.config.sync", isSync);
+
+  updateLogModules();
 }
 
 function confirm () {
   let div = document.getElementById("warning_message");
   div.classList.remove("active");
   div.hidden = true;
   let warnBox = document.getElementById("warncheck");
-  gPrefs.setBoolPref("warnOnAboutNetworking", warnBox.checked);
+  Services.prefs.setBoolPref("network.warnOnAboutNetworking", warnBox.checked);
 }
 
 function show(button) {
   let current_tab = document.querySelector(".active");
   let content = document.getElementById(button.getAttribute("value"));
   if (current_tab == content)
     return;
   current_tab.classList.remove("active");
--- a/toolkit/content/aboutNetworking.xhtml
+++ b/toolkit/content/aboutNetworking.xhtml
@@ -42,16 +42,19 @@
             </div>
             <div class="category" value="websockets">
                 <span class="category-name">&aboutNetworking.websockets;</span>
             </div>
             <hr></hr>
             <div class="category" value="dnslookuptool">
                 <span class="category-name">&aboutNetworking.dnsLookup;</span>
             </div>
+            <div class="category" value="logging">
+                <span class="category-name">&aboutNetworking.logging;</span>
+            </div>
         </div>
         <div class="main-content">
             <div class="header">
                 <div id="sectionTitle" class="header-name">
                     &aboutNetworking.HTTP;
                 </div>
                 <div id="refreshDiv">
                     <button id="refreshButton">&aboutNetworking.refresh;</button>
@@ -130,11 +133,28 @@
                   <thead>
                       <tr>
                           <th>&aboutNetworking.dnsLookupTableColumn;</th>
                       </tr>
                   </thead>
                   <tbody id="dnslookuptool_content" />
               </table>
           </div>
+
+          <div id="logging" class="tab" hidden="true">
+            <div>
+              &aboutNetworking.logTutorial;
+            </div>
+            <div>
+              &aboutNetworking.currentLogFile; <div id="current-log-file"></div><br/>
+              <input type="text" name="log-file" id="log-file"></input>
+              <button id="set-log-file-button"> &aboutNetworking.setLogFile; </button>
+            </div>
+            <div>
+              &aboutNetworking.currentLogModules; <div id="current-log-modules"></div><br/>
+              <input type="text" name="log-modules" id="log-modules" value="timestamp,sync,nsHttp:5,nsSocketTransport:5,nsStreamPump:5,nsHostResolver:5"></input>
+              <button id="set-log-modules-button"> &aboutNetworking.setLogModules; </button>
+            </div>
+          </div>
+
         </div>
     </body>
 </html>
--- a/toolkit/locales/en-US/chrome/global/aboutNetworking.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutNetworking.dtd
@@ -24,12 +24,18 @@
 <!ENTITY aboutNetworking.received              "Received">
 <!ENTITY aboutNetworking.family                "Family">
 <!ENTITY aboutNetworking.addresses             "Addresses">
 <!ENTITY aboutNetworking.expires               "Expires (Seconds)">
 <!ENTITY aboutNetworking.messagesSent          "Messages Sent">
 <!ENTITY aboutNetworking.messagesReceived      "Messages Received">
 <!ENTITY aboutNetworking.bytesSent             "Bytes Sent">
 <!ENTITY aboutNetworking.bytesReceived         "Bytes Received">
+<!ENTITY aboutNetworking.logging               "Logging">
+<!ENTITY aboutNetworking.logTutorial           "See <a href='https://developer.mozilla.org/docs/Mozilla/Debugging/HTTP_logging'>HTTP Logging</a> for instructions on how to use this tool.">
+<!ENTITY aboutNetworking.currentLogFile        "Current Log File:">
+<!ENTITY aboutNetworking.currentLogModules     "Current Log Modules:">
+<!ENTITY aboutNetworking.setLogFile            "Set Log File">
+<!ENTITY aboutNetworking.setLogModules         "Set Log Modules">
 <!ENTITY aboutNetworking.dnsLookup             "DNS Lookup">
 <!ENTITY aboutNetworking.dnsLookupButton       "Resolve">
 <!ENTITY aboutNetworking.dnsDomain             "Domain">
 <!ENTITY aboutNetworking.dnsLookupTableColumn  "IPs">