import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1209162 - Create OriginAttributes subtypes. IGNORE IDL r=sicking. (c2cbe04ef3)
- Bug 1220570 - Potential cookie lost while downgrading from Aurora 44 to 43. r=jduell (1a0111c842)
- Bug 1217456: Add a security flag for controlling redirects. Use this flag in fetch() implementation. r=bkelly,jduell (79d449e479)
- Bug 1112040 - Add a mochitest. r=bholley (566a05f720)
- Bug 1171215 - Compute third-partyness in the loadinfo instead of nsIHttpChannelInternal so that other protocols correctly respect the third-party cookie pref. r=sicking/ckerschb (06f7a10a83)
- better backport of  Bug 485941 - Stack overflow using overly-deep XML tree (DoS). r=bzbarsky (ac43feeffa)
- Bug 1182546 - Use channel->Open2() in parser/htmlparser/nsExpatDriver.cpp (r=bz) (42768f373a)
- Bug 1163435 part 1 - [css-grid][css-flexbox] Propagate an explicit CB width/height to the reflow state to resolve percentage lengths for grid items properly. Resolve percent against the size in the same axis for abs.pos. children too. r=dholbert (a55463fb05)
- Bug 1163435 part 2 - tests. (bb683c5fc6)
- Bug 1223282 - Make NS_AUTOMARGIN be a different value than NS_UNCONSTRAINEDSIZE to avoid having clamped huge margin values be interpreted as auto margins. r=roc (4cdfe0f277)
- Bug 1224230 - Explicitly store the lineContainer's writing mode in InlineIntrinsicISizeData. r=dbaron (6474515223)
- Bug 1221043. Revert to including trailing whitespace for accessibility APIs. r=marcoz,mats (406018c163)
- Bug 1227113 - Fix some indentation issues in ServiceWorkerManager, r=janv (2b343bde09)
- Bug 1223116 P1 Expose nsIServiceWorkerManager.shouldReportToWindow(). r=catalinb (02899e429d)
- Bug 1226441 - Part 1: Add wpt test verifying fetch event waits for activate to complete; r=catalinb (e8eb3e6e7a)
- Bug 1209865 - Add gecko profiler marker when mark() of User Timing API is called. r=baku (f48d76e395)
- Bug 1169068 - Performance.translateTime(), r=bz (38cd1c31b2)
- Bug 1226441 - Part 2: Delay functional event dispatch until service worker is activated; r=catalinb (778cd3dd24)
- Bug 1178233 - [non-e10s] The update process doesn't work within about:serviceworkers in non-e10s mode. Test. r=baku (4f8b6f53f8)
- Bug 1188545 - Disable unstable test: test_aboutserviceworkers.html. a=testonly (4bbe106693)
- Bug 1219255 - We should be able to attach to a service worker;r=amarchesini (0d6b71b4ec)
- Bug 1222464 - Part 2: Implement FetchEvent.clientId; r=jdm (9c8abd62dd)
- Bug 1218150 - Mark the members of Clients as NewObject; r=bzbarsky (b6b00a586c)
- Bug 1222464 - Part 3: Implement Clients.get(); r=jdm (f5ca60d801)
- Bug 1222464 - Part 1: Save a client ID for top-level navigations on the docshell and assign it as the document ID when we start loading the document; r=jdm (7dcb5ce2b6)
- Bug 1218141 - Add some SameObject and NewObject annotations to ServiceWorkerGlobalScope; r=bzbarsky (5019f58c7a)
- Bug 1218190 - Add a pref to enable Clients.openWindow, r=catalinb (dbb6d007dd)
- Bug 1218142 - Remove ServiceWorkerGlobalScope.onbeforeevicted/onevicted; r=bzbarsky (029de6f8ec)
- Bug 1218146 - Move WindowClient.frameType to Client.frameType; r=bzbarsky (00f0211276)
- Bug 1218147 - Make WindowClient.focus() NewObject; r=bzbarsky (3c6aea4b67)
- Bug 1189659 - Part 1 - Continue service worker job queue when life cycle events expire. r=bkelly (aa09cd9c60)
- Bug 1227932 - Fix Service Workers SoftUpdate and registration.update code paths. r=ehsan (24567b23c0)
- Bug 1189659 - Part 2 - Remove set of scopes being updated from ServiceWorkerManager. r=bkelly (ce581b095c)
- Bug 1189659 - Part 3 - Use separate synchronization queues for service worker register jobs and install jobs. r=bkelly (9c408a22ed)
- Bug 1189659 - Part 4 - Fix race in test_install_event.html. r=bkelly (3186ffb808)
- Bug 1189659 - Part 5 - Fix race in skip-waiting.https.html and add some logging for SkipWaitingFlag in ServiceWorkerManager. r=ehsan (4e5ddda6f3)
- Bug 1229056 - Implement ClientQueryOptions.includeUncontrolled; r=jdm (dbe56aa60d)
- namespace (3b0863d42d)
- Bug 1201127 - Return the same ServiceWorkerRegistration object from service worker APIs dealing with the same underlying registration object; r=jdm (c542688ae0)
- Bug 1171583 - Remove mutable warning from |nsSimpleURI::SetUserPass|. r=bz (73934deaad)
- Bug 1206199 - Extend channelwrapper to mediate OnStartRequest, OnStopRequest, OnDataAvailable (r=sicking) (758a7ec65c)
- Bug 1186783 (part 4) - Replace nsBaseHashtable::EnumerateRead() calls in netwerk/ with iterators. r=valentin. (681bdba278)
- Bug 1186783 (part 3) - Replace nsBaseHashtable::EnumerateRead() calls in netwerk/ with iterators. r=valentin. (76b8b7191e)
- Bug 1186783 (part 2) - Replace nsBaseHashtable::EnumerateRead() calls in netwerk/ with iterators. r=valentin. (5c0743ac49)
- Bug 1186783 (part 1) - Replace nsBaseHashtable::EnumerateRead() calls in netwerk/ with iterators. r=valentin. (952cc720cc)
- Bug 1186783 (part 5) - Replace nsBaseHashtable::EnumerateRead() calls in netwerk/ with iterators. r=valentin. (25b9735c52)
- Bug 1186783 (part 1) - Replace nsBaseHashtable::EnumerateRead() calls in netwerk/. r=michal. (ae52425809)
- Bug 1186783 (follow-up) - Bustage fix for Gonk. (d4a1b769bd)
- add back some hotfix stuff, even if unused (fe32076c5b)
- Bug 1068087: Switch about:plugins to run remotely. r=mconley (bc4316dd03)
- Bug 1214058: Part 1 - Add a simplified JSON-based add-on update protocol. r=Mossop (a3198884d5)
- Bug 1214058: Part 2 - Run add-on update tests against comparable JSON and RDF manifests. r=Mossop (aa6a796e6f)
- Bug 1152977 - Enable by default DEAA for desktop platforms that use OpenGL compositor. r=jmuizelaar (bfa9efd5c8)
This commit is contained in:
2023-03-16 14:16:15 +08:00
parent f7d677cddd
commit 393bc6639f
219 changed files with 7737 additions and 4026 deletions
+3 -1
View File
@@ -230,7 +230,9 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
nsIContent* containerElm = containerNode->IsElement() ?
containerNode->AsElement() : nullptr;
nsIFrame::RenderedText text = textFrame->GetRenderedText();
nsIFrame::RenderedText text = textFrame->GetRenderedText(0,
UINT32_MAX, nsIFrame::TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
// Remove text accessible if rendered text is empty.
if (textAcc) {
+3 -1
View File
@@ -1091,7 +1091,9 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
// Create accessible for visible text frames.
if (content->IsNodeOfType(nsINode::eTEXT)) {
nsIFrame::RenderedText text = frame->GetRenderedText();
nsIFrame::RenderedText text = frame->GetRenderedText(0,
UINT32_MAX, nsIFrame::TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
// Ignore not rendered text nodes and whitespace text nodes between table
// cells.
if (text.mString.IsEmpty() ||
+3 -1
View File
@@ -139,7 +139,9 @@ nsTextEquivUtils::AppendTextEquivFromTextContent(nsIContent *aContent,
if (aContent->TextLength() > 0) {
nsIFrame *frame = aContent->GetPrimaryFrame();
if (frame) {
nsIFrame::RenderedText text = frame->GetRenderedText();
nsIFrame::RenderedText text = frame->GetRenderedText(0,
UINT32_MAX, nsIFrame::TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
aString->Append(text.mString);
} else {
// If aContent is an object that is display: none, we have no a frame.
+3 -1
View File
@@ -394,7 +394,9 @@ Accessible::VisibilityState()
if (frame->GetType() == nsGkAtoms::textFrame &&
!(frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
frame->GetRect().IsEmpty()) {
nsIFrame::RenderedText text = frame->GetRenderedText();
nsIFrame::RenderedText text = frame->GetRenderedText(0,
UINT32_MAX, nsIFrame::TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
if (text.mString.IsEmpty()) {
return states::INVISIBLE;
}
+4 -2
View File
@@ -1985,7 +1985,8 @@ HyperTextAccessible::ContentToRenderedOffset(nsIFrame* aFrame, int32_t aContentO
"Call on primary frame only");
nsIFrame::RenderedText text = aFrame->GetRenderedText(aContentOffset,
aContentOffset + 1);
aContentOffset + 1, nsIFrame::TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
*aRenderedOffset = text.mOffsetWithinNodeRenderedText;
return NS_OK;
@@ -2009,7 +2010,8 @@ HyperTextAccessible::RenderedToContentOffset(nsIFrame* aFrame, uint32_t aRendere
"Call on primary frame only");
nsIFrame::RenderedText text = aFrame->GetRenderedText(aRenderedOffset,
aRenderedOffset + 1, nsIFrame::TextOffsetType::OFFSETS_IN_RENDERED_TEXT);
aRenderedOffset + 1, nsIFrame::TextOffsetType::OFFSETS_IN_RENDERED_TEXT,
nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
*aContentOffset = text.mOffsetWithinNodeText;
return NS_OK;
@@ -113,7 +113,7 @@
'A esoteric weapon wielded by only the most ' +
'formidable warriors, for its unrelenting strict' +
' power is unfathomable.',
'• Lists of Programming Languages', 'Lisp',
'• Lists of Programming Languages', 'Lisp ',
'1. Scheme', '2. Racket', '3. Clojure',
'4. Standard Lisp', 'link-0', ' Lisp',
'checkbox-1-5', ' LeLisp', '• JavaScript',
@@ -52,7 +52,7 @@
gQueue, docAcc, ObjectTraversalRule, null,
['Main Title', 'Lorem ipsum ',
'dolor', ' sit amet. Integer vitae urna leo, id ',
'semper', ' nulla.', 'Second Section Title',
'semper', ' nulla. ', 'Second Section Title',
'Sed accumsan luctus lacus, vitae mollis arcu tristique vulputate.',
'An ', 'embedded', ' document.', 'Hide me', 'Link 1', 'Link 2',
'Link 3', 'Hello', 'World']);
@@ -90,7 +90,7 @@
gQueue, docAcc, ObjectTraversalRule,
getAccessible(doc.getElementById('paragraph-1')),
['Lorem ipsum ', 'dolor', ' sit amet. Integer vitae urna leo, id ',
'semper', ' nulla.']);
'semper', ' nulla. ']);
gQueue.push(new setModalRootInvoker(docAcc, docAcc.parent,
NS_ERROR_INVALID_ARG));
@@ -16,8 +16,8 @@
function doTest()
{
var iframeDoc = [ getNode("iframe").contentDocument ];
testCharacterCount(iframeDoc, 13);
testText(iframeDoc, 0, 13, "outbodyinbody");
testCharacterCount(iframeDoc, 15);
testText(iframeDoc, 0, 15, "outbody inbody ");
SimpleTest.finish();
}
@@ -58,7 +58,7 @@
////////////////////////////////////////////////////////////////////////
// getTextAtOffset line boundary
testTextAtOffset(0, BOUNDARY_LINE_START, "line", 0, 4,
testTextAtOffset(0, BOUNDARY_LINE_START, "line ", 0, 5,
"hypertext3", kOk, kOk, kOk);
// XXX: see bug 634202.
@@ -14,9 +14,9 @@
function doTest()
{
testTextAtOffset("line_test_1", BOUNDARY_LINE_START,
[[0, 6, "Line 1", 0, 6],
[6, 6, "", 6, 6],
[7, 13, "Line 3", 7, 13]]);
[[0, 6, "Line 1 ", 0, 7],
[7, 7, "", 7, 7],
[8, 15, "Line 3 ", 8, 15]]);
//////////////////////////////////////////////////////////////////////////
// __h__e__l__l__o__ __m__y__ __f__r__i__e__n__d__
@@ -114,10 +114,10 @@
[ [ 0, 3, "foo\n", 0, 4 ], [ 4, 4, "", 4, 4 ] ]);
//////////////////////////////////////////////////////////////////////////
// 'Hello world'
// 'Hello world ' (\n is rendered as space)
testTextAtOffset([ "ht_4" ], BOUNDARY_LINE_START,
[ [ 0, 11, "Hello world", 0, 11 ] ]);
[ [ 0, 12, "Hello world ", 0, 12 ] ]);
//////////////////////////////////////////////////////////////////////////
// list items
@@ -89,7 +89,7 @@
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color,
"background-color": gComputedStyle.backgroundColor};
testTextAttrs(ID, 27, attrs, defAttrs, 27, 49);
testTextAttrs(ID, 27, attrs, defAttrs, 27, 50);
//////////////////////////////////////////////////////////////////////////
// area4
@@ -110,7 +110,7 @@
tempElem = tempElem.parentNode;
gComputedStyle = document.defaultView.getComputedStyle(tempElem, "");
attrs = {"color": gComputedStyle.color};
testTextAttrs(ID, 34, attrs, defAttrs, 33, 45);
testTextAttrs(ID, 34, attrs, defAttrs, 33, 46);
//////////////////////////////////////////////////////////////////////////
// area5: "Green!*!RedNormal"
@@ -144,7 +144,7 @@
// Normal
attrs = {};
testTextAttrs(ID, 11, attrs, defAttrs, 11, 17);
testTextAttrs(ID, 11, attrs, defAttrs, 11, 18);
//////////////////////////////////////////////////////////////////////////
// area6 (CSS vertical-align property, refer to bug 445938 for details
@@ -323,7 +323,7 @@
testTextAttrs(ID, 152, attrs, defAttrs, 151, 164);
attrs = {};
testTextAttrs(ID, 165, attrs, defAttrs, 164, 171);
testTextAttrs(ID, 165, attrs, defAttrs, 164, 172);
//////////////////////////////////////////////////////////////////////////
// area10, different single style spans in non-styled paragraph
@@ -383,7 +383,7 @@
testTextAttrs(ID, 111, attrs, defAttrs, 110, 123);
attrs = {};
testTextAttrs(ID, 124, attrs, defAttrs, 123, 130);
testTextAttrs(ID, 124, attrs, defAttrs, 123, 131);
//////////////////////////////////////////////////////////////////////////
// area11, "font-weight" tests
@@ -410,7 +410,7 @@
testTextAttrs(ID, 51, attrs, defAttrs, 51, 57);
attrs = { };
testTextAttrs(ID, 57, attrs, defAttrs, 57, 96);
testTextAttrs(ID, 57, attrs, defAttrs, 57, 97);
//////////////////////////////////////////////////////////////////////////
// test out of range offset
@@ -485,7 +485,7 @@
testTextAttrs(ID, 27, attrs, defAttrs, 27, 31);
attrs = { };
testTextAttrs(ID, 31, attrs, defAttrs, 31, 44);
testTextAttrs(ID, 31, attrs, defAttrs, 31, 45);
//////////////////////////////////////////////////////////////////////////
// area17, "text-decoration" tests
@@ -527,7 +527,7 @@
"text-line-through-style": "wavy",
"text-line-through-color": "rgb(0, 0, 0)",
};
testTextAttrs(ID, 39, attrs, defAttrs, 39, 43);
testTextAttrs(ID, 39, attrs, defAttrs, 39, 44);
//////////////////////////////////////////////////////////////////////////
// area18, "auto-generation text" tests
@@ -557,7 +557,7 @@
testTextAttrs(ID, 11, attrs, defAttrs, 10, 17);
attrs = {};
testTextAttrs(ID, 18, attrs, defAttrs, 17, 27);
testTextAttrs(ID, 18, attrs, defAttrs, 17, 28);
//////////////////////////////////////////////////////////////////////////
// area20, "aOffset as -1 (Mozilla Bug 789621)" test
@@ -71,7 +71,7 @@
turnCaretBrowsing(true);
// test caret offsets
testCaretOffset(document, 15);
testCaretOffset(document, 16);
testCaretOffset("textbox", -1);
testCaretOffset("textarea", -1);
testCaretOffset("p", -1);
@@ -49,14 +49,14 @@
},
{
role: ROLE_TEXT_LEAF,
name: "Hello3"
name: "Hello3 "
},
{
role: ROLE_PARAGRAPH,
children: [
{
role: ROLE_TEXT_LEAF,
name: "Hello4"
name: "Hello4 "
}
]
}
@@ -71,7 +71,7 @@
children: [
{
role: ROLE_TEXT_LEAF,
name: "helllo"
name: "helllo "
},
{
role: ROLE_PARAGRAPH,
@@ -84,7 +84,7 @@
},
{
role: ROLE_TEXT_LEAF,
name: "hello"
name: "hello "
}
]
};
+2
View File
@@ -1270,6 +1270,8 @@ pref("view_source.tab", false);
// Interception is still disabled.
pref("dom.serviceWorkers.enabled", true);
pref("dom.serviceWorkers.openWindow.enabled", true);
// Enable Push API.
pref("dom.push.enabled", true);
+64 -16
View File
@@ -28,26 +28,74 @@ namespace mozilla {
using dom::URLParams;
void OriginAttributes::InheritFromDocShellParent(const OriginAttributes& aParent)
void
PrincipalOriginAttributes::InheritFromDocShellToDoc(const DocShellOriginAttributes& aAttrs,
const nsIURI* aURI)
{
mAppId = aParent.mAppId;
mInBrowser = aParent.mInBrowser;
mUserContextId = aParent.mUserContextId;
mSignedPkg = aParent.mSignedPkg;
mAppId = aAttrs.mAppId;
mInBrowser = aAttrs.mInBrowser;
// addonId is computed from the principal URI and never propagated
mUserContextId = aAttrs.mUserContextId;
// TODO:
// Bug 1225349 - PrincipalOriginAttributes should inherit mSignedPkg
// accordingly by URI
mSignedPkg = aAttrs.mSignedPkg;
}
bool OriginAttributes::CopyFromLoadContext(nsILoadContext* aLoadContext)
void
PrincipalOriginAttributes::InheritFromNecko(const NeckoOriginAttributes& aAttrs)
{
OriginAttributes attrs;
bool result = aLoadContext->GetOriginAttributes(attrs);
NS_ENSURE_TRUE(result, false);
mAppId = aAttrs.mAppId;
mInBrowser = aAttrs.mInBrowser;
mAppId = attrs.mAppId;
mInBrowser = attrs.mInBrowser;
mAddonId = attrs.mAddonId;
mUserContextId = attrs.mUserContextId;
mSignedPkg = attrs.mSignedPkg;
return true;
// addonId is computed from the principal URI and never propagated
mUserContextId = aAttrs.mUserContextId;
mSignedPkg = aAttrs.mSignedPkg;
}
void
DocShellOriginAttributes::InheritFromDocToChildDocShell(const PrincipalOriginAttributes& aAttrs)
{
mAppId = aAttrs.mAppId;
mInBrowser = aAttrs.mInBrowser;
// addonId is computed from the principal URI and never propagated
mUserContextId = aAttrs.mUserContextId;
// TODO:
// Bug 1225353 - DocShell/NeckoOriginAttributes should inherit
// mSignedPkg accordingly by mSignedPkgInBrowser
mSignedPkg = aAttrs.mSignedPkg;
}
void
NeckoOriginAttributes::InheritFromDocToNecko(const PrincipalOriginAttributes& aAttrs)
{
mAppId = aAttrs.mAppId;
mInBrowser = aAttrs.mInBrowser;
// addonId is computed from the principal URI and never propagated
mUserContextId = aAttrs.mUserContextId;
// TODO:
// Bug 1225353 - DocShell/NeckoOriginAttributes should inherit
// mSignedPkg accordingly by mSignedPkgInBrowser
}
void
NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs)
{
mAppId = aAttrs.mAppId;
mInBrowser = aAttrs.mInBrowser;
// addonId is computed from the principal URI and never propagated
mUserContextId = aAttrs.mUserContextId;
// TODO:
// Bug 1225353 - DocShell/NeckoOriginAttributes should inherit
// mSignedPkg accordingly by mSignedPkgInBrowser
}
void
@@ -442,7 +490,7 @@ BasePrincipal::GetUnknownAppId(bool* aUnknownAppId)
}
already_AddRefed<BasePrincipal>
BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs)
BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const PrincipalOriginAttributes& aAttrs)
{
// If the URI is supposed to inherit the security context of whoever loads it,
// we shouldn't make a codebase principal for it.
+92 -35
View File
@@ -14,26 +14,19 @@
#include "mozilla/dom/ChromeUtilsBinding.h"
class nsIContentSecurityPolicy;
class nsILoadContext;
class nsIObjectOutputStream;
class nsIObjectInputStream;
class nsIURI;
class nsExpandedPrincipal;
namespace mozilla {
// Base OriginAttributes class. This has several subclass flavors, and is not
// directly constructable itself.
class OriginAttributes : public dom::OriginAttributesDictionary
{
public:
OriginAttributes() {}
OriginAttributes(uint32_t aAppId, bool aInBrowser)
{
mAppId = aAppId;
mInBrowser = aInBrowser;
}
explicit OriginAttributes(const OriginAttributesDictionary& aOther)
: OriginAttributesDictionary(aOther) {}
bool operator==(const OriginAttributes& aOther) const
{
return mAppId == aOther.mAppId &&
@@ -47,28 +40,6 @@ public:
return !(*this == aOther);
}
// The docshell often influences the origin attributes of content loaded
// inside of it, and in some cases also influences the origin attributes of
// content loaded in child docshells. We say that a given attribute "lives on
// the docshell" to indicate that this attribute is specified by the docshell
// (if any) associated with a given content document.
//
// In practice, this usually means that we need to store a copy of those
// attributes on each docshell, or provide methods on the docshell to compute
// them on-demand.
// We could track each of these attributes individually, but since the
// majority of the existing origin attributes currently live on the docshell,
// it's cleaner to simply store an entire OriginAttributes struct on each
// docshell, and selectively copy them to child docshells and content
// principals in a manner that implements our desired semantics.
//
// This method is used to propagate attributes from parent to child
// docshells.
void InheritFromDocShellParent(const OriginAttributes& aParent);
// Copy from the origin attributes of the nsILoadContext.
bool CopyFromLoadContext(nsILoadContext* aLoadContext);
// Serializes/Deserializes non-default values into the suffix format, i.e.
// |!key1=value1&key2=value2|. If there are no non-default attributes, this
// returns an empty string.
@@ -79,6 +50,92 @@ public:
// |uri!key1=value1&key2=value2| and returns the uri without the suffix.
bool PopulateFromOrigin(const nsACString& aOrigin,
nsACString& aOriginNoSuffix);
protected:
OriginAttributes() {}
explicit OriginAttributes(const OriginAttributesDictionary& aOther)
: OriginAttributesDictionary(aOther) {}
};
class PrincipalOriginAttributes;
class DocShellOriginAttributes;
class NeckoOriginAttributes;
// Various classes in Gecko contain OriginAttributes members, and those
// OriginAttributes get propagated to other classes according to certain rules.
// For example, the OriginAttributes on the docshell affect the OriginAttributes
// for the principal of a document loaded inside it, whose OriginAttributes in
// turn affect those of network loads and child docshells. To codify and
// centralize these rules, we introduce separate subclasses for the different
// flavors, and a variety of InheritFrom* methods to implement the transfer
// behavior.
// For OriginAttributes stored on principals.
class PrincipalOriginAttributes : public OriginAttributes
{
public:
PrincipalOriginAttributes() {}
PrincipalOriginAttributes(uint32_t aAppId, bool aInBrowser)
{
mAppId = aAppId;
mInBrowser = aInBrowser;
}
// Inheriting OriginAttributes from docshell to document when user navigates.
//
// @param aAttrs Origin Attributes of the docshell.
// @param aURI The URI of the document.
void InheritFromDocShellToDoc(const DocShellOriginAttributes& aAttrs,
const nsIURI* aURI);
// Inherit OriginAttributes from Necko.
void InheritFromNecko(const NeckoOriginAttributes& aAttrs);
};
// For OriginAttributes stored on docshells / loadcontexts / browsing contexts.
class DocShellOriginAttributes : public OriginAttributes
{
public:
DocShellOriginAttributes() {}
DocShellOriginAttributes(uint32_t aAppId, bool aInBrowser)
{
mAppId = aAppId;
mInBrowser = aInBrowser;
}
// Inheriting OriginAttributes from document to child docshell when an
// <iframe> is created.
//
// @param aAttrs Origin Attributes of the document.
void
InheritFromDocToChildDocShell(const PrincipalOriginAttributes& aAttrs);
};
// For OriginAttributes stored on Necko.
class NeckoOriginAttributes : public OriginAttributes
{
public:
NeckoOriginAttributes() {}
NeckoOriginAttributes(uint32_t aAppId, bool aInBrowser)
{
mAppId = aAppId;
mInBrowser = aInBrowser;
}
// Inheriting OriginAttributes from document to necko when a network request
// is made.
void InheritFromDocToNecko(const PrincipalOriginAttributes& aAttrs);
void InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs);
};
// For operating on OriginAttributes not associated with any data structure.
class GenericOriginAttributes : public OriginAttributes
{
public:
GenericOriginAttributes() {}
explicit GenericOriginAttributes(const OriginAttributesDictionary& aOther)
: OriginAttributes(aOther) {}
};
class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary
@@ -167,9 +224,9 @@ public:
static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
static already_AddRefed<BasePrincipal>
CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs);
CreateCodebasePrincipal(nsIURI* aURI, const PrincipalOriginAttributes& aAttrs);
const OriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
const PrincipalOriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
uint32_t AppId() const { return mOriginAttributes.mAppId; }
uint32_t UserContextId() const { return mOriginAttributes.mUserContextId; }
bool IsInBrowserElement() const { return mOriginAttributes.mInBrowser; }
@@ -201,7 +258,7 @@ protected:
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
OriginAttributes mOriginAttributes;
PrincipalOriginAttributes mOriginAttributes;
};
} // namespace mozilla
+1 -1
View File
@@ -160,7 +160,7 @@ nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx,
return false;
}
OriginAttributes attrs;
PrincipalOriginAttributes attrs;
attrs.PopulateFromSuffix(suffix);
info = ContentPrincipalInfo(attrs, spec);
}
+2 -2
View File
@@ -44,7 +44,7 @@ nsNullPrincipal::CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom)
}
/* static */ already_AddRefed<nsNullPrincipal>
nsNullPrincipal::Create(const OriginAttributes& aOriginAttributes)
nsNullPrincipal::Create(const PrincipalOriginAttributes& aOriginAttributes)
{
RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal();
nsresult rv = nullPrin->Init(aOriginAttributes);
@@ -54,7 +54,7 @@ nsNullPrincipal::Create(const OriginAttributes& aOriginAttributes)
}
nsresult
nsNullPrincipal::Init(const OriginAttributes& aOriginAttributes)
nsNullPrincipal::Init(const PrincipalOriginAttributes& aOriginAttributes)
{
mOriginAttributes = aOriginAttributes;
+2 -2
View File
@@ -52,9 +52,9 @@ public:
// Returns null on failure.
static already_AddRefed<nsNullPrincipal>
Create(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes());
Create(const mozilla::PrincipalOriginAttributes& aOriginAttributes = mozilla::PrincipalOriginAttributes());
nsresult Init(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes());
nsresult Init(const mozilla::PrincipalOriginAttributes& aOriginAttributes = mozilla::PrincipalOriginAttributes());
virtual void GetScriptLocation(nsACString &aStr) override;
+2 -2
View File
@@ -85,7 +85,7 @@ nsPrincipal::~nsPrincipal()
}
nsresult
nsPrincipal::Init(nsIURI *aCodebase, const OriginAttributes& aOriginAttributes)
nsPrincipal::Init(nsIURI *aCodebase, const PrincipalOriginAttributes& aOriginAttributes)
{
NS_ENSURE_STATE(!mInitialized);
NS_ENSURE_ARG(aCodebase);
@@ -391,7 +391,7 @@ nsPrincipal::Read(nsIObjectInputStream* aStream)
rv = aStream->ReadCString(suffix);
NS_ENSURE_SUCCESS(rv, rv);
OriginAttributes attrs;
PrincipalOriginAttributes attrs;
bool ok = attrs.PopulateFromSuffix(suffix);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
+1 -1
View File
@@ -34,7 +34,7 @@ public:
nsPrincipal();
// Init() must be called before the principal is in a usable state.
nsresult Init(nsIURI* aCodebase, const mozilla::OriginAttributes& aOriginAttributes);
nsresult Init(nsIURI* aCodebase, const mozilla::PrincipalOriginAttributes& aOriginAttributes);
virtual void GetScriptLocation(nsACString& aStr) override;
void SetURI(nsIURI* aURI);
+16 -14
View File
@@ -290,7 +290,7 @@ nsScriptSecurityManager::AppStatusForPrincipal(nsIPrincipal *aPrin)
// The app could contain a cross-origin iframe - make sure that the content
// is actually same-origin with the app.
MOZ_ASSERT(inMozBrowser == false, "Checked this above");
OriginAttributes attrs(appId, false);
PrincipalOriginAttributes attrs(appId, false);
nsCOMPtr<nsIPrincipal> appPrin = BasePrincipal::CreateCodebasePrincipal(appURI, attrs);
NS_ENSURE_TRUE(appPrin, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
return aPrin->Equals(appPrin) ? status
@@ -361,7 +361,7 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
}
nsresult
nsScriptSecurityManager::MaybeSetAddonIdFromURI(OriginAttributes& aAttrs, nsIURI* aURI)
nsScriptSecurityManager::MaybeSetAddonIdFromURI(PrincipalOriginAttributes& aAttrs, nsIURI* aURI)
{
nsAutoCString scheme;
nsresult rv = aURI->GetScheme(scheme);
@@ -404,7 +404,8 @@ nsScriptSecurityManager::GetChannelURIPrincipal(nsIChannel* aChannel,
return GetLoadContextCodebasePrincipal(uri, loadContext, aPrincipal);
}
OriginAttributes attrs(UNKNOWN_APP_ID, false);
//TODO: Bug 1211590. inherit Origin Attributes from LoadInfo.
PrincipalOriginAttributes attrs(UNKNOWN_APP_ID, false);
rv = MaybeSetAddonIdFromURI(attrs, uri);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
@@ -1017,7 +1018,7 @@ NS_IMETHODIMP
nsScriptSecurityManager::GetSimpleCodebasePrincipal(nsIURI* aURI,
nsIPrincipal** aPrincipal)
{
OriginAttributes attrs(UNKNOWN_APP_ID, false);
PrincipalOriginAttributes attrs(UNKNOWN_APP_ID, false);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
@@ -1027,7 +1028,7 @@ NS_IMETHODIMP
nsScriptSecurityManager::GetNoAppCodebasePrincipal(nsIURI* aURI,
nsIPrincipal** aPrincipal)
{
OriginAttributes attrs(NO_APP_ID, false);
PrincipalOriginAttributes attrs(NO_APP_ID, false);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
@@ -1044,7 +1045,7 @@ NS_IMETHODIMP
nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, JS::Handle<JS::Value> aOriginAttributes,
JSContext* aCx, nsIPrincipal** aPrincipal)
{
OriginAttributes attrs;
PrincipalOriginAttributes attrs;
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
return NS_ERROR_INVALID_ARG;
}
@@ -1057,7 +1058,7 @@ NS_IMETHODIMP
nsScriptSecurityManager::CreateNullPrincipal(JS::Handle<JS::Value> aOriginAttributes,
JSContext* aCx, nsIPrincipal** aPrincipal)
{
OriginAttributes attrs;
PrincipalOriginAttributes attrs;
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
return NS_ERROR_INVALID_ARG;
}
@@ -1091,7 +1092,7 @@ nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI,
NS_ENSURE_TRUE(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
NS_ERROR_INVALID_ARG);
OriginAttributes attrs(aAppId, aInMozBrowser);
PrincipalOriginAttributes attrs(aAppId, aInMozBrowser);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
@@ -1103,10 +1104,13 @@ nsScriptSecurityManager::
nsILoadContext* aLoadContext,
nsIPrincipal** aPrincipal)
{
OriginAttributes attrs;
bool result = attrs.CopyFromLoadContext(aLoadContext);
DocShellOriginAttributes docShellAttrs;
bool result = aLoadContext->GetOriginAttributes(docShellAttrs);;
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
PrincipalOriginAttributes attrs;
attrs.InheritFromDocShellToDoc(docShellAttrs, aURI);
nsresult rv = MaybeSetAddonIdFromURI(attrs, aURI);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
@@ -1119,10 +1123,8 @@ nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI* aURI,
nsIDocShell* aDocShell,
nsIPrincipal** aPrincipal)
{
OriginAttributes attrs;
nsDocShell* docShell= nsDocShell::Cast(aDocShell);
bool result = attrs.CopyFromLoadContext(docShell);
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
PrincipalOriginAttributes attrs;
attrs.InheritFromDocShellToDoc(nsDocShell::Cast(aDocShell)->GetOriginAttributes(), aURI);
nsresult rv = MaybeSetAddonIdFromURI(attrs, aURI);
NS_ENSURE_SUCCESS(rv, rv);
+2 -2
View File
@@ -28,7 +28,7 @@ class nsIStringBundle;
class nsSystemPrincipal;
namespace mozilla {
class OriginAttributes;
class PrincipalOriginAttributes;
} // namespace mozilla
/////////////////////////////
@@ -121,7 +121,7 @@ private:
AddSitesToFileURIWhitelist(const nsCString& aSiteList);
// If aURI is a moz-extension:// URI, set mAddonId to the associated addon.
nsresult MaybeSetAddonIdFromURI(mozilla::OriginAttributes& aAttrs, nsIURI* aURI);
nsresult MaybeSetAddonIdFromURI(mozilla::PrincipalOriginAttributes& aAttrs, nsIURI* aURI);
nsCOMPtr<nsIPrincipal> mSystemPrincipal;
bool mPrefInitialized;
+9 -9
View File
@@ -4,34 +4,34 @@
#include "gtest/gtest.h"
#include "mozilla/BasePrincipal.h"
using mozilla::OriginAttributes;
using mozilla::PrincipalOriginAttributes;
static void
TestSuffix(const OriginAttributes& attrs)
TestSuffix(const PrincipalOriginAttributes& attrs)
{
nsAutoCString suffix;
attrs.CreateSuffix(suffix);
OriginAttributes attrsFromSuffix;
PrincipalOriginAttributes attrsFromSuffix;
attrsFromSuffix.PopulateFromSuffix(suffix);
EXPECT_EQ(attrs, attrsFromSuffix);
}
TEST(OriginAttributes, Suffix_default)
TEST(PrincipalOriginAttributes, Suffix_default)
{
OriginAttributes attrs;
PrincipalOriginAttributes attrs;
TestSuffix(attrs);
}
TEST(OriginAttributes, Suffix_appId_inBrowser)
TEST(PrincipalOriginAttributes, Suffix_appId_inBrowser)
{
OriginAttributes attrs(1, true);
PrincipalOriginAttributes attrs(1, true);
TestSuffix(attrs);
}
TEST(OriginAttributes, Suffix_maxAppId_inBrowser)
TEST(PrincipalOriginAttributes, Suffix_maxAppId_inBrowser)
{
OriginAttributes attrs(4294967295, true);
PrincipalOriginAttributes attrs(4294967295, true);
TestSuffix(attrs);
}
+2 -1
View File
@@ -23,7 +23,8 @@ LoadContext::LoadContext(nsIPrincipal* aPrincipal,
, mIsNotNull(true)
#endif
{
mOriginAttributes = BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
PrincipalOriginAttributes poa = BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
mOriginAttributes = DocShellOriginAttributes(poa.mAppId, poa.mInBrowser);
if (!aOptionalBase) {
return;
+4 -4
View File
@@ -43,7 +43,7 @@ public:
// by child process.
LoadContext(const IPC::SerializedLoadContext& aToCopy,
dom::Element* aTopFrameElement,
OriginAttributes& aAttrs)
DocShellOriginAttributes& aAttrs)
: mTopFrameElement(do_GetWeakReference(aTopFrameElement))
, mNestedFrameId(0)
, mIsContent(aToCopy.mIsContent)
@@ -60,7 +60,7 @@ public:
// by child process.
LoadContext(const IPC::SerializedLoadContext& aToCopy,
uint64_t aNestedFrameId,
OriginAttributes& aAttrs)
DocShellOriginAttributes& aAttrs)
: mTopFrameElement(nullptr)
, mNestedFrameId(aNestedFrameId)
, mIsContent(aToCopy.mIsContent)
@@ -77,7 +77,7 @@ public:
bool aIsContent,
bool aUsePrivateBrowsing,
bool aUseRemoteTabs,
const OriginAttributes& aAttrs)
const DocShellOriginAttributes& aAttrs)
: mTopFrameElement(do_GetWeakReference(aTopFrameElement))
, mNestedFrameId(0)
, mIsContent(aIsContent)
@@ -117,7 +117,7 @@ private:
bool mIsContent;
bool mUsePrivateBrowsing;
bool mUseRemoteTabs;
OriginAttributes mOriginAttributes;
DocShellOriginAttributes mOriginAttributes;
#ifdef DEBUG
bool mIsNotNull;
#endif
+1 -1
View File
@@ -49,7 +49,7 @@ public:
bool mIsContent;
bool mUsePrivateBrowsing;
bool mUseRemoteTabs;
mozilla::OriginAttributes mOriginAttributes;
mozilla::DocShellOriginAttributes mOriginAttributes;
};
// Function to serialize over IPDL
+27 -12
View File
@@ -9446,7 +9446,8 @@ nsresult
nsDocShell::CreatePrincipalFromReferrer(nsIURI* aReferrer,
nsIPrincipal** aResult)
{
OriginAttributes attrs = GetOriginAttributes();
PrincipalOriginAttributes attrs;
attrs.InheritFromDocShellToDoc(GetOriginAttributes(), aReferrer);
nsCOMPtr<nsIPrincipal> prin =
BasePrincipal::CreateCodebasePrincipal(aReferrer, attrs);
prin.forget(aResult);
@@ -13890,13 +13891,19 @@ nsDocShell::GetAppId(uint32_t* aAppId)
return parent->GetAppId(aAppId);
}
OriginAttributes
DocShellOriginAttributes
nsDocShell::GetOriginAttributes()
{
OriginAttributes attrs;
DocShellOriginAttributes attrs;
RefPtr<nsDocShell> parent = GetParentDocshell();
if (parent) {
attrs.InheritFromDocShellParent(parent->GetOriginAttributes());
nsCOMPtr<nsIPrincipal> parentPrin = parent->GetDocument()->NodePrincipal();
PrincipalOriginAttributes poa = BasePrincipal::Cast(parentPrin)->OriginAttributesRef();
attrs.InheritFromDocToChildDocShell(poa);
} else {
// This is the topmost docshell, so we get the mSignedPkg attribute if it is
// set before.
attrs.mSignedPkg = mSignedPkg;
}
if (mOwnOrContainingAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
@@ -13907,9 +13914,6 @@ nsDocShell::GetOriginAttributes()
attrs.mInBrowser = true;
}
// Bug 1209162 will address the inheritance of each attributes.
attrs.mSignedPkg = mSignedPkg;
return attrs;
}
@@ -13919,8 +13923,7 @@ nsDocShell::GetOriginAttributes(JS::MutableHandle<JS::Value> aVal)
JSContext* cx = nsContentUtils::GetCurrentJSContext();
MOZ_ASSERT(cx);
OriginAttributes attrs = GetOriginAttributes();
bool ok = ToJSValue(cx, attrs, aVal);
bool ok = ToJSValue(cx, GetOriginAttributes(), aVal);
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
return NS_OK;
}
@@ -14119,7 +14122,8 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNonSubresourceReques
}
if (aIsNonSubresourceRequest) {
OriginAttributes attrs(GetAppId(), GetIsInBrowserElement());
PrincipalOriginAttributes attrs;
attrs.InheritFromDocShellToDoc(GetOriginAttributes(), aURI);
*aShouldIntercept = swm->IsAvailable(attrs, aURI);
return NS_OK;
}
@@ -14206,15 +14210,26 @@ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel,
if (!doc) {
return NS_ERROR_NOT_AVAILABLE;
}
} else {
// For top-level navigations, save a document ID which will be passed to
// the FetchEvent as the clientId later on.
rv = nsIDocument::GenerateDocumentId(mInterceptedDocumentId);
NS_ENSURE_SUCCESS(rv, rv);
}
bool isReload = mLoadType & LOAD_CMD_RELOAD;
OriginAttributes attrs(GetAppId(), GetIsInBrowserElement());
nsCOMPtr<nsIURI> uri;
rv = channel->GetURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
PrincipalOriginAttributes attrs;
attrs.InheritFromDocShellToDoc(GetOriginAttributes(), uri);
ErrorResult error;
nsCOMPtr<nsIRunnable> runnable =
swm->PrepareFetchEvent(attrs, doc, aChannel, isReload, isSubresourceLoad, error);
swm->PrepareFetchEvent(attrs, doc, mInterceptedDocumentId, aChannel,
isReload, isSubresourceLoad, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
+9 -2
View File
@@ -268,14 +268,19 @@ public:
// is no longer applied
void NotifyAsyncPanZoomStopped();
mozilla::OriginAttributes GetOriginAttributes();
void SetInFrameSwap(bool aInSwap)
{
mInFrameSwap = aInSwap;
}
bool InFrameSwap();
mozilla::DocShellOriginAttributes GetOriginAttributes();
void GetInterceptedDocumentId(nsAString& aId)
{
aId = mInterceptedDocumentId;
}
private:
// An observed docshell wrapper is created when recording markers is enabled.
mozilla::UniquePtr<mozilla::ObservedDocShell> mObserved;
@@ -1014,6 +1019,8 @@ protected:
// for a signed package.
nsString mSignedPkg;
nsString mInterceptedDocumentId;
private:
nsCString mForcedCharset;
nsCString mParentCharset;
+4 -3
View File
@@ -11,7 +11,7 @@ interface nsIDOMElement;
%{C++
#ifdef MOZILLA_INTERNAL_API
#include "mozilla/BasePrincipal.h" // for OriginAttributes
#include "mozilla/BasePrincipal.h" // for DocShellOriginAttributes
#include "mozilla/dom/ScriptSettings.h" // for AutoJSAPI
#include "xpcpublic.h" // for PrivilegedJunkScope
#include "nsContentUtils.h" // for IsSystemPrincipal
@@ -140,7 +140,7 @@ interface nsILoadContext : nsISupports
/**
* The C++ getter for origin attributes.
*/
bool GetOriginAttributes(mozilla::OriginAttributes& aAttrs)
bool GetOriginAttributes(mozilla::DocShellOriginAttributes& aAttrs)
{
mozilla::dom::AutoJSAPI jsapi;
bool ok = jsapi.Init(xpc::PrivilegedJunkScope());
@@ -156,12 +156,13 @@ interface nsILoadContext : nsISupports
MOZ_ASSERT(nsContentUtils::IsSystemPrincipal(nsContentUtils::ObjectPrincipal(obj)));
JSAutoCompartment ac(jsapi.cx(), obj);
mozilla::OriginAttributes attrs;
mozilla::DocShellOriginAttributes attrs;
ok = attrs.Init(jsapi.cx(), v);
NS_ENSURE_TRUE(ok, false);
aAttrs = attrs;
return true;
}
#endif
%}
};
+2 -2
View File
@@ -56,7 +56,7 @@ ChromeUtils::OriginAttributesToSuffix(dom::GlobalObject& aGlobal,
nsCString& aSuffix)
{
OriginAttributes attrs(aAttrs);
GenericOriginAttributes attrs(aAttrs);
attrs.CreateSuffix(aSuffix);
}
@@ -65,7 +65,7 @@ ChromeUtils::OriginAttributesMatchPattern(dom::GlobalObject& aGlobal,
const dom::OriginAttributesDictionary& aAttrs,
const dom::OriginAttributesPatternDictionary& aPattern)
{
OriginAttributes attrs(aAttrs);
GenericOriginAttributes attrs(aAttrs);
OriginAttributesPattern pattern(aPattern);
return pattern.Matches(attrs);
}
+9 -5
View File
@@ -500,16 +500,20 @@ private:
frame = *mCallData->mTopStackFrame;
}
nsString id;
nsString id = frame.mFilename;
nsString innerID;
if (mWorkerPrivate->IsSharedWorker()) {
id = NS_LITERAL_STRING("SharedWorker");
innerID = NS_LITERAL_STRING("SharedWorker");
} else if (mWorkerPrivate->IsServiceWorker()) {
id = NS_LITERAL_STRING("ServiceWorker");
innerID = NS_LITERAL_STRING("ServiceWorker");
// Use scope as ID so the webconsole can decide if the message should
// show up per tab
id.AssignWithConversion(mWorkerPrivate->WorkerName());
} else {
id = NS_LITERAL_STRING("Worker");
innerID = NS_LITERAL_STRING("Worker");
}
mCallData->SetIDs(frame.mFilename, id);
mCallData->SetIDs(id, innerID);
}
// Now we could have the correct window (if we are not window-less).
+27 -88
View File
@@ -187,8 +187,6 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel,
nsresult rv;
bool doForce = false;
bool checkWindowChain = true;
bool parentIsThird = false;
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
do_QueryInterface(aChannel);
if (httpChannelInternal) {
@@ -206,109 +204,50 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel,
*aResult = false;
return NS_OK;
}
if (flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_THIRD_PARTY) {
// Check that the two PARENT_IS_{THIRD,SAME}_PARTY are mutually exclusive.
MOZ_ASSERT(!(flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_SAME_PARTY));
// If we're not forcing and we know that the window chain of the channel
// is third party, then we know now that we're third party.
if (!doForce) {
*aResult = true;
return NS_OK;
}
checkWindowChain = false;
parentIsThird = true;
} else {
// In e10s, we can't check the parent chain in the parent, so we do so
// in the child and send the result to the parent.
// Note that we only check the window chain if neither
// THIRD_PARTY_PARENT_IS_* flag is set.
checkWindowChain = !(flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_SAME_PARTY);
parentIsThird = false;
}
}
bool parentIsThird = false;
// Obtain the URI from the channel, and its base domain.
nsCOMPtr<nsIURI> channelURI;
aChannel->GetURI(getter_AddRefs(channelURI));
NS_ENSURE_TRUE(channelURI, NS_ERROR_INVALID_ARG);
rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
if (NS_FAILED(rv))
return rv;
nsCString channelDomain;
rv = GetBaseDomain(channelURI, channelDomain);
if (NS_FAILED(rv))
return rv;
if (aURI) {
// Determine whether aURI is foreign with respect to channelURI.
bool result;
rv = IsThirdPartyInternal(channelDomain, aURI, &result);
if (NS_FAILED(rv))
return rv;
// If it's foreign, or we're forcing, we're done.
if (result || doForce) {
*aResult = result;
return NS_OK;
if (!doForce) {
if (nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo()) {
parentIsThird = loadInfo->GetIsInThirdPartyContext();
if (!parentIsThird &&
loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_DOCUMENT) {
// Check if the channel itself is third-party to its own requestor.
// Unforunately, we have to go through the loading principal.
nsCOMPtr<nsIURI> parentURI;
loadInfo->LoadingPrincipal()->GetURI(getter_AddRefs(parentURI));
rv = IsThirdPartyInternal(channelDomain, parentURI, &parentIsThird);
if (NS_FAILED(rv))
return rv;
}
} else {
NS_WARNING("Found channel with no loadinfo, assuming third-party request");
parentIsThird = true;
}
}
// If we've already computed this in the child process, we're done.
if (!checkWindowChain) {
// If we're not comparing to a URI, we have our answer. Otherwise, if
// parentIsThird, we're not forcing and we know that we're a third-party
// request.
if (!aURI || parentIsThird) {
*aResult = parentIsThird;
return NS_OK;
}
// Find the associated window and its parent window.
nsCOMPtr<nsILoadContext> ctx;
NS_QueryNotificationCallbacks(aChannel, ctx);
if (!ctx) return NS_ERROR_INVALID_ARG;
// If there is no window, the consumer kicking off the load didn't provide one
// to the channel. This is limited to loads of certain types of resources. If
// those loads require cookies, the forceAllowThirdPartyCookie property should
// be set on the channel.
nsCOMPtr<nsIDOMWindow> ourWin, parentWin;
ctx->GetAssociatedWindow(getter_AddRefs(ourWin));
if (!ourWin) return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsPIDOMWindow> piOurWin = do_QueryInterface(ourWin);
MOZ_ASSERT(piOurWin);
// We use GetScriptableParent rather than GetParent because we consider
// <iframe mozbrowser/mozapp> to be a top-level frame.
parentWin = piOurWin->GetScriptableParent();
NS_ENSURE_TRUE(parentWin, NS_ERROR_INVALID_ARG);
// Check whether this is the document channel for this window (representing a
// load of a new page). In that situation we want to avoid comparing
// channelURI to ourWin, since what's in ourWin right now will be replaced as
// the channel loads. This covers the case of a freshly kicked-off load
// (e.g. the user typing something in the location bar, or clicking on a
// bookmark), where the window's URI hasn't yet been set, and will be bogus.
// It also covers situations where a subframe is navigated to someting that
// is same-origin with all its ancestors. This is a bit of a nasty hack, but
// we will hopefully flag these channels better later.
nsLoadFlags flags;
rv = aChannel->GetLoadFlags(&flags);
NS_ENSURE_SUCCESS(rv, rv);
if (flags & nsIChannel::LOAD_DOCUMENT_URI) {
if (SameCOMIdentity(ourWin, parentWin)) {
// We only need to compare aURI to the channel URI -- the window's will be
// bogus. We already know the answer.
*aResult = false;
return NS_OK;
}
// Make sure to still compare to ourWin's ancestors
ourWin = parentWin;
}
// Check the window hierarchy. This covers most cases for an ordinary page
// load from the location bar.
return IsThirdPartyWindow(ourWin, channelURI, aResult);
// Determine whether aURI is foreign with respect to channelURI.
return IsThirdPartyInternal(channelDomain, aURI, aResult);
}
NS_IMETHODIMP
+60 -18
View File
@@ -240,6 +240,7 @@
#include "mozilla/dom/BoxObject.h"
#include "gfxVR.h"
#include "gfxPrefs.h"
#include "nsISupportsPrimitives.h"
#include "nsISpeculativeConnect.h"
@@ -1663,6 +1664,11 @@ nsDocument::~nsDocument()
mImageTracker.Clear();
mPlugins.Clear();
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
os->RemoveObserver(this, "service-worker-get-client");
}
}
NS_INTERFACE_TABLE_HEAD(nsDocument)
@@ -2064,6 +2070,11 @@ nsDocument::Init()
mozilla::HoldJSObjects(this);
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
os->AddObserver(this, "service-worker-get-client", /* ownsWeak */ true);
}
return NS_OK;
}
@@ -4702,7 +4713,10 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager();
if (swm) {
swm->MaybeStartControlling(this);
nsAutoString documentId;
static_cast<nsDocShell*>(docShell.get())->GetInterceptedDocumentId(documentId);
swm->MaybeStartControlling(this, documentId);
mMaybeServiceWorkerControlled = true;
}
}
@@ -12269,6 +12283,16 @@ nsDocument::Observe(nsISupports *aSubject,
// We don't want to style the chrome window, only app ones.
OnAppThemeChanged();
}
} else if (strcmp("service-worker-get-client", aTopic) == 0) {
nsAutoString clientId;
GetOrCreateId(clientId);
if (!clientId.IsEmpty() && clientId.Equals(aData)) {
nsCOMPtr<nsISupportsInterfacePointer> ifptr = do_QueryInterface(aSubject);
if (ifptr) {
ifptr->SetData(static_cast<nsIDocument*>(this));
ifptr->SetDataIID(&NS_GET_IID(nsIDocument));
}
}
}
return NS_OK;
}
@@ -13113,35 +13137,53 @@ nsIDocument::CreateHTMLElement(nsIAtom* aTag)
return element.forget();
}
/* static */
nsresult
nsIDocument::GetId(nsAString& aId)
nsIDocument::GenerateDocumentId(nsAString& aId)
{
nsresult rv;
nsCOMPtr<nsIUUIDGenerator> uuidgen = do_GetService("@mozilla.org/uuid-generator;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsID id;
rv = uuidgen->GenerateUUIDInPlace(&id);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Build a string in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format
char buffer[NSID_LENGTH];
id.ToProvidedString(buffer);
NS_ConvertASCIItoUTF16 uuid(buffer);
// Remove {} and the null terminator
aId.Assign(Substring(uuid, 1, NSID_LENGTH - 3));
return NS_OK;
}
nsresult
nsIDocument::GetOrCreateId(nsAString& aId)
{
if (mId.IsEmpty()) {
nsresult rv;
nsCOMPtr<nsIUUIDGenerator> uuidgen = do_GetService("@mozilla.org/uuid-generator;1", &rv);
nsresult rv = GenerateDocumentId(mId);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsID id;
rv = uuidgen->GenerateUUIDInPlace(&id);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Build a string in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format
char buffer[NSID_LENGTH];
id.ToProvidedString(buffer);
NS_ConvertASCIItoUTF16 uuid(buffer);
// Remove {} and the null terminator
mId.Assign(Substring(uuid, 1, NSID_LENGTH - 3));
}
aId = mId;
return NS_OK;
}
void
nsIDocument::SetId(const nsAString& aId)
{
MOZ_ASSERT(mId.IsEmpty(), "Cannot set the document ID after we have one");
mId = aId;
}
bool
MarkDocumentTreeToBeInSyncOperation(nsIDocument* aDoc, void* aData)
{
+13 -14
View File
@@ -280,18 +280,10 @@ nsFrameLoader::LoadURI(nsIURI* aURI)
NS_IMETHODIMP
nsFrameLoader::SwitchProcessAndLoadURI(nsIURI* aURI, const nsACString& aPackageId)
{
nsCOMPtr<nsIURI> URIToLoad = aURI;
RefPtr<TabParent> tp = nullptr;
nsCString signedPkgOrigin;
if (!aPackageId.IsEmpty()) {
// Only when aPackageId is not empty would signed package origin
// be meaningful.
nsPrincipal::GetOriginForURI(aURI, signedPkgOrigin);
}
MutableTabContext context;
nsresult rv = GetNewTabContext(&context, signedPkgOrigin, aPackageId);
nsresult rv = GetNewTabContext(&context, aURI, aPackageId);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<Element> ownerElement = mOwnerContent;
@@ -305,7 +297,7 @@ nsFrameLoader::SwitchProcessAndLoadURI(nsIURI* aURI, const nsACString& aPackageI
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
LoadURI(URIToLoad);
LoadURI(aURI);
return NS_OK;
}
@@ -3015,14 +3007,21 @@ nsFrameLoader::MaybeUpdatePrimaryTabParent(TabParentChange aChange)
nsresult
nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
const nsACString& aSignedPkgOriginNoSuffix,
nsIURI* aURI,
const nsACString& aPackageId)
{
nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
OriginAttributes attrs = OriginAttributes();
DocShellOriginAttributes attrs;
attrs.mInBrowser = OwnerIsBrowserFrame();
nsCString signedPkgOrigin;
if (!aPackageId.IsEmpty()) {
// Only when aPackageId is not empty would signed package origin
// be meaningful.
nsPrincipal::GetOriginForURI(aURI, signedPkgOrigin);
}
// Get the AppId from ownApp
uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
if (ownApp) {
@@ -3039,8 +3038,8 @@ nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
// Populate packageId to signedPkg.
attrs.mSignedPkg = NS_ConvertUTF8toUTF16(aPackageId);
bool tabContextUpdated = aTabContext->SetTabContext(ownApp, containingApp,
attrs, aSignedPkgOriginNoSuffix);
bool tabContextUpdated =
aTabContext->SetTabContext(ownApp, containingApp, attrs, signedPkgOrigin);
NS_ENSURE_STATE(tabContextUpdated);
return NS_OK;
+1 -1
View File
@@ -317,7 +317,7 @@ private:
void InitializeBrowserAPI();
nsresult GetNewTabContext(mozilla::dom::MutableTabContext* aTabContext,
const nsACString& aSignedPkgNoSuffix = EmptyCString(),
nsIURI* aURI = nullptr,
const nsACString& aPackageId = EmptyCString());
enum TabParentChange {
+27 -2
View File
@@ -226,6 +226,7 @@
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/NavigatorBinding.h"
#include "mozilla/dom/ImageBitmap.h"
#include "mozilla/dom/ServiceWorkerRegistration.h"
#ifdef HAVE_SIDEBAR
#include "mozilla/dom/ExternalBinding.h"
#endif
@@ -264,7 +265,7 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::dom::ipc;
using mozilla::BasePrincipal;
using mozilla::OriginAttributes;
using mozilla::PrincipalOriginAttributes;
using mozilla::TimeStamp;
using mozilla::TimeDuration;
using mozilla::dom::cache::CacheStorage;
@@ -1580,6 +1581,8 @@ nsGlobalWindow::CleanUp()
}
DisableTimeChangeNotifications();
mServiceWorkerRegistrationTable.Clear();
}
void
@@ -1794,6 +1797,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerRegistrationTable)
#ifdef MOZ_WEBSPEECH
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)
#endif
@@ -1865,6 +1870,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mServiceWorkerRegistrationTable)
#ifdef MOZ_WEBSPEECH
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechSynthesis)
#endif
@@ -8358,7 +8365,7 @@ nsGlobalWindow::PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessa
nsCOMPtr<nsIPrincipal> principal = nsContentUtils::SubjectPrincipal();
MOZ_ASSERT(principal);
OriginAttributes attrs = BasePrincipal::Cast(principal)->OriginAttributesRef();
PrincipalOriginAttributes attrs = BasePrincipal::Cast(principal)->OriginAttributesRef();
// Create a nsIPrincipal inheriting the app/browser attributes from the
// caller.
providedPrincipal = BasePrincipal::CreateCodebasePrincipal(originURI, attrs);
@@ -10852,6 +10859,24 @@ nsGlobalWindow::GetCaches(ErrorResult& aRv)
return ref.forget();
}
already_AddRefed<ServiceWorkerRegistrationMainThread>
nsPIDOMWindow::GetServiceWorkerRegistration(const nsAString& aScope)
{
RefPtr<ServiceWorkerRegistrationMainThread> registration;
if (!mServiceWorkerRegistrationTable.Get(aScope,
getter_AddRefs(registration))) {
registration = new ServiceWorkerRegistrationMainThread(this, aScope);
mServiceWorkerRegistrationTable.Put(aScope, registration);
}
return registration.forget();
}
void
nsPIDOMWindow::InvalidateServiceWorkerRegistration(const nsAString& aScope)
{
mServiceWorkerRegistrationTable.Remove(aScope);
}
void
nsGlobalWindow::FireOfflineStatusEventIfChanged()
{
+3 -1
View File
@@ -818,7 +818,9 @@ public:
return mAnonymousContents;
}
nsresult GetId(nsAString& aId);
static nsresult GenerateDocumentId(nsAString& aId);
nsresult GetOrCreateId(nsAString& aId);
void SetId(const nsAString& aId);
protected:
virtual Element *GetRootElementInternal() const = 0;
+11
View File
@@ -15,6 +15,7 @@
#include "nsTArray.h"
#include "mozilla/dom/EventTarget.h"
#include "js/TypeDecls.h"
#include "nsRefPtrHashtable.h"
#define DOM_WINDOW_DESTROYED_TOPIC "dom-window-destroyed"
#define DOM_WINDOW_FROZEN_TOPIC "dom-window-frozen"
@@ -37,6 +38,7 @@ namespace mozilla {
namespace dom {
class AudioContext;
class Element;
class ServiceWorkerRegistrationMainThread;
} // namespace dom
namespace gfx {
class VRHMDInfo;
@@ -218,6 +220,10 @@ public:
return mServiceWorkersTestingEnabled;
}
already_AddRefed<mozilla::dom::ServiceWorkerRegistrationMainThread>
GetServiceWorkerRegistration(const nsAString& aScope);
void InvalidateServiceWorkerRegistration(const nsAString& aScope);
protected:
// Lazily instantiate an about:blank document if necessary, and if
// we have what it takes to do so.
@@ -810,6 +816,11 @@ protected:
// mPerformance is only used on inner windows.
RefPtr<nsPerformance> mPerformance;
typedef nsRefPtrHashtable<nsStringHashKey,
mozilla::dom::ServiceWorkerRegistrationMainThread>
ServiceWorkerRegistrationTable;
ServiceWorkerRegistrationTable mServiceWorkerRegistrationTable;
uint32_t mModalStateDepth;
// These variables are only used on inner windows.
+60 -9
View File
@@ -11,6 +11,7 @@
#include "nsDOMNavigationTiming.h"
#include "nsContentUtils.h"
#include "nsIScriptSecurityManager.h"
#include "nsGlobalWindow.h"
#include "nsIDOMWindow.h"
#include "nsILoadInfo.h"
#include "nsIURI.h"
@@ -29,7 +30,10 @@
#include "mozilla/Preferences.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/TimeStamp.h"
#include "SharedWorker.h"
#include "ServiceWorker.h"
#include "js/HeapAPI.h"
#include "GeckoProfiler.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
@@ -798,15 +802,16 @@ nsPerformance::InsertUserEntry(PerformanceEntry* aEntry)
PerformanceBase::InsertUserEntry(aEntry);
}
DOMHighResTimeStamp
nsPerformance::DeltaFromNavigationStart(DOMHighResTimeStamp aTime)
TimeStamp
nsPerformance::CreationTimeStamp() const
{
// If the time we're trying to convert is equal to zero, it hasn't been set
// yet so just return 0.
if (aTime == 0) {
return 0;
}
return aTime - GetDOMTiming()->GetNavigationStart();
return GetDOMTiming()->GetNavigationStartTimeStamp();
}
DOMHighResTimeStamp
nsPerformance::CreationTime() const
{
return GetDOMTiming()->GetNavigationStart();
}
// PerformanceBase
@@ -918,6 +923,48 @@ PerformanceBase::ClearResourceTimings()
mResourceEntries.Clear();
}
DOMHighResTimeStamp
PerformanceBase::TranslateTime(DOMHighResTimeStamp aTime,
const WindowOrWorkerOrSharedWorkerOrServiceWorker& aTimeSource,
ErrorResult& aRv)
{
TimeStamp otherCreationTimeStamp;
if (aTimeSource.IsWindow()) {
RefPtr<nsPerformance> performance = aTimeSource.GetAsWindow().GetPerformance();
if (NS_WARN_IF(!performance)) {
aRv.Throw(NS_ERROR_FAILURE);
}
otherCreationTimeStamp = performance->CreationTimeStamp();
} else if (aTimeSource.IsWorker()) {
otherCreationTimeStamp = aTimeSource.GetAsWorker().CreationTimeStamp();
} else if (aTimeSource.IsSharedWorker()) {
SharedWorker& sharedWorker = aTimeSource.GetAsSharedWorker();
WorkerPrivate* workerPrivate = sharedWorker.GetWorkerPrivate();
otherCreationTimeStamp = workerPrivate->CreationTimeStamp();
} else if (aTimeSource.IsServiceWorker()) {
ServiceWorker& serviceWorker = aTimeSource.GetAsServiceWorker();
WorkerPrivate* workerPrivate = serviceWorker.GetWorkerPrivate();
otherCreationTimeStamp = workerPrivate->CreationTimeStamp();
} else {
MOZ_CRASH("This should not be possible.");
}
return RoundTime(
aTime + (otherCreationTimeStamp - CreationTimeStamp()).ToMilliseconds());
}
DOMHighResTimeStamp
PerformanceBase::RoundTime(double aTime) const
{
// Round down to the nearest 5us, because if the timer is too accurate people
// can do nasty timing attacks with it. See similar code in the worker
// Performance implementation.
const double maxResolutionMs = 0.005;
return floor(aTime / maxResolutionMs) * maxResolutionMs;
}
void
PerformanceBase::Mark(const nsAString& aName, ErrorResult& aRv)
{
@@ -934,6 +981,10 @@ PerformanceBase::Mark(const nsAString& aName, ErrorResult& aRv)
RefPtr<PerformanceMark> performanceMark =
new PerformanceMark(GetAsISupports(), aName, Now());
InsertUserEntry(performanceMark);
if (profiler_is_active()) {
PROFILER_MARKER(NS_ConvertUTF16toUTF8(aName).get());
}
}
void
@@ -968,7 +1019,7 @@ PerformanceBase::ResolveTimestampFromName(const nsAString& aName,
return 0;
}
return DeltaFromNavigationStart(ts);
return ts - CreationTime();
}
void
+22 -8
View File
@@ -23,10 +23,15 @@ class nsPerformance;
class nsIHttpChannel;
namespace mozilla {
class ErrorResult;
namespace dom {
class PerformanceEntry;
class PerformanceObserver;
class PerformanceEntry;
class PerformanceObserver;
class WindowOrWorkerOrSharedWorkerOrServiceWorker;
} // namespace dom
} // namespace mozilla
@@ -313,6 +318,11 @@ public:
virtual DOMHighResTimeStamp Now() const = 0;
DOMHighResTimeStamp
TranslateTime(DOMHighResTimeStamp aTime,
const mozilla::dom::WindowOrWorkerOrSharedWorkerOrServiceWorker& aTimeSource,
mozilla::ErrorResult& aRv);
void Mark(const nsAString& aName, mozilla::ErrorResult& aRv);
void ClearMarks(const mozilla::dom::Optional<nsAString>& aName);
void Measure(const nsAString& aName,
@@ -344,8 +354,9 @@ protected:
virtual void DispatchBufferFullEvent() = 0;
virtual DOMHighResTimeStamp
DeltaFromNavigationStart(DOMHighResTimeStamp aTime) = 0;
virtual mozilla::TimeStamp CreationTimeStamp() const = 0;
virtual DOMHighResTimeStamp CreationTime() const = 0;
virtual bool IsPerformanceTimingAttribute(const nsAString& aName) = 0;
@@ -363,6 +374,8 @@ protected:
void RunNotificationObserversTask();
void QueueEntry(PerformanceEntry* aEntry);
DOMHighResTimeStamp RoundTime(double aTime) const;
nsTObserverArray<PerformanceObserver*> mObservers;
private:
@@ -433,7 +446,11 @@ public:
IMPL_EVENT_HANDLER(resourcetimingbufferfull)
private:
mozilla::TimeStamp CreationTimeStamp() const override;
DOMHighResTimeStamp CreationTime() const override;
protected:
~nsPerformance();
nsISupports* GetAsISupports() override
@@ -445,9 +462,6 @@ private:
bool IsPerformanceTimingAttribute(const nsAString& aName) override;
DOMHighResTimeStamp
DeltaFromNavigationStart(DOMHighResTimeStamp aTime) override;
DOMHighResTimeStamp
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
+1
View File
@@ -0,0 +1 @@
/* nothing here */
+2
View File
@@ -256,6 +256,7 @@ support-files =
file_explicit_user_agent.sjs
referrer_change_server.sjs
file_change_policy_redirect.html
empty_worker.js
[test_anonymousContent_api.html]
[test_anonymousContent_append_after_reflow.html]
@@ -842,3 +843,4 @@ skip-if = e10s || os != 'linux' || buildapp != 'browser'
[test_change_policy.html]
skip-if = buildapp == 'b2g' #no ssl support
[test_document.all_iteration.html]
[test_performance_translate.html]
@@ -0,0 +1,75 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for performance.translate()</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="test_performance_user_timing.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
function testBasic() {
ok("translateTime" in performance, "Performance.translateTime exists.");
try {
performance.translateTime(0, null);
ok(false, "Wrong use of performance.translateTime.");
} catch(e) {
ok(true, "Wrong use of performance.translateTime.");
}
next();
}
function testWindow() {
is(performance.translateTime(42, this), 42, "translating time with the same window.");
var now = performance.now();
var ifr = document.createElement('iframe');
ifr.src = 'file_empty.html';
document.body.appendChild(ifr);
ifr.onload = function() {
var a = performance.translateTime(0, ifr.contentWindow);
ok (a >= now, "Time has been translated from a window that started loading later than we did");
next();
}
}
function testWorker() {
var now = performance.now();
var w = new Worker('empty_worker.js');
var a = performance.translateTime(0, w);
// bug 1226147
ok (a >= now, "Time has been translated from a Worker that started loading later than we did");
next();
}
function testSharedWorker() {
var now = performance.now();
var w = new SharedWorker('empty_worker.js');
var a = performance.translateTime(0, w);
ok (a >= now, "Time has been translated from a SharedWorker that started loading later than we did");
next();
}
var tests = [ testBasic, testWindow, testWorker, testSharedWorker ];
function next() {
if (!tests.length) {
SimpleTest.finish();
return;
}
var test = tests.shift();
test();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(next);
</script>
</pre>
</body>
</html>
+6 -6
View File
@@ -67,17 +67,17 @@ function run_test() {
NS_ERROR_INVALID_ARG);
// We can't test isThirdPartyWindow since we can't really set up a window
// heirarchy. We leave that to mochitests.
// hierarchy. We leave that to mochitests.
// Test isThirdPartyChannel. As above, we can't test the bits that require
// a load context or window heirarchy.
// a load context or window heirarchy. Because of that, the code assumes
// that these are all third-party loads.
do_check_throws(function() { util.isThirdPartyChannel(null); },
NS_ERROR_INVALID_ARG);
do_check_throws(function() { util.isThirdPartyChannel(channel1); },
NS_ERROR_INVALID_ARG);
do_check_throws(function() { util.isThirdPartyChannel(channel1, uri1); },
NS_ERROR_INVALID_ARG);
do_check_true(util.isThirdPartyChannel(channel1));
do_check_true(util.isThirdPartyChannel(channel1, uri1));
do_check_true(util.isThirdPartyChannel(channel1, uri2));
let httpchannel1 = channel1.QueryInterface(Ci.nsIHttpChannelInternal);
httpchannel1.forceAllowThirdPartyCookie = true;
do_check_false(util.isThirdPartyChannel(channel1));
+1 -1
View File
@@ -1933,7 +1933,7 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
aSavedResponseOut->mValue.principalInfo() = void_t();
if (!serializedInfo.IsEmpty()) {
nsAutoCString originNoSuffix;
OriginAttributes attrs;
PrincipalOriginAttributes attrs;
if (!attrs.PopulateFromOrigin(serializedInfo, originNoSuffix)) {
NS_WARNING("Something went wrong parsing a serialized principal!");
return NS_ERROR_FAILURE;
+2 -2
View File
@@ -58,7 +58,7 @@
}
using mozilla::BasePrincipal;
using mozilla::OriginAttributes;
using mozilla::PrincipalOriginAttributes;
namespace mozilla {
namespace dom {
@@ -211,7 +211,7 @@ ResetPermission(uint32_t aAppId, const nsAString& aOriginURL,
return rv;
}
OriginAttributes attrs(aAppId, false);
PrincipalOriginAttributes attrs(aAppId, false);
nsCOMPtr<nsIPrincipal> principal =
BasePrincipal::CreateCodebasePrincipal(uri, attrs);
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
+1 -1
View File
@@ -1131,7 +1131,7 @@ Event::TimeStamp() const
MOZ_ASSERT(workerPrivate);
TimeDuration duration =
mEvent->timeStamp - workerPrivate->NowBaseTimeStamp();
mEvent->timeStamp - workerPrivate->CreationTimeStamp();
return duration.ToMilliseconds();
}
+3 -2
View File
@@ -74,8 +74,9 @@ function testWorkerEvents() {
var worker = new Worker(window.URL.createObjectURL(blob));
worker.onmessage = function(evt) {
var timeAfterEvent = window.performance.now();
ok(evt.data > timeBeforeEvent &&
evt.data < timeAfterEvent,
var time = window.performance.translateTime(evt.data, worker);
ok(time >= timeBeforeEvent &&
time <= timeAfterEvent,
"Event timestamp in dedicated worker (" + evt.data +
") is in expected range: (" +
timeBeforeEvent + ", " + timeAfterEvent + ")");
+31 -29
View File
@@ -29,6 +29,7 @@
#include "nsPrintfCString.h"
#include "nsStreamUtils.h"
#include "nsStringStream.h"
#include "nsHttpChannel.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/workers/Workers.h"
@@ -51,7 +52,6 @@ FetchDriver::FetchDriver(InternalRequest* aRequest, nsIPrincipal* aPrincipal,
, mLoadGroup(aLoadGroup)
, mRequest(aRequest)
, mHasBeenCrossSite(false)
, mFoundOpaqueRedirect(false)
, mResponseAvailableCalled(false)
, mFetchCalled(false)
{
@@ -236,6 +236,10 @@ FetchDriver::HttpFetch()
return NS_ERROR_UNEXPECTED;
}
if (mRequest->GetRedirectMode() != RequestRedirect::Follow) {
secFlags |= nsILoadInfo::SEC_DONT_FOLLOW_REDIRECTS;
}
// From here on we create a channel and set its properties with the
// information from the InternalRequest. This is an implementation detail.
MOZ_ASSERT(mLoadGroup);
@@ -443,7 +447,9 @@ FetchDriver::IsUnsafeRequest()
}
already_AddRefed<InternalResponse>
FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aFinalURI)
FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse,
nsIURI* aFinalURI,
bool aFoundOpaqueRedirect)
{
MOZ_ASSERT(aResponse);
nsAutoCString reqURL;
@@ -456,7 +462,7 @@ FetchDriver::BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aF
MOZ_ASSERT(NS_SUCCEEDED(rv));
RefPtr<InternalResponse> filteredResponse;
if (mFoundOpaqueRedirect) {
if (aFoundOpaqueRedirect) {
filteredResponse = aResponse->OpaqueRedirectResponse();
} else {
switch (mRequest->GetResponseTainting()) {
@@ -553,10 +559,22 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(aRequest);
bool foundOpaqueRedirect = false;
if (httpChannel) {
uint32_t responseStatus;
httpChannel->GetResponseStatus(&responseStatus);
if (mozilla::net::nsHttpChannel::IsRedirectStatus(responseStatus)) {
if (mRequest->GetRedirectMode() == RequestRedirect::Error) {
FailWithNetworkError();
return NS_BINDING_FAILED;
}
if (mRequest->GetRedirectMode() == RequestRedirect::Manual) {
foundOpaqueRedirect = true;
}
}
nsAutoCString statusText;
httpChannel->GetResponseStatusText(statusText);
@@ -662,7 +680,8 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
// Resolves fetch() promise which may trigger code running in a worker. Make
// sure the Response is fully initialized before calling this.
mResponse = BeginAndGetFilteredResponse(response, channelURI);
mResponse = BeginAndGetFilteredResponse(response, channelURI,
foundOpaqueRedirect);
nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -745,6 +764,12 @@ FetchDriver::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
return NS_OK;
}
// We should only ever get here if we use a "follow" redirect policy,
// or if if we set an "error" policy as a result of a CORS policy.
MOZ_ASSERT(mRequest->GetRedirectMode() == RequestRedirect::Follow ||
(mRequest->GetRedirectMode() == RequestRedirect::Error &&
IsUnsafeRequest()));
// HTTP Fetch step 5, "redirect status", step 1
if (NS_WARN_IF(mRequest->GetRedirectMode() == RequestRedirect::Error)) {
aOldChannel->Cancel(NS_BINDING_FAILED);
@@ -765,33 +790,10 @@ FetchDriver::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
// HTTP Fetch step 5, "redirect status", step 10 requires us to halt the
// redirect, but successfully return an opaqueredirect Response to the
// initiating Fetch.
if (mRequest->GetRedirectMode() == RequestRedirect::Manual) {
// Ideally we would simply not cancel the old channel and allow it to
// be processed as normal. Unfortunately this is quite fragile and
// other redirect handlers can easily break it for certain use cases.
//
// For example, nsCORSListenerProxy cancels vetoed redirect channels.
// The HTTP cache will also error on vetoed redirects when the
// redirect has been previously cached.
//
// Therefore simulate the completion of the channel to produce the
// opaqueredirect Response and then cancel the original channel. This
// will result in OnStartRequest() getting called twice, but the second
// time will be with an error response (from the Cancel) which will
// be ignored.
MOZ_ASSERT(!mFoundOpaqueRedirect);
mFoundOpaqueRedirect = true;
Unused << OnStartRequest(aOldChannel, nullptr);
Unused << OnStopRequest(aOldChannel, nullptr, NS_OK);
aOldChannel->Cancel(NS_BINDING_FAILED);
return NS_BINDING_FAILED;
}
// The following steps are from HTTP Fetch step 5, "redirect status", step 11
// which requires the RequestRedirect to be "follow".
MOZ_ASSERT(mRequest->GetRedirectMode() == RequestRedirect::Follow);
// which requires the RequestRedirect to be "follow". We asserted that we're
// in either "follow" or "error" mode here.
// HTTP Fetch step 5, "redirect status", steps 11.1 and 11.2 block redirecting
// to a URL with credentials in CORS mode. This is implemented in
+2 -2
View File
@@ -83,7 +83,6 @@ private:
RefPtr<FetchDriverObserver> mObserver;
nsCOMPtr<nsIDocument> mDocument;
bool mHasBeenCrossSite;
bool mFoundOpaqueRedirect;
DebugOnly<bool> mResponseAvailableCalled;
DebugOnly<bool> mFetchCalled;
@@ -100,7 +99,8 @@ private:
// Returns the filtered response sent to the observer.
// Callers who don't have access to a channel can pass null for aFinalURI.
already_AddRefed<InternalResponse>
BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aFinalURI);
BeginAndGetFilteredResponse(InternalResponse* aResponse, nsIURI* aFinalURI,
bool aFoundOpaqueRedirect);
// Utility since not all cases need to do any post processing of the filtered
// response.
nsresult FailWithNetworkError();
@@ -21,11 +21,19 @@ interface nsIServiceWorkerUnregisterCallback : nsISupports
void unregisterFailed();
};
[scriptable, builtinclass, uuid(1a1e71dd-0f78-4e2e-a2db-a946fe02cddf)]
interface nsIWorkerDebugger;
[scriptable, builtinclass, uuid(76e357ed-208d-4e4c-9165-1c4059707879)]
interface nsIServiceWorkerInfo : nsISupports
{
readonly attribute DOMString scriptSpec;
readonly attribute DOMString cacheName;
readonly attribute nsIWorkerDebugger debugger;
void attachDebugger();
void detachDebugger();
};
[scriptable, uuid(87e63548-d440-4b8a-b158-65ad1de0211E)]
@@ -59,7 +67,7 @@ interface nsIServiceWorkerManagerListener : nsISupports
void onUnregister(in nsIServiceWorkerRegistrationInfo aInfo);
};
[scriptable, builtinclass, uuid(2f61820a-1e9a-4c16-bf1c-ce182c5f5d6d)]
[scriptable, builtinclass, uuid(a03f2b64-7aaf-423a-97b0-e1f733cce0f6)]
interface nsIServiceWorkerManager : nsISupports
{
/**
@@ -98,7 +106,7 @@ interface nsIServiceWorkerManager : nsISupports
*
* This MUST only be called once per document!
*/
[notxpcom,nostdcall] void MaybeStartControlling(in nsIDocument aDoc);
[notxpcom,nostdcall] void MaybeStartControlling(in nsIDocument aDoc, in DOMString aDocumentId);
/**
* Documents that have called MaybeStartControlling() should call this when
@@ -174,6 +182,8 @@ interface nsIServiceWorkerManager : nsISupports
void addListener(in nsIServiceWorkerManagerListener aListener);
void removeListener(in nsIServiceWorkerManagerListener aListener);
bool shouldReportToWindow(in nsIDOMWindow aWindow, in ACString aScope);
};
%{ C++
+1 -1
View File
@@ -154,7 +154,7 @@ AssertAppProcess(TabContext& aContext,
AssertAppProcessType aType,
const char* aCapability)
{
const mozilla::OriginAttributes& attr = aContext.OriginAttributesRef();
const mozilla::DocShellOriginAttributes& attr = aContext.OriginAttributesRef();
nsCString suffix;
attr.CreateSuffix(suffix);
+3 -6
View File
@@ -152,7 +152,7 @@ TabContext::SetTabContext(const TabContext& aContext)
return true;
}
const OriginAttributes&
const DocShellOriginAttributes&
TabContext::OriginAttributesRef() const
{
return mOriginAttributes;
@@ -167,7 +167,7 @@ TabContext::SignedPkgOriginNoSuffix() const
bool
TabContext::SetTabContext(mozIApplication* aOwnApp,
mozIApplication* aAppFrameOwnerApp,
const OriginAttributes& aOriginAttributes,
const DocShellOriginAttributes& aOriginAttributes,
const nsACString& aSignedPkgOriginNoSuffix)
{
NS_ENSURE_FALSE(mInitialized, false);
@@ -228,7 +228,7 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
: mInvalidReason(nullptr)
{
uint32_t containingAppId = NO_APP_ID;
OriginAttributes originAttributes = OriginAttributes();
DocShellOriginAttributes originAttributes;
nsAutoCString originSuffix;
nsAutoCString signedPkgOriginNoSuffix;
@@ -269,9 +269,6 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
//
// Otherwise, we're a new app window and we inherit from our
// opener app.
// FIXME bug 1212250 - use InheritFromDocToChildDocshell instead
// of copying attributes directly.
originAttributes = context->mOriginAttributes;
if (ipcContext.isBrowserElement()) {
containingAppId = context->OwnOrContainingAppId();
+6 -6
View File
@@ -104,11 +104,11 @@ public:
bool HasOwnOrContainingApp() const;
/**
* OriginAttributesRef() returns the OriginAttributes of this frame to the
* OriginAttributesRef() returns the DocShellOriginAttributes of this frame to the
* caller. This is used to store any attribute associated with the frame's
* docshell, such as the AppId.
*/
const OriginAttributes& OriginAttributesRef() const;
const DocShellOriginAttributes& OriginAttributesRef() const;
/**
* Returns the origin associated with the tab (w/o suffix) if this tab owns
@@ -142,7 +142,7 @@ protected:
*/
bool SetTabContext(mozIApplication* aOwnApp,
mozIApplication* aAppFrameOwnerApp,
const OriginAttributes& aOriginAttributes,
const DocShellOriginAttributes& aOriginAttributes,
const nsACString& aSignedPkgOriginNoSuffix);
private:
@@ -170,9 +170,9 @@ private:
uint32_t mContainingAppId;
/**
* OriginAttributes of the top level tab docShell
* DocShellOriginAttributes of the top level tab docShell
*/
OriginAttributes mOriginAttributes;
DocShellOriginAttributes mOriginAttributes;
/**
* The signed package origin without suffix. Since the signed packaged
@@ -198,7 +198,7 @@ public:
bool SetTabContext(mozIApplication* aOwnApp,
mozIApplication* aAppFrameOwnerApp,
const OriginAttributes& aOriginAttributes,
const DocShellOriginAttributes& aOriginAttributes,
const nsACString& aSignedPkgOriginNoSuffix = EmptyCString())
{
return TabContext::SetTabContext(aOwnApp,
+1 -1
View File
@@ -5261,7 +5261,7 @@ StorageDirectoryHelper::RunOnMainThread()
rv = secMan->GetSimpleCodebasePrincipal(uri,
getter_AddRefs(principal));
} else {
OriginAttributes attrs(originProps.mAppId, originProps.mInMozBrowser);
PrincipalOriginAttributes attrs(originProps.mAppId, originProps.mInMozBrowser);
principal = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
rv = principal ? NS_OK : NS_ERROR_FAILURE;
}
+9 -1
View File
@@ -225,7 +225,15 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
break;
}
case nsIContentPolicy::TYPE_DTD:
case nsIContentPolicy::TYPE_DTD: {
mimeTypeGuess = EmptyCString();
requestingContext = aLoadInfo->LoadingNode();
MOZ_ASSERT(!requestingContext ||
requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE,
"type_dtd requires requestingContext of type Document");
break;
}
case nsIContentPolicy::TYPE_FONT: {
MOZ_ASSERT(false, "contentPolicyType not supported yet");
break;
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
<meta charset=UTF-8>
</head>
<body>
<script>
parent.postMessage(document.cookie, "*");
</script>
</body>
</html>
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<html>
<head>
<meta charset=UTF-8>
</head>
<body>
<script>
document.cookie = "b=c";
parent.postMessage("done", "*");
</script>
</body>
</html>
@@ -0,0 +1,9 @@
/* vim: set ft=javascript: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function handleRequest(request, response) {
response.setHeader("Content-type", "text/html", false);
response.setStatusLine(request.httpVersion, "302", "Found");
response.setHeader("Location", request.queryString, false);
response.write("<!DOCTYPE html><html><body>Look away!</body></html>");
}
+5
View File
@@ -34,6 +34,9 @@ support-files =
utils_bug743615.js
worker_bug743615.js
file_bug927901.html
file_cookieOutputter.html
file_redirector.sjs
file_prime_cookie.html
[test_DOMWindowCreated_chromeonly.html]
[test_bug132255.html]
@@ -167,3 +170,5 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
[test_window_bar.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s
[test_bug1022869.html]
[test_bug1112040.html]
[test_bug1171215.html]
@@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1112040
-->
<head>
<title>Test for Bug 1112040</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<base href="http://mochi.test:8888/tests/dom/tests/mochitest/">
<meta charset="UTF-8">
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1112040">Mozilla Bug 1112040</a>
<p id="display">
</p>
<div id="content">
<input id="i" type="text" pattern="^.**$">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 1112040 **/
SimpleTest.runTestExpectingConsoleMessages(
function() { $('i').value = "42"; },
[{ errorMessage: "SyntaxError: nothing to repeat" }]
);
</script>
</pre>
</body>
</html>
@@ -0,0 +1,89 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1022869
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1022869</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<iframe src="about:blank"></iframe>
<script type="text/javascript; version=1.8">
var f = document.getElementsByTagName("iframe")[0];
SimpleTest.waitForExplicitFinish();
/** Test for Bug 1022869 **/
function startTest() {
// Initialize our cookie.
document.cookie = "a=b";
// Set a cookie in example.org so we can test that we can't read it in
// third-party cases.
f.contentWindow.location =
"http://example.org/tests/dom/tests/mochitest/bugs/file_prime_cookie.html";
waitForLoad().then(function() {
// Cookies are set up, disallow third-party cookies and start the test.
SpecialPowers.pushPrefEnv({ set: [[ 'network.cookie.cookieBehavior', 1 ]] },
() => { spawn_task(continueTest); });
}).catch((e) => { ok(false, `Got exception: ${e}`) });
}
function waitForLoad() {
return new Promise((resolve) => {
window.addEventListener("message", function received(msg) {
window.removeEventListener("message", received);
info(`got message ${msg.data}`);
resolve(msg.data);
});
});
}
function* continueTest() {
var sameOrigin = "http://mochi.test:8888";
var thirdParty = "http://example.org";
var page = "tests/dom/tests/mochitest/bugs/file_cookieOutputter.html"
var redirect = "tests/dom/tests/mochitest/bugs/file_redirector.sjs";
function createRedirect(firstOrigin, secondOrigin) {
return `${firstOrigin}/${redirect}?${secondOrigin}/${page}`;
}
info("starting test");
// Same origin to same origin.
f.contentWindow.location = createRedirect(sameOrigin, sameOrigin);
let cookie = yield waitForLoad();
is(cookie, "a=b", "got the cookie");
// Cross origin to cross origin.
f.contentWindow.location = createRedirect(thirdParty, thirdParty);
cookie = yield waitForLoad();
is(cookie, "", "no third-party cookies");
// Same origin to cross origin.
f.contentWindow.location = createRedirect(sameOrigin, thirdParty);
cookie = yield waitForLoad();
is(cookie, "", "no third-party cookies");
// Cross origin to same origin
f.contentWindow.location = createRedirect(thirdParty, sameOrigin);
cookie = yield waitForLoad();
is(cookie, "a=b", "got the cookie");
SimpleTest.finish();
}
</script>
</head>
<body onload="startTest()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1022869">Mozilla Bug 1022869</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>
+1 -1
View File
@@ -39,7 +39,7 @@ interface ChromeUtils : ThreadSafeChromeUtils {
* IMPORTANT: If you add any members here, you need to do the following:
* (1) Add them to both dictionaries.
* (2) Update the methods on mozilla::OriginAttributes, including equality,
* serialization, and deserialization.
* serialization, deserialization, and inheritance.
* (3) Update the methods on mozilla::OriginAttributesPattern, including matching.
*/
dictionary OriginAttributesDictionary {
+3 -3
View File
@@ -10,8 +10,9 @@
[Exposed=ServiceWorker]
interface Client {
readonly attribute DOMString id;
readonly attribute USVString url;
readonly attribute FrameType frameType;
readonly attribute DOMString id;
[Throws]
void postMessage(any message, optional sequence<Transferable> transfer);
@@ -21,9 +22,8 @@ interface Client {
interface WindowClient : Client {
readonly attribute VisibilityState visibilityState;
readonly attribute boolean focused;
readonly attribute FrameType frameType;
[Throws]
[Throws, NewObject]
Promise<WindowClient> focus();
};
+6 -3
View File
@@ -11,11 +11,14 @@
[Exposed=ServiceWorker]
interface Clients {
// The objects returned will be new instances every time
[Throws]
[NewObject]
Promise<any> get(DOMString id);
[NewObject]
Promise<sequence<Client>?> matchAll(optional ClientQueryOptions options);
[Throws]
[NewObject,
Func="mozilla::dom::workers::ServiceWorkerGlobalScope::OpenWindowEnabled"]
Promise<WindowClient> openWindow(USVString url);
[Throws]
[NewObject]
Promise<void> claim();
};
+2
View File
@@ -12,6 +12,7 @@
Exposed=(ServiceWorker)]
interface FetchEvent : ExtendableEvent {
[SameObject] readonly attribute Request? request;
readonly attribute DOMString? clientId;
readonly attribute boolean isReload;
[Throws]
@@ -20,5 +21,6 @@ interface FetchEvent : ExtendableEvent {
dictionary FetchEventInit : EventInit {
Request request;
DOMString? clientId = null;
boolean isReload = false;
};
+6 -3
View File
@@ -4,10 +4,10 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* http://www.w3.org/TR/hr-time/
* http://w3c.github.io/hr-time/
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
* Copyright © 2015 W3C® (MIT, ERCIM, Keio, Beihang).
* W3C liability, trademark and document use rules apply.
*/
typedef double DOMHighResTimeStamp;
@@ -17,6 +17,9 @@ typedef sequence <PerformanceEntry> PerformanceEntryList;
interface Performance {
[DependsOn=DeviceState, Affects=Nothing]
DOMHighResTimeStamp now();
[Throws]
DOMHighResTimeStamp translateTime(DOMHighResTimeStamp time, (Window or Worker or SharedWorker or ServiceWorker) timeSource);
};
[Exposed=Window]
+3 -5
View File
@@ -13,10 +13,10 @@
[Global=(Worker,ServiceWorker),
Exposed=ServiceWorker]
interface ServiceWorkerGlobalScope : WorkerGlobalScope {
readonly attribute Clients clients;
readonly attribute ServiceWorkerRegistration registration;
[SameObject] readonly attribute Clients clients;
[SameObject] readonly attribute ServiceWorkerRegistration registration;
[Throws]
[Throws, NewObject]
Promise<boolean> skipWaiting();
attribute EventHandler oninstall;
@@ -24,8 +24,6 @@ interface ServiceWorkerGlobalScope : WorkerGlobalScope {
[Func="mozilla::dom::workers::ServiceWorkerGlobalScope::InterceptionEnabled"]
attribute EventHandler onfetch;
attribute EventHandler onbeforeevicted;
attribute EventHandler onevicted;
// The event.source of these MessageEvents are instances of Client
attribute EventHandler onmessage;
+3 -3
View File
@@ -7,7 +7,7 @@ include protocol PBackground;
include PBackgroundSharedTypes;
include ServiceWorkerRegistrarTypes;
using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h";
using mozilla::PrincipalOriginAttributes from "mozilla/ipc/BackgroundUtils.h";
namespace mozilla {
namespace dom {
@@ -21,7 +21,7 @@ parent:
Unregister(PrincipalInfo principalInfo, nsString scope);
PropagateSoftUpdate(OriginAttributes originAttributes,
PropagateSoftUpdate(PrincipalOriginAttributes originAttributes,
nsString scope);
PropagateUnregister(PrincipalInfo principalInfo, nsString scope);
@@ -33,7 +33,7 @@ parent:
child:
NotifyRegister(ServiceWorkerRegistrationData data);
NotifySoftUpdate(OriginAttributes originAttributes, nsString scope);
NotifySoftUpdate(PrincipalOriginAttributes originAttributes, nsString scope);
NotifyUnregister(PrincipalInfo principalInfo, nsString scope);
NotifyRemove(nsCString host);
NotifyRemoveAll();
+10 -8
View File
@@ -32,7 +32,7 @@ DOMHighResTimeStamp
Performance::Now() const
{
TimeDuration duration =
TimeStamp::Now() - mWorkerPrivate->NowBaseTimeStamp();
TimeStamp::Now() - mWorkerPrivate->CreationTimeStamp();
double nowTime = duration.ToMilliseconds();
// Round down to the nearest 20us, because if the timer is too accurate people
// can do nasty timing attacks with it. See similar code in the non-worker
@@ -57,7 +57,7 @@ Performance::GetPerformanceTimingFromString(const nsAString& aProperty)
}
if (aProperty.EqualsLiteral("navigationStart")) {
return mWorkerPrivate->NowBaseTimeHighRes();
return mWorkerPrivate->CreationTime();
}
MOZ_CRASH("IsPerformanceTimingAttribute and GetPerformanceTimingFromString are out of sync");
@@ -74,14 +74,16 @@ Performance::InsertUserEntry(PerformanceEntry* aEntry)
PerformanceBase::InsertUserEntry(aEntry);
}
DOMHighResTimeStamp
Performance::DeltaFromNavigationStart(DOMHighResTimeStamp aTime)
TimeStamp
Performance::CreationTimeStamp() const
{
if (aTime == 0) {
return 0;
}
return mWorkerPrivate->CreationTimeStamp();
}
return aTime - mWorkerPrivate->NowBaseTimeHighRes();
DOMHighResTimeStamp
Performance::CreationTime() const
{
return mWorkerPrivate->CreationTime();
}
void
+3 -2
View File
@@ -55,8 +55,9 @@ private:
DOMHighResTimeStamp
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
DOMHighResTimeStamp
DeltaFromNavigationStart(DOMHighResTimeStamp aTime) override;
TimeStamp CreationTimeStamp() const override;
DOMHighResTimeStamp CreationTime() const override;
};
END_WORKERS_NAMESPACE
+10
View File
@@ -168,6 +168,7 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 1,
#define PREF_SERVICEWORKERS_TESTING_ENABLED "dom.serviceWorkers.testing.enabled"
#define PREF_INTERCEPTION_ENABLED "dom.serviceWorkers.interception.enabled"
#define PREF_INTERCEPTION_OPAQUE_ENABLED "dom.serviceWorkers.interception.opaque.enabled"
#define PREF_OPEN_WINDOW_ENABLED "dom.serviceWorkers.openWindow.enabled"
#define PREF_PUSH_ENABLED "dom.push.enabled"
#define PREF_REQUESTCONTEXT_ENABLED "dom.requestcontext.enabled"
#define PREF_OFFSCREENCANVAS_ENABLED "gfx.offscreencanvas.enabled"
@@ -1924,6 +1925,10 @@ RuntimeService::Init()
WorkerPrefChanged,
PREF_INTERCEPTION_ENABLED,
reinterpret_cast<void *>(WORKERPREF_INTERCEPTION_ENABLED))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_OPEN_WINDOW_ENABLED,
reinterpret_cast<void *>(WORKERPREF_OPEN_WINDOW_ENABLED))) ||
NS_FAILED(Preferences::RegisterCallbackAndCall(
WorkerPrefChanged,
PREF_INTERCEPTION_OPAQUE_ENABLED,
@@ -2167,6 +2172,10 @@ RuntimeService::Cleanup()
WorkerPrefChanged,
PREF_INTERCEPTION_ENABLED,
reinterpret_cast<void *>(WORKERPREF_INTERCEPTION_ENABLED))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_OPEN_WINDOW_ENABLED,
reinterpret_cast<void *>(WORKERPREF_OPEN_WINDOW_ENABLED))) ||
NS_FAILED(Preferences::UnregisterCallback(
WorkerPrefChanged,
PREF_SERVICEWORKERS_ENABLED,
@@ -2711,6 +2720,7 @@ RuntimeService::WorkerPrefChanged(const char* aPrefName, void* aClosure)
#endif
case WORKERPREF_INTERCEPTION_ENABLED:
case WORKERPREF_INTERCEPTION_OPAQUE_ENABLED:
case WORKERPREF_OPEN_WINDOW_ENABLED:
case WORKERPREF_SERVICEWORKERS:
case WORKERPREF_SERVICEWORKERS_TESTING:
case WORKERPREF_PUSH:
+7
View File
@@ -101,6 +101,13 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
aRv = workerPrivate->SendMessageEvent(aCx, aMessage, aTransferable, Move(clientInfo));
}
WorkerPrivate*
ServiceWorker::GetWorkerPrivate() const
{
ServiceWorkerPrivate* workerPrivate = mInfo->WorkerPrivate();
return workerPrivate->GetWorkerPrivate();
}
} // namespace workers
} // namespace dom
} // namespace mozilla
+3
View File
@@ -67,6 +67,9 @@ public:
const Optional<Sequence<JS::Value>>& aTransferable,
ErrorResult& aRv);
WorkerPrivate*
GetWorkerPrivate() const;
private:
// This class can only be created from the ServiceWorkerManager.
ServiceWorker(nsPIDOMWindow* aWindow, ServiceWorkerInfo* aInfo);
+1 -1
View File
@@ -34,7 +34,7 @@ ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc)
: mWindowId(0)
{
MOZ_ASSERT(aDoc);
nsresult rv = aDoc->GetId(mClientId);
nsresult rv = aDoc->GetOrCreateId(mClientId);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to get the UUID of the document.");
}
+13
View File
@@ -33,6 +33,11 @@ class ServiceWorkerClientInfo final
public:
explicit ServiceWorkerClientInfo(nsIDocument* aDoc);
const nsString& ClientId() const
{
return mClientId;
}
private:
nsString mClientId;
uint64_t mWindowId;
@@ -57,6 +62,7 @@ public:
, mId(aClientInfo.mClientId)
, mUrl(aClientInfo.mUrl)
, mWindowId(aClientInfo.mWindowId)
, mFrameType(aClientInfo.mFrameType)
{
MOZ_ASSERT(aOwner);
}
@@ -78,6 +84,12 @@ public:
aUrl.Assign(mUrl);
}
mozilla::dom::FrameType
FrameType() const
{
return mFrameType;
}
void
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
@@ -97,6 +109,7 @@ private:
protected:
uint64_t mWindowId;
mozilla::dom::FrameType mFrameType;
};
} // namespace workers
+149 -35
View File
@@ -55,53 +55,140 @@ ServiceWorkerClients::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenPro
namespace {
class ResolvePromiseWorkerRunnable final : public WorkerRunnable
class GetRunnable final : public nsRunnable
{
RefPtr<PromiseWorkerProxy> mPromiseProxy;
nsTArray<ServiceWorkerClientInfo> mValue;
public:
ResolvePromiseWorkerRunnable(WorkerPrivate* aWorkerPrivate,
PromiseWorkerProxy* aPromiseProxy,
nsTArray<ServiceWorkerClientInfo>& aValue)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
mPromiseProxy(aPromiseProxy)
class ResolvePromiseWorkerRunnable final : public WorkerRunnable
{
AssertIsOnMainThread();
mValue.SwapElements(aValue);
}
RefPtr<PromiseWorkerProxy> mPromiseProxy;
UniquePtr<ServiceWorkerClientInfo> mValue;
nsresult mRv;
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
Promise* promise = mPromiseProxy->WorkerPromise();
MOZ_ASSERT(promise);
nsTArray<RefPtr<ServiceWorkerClient>> ret;
for (size_t i = 0; i < mValue.Length(); i++) {
ret.AppendElement(RefPtr<ServiceWorkerClient>(
new ServiceWorkerWindowClient(promise->GetParentObject(),
mValue.ElementAt(i))));
public:
ResolvePromiseWorkerRunnable(WorkerPrivate* aWorkerPrivate,
PromiseWorkerProxy* aPromiseProxy,
UniquePtr<ServiceWorkerClientInfo>&& aValue,
nsresult aRv)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
mPromiseProxy(aPromiseProxy),
mValue(Move(aValue)),
mRv(Move(aRv))
{
AssertIsOnMainThread();
}
promise->MaybeResolve(ret);
mPromiseProxy->CleanUp(aCx);
return true;
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
Promise* promise = mPromiseProxy->WorkerPromise();
MOZ_ASSERT(promise);
if (NS_FAILED(mRv)) {
promise->MaybeReject(mRv);
} else if (mValue) {
RefPtr<ServiceWorkerWindowClient> windowClient =
new ServiceWorkerWindowClient(promise->GetParentObject(), *mValue);
promise->MaybeResolve(windowClient.get());
} else {
promise->MaybeResolve(JS::UndefinedHandleValue);
}
mPromiseProxy->CleanUp(aCx);
return true;
}
};
RefPtr<PromiseWorkerProxy> mPromiseProxy;
nsString mClientId;
public:
GetRunnable(PromiseWorkerProxy* aPromiseProxy,
const nsAString& aClientId)
: mPromiseProxy(aPromiseProxy),
mClientId(aClientId)
{
}
NS_IMETHOD
Run() override
{
AssertIsOnMainThread();
MutexAutoLock lock(mPromiseProxy->Lock());
if (mPromiseProxy->CleanedUp()) {
return NS_OK;
}
WorkerPrivate* workerPrivate = mPromiseProxy->GetWorkerPrivate();
MOZ_ASSERT(workerPrivate);
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
ErrorResult rv;
UniquePtr<ServiceWorkerClientInfo> result = swm->GetClient(workerPrivate->GetPrincipal(),
mClientId, rv);
RefPtr<ResolvePromiseWorkerRunnable> r =
new ResolvePromiseWorkerRunnable(mPromiseProxy->GetWorkerPrivate(),
mPromiseProxy, Move(result),
rv.StealNSResult());
rv.SuppressException();
AutoJSAPI jsapi;
jsapi.Init();
r->Dispatch(jsapi.cx());
return NS_OK;
}
};
class MatchAllRunnable final : public nsRunnable
{
class ResolvePromiseWorkerRunnable final : public WorkerRunnable
{
RefPtr<PromiseWorkerProxy> mPromiseProxy;
nsTArray<ServiceWorkerClientInfo> mValue;
public:
ResolvePromiseWorkerRunnable(WorkerPrivate* aWorkerPrivate,
PromiseWorkerProxy* aPromiseProxy,
nsTArray<ServiceWorkerClientInfo>& aValue)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
mPromiseProxy(aPromiseProxy)
{
AssertIsOnMainThread();
mValue.SwapElements(aValue);
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
{
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
Promise* promise = mPromiseProxy->WorkerPromise();
MOZ_ASSERT(promise);
nsTArray<RefPtr<ServiceWorkerClient>> ret;
for (size_t i = 0; i < mValue.Length(); i++) {
ret.AppendElement(RefPtr<ServiceWorkerClient>(
new ServiceWorkerWindowClient(promise->GetParentObject(),
mValue.ElementAt(i))));
}
promise->MaybeResolve(ret);
mPromiseProxy->CleanUp(aCx);
return true;
}
};
RefPtr<PromiseWorkerProxy> mPromiseProxy;
nsCString mScope;
bool mIncludeUncontrolled;
public:
MatchAllRunnable(PromiseWorkerProxy* aPromiseProxy,
const nsCString& aScope)
const nsCString& aScope,
bool aIncludeUncontrolled)
: mPromiseProxy(aPromiseProxy),
mScope(aScope)
mScope(aScope),
mIncludeUncontrolled(aIncludeUncontrolled)
{
MOZ_ASSERT(mPromiseProxy);
}
@@ -119,7 +206,8 @@ public:
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
nsTArray<ServiceWorkerClientInfo> result;
swm->GetAllClients(mPromiseProxy->GetWorkerPrivate()->GetPrincipal(), mScope, result);
swm->GetAllClients(mPromiseProxy->GetWorkerPrivate()->GetPrincipal(), mScope,
mIncludeUncontrolled, result);
RefPtr<ResolvePromiseWorkerRunnable> r =
new ResolvePromiseWorkerRunnable(mPromiseProxy->GetWorkerPrivate(),
mPromiseProxy, result);
@@ -569,6 +657,31 @@ private:
} // namespace
already_AddRefed<Promise>
ServiceWorkerClients::Get(const nsAString& aClientId, ErrorResult& aRv)
{
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
RefPtr<Promise> promise = Promise::Create(mWorkerScope, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
RefPtr<PromiseWorkerProxy> promiseProxy =
PromiseWorkerProxy::Create(workerPrivate, promise);
if (!promiseProxy) {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
return promise.forget();
}
RefPtr<GetRunnable> r =
new GetRunnable(promiseProxy, aClientId);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r)));
return promise.forget();
}
already_AddRefed<Promise>
ServiceWorkerClients::MatchAll(const ClientQueryOptions& aOptions,
ErrorResult& aRv)
@@ -580,7 +693,7 @@ ServiceWorkerClients::MatchAll(const ClientQueryOptions& aOptions,
nsString scope;
mWorkerScope->GetScope(scope);
if (aOptions.mIncludeUncontrolled || aOptions.mType != ClientType::Window) {
if (aOptions.mType != ClientType::Window) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return nullptr;
}
@@ -599,7 +712,8 @@ ServiceWorkerClients::MatchAll(const ClientQueryOptions& aOptions,
RefPtr<MatchAllRunnable> r =
new MatchAllRunnable(promiseProxy,
NS_ConvertUTF16toUTF8(scope));
NS_ConvertUTF16toUTF8(scope),
aOptions.mIncludeUncontrolled);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r)));
return promise.forget();
}
+3
View File
@@ -29,6 +29,9 @@ public:
explicit ServiceWorkerClients(ServiceWorkerGlobalScope* aWorkerScope);
already_AddRefed<Promise>
Get(const nsAString& aClientId, ErrorResult& aRv);
already_AddRefed<Promise>
MatchAll(const ClientQueryOptions& aOptions, ErrorResult& aRv);
+1
View File
@@ -102,6 +102,7 @@ FetchEvent::Constructor(const GlobalObject& aGlobal,
e->SetTrusted(trusted);
e->mRequest = aOptions.mRequest.WasPassed() ?
&aOptions.mRequest.Value() : nullptr;
e->mClientId = aOptions.mClientId;
e->mIsReload = aOptions.mIsReload;
return e.forget();
}
+7
View File
@@ -107,6 +107,7 @@ class FetchEvent final : public ExtendableEvent
RefPtr<Request> mRequest;
nsCString mScriptSpec;
nsCString mPreventDefaultScriptSpec;
nsString mClientId;
uint32_t mPreventDefaultLineNumber;
uint32_t mPreventDefaultColumnNumber;
bool mIsReload;
@@ -149,6 +150,12 @@ public:
return mRequest;
}
void
GetClientId(nsAString& aClientId) const
{
aClientId = mClientId;
}
bool
IsReload() const
{
File diff suppressed because it is too large Load Diff
+46 -37
View File
@@ -16,6 +16,7 @@
#include "mozilla/LinkedList.h"
#include "mozilla/Preferences.h"
#include "mozilla/TypedEnumBits.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Promise.h"
@@ -24,9 +25,9 @@
#include "mozilla/dom/ServiceWorkerRegistrar.h"
#include "mozilla/dom/ServiceWorkerRegistrarTypes.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "nsIIPCBackgroundChildCreateCallback.h"
#include "nsClassHashtable.h"
#include "nsDataHashtable.h"
#include "nsIIPCBackgroundChildCreateCallback.h"
#include "nsRefPtrHashtable.h"
#include "nsTArrayForwardDeclare.h"
#include "nsTObserverArray.h"
@@ -35,7 +36,7 @@ class mozIApplicationClearPrivateDataParams;
namespace mozilla {
class OriginAttributes;
class PrincipalOriginAttributes;
namespace dom {
@@ -47,13 +48,12 @@ class ServiceWorker;
class ServiceWorkerClientInfo;
class ServiceWorkerInfo;
class ServiceWorkerJob;
class ServiceWorkerRegisterJob;
class ServiceWorkerJobQueue;
class ServiceWorkerManagerChild;
class ServiceWorkerPrivate;
class ServiceWorkerUpdateFinishCallback;
class ServiceWorkerRegistrationInfo final : public nsIServiceWorkerRegistrationInfo
class ServiceWorkerRegistrationInfo final
: public nsIServiceWorkerRegistrationInfo
{
uint32_t mControlledDocumentsCounter;
@@ -78,7 +78,11 @@ public:
uint64_t mLastUpdateCheckTime;
RefPtr<ServiceWorkerRegisterJob> mUpdateJob;
// According to the spec, Soft Update shouldn't queue an update job
// if the registration queue is not empty. Because our job queue
// works slightly different, we use a flag to determine if the registration
// is already updating.
bool mUpdating;
// When unregister() is called on a registration, it is not immediately
// removed since documents may be controlled. It is marked as
@@ -115,13 +119,14 @@ public:
void
StopControllingADocument()
{
MOZ_ASSERT(mControlledDocumentsCounter);
--mControlledDocumentsCounter;
}
bool
IsControllingDocuments() const
{
return mActiveWorker && mControlledDocumentsCounter > 0;
return mActiveWorker && mControlledDocumentsCounter;
}
void
@@ -147,19 +152,13 @@ public:
void
NotifyListenersOnChange();
bool
IsUpdating() const;
void
AppendUpdateCallback(ServiceWorkerUpdateFinishCallback* aCallback);
};
class ServiceWorkerUpdateFinishCallback
{
protected:
virtual ~ServiceWorkerUpdateFinishCallback()
{ }
{}
public:
NS_INLINE_DECL_REFCOUNTING(ServiceWorkerUpdateFinishCallback)
@@ -281,6 +280,7 @@ public:
void
SetActivateStateUncheckedWithoutEvent(ServiceWorkerState aState)
{
AssertIsOnMainThread();
mState = aState;
}
@@ -313,7 +313,9 @@ class ServiceWorkerManager final
friend class GetRegistrationsRunnable;
friend class GetRegistrationRunnable;
friend class ServiceWorkerJobQueue;
friend class ServiceWorkerInstallJob;
friend class ServiceWorkerRegisterJob;
friend class ServiceWorkerJobBase;
friend class ServiceWorkerRegistrationInfo;
friend class ServiceWorkerUnregisterJob;
@@ -351,17 +353,18 @@ public:
nsClassHashtable<nsCStringHashKey, InterceptionList> mNavigationInterceptions;
bool
IsAvailable(const OriginAttributes& aOriginAttributes, nsIURI* aURI);
IsAvailable(const PrincipalOriginAttributes& aOriginAttributes, nsIURI* aURI);
bool
IsControlled(nsIDocument* aDocument, ErrorResult& aRv);
already_AddRefed<nsIRunnable>
PrepareFetchEvent(const OriginAttributes& aOriginAttributes,
PrepareFetchEvent(const PrincipalOriginAttributes& aOriginAttributes,
nsIDocument* aDoc,
const nsAString& aDocumentIdForTopLevelNavigation,
nsIInterceptedChannel* aChannel,
bool aIsReload,
bool aIsSubresourceLoad,
bool aIsSubresourceLoad,
ErrorResult& aRv);
void
@@ -370,17 +373,16 @@ public:
ErrorResult& aRv);
void
SoftUpdate(nsIPrincipal* aPrincipal,
const nsACString& aScope,
ServiceWorkerUpdateFinishCallback* aCallback = nullptr);
Update(nsIPrincipal* aPrincipal,
const nsACString& aScope,
ServiceWorkerUpdateFinishCallback* aCallback);
void
SoftUpdate(const OriginAttributes& aOriginAttributes,
const nsACString& aScope,
ServiceWorkerUpdateFinishCallback* aCallback = nullptr);
const nsACString& aScope);
void
PropagateSoftUpdate(const OriginAttributes& aOriginAttributes,
PropagateSoftUpdate(const PrincipalOriginAttributes& aOriginAttributes,
const nsAString& aScope);
void
@@ -434,10 +436,16 @@ public:
uint32_t aFlags,
JSExnType aExnType);
UniquePtr<ServiceWorkerClientInfo>
GetClient(nsIPrincipal* aPrincipal,
const nsAString& aClientId,
ErrorResult& aRv);
void
GetAllClients(nsIPrincipal* aPrincipal,
const nsCString& aScope,
nsTArray<ServiceWorkerClientInfo>& aControlledDocuments);
bool aIncludeUncontrolled,
nsTArray<ServiceWorkerClientInfo>& aDocuments);
void
MaybeClaimClient(nsIDocument* aDocument,
@@ -486,11 +494,6 @@ private:
void
MaybeRemoveRegistrationInfo(const nsACString& aScopeKey);
void
SoftUpdate(const nsACString& aScopeKey,
const nsACString& aScope,
ServiceWorkerUpdateFinishCallback* aCallback = nullptr);
already_AddRefed<ServiceWorkerRegistrationInfo>
GetRegistration(const nsACString& aScopeKey,
const nsACString& aScope) const;
@@ -502,7 +505,8 @@ private:
Update(ServiceWorkerRegistrationInfo* aRegistration);
nsresult
GetDocumentRegistration(nsIDocument* aDoc, ServiceWorkerRegistrationInfo** aRegistrationInfo);
GetDocumentRegistration(nsIDocument* aDoc,
ServiceWorkerRegistrationInfo** aRegistrationInfo);
NS_IMETHODIMP
GetServiceWorkerForScope(nsIDOMWindow* aWindow,
@@ -511,7 +515,7 @@ private:
nsISupports** aServiceWorker);
ServiceWorkerInfo*
GetActiveWorkerInfoForScope(const OriginAttributes& aOriginAttributes,
GetActiveWorkerInfoForScope(const PrincipalOriginAttributes& aOriginAttributes,
const nsACString& aScope);
ServiceWorkerInfo*
@@ -521,9 +525,13 @@ private:
InvalidateServiceWorkerRegistrationWorker(ServiceWorkerRegistrationInfo* aRegistration,
WhichServiceWorker aWhichOnes);
void
NotifyServiceWorkerRegistrationRemoved(ServiceWorkerRegistrationInfo* aRegistration);
void
StartControllingADocument(ServiceWorkerRegistrationInfo* aRegistration,
nsIDocument* aDoc);
nsIDocument* aDoc,
const nsAString& aDocumentId);
void
StopControllingADocument(ServiceWorkerRegistrationInfo* aRegistration);
@@ -538,7 +546,7 @@ private:
GetServiceWorkerRegistrationInfo(nsIPrincipal* aPrincipal, nsIURI* aURI);
already_AddRefed<ServiceWorkerRegistrationInfo>
GetServiceWorkerRegistrationInfo(const OriginAttributes& aOriginAttributes,
GetServiceWorkerRegistrationInfo(const PrincipalOriginAttributes& aOriginAttributes,
nsIURI* aURI);
already_AddRefed<ServiceWorkerRegistrationInfo>
@@ -577,7 +585,8 @@ private:
FireControllerChange(ServiceWorkerRegistrationInfo* aRegistration);
void
StorePendingReadyPromise(nsPIDOMWindow* aWindow, nsIURI* aURI, Promise* aPromise);
StorePendingReadyPromise(nsPIDOMWindow* aWindow, nsIURI* aURI,
Promise* aPromise);
void
CheckPendingReadyPromises();
@@ -585,11 +594,11 @@ private:
bool
CheckReadyPromise(nsPIDOMWindow* aWindow, nsIURI* aURI, Promise* aPromise);
struct PendingReadyPromise
struct PendingReadyPromise final
{
PendingReadyPromise(nsIURI* aURI, Promise* aPromise)
: mURI(aURI), mPromise(aPromise)
{ }
{}
nsCOMPtr<nsIURI> mURI;
RefPtr<Promise> mPromise;
@@ -620,7 +629,7 @@ private:
// Removes all service worker registrations that matches the given
// mozIApplicationClearPrivateDataParams.
void
RemoveAllRegistrations(OriginAttributes* aParams);
RemoveAllRegistrations(PrincipalOriginAttributes* aParams);
RefPtr<ServiceWorkerManagerChild> mActor;
+2 -2
View File
@@ -32,7 +32,7 @@ ServiceWorkerManagerChild::RecvNotifyRegister(
bool
ServiceWorkerManagerChild::RecvNotifySoftUpdate(
const OriginAttributes& aOriginAttributes,
const PrincipalOriginAttributes& aOriginAttributes,
const nsString& aScope)
{
if (mShuttingDown) {
@@ -42,7 +42,7 @@ ServiceWorkerManagerChild::RecvNotifySoftUpdate(
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
swm->SoftUpdate(aOriginAttributes, NS_ConvertUTF16toUTF8(aScope), nullptr);
swm->SoftUpdate(aOriginAttributes, NS_ConvertUTF16toUTF8(aScope));
return true;
}
+2 -2
View File
@@ -12,7 +12,7 @@
namespace mozilla {
class OriginAttributes;
class PrincipalOriginAttributes;
namespace ipc {
class BackgroundChildImpl;
@@ -36,7 +36,7 @@ public:
virtual bool RecvNotifyRegister(const ServiceWorkerRegistrationData& aData)
override;
virtual bool RecvNotifySoftUpdate(const OriginAttributes& aOriginAttributes,
virtual bool RecvNotifySoftUpdate(const PrincipalOriginAttributes& aOriginAttributes,
const nsString& aScope) override;
virtual bool RecvNotifyUnregister(const PrincipalInfo& aPrincipalInfo,
+1 -1
View File
@@ -232,7 +232,7 @@ ServiceWorkerManagerParent::RecvUnregister(const PrincipalInfo& aPrincipalInfo,
}
bool
ServiceWorkerManagerParent::RecvPropagateSoftUpdate(const OriginAttributes& aOriginAttributes,
ServiceWorkerManagerParent::RecvPropagateSoftUpdate(const PrincipalOriginAttributes& aOriginAttributes,
const nsString& aScope)
{
AssertIsOnBackgroundThread();
+6 -6
View File
@@ -11,11 +11,11 @@
namespace mozilla {
class OriginAttributes;
class PrincipalOriginAttributes;
namespace ipc {
class BackgroundParentImpl;
}
} // namespace ipc
namespace dom {
namespace workers {
@@ -42,7 +42,7 @@ private:
virtual bool RecvUnregister(const PrincipalInfo& aPrincipalInfo,
const nsString& aScope) override;
virtual bool RecvPropagateSoftUpdate(const OriginAttributes& aOriginAttributes,
virtual bool RecvPropagateSoftUpdate(const PrincipalOriginAttributes& aOriginAttributes,
const nsString& aScope) override;
virtual bool RecvPropagateUnregister(const PrincipalInfo& aPrincipalInfo,
@@ -63,8 +63,8 @@ private:
uint64_t mID;
};
} // workers namespace
} // dom namespace
} // mozilla namespace
} // namespace workers
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ServiceWorkerManagerParent_h
+1 -1
View File
@@ -111,7 +111,7 @@ ServiceWorkerManagerService::PropagateRegistration(
void
ServiceWorkerManagerService::PropagateSoftUpdate(
uint64_t aParentID,
const OriginAttributes& aOriginAttributes,
const PrincipalOriginAttributes& aOriginAttributes,
const nsAString& aScope)
{
AssertIsOnBackgroundThread();
+2 -2
View File
@@ -13,7 +13,7 @@
namespace mozilla {
class OriginAttributes;
class PrincipalOriginAttributes;
namespace ipc {
class PrincipalInfo;
@@ -42,7 +42,7 @@ public:
ServiceWorkerRegistrationData& aData);
void PropagateSoftUpdate(uint64_t aParentID,
const OriginAttributes& aOriginAttributes,
const PrincipalOriginAttributes& aOriginAttributes,
const nsAString& aScope);
void PropagateUnregister(uint64_t aParentID,
+290 -54
View File
@@ -61,6 +61,7 @@ NS_IMPL_ISUPPORTS0(KeepAliveToken)
ServiceWorkerPrivate::ServiceWorkerPrivate(ServiceWorkerInfo* aInfo)
: mInfo(aInfo)
, mIsPushWorker(false)
, mDebuggerCount(0)
, mTokenCount(0)
{
AssertIsOnMainThread();
@@ -103,46 +104,64 @@ namespace {
class CheckScriptEvaluationWithCallback final : public WorkerRunnable
{
nsMainThreadPtrHandle<KeepAliveToken> mKeepAliveToken;
RefPtr<nsRunnable> mCallback;
RefPtr<LifeCycleEventCallback> mCallback;
DebugOnly<bool> mDone;
public:
CheckScriptEvaluationWithCallback(WorkerPrivate* aWorkerPrivate,
KeepAliveToken* aKeepAliveToken,
nsRunnable* aCallback)
LifeCycleEventCallback* aCallback)
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount)
, mKeepAliveToken(new nsMainThreadPtrHolder<KeepAliveToken>(aKeepAliveToken))
, mCallback(aCallback)
, mDone(false)
{
AssertIsOnMainThread();
}
~CheckScriptEvaluationWithCallback()
{
MOZ_ASSERT(mDone);
}
bool
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
{
aWorkerPrivate->AssertIsOnWorkerThread();
if (aWorkerPrivate->WorkerScriptExecutedSuccessfully()) {
nsresult rv = NS_DispatchToMainThread(mCallback);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to dispatch CheckScriptEvaluation callback.");
}
}
Done(aWorkerPrivate->WorkerScriptExecutedSuccessfully());
return true;
}
NS_IMETHOD
Cancel() override
{
Done(false);
return WorkerRunnable::Cancel();
}
private:
void
Done(bool aResult)
{
mDone = true;
mCallback->SetResult(aResult);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(mCallback)));
}
};
} // anonymous namespace
nsresult
ServiceWorkerPrivate::ContinueOnSuccessfulScriptEvaluation(nsRunnable* aCallback)
ServiceWorkerPrivate::CheckScriptEvaluation(LifeCycleEventCallback* aCallback)
{
nsresult rv = SpawnWorkerIfNeeded(LifeCycleEvent, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(mKeepAliveToken);
RefPtr<WorkerRunnable> r = new CheckScriptEvaluationWithCallback(mWorkerPrivate,
mKeepAliveToken,
aCallback);
mKeepAliveToken,
aCallback);
AutoJSAPI jsapi;
jsapi.Init();
if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
@@ -211,7 +230,7 @@ public:
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
OriginAttributes attrs =
PrincipalOriginAttributes attrs =
mozilla::BasePrincipal::Cast(mRegistration->mPrincipal)->OriginAttributesRef();
swm->PropagateSoftUpdate(attrs,
@@ -352,6 +371,15 @@ public:
return DispatchLifecycleEvent(aCx, aWorkerPrivate);
}
NS_IMETHOD
Cancel() override
{
mCallback->SetResult(false);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(mCallback)));
return WorkerRunnable::Cancel();
}
private:
bool
DispatchLifecycleEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
@@ -359,52 +387,116 @@ private:
};
/*
* Used to handle ExtendableEvent::waitUntil() and proceed with
* installation/activation.
* Used to handle ExtendableEvent::waitUntil() and catch abnormal worker
* termination during the execution of life cycle events. It is responsible
* with advancing the job queue for install/activate tasks.
*/
class LifecycleEventPromiseHandler final : public PromiseNativeHandler
class LifeCycleEventWatcher final : public PromiseNativeHandler,
public WorkerFeature
{
WorkerPrivate* mWorkerPrivate;
RefPtr<LifeCycleEventCallback> mCallback;
bool mDone;
virtual
~LifecycleEventPromiseHandler()
{ }
~LifeCycleEventWatcher()
{
if (mDone) {
return;
}
MOZ_ASSERT(GetCurrentThreadWorkerPrivate() == mWorkerPrivate);
// XXXcatalinb: If all the promises passed to waitUntil go out of scope,
// the resulting Promise.all will be cycle collected and it will drop its
// native handlers (including this object). Instead of waiting for a timeout
// we report the failure now.
JSContext* cx = mWorkerPrivate->GetJSContext();
ReportResult(cx, false);
}
public:
NS_DECL_ISUPPORTS
explicit LifecycleEventPromiseHandler(LifeCycleEventCallback* aCallback)
: mCallback(aCallback)
LifeCycleEventWatcher(WorkerPrivate* aWorkerPrivate,
LifeCycleEventCallback* aCallback)
: mWorkerPrivate(aWorkerPrivate)
, mCallback(aCallback)
, mDone(false)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aWorkerPrivate);
aWorkerPrivate->AssertIsOnWorkerThread();
}
bool
Init()
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
JSContext* cx = mWorkerPrivate->GetJSContext();
// We need to listen for worker termination in case the event handler
// never completes or never resolves the waitUntil promise. There are
// two possible scenarios:
// 1. The keepAlive token expires and the worker is terminated, in which
// case the registration/update promise will be rejected
// 2. A new service worker is registered which will terminate the current
// installing worker.
if (NS_WARN_IF(!mWorkerPrivate->AddFeature(cx, this))) {
NS_WARNING("LifeCycleEventWatcher failed to add feature.");
ReportResult(cx, false);
return false;
}
return true;
}
bool
Notify(JSContext* aCx, Status aStatus) override
{
if (aStatus < Terminating) {
return true;
}
MOZ_ASSERT(GetCurrentThreadWorkerPrivate() == mWorkerPrivate);
ReportResult(aCx, false);
return true;
}
void
ReportResult(JSContext* aCx, bool aResult)
{
mWorkerPrivate->AssertIsOnWorkerThread();
if (mDone) {
return;
}
mDone = true;
mCallback->SetResult(aResult);
nsresult rv = NS_DispatchToMainThread(mCallback);
if (NS_WARN_IF(NS_FAILED(rv))) {
NS_RUNTIMEABORT("Failed to dispatch life cycle event handler.");
}
mWorkerPrivate->RemoveFeature(aCx, this);
}
void
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(GetCurrentThreadWorkerPrivate() == mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
mCallback->SetResult(true);
nsresult rv = NS_DispatchToMainThread(mCallback);
if (NS_WARN_IF(NS_FAILED(rv))) {
NS_RUNTIMEABORT("Failed to dispatch life cycle event handler.");
}
ReportResult(aCx, true);
}
void
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
{
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
MOZ_ASSERT(GetCurrentThreadWorkerPrivate() == mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
mCallback->SetResult(false);
nsresult rv = NS_DispatchToMainThread(mCallback);
if (NS_WARN_IF(NS_FAILED(rv))) {
NS_RUNTIMEABORT("Failed to dispatch life cycle event handler.");
}
ReportResult(aCx, false);
// Note, all WaitUntil() rejections are reported to client consoles
// by the WaitUntilHandler in ServiceWorkerEvents. This ensures that
@@ -413,7 +505,7 @@ public:
}
};
NS_IMPL_ISUPPORTS0(LifecycleEventPromiseHandler)
NS_IMPL_ISUPPORTS0(LifeCycleEventWatcher)
bool
LifecycleEventWorkerRunnable::DispatchLifecycleEvent(JSContext* aCx,
@@ -436,16 +528,23 @@ LifecycleEventWorkerRunnable::DispatchLifecycleEvent(JSContext* aCx,
event->SetTrusted(true);
// It is important to initialize the watcher before actually dispatching
// the event in order to catch worker termination while the event handler
// is still executing. This can happen with infinite loops, for example.
RefPtr<LifeCycleEventWatcher> watcher =
new LifeCycleEventWatcher(aWorkerPrivate, mCallback);
if (!watcher->Init()) {
return true;
}
RefPtr<Promise> waitUntil;
DispatchExtendableEventOnWorkerScope(aCx, aWorkerPrivate->GlobalScope(),
event, getter_AddRefs(waitUntil));
if (waitUntil) {
RefPtr<LifecycleEventPromiseHandler> handler =
new LifecycleEventPromiseHandler(mCallback);
waitUntil->AppendNativeHandler(handler);
waitUntil->AppendNativeHandler(watcher);
} else {
mCallback->SetResult(false);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(mCallback)));
watcher->ReportResult(aCx, false);
}
return true;
@@ -590,6 +689,14 @@ ServiceWorkerPrivate::SendPushEvent(const Maybe<nsTArray<uint8_t>>& aData,
mKeepAliveToken,
aData,
regInfo);
if (mInfo->State() == ServiceWorkerState::Activating) {
mPendingFunctionalEvents.AppendElement(r.forget());
return NS_OK;
}
MOZ_ASSERT(mInfo->State() == ServiceWorkerState::Activated);
AutoJSAPI jsapi;
jsapi.Init();
if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
@@ -909,6 +1016,7 @@ class FetchEventRunnable : public ExtendableFunctionalEventWorkerRunnable
nsTArray<nsCString> mHeaderValues;
nsCString mSpec;
nsCString mMethod;
nsString mClientId;
bool mIsReload;
DebugOnly<bool> mIsHttpChannel;
RequestMode mRequestMode;
@@ -925,12 +1033,13 @@ public:
// later on.
const nsACString& aScriptSpec,
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
const nsAString& aDocumentId,
bool aIsReload)
: ExtendableFunctionalEventWorkerRunnable(
aWorkerPrivate, aKeepAliveToken, aRegistration)
, mInterceptedChannel(aChannel)
, mScriptSpec(aScriptSpec)
, mClientId(aDocumentId)
, mIsReload(aIsReload)
, mIsHttpChannel(false)
, mRequestMode(RequestMode::No_cors)
@@ -1057,6 +1166,17 @@ public:
return DispatchFetchEvent(aCx, aWorkerPrivate);
}
NS_IMETHOD
Cancel() override
{
nsCOMPtr<nsIRunnable> runnable = new ResumeRequest(mInterceptedChannel);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
NS_WARNING("Failed to resume channel on FetchEventRunnable::Cancel()!\n");
}
WorkerRunnable::Cancel();
return NS_OK;
}
private:
~FetchEventRunnable() {}
@@ -1143,6 +1263,7 @@ private:
init.mRequest.Value() = request;
init.mBubbles = false;
init.mCancelable = true;
init.mClientId = mClientId;
init.mIsReload = mIsReload;
RefPtr<FetchEvent> event =
FetchEvent::Constructor(globalObj, NS_LITERAL_STRING("fetch"), init, result);
@@ -1243,9 +1364,11 @@ NS_IMPL_ISUPPORTS_INHERITED(FetchEventRunnable, WorkerRunnable, nsIHttpHeaderVis
nsresult
ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
nsILoadGroup* aLoadGroup,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
const nsAString& aDocumentId,
bool aIsReload)
{
AssertIsOnMainThread();
// if the ServiceWorker script fails to load for some reason, just resume
// the original channel.
nsCOMPtr<nsIRunnable> failRunnable =
@@ -1273,12 +1396,19 @@ ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
RefPtr<FetchEventRunnable> r =
new FetchEventRunnable(mWorkerPrivate, mKeepAliveToken, handle,
mInfo->ScriptSpec(), regInfo,
Move(aClientInfo), aIsReload);
aDocumentId, aIsReload);
rv = r->Init();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (mInfo->State() == ServiceWorkerState::Activating) {
mPendingFunctionalEvents.AppendElement(r.forget());
return NS_OK;
}
MOZ_ASSERT(mInfo->State() == ServiceWorkerState::Activated);
AutoJSAPI jsapi;
jsapi.Init();
if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
@@ -1303,7 +1433,7 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
if (mWorkerPrivate) {
mWorkerPrivate->UpdateOverridenLoadGroup(aLoadGroup);
ResetIdleTimeout(aWhy);
RenewKeepAliveToken(aWhy);
return NS_OK;
}
@@ -1383,7 +1513,7 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
}
mIsPushWorker = false;
ResetIdleTimeout(aWhy);
RenewKeepAliveToken(aWhy);
return NS_OK;
}
@@ -1425,6 +1555,15 @@ ServiceWorkerPrivate::TerminateWorker()
NS_WARN_IF(!mWorkerPrivate->Terminate(jsapi.cx()));
mWorkerPrivate = nullptr;
mSupportsArray.Clear();
// Any pending events are never going to fire on this worker. Cancel
// them so that intercepted channels can be reset and other resources
// cleaned up.
nsTArray<RefPtr<WorkerRunnable>> pendingEvents;
mPendingFunctionalEvents.SwapElements(pendingEvents);
for (uint32_t i = 0; i < pendingEvents.Length(); ++i) {
pendingEvents[i]->Cancel();
}
}
}
@@ -1440,13 +1579,98 @@ void
ServiceWorkerPrivate::NoteStoppedControllingDocuments()
{
AssertIsOnMainThread();
if (mIsPushWorker) {
if (mIsPushWorker || mDebuggerCount) {
return;
}
TerminateWorker();
}
void
ServiceWorkerPrivate::Activated()
{
AssertIsOnMainThread();
// If we had to queue up events due to the worker activating, that means
// the worker must be currently running. We should be called synchronously
// when the worker becomes activated.
MOZ_ASSERT_IF(!mPendingFunctionalEvents.IsEmpty(), mWorkerPrivate);
nsTArray<RefPtr<WorkerRunnable>> pendingEvents;
mPendingFunctionalEvents.SwapElements(pendingEvents);
for (uint32_t i = 0; i < pendingEvents.Length(); ++i) {
RefPtr<WorkerRunnable> r = pendingEvents[i].forget();
AutoJSAPI jsapi;
jsapi.Init();
if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
NS_WARNING("Failed to dispatch pending functional event!");
}
}
}
nsresult
ServiceWorkerPrivate::GetDebugger(nsIWorkerDebugger** aResult)
{
AssertIsOnMainThread();
MOZ_ASSERT(aResult);
if (!mDebuggerCount) {
return NS_OK;
}
MOZ_ASSERT(mWorkerPrivate);
nsCOMPtr<nsIWorkerDebugger> debugger = do_QueryInterface(mWorkerPrivate->Debugger());
debugger.forget(aResult);
return NS_OK;
}
nsresult
ServiceWorkerPrivate::AttachDebugger()
{
AssertIsOnMainThread();
// When the first debugger attaches to a worker, we spawn a worker if needed,
// and cancel the idle timeout. The idle timeout should not be reset until
// the last debugger detached from the worker.
if (!mDebuggerCount) {
nsresult rv = SpawnWorkerIfNeeded(AttachEvent, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
mIdleWorkerTimer->Cancel();
}
++mDebuggerCount;
return NS_OK;
}
nsresult
ServiceWorkerPrivate::DetachDebugger()
{
AssertIsOnMainThread();
if (!mDebuggerCount) {
return NS_ERROR_UNEXPECTED;
}
--mDebuggerCount;
// When the last debugger detaches from a worker, we either reset the idle
// timeout, or terminate the worker if there are no more active tokens.
if (!mDebuggerCount) {
if (mTokenCount) {
ResetIdleTimeout();
} else {
TerminateWorker();
}
}
return NS_OK;
}
/* static */ void
ServiceWorkerPrivate::NoteIdleWorkerCallback(nsITimer* aTimer, void* aPrivate)
{
@@ -1490,24 +1714,36 @@ ServiceWorkerPrivate::TerminateWorkerCallback(nsITimer* aTimer, void *aPrivate)
}
void
ServiceWorkerPrivate::ResetIdleTimeout(WakeUpReason aWhy)
ServiceWorkerPrivate::RenewKeepAliveToken(WakeUpReason aWhy)
{
// We should have an active worker if we're reseting the idle timeout
// We should have an active worker if we're renewing the keep alive token.
MOZ_ASSERT(mWorkerPrivate);
if (aWhy == PushEvent || aWhy == PushSubscriptionChangeEvent) {
mIsPushWorker = true;
}
// If there is at least one debugger attached to the worker, the idle worker
// timeout was canceled when the first debugger attached to the worker. It
// should not be reset until the last debugger detaches from the worker.
if (!mDebuggerCount) {
ResetIdleTimeout();
}
if (!mKeepAliveToken) {
mKeepAliveToken = new KeepAliveToken(this);
}
}
void
ServiceWorkerPrivate::ResetIdleTimeout()
{
uint32_t timeout = Preferences::GetInt("dom.serviceWorkers.idle_timeout");
DebugOnly<nsresult> rv =
mIdleWorkerTimer->InitWithFuncCallback(ServiceWorkerPrivate::NoteIdleWorkerCallback,
this, timeout,
nsITimer::TYPE_ONE_SHOT);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (!mKeepAliveToken) {
mKeepAliveToken = new KeepAliveToken(this);
}
}
void
+33 -7
View File
@@ -72,11 +72,9 @@ public:
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo);
// This is used to validate the worker script and continue the installation
// process. Note that the callback is dispatched to the main thread
// ONLY if the evaluation was successful. Failure is handled by the JS
// exception handler which will call ServiceWorkerManager::HandleError.
// process.
nsresult
ContinueOnSuccessfulScriptEvaluation(nsRunnable* aCallback);
CheckScriptEvaluation(LifeCycleEventCallback* aCallback);
nsresult
SendLifeCycleEvent(const nsAString& aEventType,
@@ -105,7 +103,7 @@ public:
nsresult
SendFetchEvent(nsIInterceptedChannel* aChannel,
nsILoadGroup* aLoadGroup,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
const nsAString& aDocumentId,
bool aIsReload);
void
@@ -128,6 +126,24 @@ public:
void
NoteStoppedControllingDocuments();
WorkerPrivate*
GetWorkerPrivate() const
{
return mWorkerPrivate;
}
void
Activated();
nsresult
GetDebugger(nsIWorkerDebugger** aResult);
nsresult
AttachDebugger();
nsresult
DetachDebugger();
private:
enum WakeUpReason {
FetchEvent = 0,
@@ -135,7 +151,8 @@ private:
PushSubscriptionChangeEvent,
MessageEvent,
NotificationClickEvent,
LifeCycleEvent
LifeCycleEvent,
AttachEvent
};
// Timer callbacks
@@ -146,7 +163,10 @@ private:
TerminateWorkerCallback(nsITimer* aTimer, void *aPrivate);
void
ResetIdleTimeout(WakeUpReason aWhy);
RenewKeepAliveToken(WakeUpReason aWhy);
void
ResetIdleTimeout();
void
AddToken();
@@ -184,6 +204,8 @@ private:
// worker a grace period after each event.
RefPtr<KeepAliveToken> mKeepAliveToken;
uint64_t mDebuggerCount;
uint64_t mTokenCount;
// Meant for keeping objects alive while handling requests from the worker
@@ -191,6 +213,10 @@ private:
// |StoreISupports| and |RemoveISupports|. Note that the array is also
// cleared whenever the worker is terminated.
nsTArray<nsCOMPtr<nsISupports>> mSupportsArray;
// Array of function event worker runnables that are pending due to
// the worker activating. Main thread only.
nsTArray<RefPtr<WorkerRunnable>> mPendingFunctionalEvents;
};
} // namespace workers
+1 -1
View File
@@ -326,7 +326,7 @@ ServiceWorkerRegistrar::ReadData()
nsAutoCString suffix;
GET_LINE(suffix);
OriginAttributes attrs;
PrincipalOriginAttributes attrs;
if (!attrs.PopulateFromSuffix(suffix)) {
return NS_ERROR_INVALID_ARG;
}
+32 -6
View File
@@ -250,6 +250,19 @@ ServiceWorkerRegistrationMainThread::InvalidateWorkers(WhichServiceWorker aWhich
if (aWhichOnes & WhichServiceWorker::ACTIVE_WORKER) {
mActiveWorker = nullptr;
}
}
void
ServiceWorkerRegistrationMainThread::RegistrationRemoved()
{
// If the registration is being removed completely, remove it from the
// window registration hash table so that a new registration would get a new
// wrapper JS object.
nsCOMPtr<nsPIDOMWindow> window = GetOwner();
if (window) {
window->InvalidateServiceWorkerRegistration(mScope);
}
}
namespace {
@@ -266,8 +279,7 @@ UpdateInternal(nsIPrincipal* aPrincipal,
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
// The spec defines ServiceWorkerRegistration.update() exactly as Soft Update.
swm->SoftUpdate(aPrincipal, NS_ConvertUTF16toUTF8(aScope), aCallback);
swm->Update(aPrincipal, NS_ConvertUTF16toUTF8(aScope), aCallback);
}
class MainThreadUpdateCallback final : public ServiceWorkerUpdateFinishCallback
@@ -393,14 +405,22 @@ public:
AssertIsOnMainThread();
ErrorResult result;
MutexAutoLock lock(mPromiseProxy->Lock());
if (mPromiseProxy->CleanedUp()) {
return NS_OK;
nsCOMPtr<nsIPrincipal> principal;
// UpdateInternal may try to reject the promise synchronously leading
// to a deadlock.
{
MutexAutoLock lock(mPromiseProxy->Lock());
if (mPromiseProxy->CleanedUp()) {
return NS_OK;
}
principal = mPromiseProxy->GetWorkerPrivate()->GetPrincipal();
}
MOZ_ASSERT(principal);
RefPtr<WorkerThreadUpdateCallback> cb =
new WorkerThreadUpdateCallback(mPromiseProxy);
UpdateInternal(mPromiseProxy->GetWorkerPrivate()->GetPrincipal(), mScope, cb);
UpdateInternal(principal, mScope, cb);
return NS_OK;
}
@@ -857,6 +877,12 @@ public:
// FIXME(nsm);
}
void
RegistrationRemoved() override
{
AssertIsOnMainThread();
}
void
GetScope(nsAString& aScope) const override
{
+9 -3
View File
@@ -65,6 +65,9 @@ public:
virtual void
InvalidateWorkers(WhichServiceWorker aWhichOnes) = 0;
virtual void
RegistrationRemoved() = 0;
virtual void
GetScope(nsAString& aScope) const = 0;
};
@@ -106,9 +109,6 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerRegistrationMainThread,
ServiceWorkerRegistrationBase)
ServiceWorkerRegistrationMainThread(nsPIDOMWindow* aWindow,
const nsAString& aScope);
already_AddRefed<Promise>
Update(ErrorResult& aRv);
@@ -154,6 +154,9 @@ public:
void
InvalidateWorkers(WhichServiceWorker aWhichOnes) override;
void
RegistrationRemoved() override;
void
GetScope(nsAString& aScope) const override
{
@@ -161,6 +164,9 @@ public:
}
private:
friend nsPIDOMWindow;
ServiceWorkerRegistrationMainThread(nsPIDOMWindow* aWindow,
const nsAString& aScope);
~ServiceWorkerRegistrationMainThread();
already_AddRefed<workers::ServiceWorker>
+1 -9
View File
@@ -24,8 +24,7 @@ public:
const ServiceWorkerClientInfo& aClientInfo)
: ServiceWorkerClient(aOwner, aClientInfo),
mVisibilityState(aClientInfo.mVisibilityState),
mFocused(aClientInfo.mFocused),
mFrameType(aClientInfo.mFrameType)
mFocused(aClientInfo.mFocused)
{
}
@@ -44,12 +43,6 @@ public:
return mFocused;
}
mozilla::dom::FrameType
FrameType() const
{
return mFrameType;
}
already_AddRefed<Promise>
Focus(ErrorResult& aRv) const;
@@ -59,7 +52,6 @@ private:
mozilla::dom::VisibilityState mVisibilityState;
bool mFocused;
mozilla::dom::FrameType mFrameType;
};
} // namespace workers
-13
View File
@@ -2190,24 +2190,11 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
aParent->CopyJSSettings(mJSSettings);
MOZ_ASSERT(IsDedicatedWorker());
mNowBaseTimeStamp = aParent->NowBaseTimeStamp();
mNowBaseTimeHighRes = aParent->NowBaseTimeHighRes();
}
else {
AssertIsOnMainThread();
RuntimeService::GetDefaultJSSettings(mJSSettings);
if (IsDedicatedWorker() && mLoadInfo.mWindow &&
mLoadInfo.mWindow->GetPerformance()) {
mNowBaseTimeStamp = mLoadInfo.mWindow->GetPerformance()->GetDOMTiming()->
GetNavigationStartTimeStamp();
mNowBaseTimeHighRes = mLoadInfo.mWindow->GetPerformance()->GetDOMTiming()->
GetNavigationStartHighRes();
} else {
mNowBaseTimeStamp = CreationTimeStamp();
mNowBaseTimeHighRes = CreationTimeHighRes();
}
}
}
+8 -13
View File
@@ -191,8 +191,6 @@ private:
WorkerType mWorkerType;
TimeStamp mCreationTimeStamp;
DOMHighResTimeStamp mCreationTimeHighRes;
TimeStamp mNowBaseTimeStamp;
DOMHighResTimeStamp mNowBaseTimeHighRes;
protected:
// The worker is owned by its thread, which is represented here. This is set
@@ -549,21 +547,11 @@ public:
return mCreationTimeStamp;
}
DOMHighResTimeStamp CreationTimeHighRes() const
DOMHighResTimeStamp CreationTime() const
{
return mCreationTimeHighRes;
}
TimeStamp NowBaseTimeStamp() const
{
return mNowBaseTimeStamp;
}
DOMHighResTimeStamp NowBaseTimeHighRes() const
{
return mNowBaseTimeHighRes;
}
nsIPrincipal*
GetPrincipal() const
{
@@ -1278,6 +1266,13 @@ public:
return mPreferences[WORKERPREF_INTERCEPTION_ENABLED];
}
bool
OpenWindowEnabled() const
{
AssertIsOnWorkerThread();
return mPreferences[WORKERPREF_OPEN_WINDOW_ENABLED];
}
bool
OpaqueInterceptionEnabled() const
{
+12 -1
View File
@@ -591,7 +591,9 @@ public:
AutoJSAPI jsapi;
jsapi.Init();
runnable->Dispatch(jsapi.cx());
if (!runnable->Dispatch(jsapi.cx())) {
NS_WARNING("Failed to dispatch SkipWaitingResultRunnable to the worker.");
}
return NS_OK;
}
};
@@ -634,6 +636,15 @@ ServiceWorkerGlobalScope::InterceptionEnabled(JSContext* aCx, JSObject* aObj)
return worker->InterceptionEnabled();
}
bool
ServiceWorkerGlobalScope::OpenWindowEnabled(JSContext* aCx, JSObject* aObj)
{
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
return worker->OpenWindowEnabled();
}
WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope(
WorkerPrivate* aWorkerPrivate)
: mWorkerPrivate(aWorkerPrivate)
+3 -2
View File
@@ -249,6 +249,9 @@ public:
static bool
InterceptionEnabled(JSContext* aCx, JSObject* aObj);
static bool
OpenWindowEnabled(JSContext* aCx, JSObject* aObj);
void
GetScope(nsString& aScope) const
{
@@ -265,8 +268,6 @@ public:
SkipWaiting(ErrorResult& aRv);
IMPL_EVENT_HANDLER(activate)
IMPL_EVENT_HANDLER(beforeevicted)
IMPL_EVENT_HANDLER(evicted)
IMPL_EVENT_HANDLER(fetch)
IMPL_EVENT_HANDLER(install)
IMPL_EVENT_HANDLER(message)
+1
View File
@@ -201,6 +201,7 @@ enum WorkerPreference
WORKERPREF_DOM_CACHES, // dom.caches.enabled
WORKERPREF_SERVICEWORKERS, // dom.serviceWorkers.enabled
WORKERPREF_INTERCEPTION_ENABLED, // dom.serviceWorkers.interception.enabled
WORKERPREF_OPEN_WINDOW_ENABLED, // dom.serviceWorkers.openWindow.enabled
WORKERPREF_DOM_WORKERNOTIFICATION, // dom.webnotifications.workers.enabled
WORKERPREF_DOM_SERVICEWORKERNOTIFICATION, // dom.webnotifications.serviceworker.enabled
WORKERPREF_DOM_CACHES_TESTING, // dom.caches.testing.enabled

Some files were not shown because too many files have changed in this diff Show More