Bug 1229177 - Show the tracking protection shield for fetch and XHR requests. r=jduell
authorBlake Kaplan <mrbkap@gmail.com>
Mon, 21 Dec 2015 14:12:52 -0800
changeset 277328 74d2f955790a65ffd4a11075b08937536cfc5272
parent 277327 05086686c328162f2a965a5ddd1ba27f46df4b95
child 277329 76d24989a1b0f0e980c352e559d7598088da1b56
push id69452
push usermrbkap@mozilla.com
push dateTue, 22 Dec 2015 18:26:53 +0000
treeherdermozilla-inbound@74d2f955790a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjduell
bugs1229177
milestone46.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 1229177 - Show the tracking protection shield for fetch and XHR requests. r=jduell
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()
 {
@@ -868,17 +868,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();
@@ -897,22 +897,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
@@ -161,17 +161,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,