Bug 1229177 - Show the tracking protection shield for fetch and XHR requests. r=jduell, a=sylvestre
authorBlake Kaplan <mrbkap@gmail.com>
Mon, 21 Dec 2015 14:12:52 -0800
changeset 310943 f79f1b917e14f361ed29852325e7139d0c97882b
parent 310942 464e2865229ba8bf20426b395606b6afed1beacc
child 310944 9f43613d01906828fd6cad84dbd8a3df32000c73
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjduell, sylvestre
bugs1229177
milestone45.0a2
Bug 1229177 - Show the tracking protection shield for fetch and XHR requests. r=jduell, a=sylvestre
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_trackingUI_6.js
browser/base/content/test/general/file_trackingUI_6.html
browser/base/content/test/general/file_trackingUI_6.js
browser/base/content/test/general/file_trackingUI_6.js^headers^
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -446,16 +446,22 @@ tags = trackingprotection
 tags = trackingprotection
 support-files =
   trackingPage.html
   benignPage.html
 [browser_trackingUI_5.js]
 tags = trackingprotection
 support-files =
   trackingPage.html
+[browser_trackingUI_6.js]
+tags = trackingprotection
+support-files =
+  file_trackingUI_6.html
+  file_trackingUI_6.js
+  file_trackingUI_6.js^headers^
 [browser_trackingUI_telemetry.js]
 tags = trackingprotection
 support-files =
   trackingPage.html
 [browser_typeAheadFind.js]
 skip-if = buildapp == 'mulet'
 [browser_unknownContentType_title.js]
 [browser_unloaddialogs.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_trackingUI_6.js
@@ -0,0 +1,46 @@
+const URL = "http://mochi.test:8888/browser/browser/base/content/test/general/file_trackingUI_6.html";
+
+function waitForSecurityChange(numChanges = 1) {
+  return new Promise(resolve => {
+    let n = 0;
+    let listener = {
+      onSecurityChange: function() {
+        n = n + 1;
+        info ("Received onSecurityChange event " + n + " of " + numChanges);
+        if (n >= numChanges) {
+          gBrowser.removeProgressListener(listener);
+          resolve();
+        }
+      }
+    };
+    gBrowser.addProgressListener(listener);
+  });
+}
+
+add_task(function* test_fetch() {
+  yield new Promise(resolve => {
+    SpecialPowers.pushPrefEnv({ set: [['privacy.trackingprotection.enabled', true]] },
+                              resolve);
+  });
+
+  yield BrowserTestUtils.withNewTab({ gBrowser, url: URL }, function* (newTabBrowser) {
+    let securityChange = waitForSecurityChange();
+    yield ContentTask.spawn(newTabBrowser, null, function* () {
+      yield content.wrappedJSObject.test_fetch()
+                   .then((response) => { ok(false, "should have denied the request"); })
+                   .catch((e) => { ok(true, `Caught exception: ${e}`); });
+    });
+    yield securityChange;
+
+    var TrackingProtection = newTabBrowser.ownerGlobal.TrackingProtection;
+    ok(TrackingProtection, "got TP object");
+    ok(TrackingProtection.enabled, "TP is enabled");
+
+    is(TrackingProtection.content.getAttribute("state"), "blocked-tracking-content",
+        'content: state="blocked-tracking-content"');
+    is(TrackingProtection.icon.getAttribute("state"), "blocked-tracking-content",
+        'icon: state="blocked-tracking-content"');
+    is(TrackingProtection.icon.getAttribute("tooltiptext"),
+       gNavigatorBundle.getString("trackingProtection.icon.activeTooltip"), "correct tooltip");
+  });
+});
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/file_trackingUI_6.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="UTF-8">
+  <title>Testing the shield from fetch and XHR</title>
+</head>
+<body>
+  <p>Hello there!</p>
+  <script type="application/javascript; version=1.8">
+    function test_fetch() {
+      let url = "http://trackertest.org/browser/browser/base/content/test/general/file_trackingUI_6.js";
+      return fetch(url);
+    }
+  </script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/file_trackingUI_6.js
@@ -0,0 +1,2 @@
+/* Some code goes here! */
+void 0;
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/file_trackingUI_6.js^headers^
@@ -0,0 +1,1 @@
+Access-Control-Allow-Origin: *
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -149,17 +149,17 @@ InterceptStreamListener::OnDataAvailable
   return NS_OK;
 }
 
 NS_IMETHODIMP
 InterceptStreamListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatusCode)
 {
   if (mOwner) {
     mOwner->DoPreOnStopRequest(aStatusCode);
-    mOwner->DoOnStopRequest(mOwner, mContext);
+    mOwner->DoOnStopRequest(mOwner, aStatusCode, mContext);
   }
   Cleanup();
   return NS_OK;
 }
 
 void
 InterceptStreamListener::Cleanup()
 {
@@ -934,17 +934,17 @@ HttpChannelChild::OnStopRequest(const ns
 
   DoPreOnStopRequest(channelStatus);
 
   { // We must flush the queue before we Send__delete__
     // (although we really shouldn't receive any msgs after OnStop),
     // so make sure this goes out of scope before then.
     AutoEventEnqueuer ensureSerialDispatch(mEventQ);
 
-    DoOnStopRequest(this, mListenerContext);
+    DoOnStopRequest(this, channelStatus, mListenerContext);
   }
 
   ReleaseListeners();
 
   if (mLoadFlags & LOAD_DOCUMENT_URI) {
     // Keep IPDL channel open, but only for updating security info.
     mKeptAlive = true;
     SendDocumentChannelCleanup();
@@ -963,22 +963,25 @@ HttpChannelChild::DoPreOnStopRequest(nsr
   mIsPending = false;
 
   if (!mCanceled && NS_SUCCEEDED(mStatus)) {
     mStatus = aStatus;
   }
 }
 
 void
-HttpChannelChild::DoOnStopRequest(nsIRequest* aRequest, nsISupports* aContext)
+HttpChannelChild::DoOnStopRequest(nsIRequest* aRequest, nsresult aChannelStatus, nsISupports* aContext)
 {
   LOG(("HttpChannelChild::DoOnStopRequest [this=%p]\n", this));
   MOZ_ASSERT(!mIsPending);
 
-  if (mStatus == NS_ERROR_TRACKING_URI) {
+  // NB: We use aChannelStatus here instead of mStatus because if there was an
+  // nsCORSListenerProxy on this request, it will override the tracking
+  // protection's return value.
+  if (aChannelStatus == NS_ERROR_TRACKING_URI) {
     nsChannelClassifier::SetBlockedTrackingContent(this);
   }
 
   mListener->OnStopRequest(aRequest, aContext, mStatus);
 
   mListener = 0;
   mListenerContext = 0;
   mCacheEntryAvailable = false;
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -165,17 +165,17 @@ private:
   nsresult ContinueAsyncOpen();
 
   void DoOnStartRequest(nsIRequest* aRequest, nsISupports* aContext);
   void DoOnStatus(nsIRequest* aRequest, nsresult status);
   void DoOnProgress(nsIRequest* aRequest, int64_t progress, int64_t progressMax);
   void DoOnDataAvailable(nsIRequest* aRequest, nsISupports* aContext, nsIInputStream* aStream,
                          uint64_t offset, uint32_t count);
   void DoPreOnStopRequest(nsresult aStatus);
-  void DoOnStopRequest(nsIRequest* aRequest, nsISupports* aContext);
+  void DoOnStopRequest(nsIRequest* aRequest, nsresult aChannelStatus, nsISupports* aContext);
 
   // Discard the prior interception and continue with the original network request.
   void ResetInterception();
 
   // Override this channel's pending response with a synthesized one. The content will be
   // asynchronously read from the pump.
   void OverrideWithSynthesizedResponse(nsAutoPtr<nsHttpResponseHead>& aResponseHead,
                                        nsIInputStream* aSynthesizedInput,