Bug 1402892 - Implement Request.destination. r=asuth,baku

This commit is contained in:
Catalin Badea 2018-03-09 14:11:27 +00:00
parent 8219c503ed
commit 1cf810fbe8
8 changed files with 94 additions and 104 deletions

View File

@ -33,7 +33,6 @@ DOM_PREF(StorageManagerEnabled, "dom.storageManager.enabled")
DOM_PREF(PromiseRejectionEventsEnabled, "dom.promise_rejection_events.enabled") DOM_PREF(PromiseRejectionEventsEnabled, "dom.promise_rejection_events.enabled")
DOM_PREF(PushEnabled, "dom.push.enabled") DOM_PREF(PushEnabled, "dom.push.enabled")
DOM_PREF(StreamsEnabled, "dom.streams.enabled") DOM_PREF(StreamsEnabled, "dom.streams.enabled")
DOM_PREF(RequestContextEnabled, "dom.requestcontext.enabled")
DOM_PREF(OffscreenCanvasEnabled, "gfx.offscreencanvas.enabled") DOM_PREF(OffscreenCanvasEnabled, "gfx.offscreencanvas.enabled")
DOM_PREF(WebkitBlinkDirectoryPickerEnabled, "dom.webkitBlink.dirPicker.enabled") DOM_PREF(WebkitBlinkDirectoryPickerEnabled, "dom.webkitBlink.dirPicker.enabled")
DOM_PREF(NetworkInformationEnabled, "dom.netinfo.enabled") DOM_PREF(NetworkInformationEnabled, "dom.netinfo.enabled")
@ -52,7 +51,6 @@ DOM_WEBIDL_PREF(StorageManagerEnabled)
DOM_WEBIDL_PREF(PromiseRejectionEventsEnabled) DOM_WEBIDL_PREF(PromiseRejectionEventsEnabled)
DOM_WEBIDL_PREF(PushEnabled) DOM_WEBIDL_PREF(PushEnabled)
DOM_WEBIDL_PREF(StreamsEnabled) DOM_WEBIDL_PREF(StreamsEnabled)
DOM_WEBIDL_PREF(RequestContextEnabled)
DOM_WEBIDL_PREF(OffscreenCanvasEnabled) DOM_WEBIDL_PREF(OffscreenCanvasEnabled)
DOM_WEBIDL_PREF(WebkitBlinkDirectoryPickerEnabled) DOM_WEBIDL_PREF(WebkitBlinkDirectoryPickerEnabled)
DOM_WEBIDL_PREF(NetworkInformationEnabled) DOM_WEBIDL_PREF(NetworkInformationEnabled)

View File

@ -941,9 +941,11 @@ Link::AsValueToContentPolicy(const nsAttrValue& aValue)
case DESTINATION_INVALID: case DESTINATION_INVALID:
return nsIContentPolicy::TYPE_INVALID; return nsIContentPolicy::TYPE_INVALID;
case DESTINATION_AUDIO: case DESTINATION_AUDIO:
return nsIContentPolicy::TYPE_INTERNAL_AUDIO;
case DESTINATION_TRACK: case DESTINATION_TRACK:
return nsIContentPolicy::TYPE_INTERNAL_TRACK;
case DESTINATION_VIDEO: case DESTINATION_VIDEO:
return nsIContentPolicy::TYPE_MEDIA; return nsIContentPolicy::TYPE_INTERNAL_VIDEO;
case DESTINATION_FONT: case DESTINATION_FONT:
return nsIContentPolicy::TYPE_FONT; return nsIContentPolicy::TYPE_FONT;
case DESTINATION_IMAGE: case DESTINATION_IMAGE:

View File

@ -231,116 +231,121 @@ InternalRequest::OverrideContentPolicyType(nsContentPolicyType aContentPolicyTyp
mContentPolicyTypeOverridden = true; mContentPolicyTypeOverridden = true;
} }
/* static */ /* static */ RequestDestination
RequestContext InternalRequest::MapContentPolicyTypeToRequestDestination(nsContentPolicyType aContentPolicyType)
InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aContentPolicyType)
{ {
RequestContext context = RequestContext::Internal; RequestDestination destination = RequestDestination::_empty;
switch (aContentPolicyType) { switch (aContentPolicyType) {
case nsIContentPolicy::TYPE_OTHER: case nsIContentPolicy::TYPE_OTHER:
context = RequestContext::Internal; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: case nsIContentPolicy::TYPE_INTERNAL_SCRIPT:
case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD:
case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER: case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER:
case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS: case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS:
context = RequestContext::Script; case nsIContentPolicy::TYPE_SCRIPT:
destination = RequestDestination::Script;
break; break;
case nsIContentPolicy::TYPE_INTERNAL_WORKER: case nsIContentPolicy::TYPE_INTERNAL_WORKER:
context = RequestContext::Worker; destination = RequestDestination::Worker;
break; break;
case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER: case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER:
context = RequestContext::Sharedworker; destination = RequestDestination::Sharedworker;
break; break;
case nsIContentPolicy::TYPE_IMAGESET:
case nsIContentPolicy::TYPE_INTERNAL_IMAGE: case nsIContentPolicy::TYPE_INTERNAL_IMAGE:
case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD: case nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD:
case nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON: case nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON:
context = RequestContext::Image; case nsIContentPolicy::TYPE_IMAGE:
destination = RequestDestination::Image;
break; break;
case nsIContentPolicy::TYPE_STYLESHEET:
case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET: case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET:
case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD: case nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD:
context = RequestContext::Style; destination = RequestDestination::Style;
break; break;
case nsIContentPolicy::TYPE_OBJECT:
case nsIContentPolicy::TYPE_INTERNAL_OBJECT: case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
context = RequestContext::Object; destination = RequestDestination::Object;
break; break;
case nsIContentPolicy::TYPE_INTERNAL_EMBED: case nsIContentPolicy::TYPE_INTERNAL_EMBED:
context = RequestContext::Embed; destination = RequestDestination::Embed;
break; break;
case nsIContentPolicy::TYPE_DOCUMENT: case nsIContentPolicy::TYPE_DOCUMENT:
context = RequestContext::Internal; case nsIContentPolicy::TYPE_SUBDOCUMENT:
break;
case nsIContentPolicy::TYPE_INTERNAL_IFRAME: case nsIContentPolicy::TYPE_INTERNAL_IFRAME:
context = RequestContext::Iframe; destination = RequestDestination::Document;
break; break;
case nsIContentPolicy::TYPE_INTERNAL_FRAME: case nsIContentPolicy::TYPE_INTERNAL_FRAME:
context = RequestContext::Frame; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_REFRESH: case nsIContentPolicy::TYPE_REFRESH:
context = RequestContext::Internal; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_XBL: case nsIContentPolicy::TYPE_XBL:
context = RequestContext::Internal; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_PING: case nsIContentPolicy::TYPE_PING:
context = RequestContext::Ping; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_XMLHTTPREQUEST:
case nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST: case nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST:
context = RequestContext::Xmlhttprequest; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE: case nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE:
context = RequestContext::Eventsource; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST:
context = RequestContext::Plugin; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_DTD: case nsIContentPolicy::TYPE_DTD:
context = RequestContext::Internal; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_FONT: case nsIContentPolicy::TYPE_FONT:
context = RequestContext::Font; destination = RequestDestination::Font;
break;
case nsIContentPolicy::TYPE_MEDIA:
destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_INTERNAL_AUDIO: case nsIContentPolicy::TYPE_INTERNAL_AUDIO:
context = RequestContext::Audio; destination = RequestDestination::Audio;
break; break;
case nsIContentPolicy::TYPE_INTERNAL_VIDEO: case nsIContentPolicy::TYPE_INTERNAL_VIDEO:
context = RequestContext::Video; destination = RequestDestination::Video;
break; break;
case nsIContentPolicy::TYPE_INTERNAL_TRACK: case nsIContentPolicy::TYPE_INTERNAL_TRACK:
context = RequestContext::Track; destination = RequestDestination::Track;
break; break;
case nsIContentPolicy::TYPE_WEBSOCKET: case nsIContentPolicy::TYPE_WEBSOCKET:
context = RequestContext::Internal; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_CSP_REPORT: case nsIContentPolicy::TYPE_CSP_REPORT:
context = RequestContext::Cspreport; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_XSLT: case nsIContentPolicy::TYPE_XSLT:
context = RequestContext::Xslt; destination = RequestDestination::Xslt;
break; break;
case nsIContentPolicy::TYPE_BEACON: case nsIContentPolicy::TYPE_BEACON:
context = RequestContext::Beacon; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_FETCH: case nsIContentPolicy::TYPE_FETCH:
context = RequestContext::Fetch; destination = RequestDestination::_empty;
break;
case nsIContentPolicy::TYPE_IMAGESET:
context = RequestContext::Imageset;
break; break;
case nsIContentPolicy::TYPE_WEB_MANIFEST: case nsIContentPolicy::TYPE_WEB_MANIFEST:
context = RequestContext::Manifest; destination = RequestDestination::Manifest;
break; break;
case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD: case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD:
context = RequestContext::Internal; destination = RequestDestination::_empty;
break; break;
case nsIContentPolicy::TYPE_SPECULATIVE: case nsIContentPolicy::TYPE_SPECULATIVE:
context = RequestContext::Internal; destination = RequestDestination::_empty;
break; break;
default: default:
MOZ_ASSERT(false, "Unhandled nsContentPolicyType value"); MOZ_ASSERT(false, "Unhandled nsContentPolicyType value");
break; break;
} }
return context;
return destination;
} }
// static // static
@ -376,7 +381,7 @@ InternalRequest::IsWorkerContentPolicy(nsContentPolicyType aContentPolicyType)
// "worker". // "worker".
// //
// Note, service workers are not included here because currently there is // Note, service workers are not included here because currently there is
// no way to generate a Request with a "serviceworker" RequestContext. // no way to generate a Request with a "serviceworker" RequestDestination.
// ServiceWorker scripts cannot be intercepted. // ServiceWorker scripts cannot be intercepted.
return aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_WORKER || return aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER; aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;

View File

@ -31,56 +31,36 @@ class PrincipalInfo;
namespace dom { namespace dom {
/* /*
* The mapping of RequestContext and nsContentPolicyType is currently as the * The mapping of RequestDestination and nsContentPolicyType is currently as the
* following. Note that this mapping is not perfect yet (see the TODO comments * following. Note that this mapping is not perfect yet (see the TODO comments
* below for examples). * below for examples).
* *
* RequestContext | nsContentPolicyType * RequestDestination| nsContentPolicyType
* ------------------+-------------------- * ------------------+--------------------
* audio | TYPE_INTERNAL_AUDIO * audio | TYPE_INTERNAL_AUDIO
* beacon | TYPE_BEACON * audioworklet | TODO
* cspreport | TYPE_CSP_REPORT * document | TYPE_DOCUMENT, TYPE_INTERNAL_IFRAME, TYPE_SUBDOCUMENT
* download |
* embed | TYPE_INTERNAL_EMBED * embed | TYPE_INTERNAL_EMBED
* eventsource |
* favicon |
* fetch | TYPE_FETCH
* font | TYPE_FONT * font | TYPE_FONT
* form | * image | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD,
* frame | TYPE_INTERNAL_FRAME * | TYPE_IMAGE, TYPE_INTERNAL_IMAGE_FAVICON, TYPE_IMAGESET
* hyperlink |
* iframe | TYPE_INTERNAL_IFRAME
* image | TYPE_INTERNAL_IMAGE, TYPE_INTERNAL_IMAGE_PRELOAD, TYPE_INTERNAL_IMAGE_FAVICON
* imageset | TYPE_IMAGESET
* import | Not supported by Gecko
* internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER, TYPE_SAVEAS_DOWNLOAD
* location |
* manifest | TYPE_WEB_MANIFEST * manifest | TYPE_WEB_MANIFEST
* object | TYPE_INTERNAL_OBJECT * object | TYPE_INTERNAL_OBJECT, TYPE_OBJECT
* ping | TYPE_PING * "paintworklet" | TODO
* plugin | TYPE_OBJECT_SUBREQUEST * report" | TODO
* prefetch | * script | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD, TYPE_SCRIPT
* script | TYPE_INTERNAL_SCRIPT, TYPE_INTERNAL_SCRIPT_PRELOAD * | TYPE_INTERNAL_SERVICE_WORKER, TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS
* sharedworker | TYPE_INTERNAL_SHARED_WORKER * sharedworker | TYPE_INTERNAL_SHARED_WORKER
* subresource | Not supported by Gecko * serviceworker | The spec lists this as a valid value for the enum,however it
* style | TYPE_INTERNAL_STYLESHEET, TYPE_INTERNAL_STYLESHEET_PRELOAD * | is impossible to observe a request with this destination value.
* style | TYPE_INTERNAL_STYLESHEET, TYPE_INTERNAL_STYLESHEET_PRELOAD,
* | TYPE_STYLESHEET
* track | TYPE_INTERNAL_TRACK * track | TYPE_INTERNAL_TRACK
* video | TYPE_INTERNAL_VIDEO * video | TYPE_INTERNAL_VIDEO
* worker | TYPE_INTERNAL_WORKER * worker | TYPE_INTERNAL_WORKER
* xmlhttprequest | TYPE_INTERNAL_XMLHTTPREQUEST
* eventsource | TYPE_INTERNAL_EVENTSOURCE
* xslt | TYPE_XSLT * xslt | TYPE_XSLT
* _empty | Default for everything else.
* *
* TODO: Figure out if TYPE_REFRESH maps to anything useful
* TODO: Figure out if TYPE_DTD maps to anything useful
* TODO: Figure out if TYPE_WEBSOCKET maps to anything useful
* TODO: Add a content type for prefetch
* TODO: Use the content type for manifest when it becomes available
* TODO: Add a content type for location
* TODO: Add a content type for hyperlink
* TODO: Add a content type for form
* TODO: Add a content type for favicon
* TODO: Add a content type for download
*/ */
class Request; class Request;
@ -432,10 +412,10 @@ public:
void void
OverrideContentPolicyType(nsContentPolicyType aContentPolicyType); OverrideContentPolicyType(nsContentPolicyType aContentPolicyType);
RequestContext RequestDestination
Context() const Destination() const
{ {
return MapContentPolicyTypeToRequestContext(mContentPolicyType); return MapContentPolicyTypeToRequestDestination(mContentPolicyType);
} }
bool bool
@ -570,8 +550,15 @@ private:
~InternalRequest(); ~InternalRequest();
static RequestContext // Map the content policy type to the associated fetch destination, as defined
MapContentPolicyTypeToRequestContext(nsContentPolicyType aContentPolicyType); // by the spec at https://fetch.spec.whatwg.org/#concept-request-destination.
// Note that while the HTML spec for the "Link" element and its "as" attribute
// (https://html.spec.whatwg.org/#attr-link-as) reuse fetch's definition of
// destination, and the Link class has an internal Link::AsDestination enum type,
// the latter is only a support type to map the string values via
// Link::ParseAsValue and Link::AsValueToContentPolicy to our canonical nsContentPolicyType.
static RequestDestination
MapContentPolicyTypeToRequestDestination(nsContentPolicyType aContentPolicyType);
static bool static bool
IsNavigationContentPolicy(nsContentPolicyType aContentPolicyType); IsNavigationContentPolicy(nsContentPolicyType aContentPolicyType);

View File

@ -91,10 +91,10 @@ public:
return mRequest->MozErrors(); return mRequest->MozErrors();
} }
RequestContext RequestDestination
Context() const Destination() const
{ {
return mRequest->Context(); return mRequest->Destination();
} }
void void

View File

@ -17,8 +17,7 @@ interface Request {
readonly attribute USVString url; readonly attribute USVString url;
[SameObject] readonly attribute Headers headers; [SameObject] readonly attribute Headers headers;
[Func="mozilla::dom::DOMPrefs::RequestContextEnabled"] readonly attribute RequestDestination destination;
readonly attribute RequestContext context;
readonly attribute USVString referrer; readonly attribute USVString referrer;
readonly attribute ReferrerPolicy referrerPolicy; readonly attribute ReferrerPolicy referrerPolicy;
readonly attribute RequestMode mode; readonly attribute RequestMode mode;
@ -65,14 +64,11 @@ dictionary RequestInit {
ObserverCallback observe; ObserverCallback observe;
}; };
// Gecko currently does not ship RequestContext, so please don't use it in IDL enum RequestDestination {
// that is exposed to script. "",
enum RequestContext { "audio", "audioworklet", "document", "embed", "font", "image", "manifest", "object",
"audio", "beacon", "cspreport", "download", "embed", "eventsource", "favicon", "fetch", "paintworklet", "report", "script", "sharedworker", "style", "track", "video",
"font", "form", "frame", "hyperlink", "iframe", "image", "imageset", "import", "worker", "xslt"
"internal", "location", "manifest", "object", "ping", "plugin", "prefetch", "script",
"sharedworker", "subresource", "style", "track", "video", "worker", "xmlhttprequest",
"xslt"
}; };
enum RequestMode { "same-origin", "no-cors", "cors", "navigate" }; enum RequestMode { "same-origin", "no-cors", "cors", "navigate" };

View File

@ -9,7 +9,8 @@ let frame;
// Set up the service worker and the frame. // Set up the service worker and the frame.
promise_test(t => { promise_test(t => {
const kScope = 'resources/empty.https.html'; const kScope = 'resources/';
const kFrame = 'resources/empty.https.html';
const kScript = 'resources/fetch-destination-worker-no-load-event.js'; const kScript = 'resources/fetch-destination-worker-no-load-event.js';
return service_worker_unregister_and_register(t, kScript, kScope) return service_worker_unregister_and_register(t, kScript, kScope)
.then(registration => { .then(registration => {
@ -20,7 +21,7 @@ promise_test(t => {
return wait_for_state(t, registration.installing, 'activated'); return wait_for_state(t, registration.installing, 'activated');
}) })
.then(() => { .then(() => {
return with_iframe(kScope); return with_iframe(kFrame);
}) })
.then(f => { .then(f => {
frame = f; frame = f;
@ -111,7 +112,6 @@ promise_test(async t => {
// style destination // style destination
///////////////////// /////////////////////
// @import - style destination // @import - style destination
promise_test(async t => { promise_test(async t => {
let node = frame.contentWindow.document.createElement("style"); let node = frame.contentWindow.document.createElement("style");

View File

@ -2,11 +2,13 @@ self.addEventListener('fetch', function(event) {
if (event.request.url.includes('dummy')) { if (event.request.url.includes('dummy')) {
event.waitUntil(async function() { event.waitUntil(async function() {
let destination = new URL(event.request.url).searchParams.get("dest"); let destination = new URL(event.request.url).searchParams.get("dest");
let client = await self.clients.get(event.clientId); var result = "FAIL";
if (event.request.destination == destination) { if (event.request.destination == destination) {
client.postMessage("PASS"); result = "PASS";
} else { }
client.postMessage("FAIL"); let cl = await clients.matchAll({includeUncontrolled: true});
for (i = 0; i < cl.length; i++) {
cl[i].postMessage(result);
} }
}()) }())
} }