Last Comment Bug 629535 - add do-not-track signal to navigator global object
: add do-not-track signal to navigator global object
Status: VERIFIED FIXED
[qa!]
: dev-doc-complete, verified-aurora, verified-beta
Product: Core
Classification: Components
Component: DOM: Core & HTML (show other bugs)
: Trunk
: All All
: -- enhancement (vote)
: mozilla9
Assigned To: Justin Lebar (not reading bugmail)
:
Mentors:
Depends on: DNT
Blocks:
  Show dependency treegraph
 
Reported: 2011-01-27 15:32 PST by Sid Stamm [:geekboy or :sstamm]
Modified: 2013-09-23 16:49 PDT (History)
32 users (show)
See Also:
Crash Signature:
(edit)
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---


Attachments
Patch v1 (5.90 KB, patch)
2011-09-15 20:15 PDT, Justin Lebar (not reading bugmail)
no flags Details | Diff | Splinter Review
Patch v2 (5.90 KB, patch)
2011-09-16 00:00 PDT, Justin Lebar (not reading bugmail)
no flags Details | Diff | Splinter Review
Patch v3 (with updated test) (6.22 KB, patch)
2011-09-16 00:05 PDT, Justin Lebar (not reading bugmail)
jonas: review+
mounir: feedback+
Details | Diff | Splinter Review

Description Sid Stamm [:geekboy or :sstamm] 2011-01-27 15:32:28 PST
So that js-oriented tracking systems can take better advantage of the do-not-track header (bug 628197), we should expose a global variable when the "do not track" opt-out header feature is enabled.  This way, a web page can decide whether or not to even make the request for tracking code based on the user's choice, and through the global js navigator object, can examine the value sent with the HTTP header.

I'd like to propose we make do-not-track state accessible in this way:

<script>
if (!navigator.donottrack) {
  trackingStuffHere();
}
</script>

This likely involves editing nsIDOMNavigator.idl to include a new read-only string attribute "donottrack", and then the proper code in nsGlobalWindow.cpp::nsNavigator class to obtain the value that is transmitted with the header when the feature is enabled.
Comment 1 Brendan Eich [:brendan] 2011-01-27 18:07:07 PST
We use camelCaps for property names.

Also, a page can easily delete window.navigator even if navigator.doNotTrack is non-writable and non-configurable. FYI only.

/be
Comment 2 Anthon Pang 2011-02-01 09:12:11 PST
Sounds good.  Piwik trunk already has a check for the proposed variable to
abort the tracking request and delete existing first party cookies.

BTW navigator.doNotTrack doesn't have to be read-only.  The intent is that
setting the value to false doesn't disable the header.
Comment 3 Peter Eckersley 2011-02-03 17:54:13 PST
I think it's good to make this variable available by JS, but there is one nasty corner case to at least note, even if we can't necessarily fix it elegantly.  People who enable DNT may also disable JavaScript, probably by using NoScript.  They may also have a tracking cookie set.

So if servers assume that they can spot DNT from JS, but keep logging whatever cookies they receive at the HTTP layer, they may keep tracking a user who has set DNT 1.

One way to mitigate this problem would be to standardise a server-side response that says, "yep, I got your DNT request and I'm honoring it" (also optionally "I got it but I'm not honoring it for reason X").  It could be a header or something in the DOM.  Then at least we can spot cases where the client sends DNT but server-side infrastructure misses it.

A different way to mitigate the problem would be to note carefully in the documentation for this JS variable that if you rely on it you should detect JS disabled users and send them to a magic URI that checks for the header using Apache or whatever, and wipes tracking cookies accordingly.
Comment 4 Anthon Pang 2011-02-03 21:16:43 PST
Isn't the case of NoScript a non-issue?  If the tracking server is a third-party, but uses first party cookies via JS, then the first party tracking cookies won't be relayed to the tracking server, by virtue of JS being disabled.

If the tracking server is a first-party (or appears to be one via some proxy), there's no need for a specialized server response.  A server that honors the DNT header should delete the tracking cookies (ie setting the expiry date in the past).  That's what the (server-side) DNT plugin for Piwik does.
Comment 5 Peter Eckersley 2011-02-04 09:03:06 PST
Anthon: I see what you're saying.  If NoScript blocks the fetching of JS objects, this is trully an obscure corner case.  It could still happen if, say, it's a 3rd party iframe that *contains* JS, and the 3rd party's developer was expecting the JS to process DNT for the entire frame.
Comment 6 Anthon Pang 2011-02-04 09:43:51 PST
If that should happen (and I don't think it would if the developer implements both client- and server-side DNT checks), then the corrective action would be for NoScript to whitelist a 3rd party that does honor DNT.

The JS required to delete a tracking cookie is akin to a surgical procedure;  NoScript is a sledgehammer that materially changes the flow of JS execution..
Comment 7 Jonathan Mayer 2011-02-17 21:28:42 PST
A couple concerns.

First, how would the JavaScript flag handle third-party scripts included in a first-party (or other third-party) page?  For example, the common:

<script type="text/javascript" async="true" src="http://www.google-analytics.com/ga.js" />

If the user has enabled Do Not Track universally, there's no issue.  But if the user has enabled Do Not Track with some granularity (which we'd like to allow), the Google Analytics script would see the preference for its host page - not Google Analytics.

Second concern: What about the initial request for third-party JavaScript?  Assuming Do Not Track has implications for logging, a third party would still have to look for the request header.
Comment 8 Justin Lebar (not reading bugmail) 2011-09-15 15:12:05 PDT
I'm going to work on this.
Comment 9 Justin Lebar (not reading bugmail) 2011-09-15 16:11:20 PDT
(From comment 0)
> through the global js navigator object, [the page] can examine the value sent with the 
> HTTP header.

I think navigator.doNotTrack should take on [true, false, null], rather than ["0", "1", ""].  This way, |if (navigator.doNotTrack)| works as one would expect.
Comment 10 Justin Lebar (not reading bugmail) 2011-09-15 19:34:32 PDT
After speaking with Jonas and Sid, I think we should use a string with ["yes", "no", "unspecified"].  (Or some other string than "unspecified".)  This fails closed -- if someone does |if (navigator.doNotTrack)|, it'll always be true.  And it forces people to explicitly handle the "unspecified" case, rather than lumping it together with |true| or |false|.
Comment 11 Justin Lebar (not reading bugmail) 2011-09-15 20:15:50 PDT
Created attachment 560503 [details] [diff] [review]
Patch v1
Comment 12 Justin Lebar (not reading bugmail) 2011-09-15 20:16:29 PDT
Comment on attachment 560503 [details] [diff] [review]
Patch v1

Suggestions welcome on an alternative to "unspecified".
Comment 13 Mounir Lamouri (:mounir) 2011-09-15 20:37:59 PDT
Comment on attachment 560503 [details] [diff] [review]
Patch v1

Review of attachment 560503 [details] [diff] [review]:
-----------------------------------------------------------------

::: dom/tests/mochitest/general/test_bug629535.html
@@ +15,5 @@
> +
> +const dntPref = 'privacy.donottrackheader.enabled';
> +const oldDNT = SpecialPowers.getBoolPref(dntPref);
> +
> +SpecialPowers.setBoolPref(dntPref, true);

Could you check the default value before setting? If there is a default value.

@@ +16,5 @@
> +const dntPref = 'privacy.donottrackheader.enabled';
> +const oldDNT = SpecialPowers.getBoolPref(dntPref);
> +
> +SpecialPowers.setBoolPref(dntPref, true);
> +is(navigator.doNotTrack, "yes");

Could you check with setting "false" too?

@@ +21,5 @@
> +
> +SpecialPowers.clearUserPref(dntPref);
> +is(navigator.doNotTrack, "unspecified");
> +
> +dump('Old DNT is ' + oldDNT + '\n\n\n');

I think you do not want to keep this.
Comment 14 Justin Lebar (not reading bugmail) 2011-09-15 20:48:36 PDT
> Could you check the default value before setting? If there is a default value.

Do you mean that I should test that oldDNT == false?
Comment 15 Justin Lebar (not reading bugmail) 2011-09-16 00:00:00 PDT
Created attachment 560517 [details] [diff] [review]
Patch v2
Comment 16 Justin Lebar (not reading bugmail) 2011-09-16 00:05:15 PDT
Created attachment 560518 [details] [diff] [review]
Patch v3 (with updated test)
Comment 17 Mounir Lamouri (:mounir) 2011-09-16 00:09:16 PDT
Comment on attachment 560518 [details] [diff] [review]
Patch v3 (with updated test)

Review of attachment 560518 [details] [diff] [review]:
-----------------------------------------------------------------

I would have name the test test_navigator_doNotTrack.html instead of using a cryptic bug number.

f=me. If Jonas wants to delegate his review to me, feel free to take this as a r+ ;)

::: dom/base/nsGlobalWindow.cpp
@@ +11132,5 @@
> +  if (gDoNotTrackEnabled) {
> +    aResult.AssignLiteral("yes");
> +  }
> +  else {
> +    aResult.AssignLiteral("unspecified");

I would have do:
aResult.AssignLiteral(gDoNotTrackEnabled ? "yes" : "unspecified");

but that might just be a matter of taste.
Comment 18 Jonas Sicking (:sicking) PTO Until July 5th 2011-09-19 12:31:06 PDT
Comment on attachment 560518 [details] [diff] [review]
Patch v3 (with updated test)

Review of attachment 560518 [details] [diff] [review]:
-----------------------------------------------------------------

Looks good to me. I don't think you can use AssignLiteral with Mounir's suggestion due to the template magic that AssignLiteral uses.
Comment 19 Justin Lebar (not reading bugmail) 2011-09-19 13:01:13 PDT
Inbound: https://hg.mozilla.org/integration/mozilla-inbound/rev/40e482df5ab5
Comment 21 Eric Shepherd [:sheppy] 2011-10-14 12:46:15 PDT
Documented:

https://developer.mozilla.org/en/DOM/navigator.doNotTrack

Added to the window.navigator page list of properties:

https://developer.mozilla.org/en/DOM/window.navigator

And mentioned on Firefox 9 for developers.
Comment 22 Ioana (away) 2011-11-10 02:20:00 PST
Verified that the automated test has passed on all OSs:
https://tbpl.mozilla.org/php/getParsedLog.php?id=7322343&full=1&branch=mozilla-beta
https://tbpl.mozilla.org/php/getParsedLog.php?id=7322331&full=1&branch=mozilla-beta
https://tbpl.mozilla.org/php/getParsedLog.php?id=7322030&full=1&branch=mozilla-beta
https://tbpl.mozilla.org/php/getParsedLog.php?id=7320492&full=1&branch=mozilla-beta

Verified as fixed with manual tests (added here http://bit.ly/sXdHaE) on Firefox 9.0 beta 1:
Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:9.0) Gecko/20100101 Firefox/9.0
Mozilla/5.0 (Windows NT 6.1; rv:9.0) Gecko/20100101 Firefox/9.0
Mozilla/5.0 (X11; Linux i686; rv:9.0) Gecko/20100101 Firefox/9.0
Comment 23 Ioana (away) 2011-11-14 02:04:24 PST
Verified as fixed on Aurora(Fx 10): 
Manual tests - http://bit.ly/sXdHaE
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0a2) Gecko/20111109 Firefox/10.0a2
Mozilla/5.0 (X11; Linux i686; rv:10.0a2) Gecko/20111109 Firefox/10.0a2
Mozilla/5.0 (Windows NT 5.1; rv:10.0a2) Gecko/20111110 Firefox/10.0a2
Mozilla/5.0 (Windows NT 6.1; rv:10.0a2) Gecko/20111113 Firefox/10.0a2

Automated test - dom/tests/mochitest/general/test_bug629535.html
https://tbpl.mozilla.org/php/getParsedLog.php?id=7374068&full=1&branch=mozilla-aurora
https://tbpl.mozilla.org/php/getParsedLog.php?id=7368649&full=1&branch=mozilla-aurora
https://tbpl.mozilla.org/php/getParsedLog.php?id=7368492&full=1&branch=mozilla-aurora
https://tbpl.mozilla.org/php/getParsedLog.php?id=7374991&full=1&branch=mozilla-aurora

Verified as fixed on Central(Fx11):
Manual tests - http://bit.ly/sXdHaE
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:11.0a1) Gecko/20111109 Firefox/11.0a1
Mozilla/5.0 (X11; Linux i686; rv:11.0a1) Gecko/20111109 Firefox/11.0a1
Mozilla/5.0 (Windows NT 5.1; rv:11.0a1) Gecko/20111110 Firefox/11.0a1
Mozilla/5.0 (Windows NT 6.1; rv:11.0a1) Gecko/20111113 Firefox/11.0a1

Automated test - dom/tests/mochitest/general/test_bug629535.html
https://tbpl.mozilla.org/php/getParsedLog.php?id=7383147&full=1&branch=services-central
https://tbpl.mozilla.org/php/getParsedLog.php?id=7382741&full=1&branch=services-central
https://tbpl.mozilla.org/php/getParsedLog.php?id=7383091&full=1&branch=services-central
https://tbpl.mozilla.org/php/getParsedLog.php?id=7383079&full=1&branch=services-central

This issue will be set as VERIFIED FIXED as soon as I can be verified on Firefox 9.0 RC.
Comment 24 Ioana (away) 2011-12-21 04:28:42 PST
This feature has been released in Firefox 9.0 and signed off by QA. No issues were found.

Note You need to log in before you can comment on or make changes to this bug.