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 315849 e4508f246a862379bc3e40380f1972fa808fc685
parent 315848 930ead1e6df1dd3e4d75c8fbbfdd83b5b38419c8
child 315850 f325ed1abef16a4090cd6d3fd7a81d245c2de705
push id20634
push usercbook@mozilla.com
push dateFri, 30 Sep 2016 10:10:13 +0000
treeherderfx-team@afe79b010d13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws, mcmanus
bugs1303762
milestone52.0a1
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">