author | Wes Kocher <wkocher@mozilla.com> |
Tue, 26 May 2015 16:16:26 -0700 | |
changeset 245733 | ff2e0722804149cc85a6f4a26ae9983a10e4800c |
parent 245732 | 1e4e369822ac4672bddebc2f78d0df00a7904217 (current diff) |
parent 245653 | ff31a31f9203b1e63ee6b735a59696b29a0e49d5 (diff) |
child 245734 | eba8b4d8703aae0dec7ed28ea3e7a01d7d68f993 |
child 245842 | b991cd5a0ad1bb6ebcbdd7e01b1d13140dceef18 |
child 245863 | bf5bdca043c525b3e349c77d40836f94ad4c3b65 |
push id | 60257 |
push user | kwierso@gmail.com |
push date | Tue, 26 May 2015 23:25:15 +0000 |
treeherder | mozilla-inbound@eba8b4d8703a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 41.0a1 |
first release with | nightly linux32
ff2e07228041
/
41.0a1
/
20150527030204
/
files
nightly linux64
ff2e07228041
/
41.0a1
/
20150527030204
/
files
nightly mac
ff2e07228041
/
41.0a1
/
20150527030204
/
files
nightly win32
ff2e07228041
/
41.0a1
/
20150527135446
/
files
nightly win64
ff2e07228041
/
41.0a1
/
20150527030204
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
41.0a1
/
20150527030204
/
pushlog to previous
nightly linux64
41.0a1
/
20150527030204
/
pushlog to previous
nightly mac
41.0a1
/
20150527030204
/
pushlog to previous
nightly win32
41.0a1
/
20150527135446
/
pushlog to previous
nightly win64
41.0a1
/
20150527030204
/
pushlog to previous
|
--- a/accessible/jsat/AccessFu.jsm +++ b/accessible/jsat/AccessFu.jsm @@ -412,24 +412,16 @@ this.AccessFu = { // jshint ignore:line function(aJsonBounds, aBrowser, aToCSSPixels) { let bounds = new Rect(aJsonBounds.left, aJsonBounds.top, aJsonBounds.right - aJsonBounds.left, aJsonBounds.bottom - aJsonBounds.top); let win = Utils.win; let dpr = win.devicePixelRatio; let offset = { left: -win.mozInnerScreenX, top: -win.mozInnerScreenY }; - if (!aBrowser.contentWindow) { - // OOP browser, add offset of browser. - // The offset of the browser element in relation to its parent window. - let clientRect = aBrowser.getBoundingClientRect(); - let win = aBrowser.ownerDocument.defaultView; - offset.left += clientRect.left + win.mozInnerScreenX; - offset.top += clientRect.top + win.mozInnerScreenY; - } // Add the offset; the offset is in CSS pixels, so multiply the // devicePixelRatio back in before adding to preserve unit consistency. bounds = bounds.translate(offset.left * dpr, offset.top * dpr); // If we want to get to CSS pixels from device pixels, this needs to be // further divided by the devicePixelRatio due to widget scaling. if (aToCSSPixels) { bounds = bounds.scale(1 / dpr, 1 / dpr);
--- a/browser/base/content/test/general/test_contextmenu.html +++ b/browser/base/content/test/general/test_contextmenu.html @@ -352,18 +352,18 @@ function runTest(testNum) { closeContextMenu(); openContextMenuFor(textarea); // Invoke context menu for next test }, function () { // Context menu for textarea before spell check initialization finishes checkContextMenu(["context-undo", false, "---", null, - "context-cut", false, - "context-copy", false, + "context-cut", true, + "context-copy", true, "context-paste", null, "context-delete", false, "---", null, "context-selectall", true, "---", null, "spell-add-dictionaries-main", true, ].concat(inspectItems)); closeContextMenu(); @@ -372,18 +372,18 @@ function runTest(testNum) { function () { // Context menu for textarea after spell check initialization finishes checkContextMenu(["*chubbiness", true, // spelling suggestion "spell-add-to-dictionary", true, "---", null, "context-undo", false, "---", null, - "context-cut", false, - "context-copy", false, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", false, "---", null, "context-selectall", true, "---", null, "spell-check-enabled", true, "spell-dictionaries", true, ["spell-check-dictionary-en-US", true, @@ -404,18 +404,18 @@ function runTest(testNum) { function () { // Context menu for textarea after a word has been added // to the dictionary checkContextMenu(["spell-undo-add-to-dictionary", true, "---", null, "context-undo", false, "---", null, - "context-cut", false, - "context-copy", false, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", false, "---", null, "context-selectall", true, "---", null, "spell-check-enabled", true, "spell-dictionaries", true, ["spell-check-dictionary-en-US", true, @@ -429,18 +429,18 @@ function runTest(testNum) { function () { // Context menu for contenteditable checkContextMenu(["spell-no-suggestions", false, "spell-add-to-dictionary", true, "---", null, "context-undo", false, "---", null, - "context-cut", false, - "context-copy", false, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", false, "---", null, "context-selectall", true, "---", null, "spell-check-enabled", true, "spell-dictionaries", true, ["spell-check-dictionary-en-US", true, @@ -645,18 +645,18 @@ function runTest(testNum) { selectInputText(select_inputtext_password); // Select text prior to opening context menu. openContextMenuFor(select_inputtext_password); // Invoke context menu for next test. }, function () { // Context menu for selected text in input[type="password"] checkContextMenu(["context-undo", false, "---", null, - "context-cut", false, - "context-copy", false, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", true, "---", null, "context-selectall", true, "---", null, "spell-check-enabled", true, //spell checker is shown on input[type="password"] on this testcase "spell-dictionaries", true, @@ -738,18 +738,18 @@ function runTest(testNum) { closeContextMenu(); openContextMenuFor(inputspellfalse, false, true); // Invoke context menu for next test. }, function () { // Context menu for text input field with spellcheck=false checkContextMenu(["context-undo", false, "---", null, - "context-cut", false, - "context-copy", false, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", false, "---", null, "context-selectall", true, "---", null, "spell-add-dictionaries-main", true, ].concat(inspectItems));
--- a/browser/base/content/test/general/test_contextmenu_input.html +++ b/browser/base/content/test/general/test_contextmenu_input.html @@ -35,18 +35,18 @@ function runTest(testNum) { case 1: openContextMenuFor(input); // Invoke context menu for next test. break; case 2: // Context menu for text input field. checkContextMenu(["context-undo", false, "---", null, - "context-cut", false, - "context-copy", false, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", false, "---", null, "context-selectall", false, "---", null, "spell-check-enabled", true, "---", null, "context-inspect", true]); @@ -56,18 +56,18 @@ function runTest(testNum) { openContextMenuFor(input, false, true); break; case 3: var value = false; // Context menu for spell-check input. checkContextMenu(["context-undo", value, "---", null, - "context-cut", value, - "context-copy", value, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", value, "---", null, "context-selectall", value, "---", null, "spell-check-enabled", true, "spell-dictionaries", true, ["spell-check-dictionary-en-US", true, @@ -85,18 +85,18 @@ function runTest(testNum) { case 4: var value = false; // Context menu for spell-check input with a unknwon word. checkContextMenu(["*prodigality", true, // spelling suggestion "spell-add-to-dictionary", true, "---", null, "context-undo", value, "---", null, - "context-cut", value, - "context-copy", value, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", value, "---", null, "context-selectall", true, "---", null, "spell-check-enabled", true, "spell-dictionaries", true, ["spell-check-dictionary-en-US", true, @@ -110,18 +110,18 @@ function runTest(testNum) { openContextMenuFor(inputspellcorrect, false, true); break; case 5: var value = false; // Context menu for spell-check input with a known word. checkContextMenu(["context-undo", value, "---", null, - "context-cut", value, - "context-copy", value, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", value, "---", null, "context-selectall", true, "---", null, "spell-check-enabled", true, "spell-dictionaries", true, ["spell-check-dictionary-en-US", true, @@ -134,55 +134,72 @@ function runTest(testNum) { input.disabled = true; openContextMenuFor(input); // Invoke context menu for next test. break; case 6: // Context menu for disabled input. checkContextMenu(["context-undo", false, "---", null, - "context-cut", false, - "context-copy", false, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", false, "---", null, "context-selectall", true, "---", null, "spell-check-enabled", true, "---", null, "context-inspect", true]); closeContextMenu(); input.disabled = false; input.type = 'password'; openContextMenuFor(input); // Invoke context menu for next test. break; case 7: // password - case 8: // email - case 9: // url - case 10: // tel - case 11: // type='number' - // Context menu for tel, password, email, url and number input fields. + // Context menu for password input fields. checkContextMenu(["context-undo", false, "---", null, - "context-cut", false, - "context-copy", false, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", false, "---", null, "context-selectall", false, "---", null, "context-inspect", true]); closeContextMenu(); - if (testNum == 7) { - input.type = 'email'; - } else if (testNum == 8) { + input.type = 'email'; + + openContextMenuFor(input); // Invoke context menu for next test. + break; + + case 8: // email + case 9: // url + case 10: // tel + case 11: // type='number' + // Context menu for tel, email, url and number input fields. + checkContextMenu(["context-undo", false, + "---", null, + "context-cut", true, + "context-copy", true, + "context-paste", null, // ignore clipboard state + "context-delete", false, + "---", null, + "context-selectall", false, + "---", null, + "context-inspect", true]); + + closeContextMenu(); + + if (testNum == 8) { input.type = 'url'; } else if (testNum == 9) { input.type = 'tel'; } else if (testNum == 10) { input.type = 'number'; } else if (testNum == 11) { input.type = 'date'; } @@ -223,18 +240,18 @@ function runTest(testNum) { openContextMenuFor(input); break; case 16: // type='search' // Context menu for search input fields. checkContextMenu(["context-undo", false, "---", null, - "context-cut", false, - "context-copy", false, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", false, "---", null, "context-selectall", false, "---", null, "spell-check-enabled", true, "---", null, "context-inspect", true]); @@ -252,18 +269,18 @@ function runTest(testNum) { input.readOnly = true; openContextMenuFor(input); break; case 17: // Context menu for a read-only input. checkContextMenu(["context-undo", false, "---", null, - "context-cut", false, - "context-copy", false, + "context-cut", true, + "context-copy", true, "context-paste", null, // ignore clipboard state "context-delete", false, "---", null, "context-selectall", false, "---", null, "context-inspect", true]); closeContextMenu();
--- a/browser/components/customizableui/test/browser_947914_button_copy.js +++ b/browser/components/customizableui/test/browser_947914_button_copy.js @@ -14,26 +14,26 @@ add_task(function() { gURLBar.focus(); info("The URL bar was focused"); yield PanelUI.show(); info("Menu panel was opened"); let copyButton = document.getElementById("copy-button"); ok(copyButton, "Copy button exists in Panel Menu"); - is(copyButton.getAttribute("disabled"), "true", "Copy button is initially disabled"); + ok(!copyButton.getAttribute("disabled"), "Copy button is initially enabled"); // copy text from URL bar gURLBar.value = testText; gURLBar.focus(); gURLBar.select(); yield PanelUI.show(); info("Menu panel was opened"); - ok(!copyButton.hasAttribute("disabled"), "Copy button gets enabled"); + ok(!copyButton.hasAttribute("disabled"), "Copy button is enabled when selecting"); copyButton.click(); is(gURLBar.value, testText, "Selected text is unaltered when clicking copy"); // check that the text was added to the clipboard let clipboard = Services.clipboard; let transferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable); globalClipboard = clipboard.kGlobalClipboard;
--- a/browser/components/customizableui/test/browser_947914_button_cut.js +++ b/browser/components/customizableui/test/browser_947914_button_cut.js @@ -13,26 +13,26 @@ add_task(function() { let testText = "cut text test"; gURLBar.focus(); yield PanelUI.show(); info("Menu panel was opened"); let cutButton = document.getElementById("cut-button"); ok(cutButton, "Cut button exists in Panel Menu"); - ok(cutButton.getAttribute("disabled"), "Cut button is disabled"); + ok(!cutButton.hasAttribute("disabled"), "Cut button is enabled"); // cut text from URL bar gURLBar.value = testText; gURLBar.focus(); gURLBar.select(); yield PanelUI.show(); info("Menu panel was opened"); - ok(!cutButton.hasAttribute("disabled"), "Cut button gets enabled"); + ok(!cutButton.hasAttribute("disabled"), "Cut button is enabled when selecting"); cutButton.click(); is(gURLBar.value, "", "Selected text is removed from source when clicking on cut"); // check that the text was added to the clipboard let clipboard = Services.clipboard; let transferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable); globalClipboard = clipboard.kGlobalClipboard;
--- a/browser/devtools/scratchpad/test/browser_scratchpad_edit_ui_updates.js +++ b/browser/devtools/scratchpad/test/browser_scratchpad_edit_ui_updates.js @@ -114,17 +114,17 @@ function runTests() } } else { menuPopup.hidePopup(); } }); }; let firstShow = function() { - ok(cutItem.hasAttribute("disabled"), "cut menuitem is disabled"); + ok(!cutItem.hasAttribute("disabled"), "cut menuitem is enabled"); closeMenu(firstHide); }; let firstHide = function() { sp.editor.setSelection({ line: 0, ch: 0 }, { line: 0, ch: 10 }); openMenu(11, 11, showAfterSelect); }; @@ -144,17 +144,17 @@ function runTests() }; let onCut = function() { sp.editor.off("change", onCut); openMenu(12, 12, showAfterCut); }; let showAfterCut = function() { - ok(cutItem.hasAttribute("disabled"), "cut menuitem is disabled after cut"); + ok(!cutItem.hasAttribute("disabled"), "cut menuitem is enabled after cut"); ok(!pasteItem.hasAttribute("disabled"), "paste menuitem is enabled after cut"); closeMenu(hideAfterCut); }; let hideAfterCut = function() { waitForFocus(function () { sp.editor.on("change", onPaste); EventUtils.synthesizeKey("v", {accelKey: true}, gScratchpadWindow); @@ -162,17 +162,17 @@ function runTests() }; let onPaste = function() { sp.editor.off("change", onPaste); openMenu(13, 13, showAfterPaste); }; let showAfterPaste = function() { - ok(cutItem.hasAttribute("disabled"), "cut menuitem is disabled after paste"); + ok(!cutItem.hasAttribute("disabled"), "cut menuitem is enabled after paste"); ok(!pasteItem.hasAttribute("disabled"), "paste menuitem is enabled after paste"); closeMenu(hideAfterPaste); }; let hideAfterPaste = function() { if (pass == 0) { pass++; testContextMenu();
--- a/build/unix/elfhack/inject/moz.build +++ b/build/unix/elfhack/inject/moz.build @@ -12,13 +12,11 @@ elif CONFIG['TARGET_CPU'].startswith('ar cpu = 'arm' else: cpu = CONFIG['TARGET_CPU'] GENERATED_SOURCES += [ "%s.c" % cpu, ] -DEFINES['ELFHACK_BUILD'] = True - NO_PGO = True NO_VISIBILITY_FLAGS = True
--- a/build/unix/elfhack/moz.build +++ b/build/unix/elfhack/moz.build @@ -20,11 +20,9 @@ if not CONFIG['CROSS_COMPILE']: HOST_SOURCES += [ 'elf.cpp', 'elfhack.cpp', ] HostProgram('elfhack') -DEFINES['ELFHACK_BUILD'] = True - NO_PGO = True
--- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -6625,16 +6625,24 @@ nsContentUtils::IsRequestFullScreenAllow { return !sTrustedFullScreenOnly || EventStateManager::IsHandlingUserInput() || IsCallerChrome(); } /* static */ bool +nsContentUtils::IsCutCopyAllowed() +{ + return EventStateManager::IsHandlingUserInput() || + IsCallerChrome(); +} + +/* static */ +bool nsContentUtils::HaveEqualPrincipals(nsIDocument* aDoc1, nsIDocument* aDoc2) { if (!aDoc1 || !aDoc2) { return false; } bool principalsEqual = false; aDoc1->NodePrincipal()->Equals(aDoc2->NodePrincipal(), &principalsEqual); return principalsEqual;
--- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -1858,16 +1858,23 @@ public: /** * Returns true if requests for full-screen are allowed in the current * context. Requests are only allowed if the user initiated them (like with * a mouse-click or key press), unless this check has been disabled by * setting the pref "full-screen-api.allow-trusted-requests-only" to false. */ static bool IsRequestFullScreenAllowed(); + /** + * Returns true if calling execCommand with 'cut' or 'copy' arguments is + * allowed in the current context. These are only allowed if the user initiated + * them (like with a mouse-click or key press). + */ + static bool IsCutCopyAllowed(); + /* * Returns true if the performance timing APIs are enabled. */ static bool IsPerformanceTimingEnabled() { return sIsPerformanceTimingEnabled; }
--- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -1147,20 +1147,22 @@ nsDOMClassInfo::PostCreatePrototype(JSCo nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); NS_ENSURE_TRUE(nameSpaceManager, NS_OK); JS::Rooted<JSPropertyDescriptor> desc(cx); nsresult rv = ResolvePrototype(sXPConnect, win, cx, global, mData->mNameUTF16, mData, nullptr, nameSpaceManager, proto, &desc); NS_ENSURE_SUCCESS(rv, rv); - if (!contentDefinedProperty && desc.object() && !desc.value().isUndefined() && - !JS_DefineUCProperty(cx, global, mData->mNameUTF16, - NS_strlen(mData->mNameUTF16), desc)) { - return NS_ERROR_UNEXPECTED; + if (!contentDefinedProperty && desc.object() && !desc.value().isUndefined()) { + desc.attributesRef() |= JSPROP_RESOLVING; + if (!JS_DefineUCProperty(cx, global, mData->mNameUTF16, + NS_strlen(mData->mNameUTF16), desc)) { + return NS_ERROR_UNEXPECTED; + } } return NS_OK; } // static nsIClassInfo * NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID)
--- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -2116,16 +2116,19 @@ GK_ATOM(x_symbol, "x-symbol") // additional languages that have special case transformations GK_ATOM(az, "az") GK_ATOM(ba, "ba") GK_ATOM(crh, "crh") GK_ATOM(el, "el") GK_ATOM(ga, "ga") GK_ATOM(nl, "nl") +// mathematical language, used for MathML +GK_ATOM(x_math, "x-math") + // Names for editor transactions GK_ATOM(TypingTxnName, "Typing") GK_ATOM(IMETxnName, "IME") GK_ATOM(DeleteTxnName, "Deleting") // IPC stuff GK_ATOM(Remote, "remote") GK_ATOM(RemoteId, "_remote_id")
--- a/dom/base/nsPerformance.h +++ b/dom/base/nsPerformance.h @@ -418,17 +418,17 @@ public: private: ~nsPerformance(); nsISupports* GetAsISupports() override { return this; } - void InsertUserEntry(PerformanceEntry* aEntry); + void InsertUserEntry(PerformanceEntry* aEntry) override; bool IsPerformanceTimingAttribute(const nsAString& aName) override; DOMHighResTimeStamp DeltaFromNavigationStart(DOMHighResTimeStamp aTime) override; DOMHighResTimeStamp GetPerformanceTimingFromString(const nsAString& aTimingName) override;
--- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -545,17 +545,17 @@ DefineConstructor(JSContext* cx, JS::Han { bool alreadyDefined; if (!JS_AlreadyHasOwnProperty(cx, global, name, &alreadyDefined)) { return false; } // This is Enumerable: False per spec. return alreadyDefined || - JS_DefineProperty(cx, global, name, constructor, 0); + JS_DefineProperty(cx, global, name, constructor, JSPROP_RESOLVING); } static JSObject* CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global, JS::Handle<JSObject*> constructorProto, const js::Class* constructorClass, const JSNativeHolder* constructorNative, unsigned ctorNargs, const NamedConstructor* namedConstructors,
--- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -7798,19 +7798,21 @@ class CGResolveHook(CGAbstractClassHook) return false; } if (!desc.object()) { return true; } // If desc.value() is undefined, then the DoResolve call // has already defined it on the object. Don't try to also // define it. - if (!desc.value().isUndefined() && - !JS_DefinePropertyById(cx, obj, id, desc)) { - return false; + if (!desc.value().isUndefined()) { + desc.attributesRef() |= JSPROP_RESOLVING; + if (!JS_DefinePropertyById(cx, obj, id, desc)) { + return false; + } } *resolvedp = true; return true; """) def definition_body(self): if self.descriptor.isGlobal(): # Resolve standard classes
--- a/dom/crypto/CryptoKey.cpp +++ b/dom/crypto/CryptoKey.cpp @@ -58,16 +58,39 @@ StringToUsage(const nsString& aUsage, Cr } else if (aUsage.EqualsLiteral(WEBCRYPTO_KEY_USAGE_UNWRAPKEY)) { aUsageOut = CryptoKey::UNWRAPKEY; } else { return NS_ERROR_DOM_SYNTAX_ERR; } return NS_OK; } +SECKEYPrivateKey* +PrivateKeyFromPrivateKeyTemplate(SECItem* aObjID, + CK_ATTRIBUTE* aTemplate, + CK_ULONG aTemplateSize) +{ + // Create a generic object with the contents of the key + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + if (!slot) { + return nullptr; + } + + ScopedPK11GenericObject obj(PK11_CreateGenericObject(slot, + aTemplate, + aTemplateSize, + PR_FALSE)); + if (!obj) { + return nullptr; + } + + // Have NSS translate the object to a private key. + return PK11_FindKeyByKeyID(slot, aObjID, nullptr); +} + CryptoKey::CryptoKey(nsIGlobalObject* aGlobal) : mGlobal(aGlobal) , mAttributes(0) , mSymKey() , mPrivateKey(nullptr) , mPublicKey(nullptr) { } @@ -218,16 +241,83 @@ void CryptoKey::SetExtractable(bool aExtractable) { mAttributes &= CLEAR_EXTRACTABLE; if (aExtractable) { mAttributes |= EXTRACTABLE; } } +// NSS exports private EC keys without the CKA_EC_POINT attribute, i.e. the +// public value. To properly export the private key to JWK or PKCS #8 we need +// the public key data though and so we use this method to augment a private +// key with data from the given public key. +nsresult +CryptoKey::AddPublicKeyData(SECKEYPublicKey* aPublicKey) +{ + // This should be a private key. + MOZ_ASSERT(GetKeyType() == PRIVATE); + // There should be a private NSS key with type 'EC'. + MOZ_ASSERT(mPrivateKey && mPrivateKey->keyType == ecKey); + // The given public key should have the same key type. + MOZ_ASSERT(aPublicKey->keyType == mPrivateKey->keyType); + + nsNSSShutDownPreventionLock locker; + + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + if (!slot) { + return NS_ERROR_DOM_OPERATION_ERR; + } + + // Generate a random 160-bit object ID. + ScopedSECItem objID(::SECITEM_AllocItem(nullptr, nullptr, 20)); + SECStatus rv = PK11_GenerateRandomOnSlot(slot, objID->data, objID->len); + if (rv != SECSuccess) { + return NS_ERROR_DOM_OPERATION_ERR; + } + + // Read EC params. + ScopedSECItem params(::SECITEM_AllocItem(nullptr, nullptr, 0)); + rv = PK11_ReadRawAttribute(PK11_TypePrivKey, mPrivateKey, CKA_EC_PARAMS, + params); + if (rv != SECSuccess) { + return NS_ERROR_DOM_OPERATION_ERR; + } + + // Read private value. + ScopedSECItem value(::SECITEM_AllocItem(nullptr, nullptr, 0)); + rv = PK11_ReadRawAttribute(PK11_TypePrivKey, mPrivateKey, CKA_VALUE, value); + if (rv != SECSuccess) { + return NS_ERROR_DOM_OPERATION_ERR; + } + + SECItem* point = &aPublicKey->u.ec.publicValue; + CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY; + CK_BBOOL falseValue = CK_FALSE; + CK_KEY_TYPE ecValue = CKK_EC; + + CK_ATTRIBUTE keyTemplate[9] = { + { CKA_CLASS, &privateKeyValue, sizeof(privateKeyValue) }, + { CKA_KEY_TYPE, &ecValue, sizeof(ecValue) }, + { CKA_TOKEN, &falseValue, sizeof(falseValue) }, + { CKA_SENSITIVE, &falseValue, sizeof(falseValue) }, + { CKA_PRIVATE, &falseValue, sizeof(falseValue) }, + { CKA_ID, objID->data, objID->len }, + { CKA_EC_PARAMS, params->data, params->len }, + { CKA_EC_POINT, point->data, point->len }, + { CKA_VALUE, value->data, value->len }, + }; + + mPrivateKey = PrivateKeyFromPrivateKeyTemplate(objID, keyTemplate, + PR_ARRAY_SIZE(keyTemplate)); + NS_ENSURE_TRUE(mPrivateKey, NS_ERROR_DOM_OPERATION_ERR); + + return NS_OK; +} + void CryptoKey::ClearUsages() { mAttributes &= CLEAR_USAGES; } nsresult CryptoKey::AddUsage(const nsString& aUsage) @@ -362,16 +452,19 @@ void CryptoKey::destructorSafeDestroyNSS // Serialization and deserialization convenience methods SECKEYPrivateKey* CryptoKey::PrivateKeyFromPkcs8(CryptoBuffer& aKeyData, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { SECKEYPrivateKey* privKey; ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + if (!slot) { + return nullptr; + } ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); if (!arena) { return nullptr; } SECItem pkcs8Item = { siBuffer, nullptr, 0 }; if (!aKeyData.ToSECItem(arena, &pkcs8Item)) { @@ -578,46 +671,16 @@ CreateECPointForCoordinates(const Crypto point->data[0] = EC_POINT_FORM_UNCOMPRESSED; memcpy(point->data + 1, aX.Elements(), aX.Length()); memcpy(point->data + 1 + aX.Length(), aY.Elements(), aY.Length()); return point; } SECKEYPrivateKey* -PrivateKeyFromPrivateKeyTemplate(SECItem* aObjID, - CK_ATTRIBUTE* aTemplate, - CK_ULONG aTemplateSize) -{ - // Create a generic object with the contents of the key - ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); - if (!slot.get()) { - return nullptr; - } - - ScopedPK11GenericObject obj(PK11_CreateGenericObject(slot.get(), - aTemplate, - aTemplateSize, - PR_FALSE)); - if (!obj.get()) { - return nullptr; - } - - // Have NSS translate the object to a private key by inspection - // and make a copy we can own - ScopedSECKEYPrivateKey privKey(PK11_FindKeyByKeyID(slot.get(), aObjID, - nullptr)); - if (!privKey.get()) { - return nullptr; - } - - return SECKEY_CopyPrivateKey(privKey.get()); -} - -SECKEYPrivateKey* CryptoKey::PrivateKeyFromJwk(const JsonWebKey& aJwk, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY; CK_BBOOL falseValue = CK_FALSE; if (aJwk.mKty.EqualsLiteral(JWK_TYPE_EC)) { // Verify that all of the required parameters are present @@ -1084,21 +1147,25 @@ CryptoKey::WriteStructuredClone(JSStruct // 1. Attributes // 2. Symmetric key as raw (if present) // 3. Private key as pkcs8 (if present) // 4. Public key as spki (if present) // 5. Algorithm in whatever form it chooses CryptoBuffer priv, pub; if (mPrivateKey) { - CryptoKey::PrivateKeyToPkcs8(mPrivateKey, priv, locker); + if (NS_FAILED(CryptoKey::PrivateKeyToPkcs8(mPrivateKey, priv, locker))) { + return false; + } } if (mPublicKey) { - CryptoKey::PublicKeyToSpki(mPublicKey, pub, locker); + if (NS_FAILED(CryptoKey::PublicKeyToSpki(mPublicKey, pub, locker))) { + return false; + } } return JS_WriteUint32Pair(aWriter, mAttributes, CRYPTOKEY_SC_VERSION) && WriteBuffer(aWriter, mSymKey) && WriteBuffer(aWriter, priv) && WriteBuffer(aWriter, pub) && mAlgorithm.WriteStructuredClone(aWriter); }
--- a/dom/crypto/CryptoKey.h +++ b/dom/crypto/CryptoKey.h @@ -111,16 +111,17 @@ public: // them to manipulate the object KeyAlgorithmProxy& Algorithm(); const KeyAlgorithmProxy& Algorithm() const; KeyType GetKeyType() const; nsresult SetType(const nsString& aType); void SetType(KeyType aType); void SetExtractable(bool aExtractable); + nsresult AddPublicKeyData(SECKEYPublicKey* point); void ClearUsages(); nsresult AddUsage(const nsString& aUsage); nsresult AddUsageIntersecting(const nsString& aUsage, uint32_t aUsageMask); void AddUsage(KeyUsage aUsage); bool HasAnyUsage(); bool HasUsage(KeyUsage aUsage); bool HasUsageOtherThan(uint32_t aUsages); static bool IsRecognizedUsage(const nsString& aUsage); @@ -150,29 +151,29 @@ public: static SECKEYPrivateKey* PrivateKeyFromPkcs8(CryptoBuffer& aKeyData, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static nsresult PrivateKeyToPkcs8(SECKEYPrivateKey* aPrivKey, CryptoBuffer& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static SECKEYPublicKey* PublicKeyFromSpki(CryptoBuffer& aKeyData, const nsNSSShutDownPreventionLock& /*proofOfLock*/); - static nsresult PublicKeyToSpki(SECKEYPublicKey* aPrivKey, + static nsresult PublicKeyToSpki(SECKEYPublicKey* aPubKey, CryptoBuffer& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static SECKEYPrivateKey* PrivateKeyFromJwk(const JsonWebKey& aJwk, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static nsresult PrivateKeyToJwk(SECKEYPrivateKey* aPrivKey, JsonWebKey& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static SECKEYPublicKey* PublicKeyFromJwk(const JsonWebKey& aKeyData, const nsNSSShutDownPreventionLock& /*proofOfLock*/); - static nsresult PublicKeyToJwk(SECKEYPublicKey* aPrivKey, + static nsresult PublicKeyToJwk(SECKEYPublicKey* aPubKey, JsonWebKey& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static SECKEYPublicKey* PublicDhKeyFromRaw(CryptoBuffer& aKeyData, const CryptoBuffer& aPrime, const CryptoBuffer& aGenerator, const nsNSSShutDownPreventionLock& /*proofOfLock*/); static nsresult PublicDhKeyToRaw(SECKEYPublicKey* aPubKey,
--- a/dom/crypto/WebCryptoTask.cpp +++ b/dom/crypto/WebCryptoTask.cpp @@ -1908,19 +1908,23 @@ private: return NS_OK; } else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_PKCS8)) { if (!mPrivateKey) { return NS_ERROR_DOM_NOT_SUPPORTED_ERR; } switch (mPrivateKey->keyType) { - case rsaKey: - CryptoKey::PrivateKeyToPkcs8(mPrivateKey.get(), mResult, locker); + case rsaKey: { + nsresult rv = CryptoKey::PrivateKeyToPkcs8(mPrivateKey.get(), mResult, locker); + if (NS_FAILED(rv)) { + return NS_ERROR_DOM_OPERATION_ERR; + } return NS_OK; + } default: return NS_ERROR_DOM_NOT_SUPPORTED_ERR; } } else if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_SPKI)) { if (!mPublicKey) { return NS_ERROR_DOM_NOT_SUPPORTED_ERR; } @@ -2322,16 +2326,24 @@ private: PR_FALSE, PR_FALSE, nullptr); mPublicKey = pubKey; if (!mPrivateKey.get() || !mPublicKey.get()) { return NS_ERROR_DOM_UNKNOWN_ERR; } mKeyPair.mPrivateKey.get()->SetPrivateKey(mPrivateKey); mKeyPair.mPublicKey.get()->SetPublicKey(mPublicKey); + + // PK11_GenerateKeyPair() does not set a CKA_EC_POINT attribute on the + // private key, we need this later when exporting to PKCS8 and JWK though. + if (mMechanism == CKM_EC_KEY_PAIR_GEN) { + nsresult rv = mKeyPair.mPrivateKey->AddPublicKeyData(mPublicKey); + NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_OPERATION_ERR); + } + return NS_OK; } virtual void Resolve() override { mResultPromise->MaybeResolve(mKeyPair); } };
--- a/dom/crypto/test/test_WebCrypto_ECDH.html +++ b/dom/crypto/test/test_WebCrypto_ECDH.html @@ -295,16 +295,47 @@ TestArray.addTest( .then(error(that), doTryImport(tvs.jwk_missing_x)) .then(error(that), doTryImport(tvs.jwk_missing_y)) .then(error(that), complete(that)); } ); // ----------------------------------------------------------------------------- TestArray.addTest( + "JWK export of a newly generated ECDH private key", + function () { + var that = this; + var alg = { name: "ECDH", namedCurve: "P-256" }; + var reBase64URL = /^[a-zA-Z0-9_-]+$/; + + function doExportToJWK(x) { + return crypto.subtle.exportKey("jwk", x.privateKey) + } + + crypto.subtle.generateKey(alg, true, ["deriveKey", "deriveBits"]) + .then(doExportToJWK) + .then( + complete(that, function(x) { + return x.ext && + x.kty == 'EC' && + x.crv == 'P-256' && + reBase64URL.test(x.x) && + reBase64URL.test(x.y) && + reBase64URL.test(x.d) && + x.x.length == 43 && // 32 octets, base64-encoded + x.y.length == 43 && // 32 octets, base64-encoded + shallowArrayEquals(x.key_ops, ['deriveKey', 'deriveBits']); + }), + error(that) + ); + } +); + +// ----------------------------------------------------------------------------- +TestArray.addTest( "Derive an HMAC key from two ECDH keys and test sign/verify", function() { var that = this; var alg = { name: "ECDH" }; var algDerived = { name: "HMAC", hash: {name: "SHA-1"} }; var pubKey, privKey; function setPub(x) { pubKey = x; }
--- a/dom/crypto/test/test_WebCrypto_RSA_OAEP.html +++ b/dom/crypto/test/test_WebCrypto_RSA_OAEP.html @@ -17,16 +17,19 @@ <script src="./test-vectors.js"></script> <!-- General testing framework --> <script src="./test-array.js"></script> <script>/*<![CDATA[*/ "use strict"; +// Generating 2048-bit keys takes some time. +SimpleTest.requestLongerTimeout(2); + // ----------------------------------------------------------------------------- TestArray.addTest( "RSA-OAEP encrypt/decrypt round-trip", function () { var that = this; var privKey, pubKey; var alg = {name: "RSA-OAEP", hash: "SHA-1"};
--- a/dom/crypto/test/test_WebCrypto_Reject_Generating_Keys_Without_Usages.html +++ b/dom/crypto/test/test_WebCrypto_Reject_Generating_Keys_Without_Usages.html @@ -17,16 +17,19 @@ <script src="./test-vectors.js"></script> <!-- General testing framework --> <script src="./test-array.js"></script> <script>/*<![CDATA[*/ "use strict"; +// Generating 2048-bit keys takes some time. +SimpleTest.requestLongerTimeout(2); + TestArray.addTest( "Test that we reject generating keys without any usage", function() { var that = this; var alg = { name: "RSA-OAEP", hash: "SHA-256", modulusLength: 2048,
--- a/dom/events/IMEContentObserver.cpp +++ b/dom/events/IMEContentObserver.cpp @@ -38,17 +38,18 @@ namespace mozilla { using namespace widget; NS_IMPL_CYCLE_COLLECTION_CLASS(IMEContentObserver) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IMEContentObserver) nsAutoScriptBlocker scriptBlocker; - tmp->UnregisterObservers(true); + tmp->NotifyIMEOfBlur(); + tmp->UnregisterObservers(); NS_IMPL_CYCLE_COLLECTION_UNLINK(mWidget) NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelection) NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootContent) NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditableNode) NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell) NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditor) NS_IMPL_CYCLE_COLLECTION_UNLINK(mEndOfAddedTextCache.mContainerNode) @@ -81,16 +82,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION( NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(IMEContentObserver) NS_IMPL_CYCLE_COLLECTING_RELEASE(IMEContentObserver) IMEContentObserver::IMEContentObserver() : mESM(nullptr) , mPreCharacterDataChangeLength(-1) + , mIsObserving(false) , mIsSelectionChangeEventPending(false) , mSelectionChangeCausedOnlyByComposition(false) , mIsPositionChangeEventPending(false) , mIsFlushingPendingNotifications(false) { #ifdef DEBUG TestMergingTextChangeData(); #endif @@ -99,27 +101,45 @@ IMEContentObserver::IMEContentObserver() void IMEContentObserver::Init(nsIWidget* aWidget, nsPresContext* aPresContext, nsIContent* aContent, nsIEditor* aEditor) { MOZ_ASSERT(aEditor, "aEditor must not be null"); + State state = GetState(); + if (NS_WARN_IF(state == eState_Observing)) { + return; // Nothing to do. + } + + bool firstInitialization = state != eState_StoppedObserving; + if (!firstInitialization) { + // If this is now trying to initialize with new contents, all observers + // should be registered again for simpler implementation. + UnregisterObservers(); + // Clear members which may not be initialized again. + mRootContent = nullptr; + mEditor = nullptr; + mSelection = nullptr; + mDocShell = nullptr; + } + mESM = aPresContext->EventStateManager(); mESM->OnStartToObserveContent(this); mWidget = aWidget; - mEditableNode = IMEStateManager::GetRootEditableNode(aPresContext, aContent); + + mEditableNode = + IMEStateManager::GetRootEditableNode(aPresContext, aContent); if (!mEditableNode) { return; } mEditor = aEditor; - mEditor->AddEditorObserver(this); nsIPresShell* presShell = aPresContext->PresShell(); // get selection and root content nsCOMPtr<nsISelectionController> selCon; if (mEditableNode->IsNodeOfType(nsINode::eCONTENT)) { nsIFrame* frame = static_cast<nsIContent*>(mEditableNode.get())->GetPrimaryFrame(); @@ -149,41 +169,50 @@ IMEContentObserver::Init(nsIWidget* aWid } if (!mRootContent && mEditableNode->IsNodeOfType(nsINode::eDOCUMENT)) { // The document node is editable, but there are no contents, this document // is not editable. return; } NS_ENSURE_TRUE_VOID(mRootContent); - if (IMEStateManager::IsTestingIME()) { - nsIDocument* doc = aPresContext->Document(); - (new AsyncEventDispatcher(doc, NS_LITERAL_STRING("MozIMEFocusIn"), - false, false))->RunDOMEventWhenSafe(); - } + if (firstInitialization) { + aWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_FOCUS)); - aWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_FOCUS)); + // While Init() notifies IME of focus, pending layout may be flushed + // because the notification may cause querying content. Then, recursive + // call of Init() with the latest content may be occur. In such case, we + // shouldn't keep first initialization. + if (GetState() != eState_Initializing) { + return; + } - // NOTIFY_IME_OF_FOCUS might cause recreating IMEContentObserver - // instance via IMEStateManager::UpdateIMEState(). So, this - // instance might already have been destroyed, check it. - if (!mRootContent) { - return; + // NOTIFY_IME_OF_FOCUS might cause recreating IMEContentObserver + // instance via IMEStateManager::UpdateIMEState(). So, this + // instance might already have been destroyed, check it. + if (!mRootContent) { + return; + } } mDocShell = aPresContext->GetDocShell(); ObserveEditableNode(); } void IMEContentObserver::ObserveEditableNode() { - MOZ_ASSERT(mSelection); - MOZ_ASSERT(mRootContent); + MOZ_RELEASE_ASSERT(mEditor); + MOZ_RELEASE_ASSERT(mSelection); + MOZ_RELEASE_ASSERT(mRootContent); + MOZ_RELEASE_ASSERT(GetState() != eState_Observing); + + mIsObserving = true; + mEditor->AddEditorObserver(this); mUpdatePreference = mWidget->GetIMEUpdatePreference(); if (mUpdatePreference.WantSelectionChange()) { // add selection change listener nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection)); NS_ENSURE_TRUE_VOID(selPrivate); nsresult rv = selPrivate->AddSelectionListener(this); NS_ENSURE_SUCCESS_VOID(rv); @@ -198,42 +227,40 @@ IMEContentObserver::ObserveEditableNode( // Add scroll position listener and reflow observer to detect position and // size changes mDocShell->AddWeakScrollObserver(this); mDocShell->AddWeakReflowObserver(this); } } void -IMEContentObserver::UnregisterObservers(bool aPostEvent) +IMEContentObserver::NotifyIMEOfBlur() { - if (mEditor) { - mEditor->RemoveEditorObserver(this); + // If this failed to initialize, mRootContent may be null, then, we + // should not call NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR)) + if (!mRootContent || !mWidget) { + return; } - // If CreateTextStateManager failed, mRootContent will be null, then, we - // should not call NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR)) - if (mRootContent && mWidget) { - if (IMEStateManager::IsTestingIME() && mEditableNode) { - nsIDocument* doc = mEditableNode->OwnerDoc(); - if (doc) { - nsRefPtr<AsyncEventDispatcher> dispatcher = - new AsyncEventDispatcher(doc, NS_LITERAL_STRING("MozIMEFocusOut"), - false, false); - if (aPostEvent) { - dispatcher->PostDOMEvent(); - } else { - dispatcher->RunDOMEventWhenSafe(); - } - } - } - // A test event handler might destroy the widget. - if (mWidget) { - mWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR)); - } + // A test event handler might destroy the widget. + if (mWidget) { + mWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR)); + } +} + +void +IMEContentObserver::UnregisterObservers() +{ + if (!mIsObserving) { + return; + } + mIsObserving = false; + + if (mEditor) { + mEditor->RemoveEditorObserver(this); } if (mUpdatePreference.WantSelectionChange() && mSelection) { nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection)); if (selPrivate) { selPrivate->RemoveSelectionListener(this); } } @@ -254,17 +281,18 @@ IMEContentObserver::GetPresContext() con return mESM ? mESM->GetPresContext() : nullptr; } void IMEContentObserver::Destroy() { // WARNING: When you change this method, you have to check Unlink() too. - UnregisterObservers(false); + NotifyIMEOfBlur(); + UnregisterObservers(); mEditor = nullptr; // Even if there are some pending notification, it'll never notify the widget. mWidget = nullptr; mSelection = nullptr; mRootContent = nullptr; mEditableNode = nullptr; mDocShell = nullptr; @@ -278,25 +306,56 @@ IMEContentObserver::Destroy() void IMEContentObserver::DisconnectFromEventStateManager() { mESM = nullptr; } bool +IMEContentObserver::MaybeReinitialize(nsIWidget* aWidget, + nsPresContext* aPresContext, + nsIContent* aContent, + nsIEditor* aEditor) +{ + if (!IsObservingContent(aPresContext, aContent)) { + return false; + } + + if (GetState() == eState_StoppedObserving) { + Init(aWidget, aPresContext, aContent, aEditor); + } + return IsManaging(aPresContext, aContent); +} + +bool IMEContentObserver::IsManaging(nsPresContext* aPresContext, nsIContent* aContent) { + return GetState() == eState_Observing && + IsObservingContent(aPresContext, aContent); +} + +IMEContentObserver::State +IMEContentObserver::GetState() const +{ if (!mSelection || !mRootContent || !mEditableNode) { - return false; // failed to initialize. + return eState_NotObserving; // failed to initialize or finalized. } if (!mRootContent->IsInComposedDoc()) { - return false; // the focused editor has already been reframed. + // the focused editor has already been reframed. + return eState_StoppedObserving; } + return mIsObserving ? eState_Observing : eState_Initializing; +} + +bool +IMEContentObserver::IsObservingContent(nsPresContext* aPresContext, + nsIContent* aContent) const +{ return mEditableNode == IMEStateManager::GetRootEditableNode(aPresContext, aContent); } bool IMEContentObserver::IsEditorHandlingEventForComposition() const { if (!mWidget) {
--- a/dom/events/IMEContentObserver.h +++ b/dom/events/IMEContentObserver.h @@ -67,16 +67,27 @@ public: nsIContent* aContent, nsIEditor* aEditor); void Destroy(); /** * IMEContentObserver is stored by EventStateManager during observing. * DisconnectFromEventStateManager() is called when EventStateManager stops * storing the instance. */ void DisconnectFromEventStateManager(); + /** + * MaybeReinitialize() tries to restart to observe the editor's root node. + * This is useful when the editor is reframed and all children are replaced + * with new node instances. + * @return Returns true if the instance is managing the content. + * Otherwise, false. + */ + bool MaybeReinitialize(nsIWidget* aWidget, + nsPresContext* aPresContext, + nsIContent* aContent, + nsIEditor* aEditor); bool IsManaging(nsPresContext* aPresContext, nsIContent* aContent); bool IsEditorHandlingEventForComposition() const; bool KeepAliveDuringDeactive() const { return mUpdatePreference.WantDuringDeactive(); } nsIWidget* GetWidget() const { return mWidget; } nsPresContext* GetPresContext() const; @@ -128,28 +139,39 @@ public: { return mAddedEndOffset - mRemovedEndOffset; } }; private: ~IMEContentObserver() {} + enum State { + eState_NotObserving, + eState_Initializing, + eState_StoppedObserving, + eState_Observing + }; + State GetState() const; + bool IsObservingContent(nsPresContext* aPresContext, + nsIContent* aContent) const; void MaybeNotifyIMEOfTextChange(const TextChangeData& aTextChangeData); void MaybeNotifyIMEOfSelectionChange(bool aCausedByComposition); void MaybeNotifyIMEOfPositionChange(); void NotifyContentAdded(nsINode* aContainer, int32_t aStart, int32_t aEnd); void ObserveEditableNode(); /** - * UnregisterObservers() unresiters all listeners and observers. - * @param aPostEvent When true, DOM event will be posted to the thread. - * Otherwise, dispatched when safe. + * NotifyIMEOfBlur() notifies IME of blur. */ - void UnregisterObservers(bool aPostEvent); + void NotifyIMEOfBlur(); + /** + * UnregisterObservers() unregisters all listeners and observers. + */ + void UnregisterObservers(); void StoreTextChangeData(const TextChangeData& aTextChangeData); void FlushMergeableNotifications(); #ifdef DEBUG void TestMergingTextChangeData(); #endif nsCOMPtr<nsIWidget> mWidget; @@ -216,16 +238,17 @@ private: TextChangeData mTextChangeData; EventStateManager* mESM; nsIMEUpdatePreference mUpdatePreference; uint32_t mPreAttrChangeLength; int64_t mPreCharacterDataChangeLength; + bool mIsObserving; bool mIsSelectionChangeEventPending; bool mSelectionChangeCausedOnlyByComposition; bool mIsPositionChangeEventPending; bool mIsFlushingPendingNotifications; }; } // namespace mozilla
--- a/dom/events/IMEStateManager.cpp +++ b/dom/events/IMEStateManager.cpp @@ -175,17 +175,16 @@ GetNotifyIMEMessageName(IMEMessage aMess default: return "unacceptable IME notification message"; } } nsIContent* IMEStateManager::sContent = nullptr; nsPresContext* IMEStateManager::sPresContext = nullptr; bool IMEStateManager::sInstalledMenuKeyboardListener = false; -bool IMEStateManager::sIsTestingIME = false; bool IMEStateManager::sIsGettingNewIMEState = false; // sActiveIMEContentObserver points to the currently active IMEContentObserver. // sActiveIMEContentObserver is null if there is no focused editor. IMEContentObserver* IMEStateManager::sActiveIMEContentObserver = nullptr; TextCompositionArray* IMEStateManager::sTextCompositions = nullptr; // static @@ -644,19 +643,33 @@ IMEStateManager::UpdateIMEState(const IM nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget(); if (NS_WARN_IF(!widget)) { MOZ_LOG(sISMLog, PR_LOG_ERROR, ("ISM: IMEStateManager::UpdateIMEState(), FAILED due to " "no widget for the managing nsPresContext")); return; } - // If the IMEContentObserver instance isn't managing the editor's current - // editable root content, the editor frame might be reframed. We should - // recreate the instance at that time. + // Even if there is active IMEContentObserver, it may not be observing the + // editor with current editable root content due to reframed. In such case, + // We should try to reinitialize the IMEContentObserver. + if (sActiveIMEContentObserver && IsIMEObserverNeeded(aNewIMEState)) { + PR_LOG(sISMLog, PR_LOG_DEBUG, + ("ISM: IMEStateManager::UpdateIMEState(), try to reinitialize the " + "active IMEContentObserver")); + if (!sActiveIMEContentObserver->MaybeReinitialize(widget, sPresContext, + aContent, aEditor)) { + PR_LOG(sISMLog, PR_LOG_ERROR, + ("ISM: IMEStateManager::UpdateIMEState(), failed to reinitialize the " + "active IMEContentObserver")); + } + } + + // If there is no active IMEContentObserver or it isn't observing the + // editor correctly, we should recreate it. bool createTextStateManager = (!sActiveIMEContentObserver || !sActiveIMEContentObserver->IsManaging(sPresContext, aContent)); bool updateIMEState = (widget->GetInputContext().mIMEState.mEnabled != aNewIMEState.mEnabled); if (updateIMEState) { @@ -1123,28 +1136,19 @@ IMEStateManager::GetRootEditableNode(nsP return document; } } return nullptr; } // static bool -IMEStateManager::IsEditableIMEState(nsIWidget* aWidget) +IMEStateManager::IsIMEObserverNeeded(const IMEState& aState) { - switch (aWidget->GetInputContext().mIMEState.mEnabled) { - case IMEState::ENABLED: - case IMEState::PASSWORD: - return true; - case IMEState::PLUGIN: - case IMEState::DISABLED: - return false; - default: - MOZ_CRASH("Unknown IME enable state"); - } + return aState.IsEditable(); } // static void IMEStateManager::DestroyIMEContentObserver() { MOZ_LOG(sISMLog, PR_LOG_ALWAYS, ("ISM: IMEStateManager::DestroyIMEContentObserver(), " @@ -1188,30 +1192,24 @@ IMEStateManager::CreateIMEContentObserve nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget(); if (!widget) { MOZ_LOG(sISMLog, PR_LOG_ERROR, ("ISM: IMEStateManager::CreateIMEContentObserver(), FAILED due to " "there is a root widget for the nsPresContext")); return; // Sometimes, there are no widgets. } - // If it's not text ediable, we don't need to create IMEContentObserver. - if (!IsEditableIMEState(widget)) { + // If it's not text editable, we don't need to create IMEContentObserver. + if (!IsIMEObserverNeeded(widget->GetInputContext().mIMEState)) { MOZ_LOG(sISMLog, PR_LOG_DEBUG, ("ISM: IMEStateManager::CreateIMEContentObserver() doesn't create " "IMEContentObserver because of non-editable IME state")); return; } - static bool sInitializeIsTestingIME = true; - if (sInitializeIsTestingIME) { - Preferences::AddBoolVarCache(&sIsTestingIME, "test.IME", false); - sInitializeIsTestingIME = false; - } - MOZ_LOG(sISMLog, PR_LOG_DEBUG, ("ISM: IMEStateManager::CreateIMEContentObserver() is creating an " "IMEContentObserver instance...")); sActiveIMEContentObserver = new IMEContentObserver(); NS_ADDREF(sActiveIMEContentObserver); // IMEContentObserver::Init() might create another IMEContentObserver // instance. So, sActiveIMEContentObserver would be replaced with new one.
--- a/dom/events/IMEStateManager.h +++ b/dom/events/IMEStateManager.h @@ -133,17 +133,16 @@ public: * Send a notification to IME. It depends on the IME or platform spec what * will occur (or not occur). */ static nsresult NotifyIME(IMEMessage aMessage, nsIWidget* aWidget); static nsresult NotifyIME(IMEMessage aMessage, nsPresContext* aPresContext); static nsINode* GetRootEditableNode(nsPresContext* aPresContext, nsIContent* aContent); - static bool IsTestingIME() { return sIsTestingIME; } protected: static nsresult OnChangeFocusInternal(nsPresContext* aPresContext, nsIContent* aContent, InputContextAction aAction); static void SetIMEState(const IMEState &aState, nsIContent* aContent, nsIWidget* aWidget, @@ -152,22 +151,21 @@ protected: nsIContent* aContent); static void EnsureTextCompositionArray(); static void CreateIMEContentObserver(nsIEditor* aEditor); static void DestroyIMEContentObserver(); static bool IsEditable(nsINode* node); - static bool IsEditableIMEState(nsIWidget* aWidget); + static bool IsIMEObserverNeeded(const IMEState& aState); static nsIContent* sContent; static nsPresContext* sPresContext; static bool sInstalledMenuKeyboardListener; - static bool sIsTestingIME; static bool sIsGettingNewIMEState; class MOZ_STACK_CLASS GettingNewIMEStateBlocker final { public: GettingNewIMEStateBlocker() : mOldValue(IMEStateManager::sIsGettingNewIMEState) {
--- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -219,33 +219,44 @@ FetchRequest(nsIGlobalObject* aGlobal, c aRv = UpdateRequestReferrer(aGlobal, r); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } if (NS_IsMainThread()) { nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal); - if (!window) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - nsCOMPtr<nsIDocument> doc = window->GetExtantDoc(); - if (!doc) { - aRv.Throw(NS_ERROR_FAILURE); - return nullptr; + nsCOMPtr<nsIDocument> doc; + nsCOMPtr<nsILoadGroup> loadGroup; + nsIPrincipal* principal; + if (window) { + doc = window->GetExtantDoc(); + if (!doc) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + principal = doc->NodePrincipal(); + loadGroup = doc->GetDocumentLoadGroup(); + } else { + principal = aGlobal->PrincipalOrNull(); + if (NS_WARN_IF(!principal)) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + nsresult rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), principal); + if (NS_WARN_IF(NS_FAILED(rv))) { + aRv.Throw(rv); + return nullptr; + } } Telemetry::Accumulate(Telemetry::FETCH_IS_MAINTHREAD, 1); nsRefPtr<MainThreadFetchResolver> resolver = new MainThreadFetchResolver(p); - nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup(); - nsRefPtr<FetchDriver> fetch = - new FetchDriver(r, doc->NodePrincipal(), loadGroup); + nsRefPtr<FetchDriver> fetch = new FetchDriver(r, principal, loadGroup); fetch->SetDocument(doc); aRv = fetch->Fetch(resolver); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } else { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); @@ -406,16 +417,33 @@ UpdateRequestReferrer(nsIGlobalObject* a nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal); if (window) { nsCOMPtr<nsIDocument> doc = window->GetExtantDoc(); if (doc) { nsAutoString referrer; doc->GetReferrer(referrer); aRequest->SetReferrer(referrer); } + } else if (NS_IsMainThread()) { + // Pull the principal from the global for non-worker scripts. + nsIPrincipal *principal = aGlobal->PrincipalOrNull(); + bool isNull; + // Only set the referrer if the principal is present, + // and the principal is not null or the system principal. + if (principal && + NS_SUCCEEDED(principal->GetIsNullPrincipal(&isNull)) && !isNull && + !nsContentUtils::IsSystemPrincipal(principal)) { + nsCOMPtr<nsIURI> uri; + if (NS_SUCCEEDED(principal->GetURI(getter_AddRefs(uri))) && uri) { + nsAutoCString referrer; + if (NS_SUCCEEDED(uri->GetSpec(referrer))) { + aRequest->SetReferrer(NS_ConvertUTF8toUTF16(referrer)); + } + } + } } else { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); worker->AssertIsOnWorkerThread(); WorkerPrivate::LocationInfo& info = worker->GetLocationInfo(); aRequest->SetReferrer(NS_ConvertUTF8toUTF16(info.mHref)); }
--- a/dom/html/nsHTMLDocument.cpp +++ b/dom/html/nsHTMLDocument.cpp @@ -3348,16 +3348,29 @@ nsHTMLDocument::QueryCommandEnabled(cons bool nsHTMLDocument::QueryCommandEnabled(const nsAString& commandID, ErrorResult& rv) { nsAutoCString cmdToDispatch; if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) { return false; } + // cut & copy are always allowed + bool isCutCopy = commandID.LowerCaseEqualsLiteral("cut") || + commandID.LowerCaseEqualsLiteral("copy"); + if (isCutCopy) { + return nsContentUtils::IsCutCopyAllowed(); + } + + // Report false for restricted commands + bool restricted = commandID.LowerCaseEqualsLiteral("paste"); + if (restricted && !nsContentUtils::IsCallerChrome()) { + return false; + } + // if editing is not on, bail if (!IsEditingOnAfterFlush()) { rv.Throw(NS_ERROR_FAILURE); return false; } // get command manager and dispatch command to our window if it's acceptable nsCOMPtr<nsICommandManager> cmdMgr;
--- a/dom/html/test/test_iframe_sandbox_navigation.html +++ b/dom/html/test/test_iframe_sandbox_navigation.html @@ -10,16 +10,17 @@ Implement HTML5 sandbox attribute for IF <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> </head> <script type="application/javascript"> /** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/ /** Navigation tests Part 1**/ +SimpleTest.requestLongerTimeout(2); // slow on Android SimpleTest.waitForExplicitFinish(); SimpleTest.requestFlakyTimeout("untriaged"); // a postMessage handler that is used by sandboxed iframes without // 'allow-same-origin'/other windows to communicate pass/fail back to this main page. // it expects to be called with an object like {ok: true/false, desc: // <description of the test> which it then forwards to ok() window.addEventListener("message", receiveMessage, false);
--- a/dom/html/test/test_iframe_sandbox_navigation2.html +++ b/dom/html/test/test_iframe_sandbox_navigation2.html @@ -11,16 +11,17 @@ Implement HTML5 sandbox attribute for IF <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> </head> <script type="application/javascript"> /** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/ /** Navigation tests Part 2**/ SimpleTest.expectAssertions(0); +SimpleTest.requestLongerTimeout(2); // slow on Android SimpleTest.waitForExplicitFinish(); SimpleTest.requestFlakyTimeout("untriaged"); // a postMessage handler that is used by sandboxed iframes without // 'allow-same-origin'/other windows to communicate pass/fail back to this main page. // it expects to be called with an object like {ok: true/false, desc: // <description of the test> which it then forwards to ok() window.addEventListener("message", receiveMessage, false);
--- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -2241,16 +2241,24 @@ TabParent::HandleQueryContentEvent(Widge uint32_t baseOffset = aEvent.mInput.mOffset - mIMECompositionRectOffset; uint32_t endOffset = baseOffset + aEvent.mInput.mLength; aEvent.mReply.mRect.SetEmpty(); for (uint32_t i = baseOffset; i < endOffset; i++) { aEvent.mReply.mRect = aEvent.mReply.mRect.Union(mIMECompositionRects[i]); } + if (aEvent.mInput.mOffset < mIMECacheText.Length()) { + aEvent.mReply.mString = + Substring(mIMECacheText, aEvent.mInput.mOffset, + mIMECacheText.Length() >= aEvent.mInput.EndOffset() ? + aEvent.mInput.mLength : UINT32_MAX); + } else { + aEvent.mReply.mString.Truncate(); + } aEvent.mReply.mOffset = aEvent.mInput.mOffset; aEvent.mReply.mRect = aEvent.mReply.mRect - GetChildProcessOffset(); aEvent.mReply.mWritingMode = mWritingMode; aEvent.mSucceeded = true; } break; case NS_QUERY_CARET_RECT: {
--- a/dom/media/CanvasCaptureMediaStream.h +++ b/dom/media/CanvasCaptureMediaStream.h @@ -1,16 +1,19 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_dom_CanvasCaptureMediaStream_h_ #define mozilla_dom_CanvasCaptureMediaStream_h_ +#include "DOMMediaStream.h" +#include "StreamBuffer.h" + namespace mozilla { class DOMMediaStream; class MediaStreamListener; class SourceMediaStream; namespace layers { class Image; }
--- a/dom/media/IdpSandbox.jsm +++ b/dom/media/IdpSandbox.jsm @@ -202,17 +202,17 @@ IdpSandbox.prototype = { this.sandbox = Cu.Sandbox(principal, { sandboxName: 'IdP-' + this.source.host, wantComponents: false, wantExportHelpers: false, wantGlobalProperties: [ 'indexedDB', 'XMLHttpRequest', 'TextEncoder', 'TextDecoder', 'URL', 'URLSearchParams', 'atob', 'btoa', 'Blob', 'crypto', - 'rtcIdentityProvider' + 'rtcIdentityProvider', 'fetch' ] }); let registrar = this.sandbox.rtcIdentityProvider; if (!Cu.isXrayWrapper(registrar)) { throw new Error('IdP setup failed'); } // have to use the ultimate URI, not the starting one to avoid
--- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -1073,16 +1073,27 @@ MediaDecoderStateMachine::OnVideoDecoded } case DECODER_STATE_DECODING: { Push(video); if (mIsVideoPrerolling && DonePrerollingVideo()) { StopPrerollingVideo(); } + // Schedule the state machine to send stream data as soon as possible or + // the VideoQueue() is empty before the Push(). + // VideoQueue() is empty implies the state machine thread doesn't have + // precise time information about video frames. Once the first video + // frame pushed in the queue, schedule the state machine as soon as + // possible to render the video frame or delay the state machine thread + // accurately. + if (mAudioCaptured || VideoQueue().GetSize() == 1) { + ScheduleStateMachine(); + } + // For non async readers, if the requested video sample was slow to // arrive, increase the amount of audio we buffer to ensure that we // don't run out of audio. This is unnecessary for async readers, // since they decode audio and video on different threads so they // are unlikely to run out of decoded audio. if (mReader->IsAsync()) { return; } @@ -1092,21 +1103,16 @@ MediaDecoderStateMachine::OnVideoDecoded { mLowAudioThresholdUsecs = std::min(THRESHOLD_FACTOR * DurationToUsecs(decodeTime), mAmpleAudioThresholdUsecs); mAmpleAudioThresholdUsecs = std::max(THRESHOLD_FACTOR * mLowAudioThresholdUsecs, mAmpleAudioThresholdUsecs); DECODER_LOG("Slow video decode, set mLowAudioThresholdUsecs=%lld mAmpleAudioThresholdUsecs=%lld", mLowAudioThresholdUsecs, mAmpleAudioThresholdUsecs); } - - // Schedule the state machine to send stream data as soon as possible. - if (mAudioCaptured) { - ScheduleStateMachine(); - } return; } case DECODER_STATE_SEEKING: { if (!mCurrentSeek.Exists()) { // We've received a sample from a previous decode. Discard it. return; } if (mDropVideoUntilNextDiscontinuity) { @@ -2954,19 +2960,17 @@ void MediaDecoderStateMachine::AdvanceFr OnPlaybackOffsetUpdate(frame->mOffset); if (VideoQueue().GetSize() == 0) break; frame = VideoQueue().PeekFront(); } // Current frame has already been presented, wait until it's time to // present the next frame. if (frame && !currentFrame) { - int64_t now = IsPlaying() ? clock_time : mStartTime + mPlayDuration; - - remainingTime = frame->mTime - now; + remainingTime = frame->mTime - clock_time; } } // Check to see if we don't have enough data to play up to the next frame. // If we don't, switch to buffering mode. if (mState == DECODER_STATE_DECODING && mPlayState == MediaDecoder::PLAY_STATE_PLAYING && mDecoder->IsExpectingMoreData()) { @@ -3038,16 +3042,32 @@ void MediaDecoderStateMachine::AdvanceFr return; } MediaDecoder::FrameStatistics& frameStats = mDecoder->GetFrameStatistics(); frameStats.NotifyPresentedFrame(); remainingTime = currentFrame->GetEndTime() - clock_time; currentFrame = nullptr; } + // The remainingTime is negative (include zero): + // 1. When the clock_time is larger than the latest video frame's endtime. + // All the video frames should be rendered or dropped, nothing left in + // VideoQueue. And since the VideoQueue is empty, we don't need to wake up + // statemachine thread immediately, so set the remainingTime to default value. + // 2. Current frame's endtime is smaller than clock_time but there still exist + // newer frames in queue. Re-calculate the remainingTime. + if (remainingTime <= 0) { + VideoData* nextFrame = VideoQueue().PeekFront(); + if (nextFrame) { + remainingTime = nextFrame->mTime - clock_time; + } else { + remainingTime = AUDIO_DURATION_USECS; + } + } + int64_t delay = remainingTime / mPlaybackRate; if (delay > 0) { ScheduleStateMachineIn(delay); } else { ScheduleStateMachine(); } }
--- a/dom/media/omx/MediaCodecReader.cpp +++ b/dom/media/omx/MediaCodecReader.cpp @@ -62,43 +62,16 @@ IsValidDurationUs(int64_t aDuration) } inline bool IsValidTimestampUs(int64_t aTimestamp) { return aTimestamp >= INT64_C(0); } -MediaCodecReader::VideoResourceListener::VideoResourceListener( - MediaCodecReader* aReader) - : mReader(aReader) -{ -} - -MediaCodecReader::VideoResourceListener::~VideoResourceListener() -{ - mReader = nullptr; -} - -void -MediaCodecReader::VideoResourceListener::codecReserved() -{ - if (mReader) { - mReader->VideoCodecReserved(); - } -} - -void -MediaCodecReader::VideoResourceListener::codecCanceled() -{ - if (mReader) { - mReader->VideoCodecCanceled(); - } -} - MediaCodecReader::TrackInputCopier::~TrackInputCopier() { } bool MediaCodecReader::TrackInputCopier::Copy(MediaBuffer* aSourceBuffer, sp<ABuffer> aCodecBuffer) { @@ -271,17 +244,16 @@ MediaCodecReader::MediaCodecReader(Abstr , mIsWaitingResources(false) , mTextureClientIndexesLock("MediaCodecReader::mTextureClientIndexesLock") , mColorConverterBufferSize(0) , mParserMonitor("MediaCodecReader::mParserMonitor") , mParseDataFromCache(true) , mNextParserPosition(INT64_C(0)) , mParsedDataLength(INT64_C(0)) { - mVideoListener = new VideoResourceListener(this); } MediaCodecReader::~MediaCodecReader() { } nsresult MediaCodecReader::Init(MediaDecoderReader* aCloneDonor) @@ -671,24 +643,16 @@ MediaCodecReader::ReadMetadata(MediaInfo // relies on IsWaitingMediaResources() function. And the waiting state will be // changed by binder thread, so we store the waiting state in a cache value to // make them in the same waiting state. UpdateIsWaitingMediaResources(); if (IsWaitingMediaResources()) { return NS_OK; } - // Configure video codec after the codecReserved. - if (mVideoTrack.mSource != nullptr) { - if (!ConfigureMediaCodec(mVideoTrack)) { - DestroyMediaCodec(mVideoTrack); - return NS_ERROR_FAILURE; - } - } - // TODO: start streaming if (!UpdateDuration()) { return NS_ERROR_FAILURE; } if (!UpdateAudioInfo()) { return NS_ERROR_FAILURE; @@ -1290,42 +1254,45 @@ MediaCodecReader::CreateTaskQueues() } return true; } bool MediaCodecReader::CreateMediaCodecs() { - if (CreateMediaCodec(mLooper, mAudioTrack, false, nullptr) && - CreateMediaCodec(mLooper, mVideoTrack, true, mVideoListener)) { + if (CreateMediaCodec(mLooper, mAudioTrack, nullptr) && + CreateMediaCodec(mLooper, mVideoTrack, nullptr)) { return true; } return false; } bool MediaCodecReader::CreateMediaCodec(sp<ALooper>& aLooper, Track& aTrack, - bool aAsync, wp<MediaCodecProxy::CodecResourceListener> aListener) { if (aTrack.mSource != nullptr && aTrack.mCodec == nullptr) { sp<MetaData> sourceFormat = aTrack.mSource->getFormat(); const char* mime; if (sourceFormat->findCString(kKeyMIMEType, &mime)) { aTrack.mCodec = MediaCodecProxy::CreateByType(aLooper, mime, false, aListener); } if (aTrack.mCodec == nullptr) { NS_WARNING("Couldn't create MediaCodecProxy"); return false; } + if (!aTrack.mCodec->AskMediaCodecAndWait()) { + NS_WARNING("AskMediaCodecAndWait fail"); + return false; + } if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { aTrack.mInputCopier = new VorbisInputCopier; } else { aTrack.mInputCopier = new TrackInputCopier; } uint32_t capability = MediaCodecProxy::kEmptyCapability; @@ -1338,24 +1305,20 @@ MediaCodecReader::CreateMediaCodec(sp<AL GonkBufferQueue::createBufferQueue(&producer, &consumer); aTrack.mNativeWindow = new GonkNativeWindow(consumer); aTrack.mGraphicBufferProducer = producer; #else aTrack.mNativeWindow = new GonkNativeWindow(); #endif } - if (!aAsync) { - // Pending configure() and start() to codecReserved() if the creation - // should be asynchronous. - if (!aTrack.mCodec->allocated() || !ConfigureMediaCodec(aTrack)){ - NS_WARNING("Couldn't create and configure MediaCodec synchronously"); - DestroyMediaCodec(aTrack); - return false; - } + if (!aTrack.mCodec->allocated() || !ConfigureMediaCodec(aTrack)) { + NS_WARNING("Couldn't create and configure MediaCodec synchronously"); + DestroyMediaCodec(aTrack); + return false; } } return true; } bool MediaCodecReader::ConfigureMediaCodec(Track& aTrack) @@ -1864,37 +1827,32 @@ MediaCodecReader::EnsureCodecFormatParse } status_t status = OK; size_t index = 0; size_t offset = 0; size_t size = 0; int64_t timeUs = INT64_C(0); uint32_t flags = 0; + FillCodecInputData(aTrack); while ((status = aTrack.mCodec->dequeueOutputBuffer(&index, &offset, &size, &timeUs, &flags)) != INFO_FORMAT_CHANGED) { if (status == OK) { aTrack.mCodec->releaseOutputBuffer(index); } else if (status == INFO_OUTPUT_BUFFERS_CHANGED) { // Update output buffers of MediaCodec. if (aTrack.mCodec->getOutputBuffers(&aTrack.mOutputBuffers) != OK) { NS_WARNING("Couldn't get output buffers from MediaCodec"); return false; } - } else if (status != -EAGAIN && status != INVALID_OPERATION){ + } else if (status != -EAGAIN && status != INVALID_OPERATION) { // FIXME: let INVALID_OPERATION pass? return false; // something wrong!!! } - - status = FillCodecInputData(aTrack); - if (status == INFO_FORMAT_CHANGED) { - break; - } else if (status != OK) { - return false; - } + FillCodecInputData(aTrack); } return aTrack.mCodec->getOutputFormat(&format) == OK; } uint8_t* MediaCodecReader::GetColorConverterBuffer(int32_t aWidth, int32_t aHeight) { // Allocate a temporary YUV420Planer buffer. @@ -1912,27 +1870,9 @@ MediaCodecReader::GetColorConverterBuffe void MediaCodecReader::ClearColorConverterBuffer() { mColorConverterBuffer = nullptr; mColorConverterBufferSize = 0; } -// Called on Binder thread. -void -MediaCodecReader::VideoCodecReserved() -{ - mDecoder->NotifyWaitingForResourcesStatusChanged(); -} - -// Called on Binder thread. -void -MediaCodecReader::VideoCodecCanceled() -{ - if (mVideoTrack.mTaskQueue) { - RefPtr<nsIRunnable> task = - NS_NewRunnableMethod(this, &MediaCodecReader::ReleaseCriticalResources); - mVideoTrack.mTaskQueue->Dispatch(task.forget()); - } -} - } // namespace mozilla
--- a/dom/media/omx/MediaCodecReader.h +++ b/dom/media/omx/MediaCodecReader.h @@ -172,55 +172,28 @@ protected: Track(const Track &rhs) = delete; const Track &operator=(const Track&) = delete; }; // Receive a message from MessageHandler. // Called on MediaCodecReader::mLooper thread. void onMessageReceived(const android::sp<android::AMessage>& aMessage); - // Receive a notify from ResourceListener. - // Called on Binder thread. - virtual void VideoCodecReserved(); - virtual void VideoCodecCanceled(); - virtual bool CreateExtractor(); // Check the underlying HW resource is available and store the result in // mIsWaitingResources. void UpdateIsWaitingMediaResources(); android::sp<android::MediaExtractor> mExtractor; // A cache value updated by UpdateIsWaitingMediaResources(), makes the // "waiting resources state" is synchronous to StateMachine. bool mIsWaitingResources; private: - - // An intermediary class that can be managed by android::sp<T>. - // Redirect codecReserved() and codecCanceled() to MediaCodecReader. - class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener - { - public: - VideoResourceListener(MediaCodecReader* aReader); - ~VideoResourceListener(); - - virtual void codecReserved(); - virtual void codecCanceled(); - - private: - // Forbidden - VideoResourceListener() = delete; - VideoResourceListener(const VideoResourceListener& rhs) = delete; - const VideoResourceListener& operator=(const VideoResourceListener& rhs) = delete; - - MediaCodecReader* mReader; - }; - friend class VideoResourceListener; - class VorbisInputCopier : public TrackInputCopier { virtual bool Copy(android::MediaBuffer* aSourceBuffer, android::sp<android::ABuffer> aCodecBuffer); }; struct AudioTrack : public Track { @@ -349,17 +322,16 @@ private: void DestroyExtractor(); bool CreateMediaSources(); void DestroyMediaSources(); bool CreateMediaCodecs(); static bool CreateMediaCodec(android::sp<android::ALooper>& aLooper, Track& aTrack, - bool aAsync, android::wp<android::MediaCodecProxy::CodecResourceListener> aListener); static bool ConfigureMediaCodec(Track& aTrack); void DestroyMediaCodecs(); static void DestroyMediaCodec(Track& aTrack); bool CreateTaskQueues(); void ShutdownTaskQueues(); void DecodeVideoFrameTask(int64_t aTimeThreshold); @@ -410,18 +382,16 @@ private: static PLDHashOperator ReleaseTextureClient(TextureClient* aClient, size_t& aIndex, void* aUserArg); PLDHashOperator ReleaseTextureClient(TextureClient* aClient, size_t& aIndex); void ReleaseAllTextureClients(); - android::sp<VideoResourceListener> mVideoListener; - android::sp<android::ALooper> mLooper; android::sp<android::MetaData> mMetaData; Mutex mTextureClientIndexesLock; nsDataHashtable<nsPtrHashKey<TextureClient>, size_t> mTextureClientIndexes; // media tracks AudioTrack mAudioTrack;
--- a/dom/media/tests/mochitest/identity/idp.js +++ b/dom/media/tests/mochitest/identity/idp.js @@ -16,22 +16,18 @@ var path = global.location.pathname; this.protocol = path.substring(path.lastIndexOf('/') + 1) + global.location.hash; this.id = crypto.getRandomValues(new Uint8Array(10)).join('.'); } IDPJS.prototype = { getLogin: function() { - var xhr = new XMLHttpRequest(); - xhr.open('GET', 'https://example.com/.well-known/idp-proxy/idp.sjs?' + this.id); - return new Promise(resolve => { - xhr.onload = e => resolve(xhr.status === 200); - xhr.send(); - }); + return fetch('https://example.com/.well-known/idp-proxy/idp.sjs?' + this.id) + .then(response => response.status === 200); }, checkLogin: function(result) { return this.getLogin() .then(loggedIn => { if (loggedIn) { return result; } return Promise.reject({
--- a/dom/tests/mochitest/bugs/test_bug346659.html +++ b/dom/tests/mochitest/bugs/test_bug346659.html @@ -14,16 +14,17 @@ https://bugzilla.mozilla.org/show_bug.cg <div id="content" style="display: none"> </div> <pre id="test"> <script type="application/javascript"> /** Test for Bug 346659 **/ var numTests = 10; +SimpleTest.requestLongerTimeout(2); // test takes a long time on android and b2g emulators SimpleTest.waitForExplicitFinish(); var wins = []; function r(base, tail) { return base.replace(/\/[^\/]*$/, "/" + tail); }
--- a/dom/tests/mochitest/fetch/test_fetch_basic.js +++ b/dom/tests/mochitest/fetch/test_fetch_basic.js @@ -34,16 +34,17 @@ function testDataURL() { }); }); } function testSameOriginBlobURL() { var blob = new Blob(["english ", "sentence"], { type: "text/plain" }); var url = URL.createObjectURL(blob); return fetch(url).then(function(res) { + URL.revokeObjectURL(url); ok(true, "Blob URL fetch should resolve"); if (res.type == "error") { ok(false, "Blob URL fetch should not fail."); return Promise.reject(); } ok(res instanceof Response, "Fetch should resolve to a Response"); is(res.status, 200, "Blob fetch status should be 200"); is(res.statusText, "OK", "Blob fetch statusText should be OK");
--- a/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js +++ b/editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js @@ -302,16 +302,25 @@ const knownFailures = { "QE-Proposed-INSERTLINEBREAK_TEXT-1-body": true, "QE-Proposed-INSERTLINEBREAK_TEXT-1-div": true, "QE-Proposed-CREATEBOOKMARK_TEXT-1-dM": true, "QE-Proposed-CREATEBOOKMARK_TEXT-1-body": true, "QE-Proposed-CREATEBOOKMARK_TEXT-1-div": true, "QE-Proposed-UNBOOKMARK_TEXT-1-dM": true, "QE-Proposed-UNBOOKMARK_TEXT-1-body": true, "QE-Proposed-UNBOOKMARK_TEXT-1-div": true, + "QE-Proposed-COPY_TEXT-1-dM": true, + "QE-Proposed-COPY_TEXT-1-body": true, + "QE-Proposed-COPY_TEXT-1-div": true, + "QE-Proposed-CUT_TEXT-1-dM": true, + "QE-Proposed-CUT_TEXT-1-body": true, + "QE-Proposed-CUT_TEXT-1-div": true, + "QE-Proposed-PASTE_TEXT-1-dM": true, + "QE-Proposed-PASTE_TEXT-1-body": true, + "QE-Proposed-PASTE_TEXT-1-div": true, "QS-Proposed-SUB_SPAN.sub-1-SI-dM": true, "QS-Proposed-SUB_SPAN.sub-1-SI-body": true, "QS-Proposed-SUB_SPAN.sub-1-SI-div": true, "QS-Proposed-SUB_MYSUB-1-SI-dM": true, "QS-Proposed-SUB_MYSUB-1-SI-body": true, "QS-Proposed-SUB_MYSUB-1-SI-div": true, "QS-Proposed-SUP_SPAN.sup-1-SI-dM": true, "QS-Proposed-SUP_SPAN.sup-1-SI-body": true,
--- a/editor/libeditor/tests/mochitest.ini +++ b/editor/libeditor/tests/mochitest.ini @@ -157,9 +157,10 @@ skip-if = toolkit == 'android' # bug 105 [test_dom_input_event_on_texteditor.html] [test_keypress_untrusted_event.html] [test_root_element_replacement.html] [test_select_all_without_body.html] skip-if = e10s [test_spellcheck_pref.html] skip-if = toolkit == 'android' [test_bug1068979.html] -[test_bug1109465.html] \ No newline at end of file +[test_bug1109465.html] +[test_bug1162952.html]
new file mode 100644 --- /dev/null +++ b/editor/libeditor/tests/test_bug1162952.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1162952 +--> +<head> + <title>Test for Bug 1162952</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1162952">Mozilla Bug 1162952</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="text/javascript"> + +/** Test for Bug 1162952 **/ +var userCallbackRun = false; + +document.addEventListener('keydown', function() { + // During a user callback, the commands should be enabled + userCallbackRun = true; + is(true, document.queryCommandEnabled('cut')); + is(true, document.queryCommandEnabled('copy')); +}); + +// Otherwise, they should be disabled +is(false, document.queryCommandEnabled('cut')); +is(false, document.queryCommandEnabled('copy')); + +// Fire a user callback +synthesizeKey('A', {}); + +ok(userCallbackRun, "User callback should've been run"); + +</script> +</pre> +</body> +</html>
--- a/editor/libeditor/tests/test_bug408231.html +++ b/editor/libeditor/tests/test_bug408231.html @@ -40,17 +40,17 @@ https://bugzilla.mozilla.org/show_bug.cg ["insertunorderedlist", "true"], ["insertparagraph", "true"], ["italic", "true"], ["justifycenter", "true"], ["justifyfull", "true"], ["justifyleft", "true"], ["justifyright", "true"], ["outdent", "true"], - //["paste", "true"], + ["paste", "false"], ["redo", "false"], ["removeformat", "true"], ["selectall", "true"], ["strikethrough", "true"], ["styleWithCSS", "true"], ["subscript", "true"], ["superscript", "true"], ["underline", "true"],
--- a/editor/libeditor/tests/test_bug676401.html +++ b/editor/libeditor/tests/test_bug676401.html @@ -30,16 +30,17 @@ https://bugzilla.mozilla.org/show_bug.cg SimpleTest.waitForExplicitFinish(); SimpleTest.waitForFocus(runTests); var gBlock1, gBlock2; var alwaysEnabledCommands = [ "contentReadOnly", "copy", + "cut", "enableInlineTableEditing", "enableObjectResizing", "insertBrOnReturn", "selectAll", "styleWithCSS", ]; function IsCommandEnabled(command) { @@ -84,19 +85,22 @@ function runTests() { IsCommandEnabled(commands[i]); // Mozilla-specific stuff commands = ["enableInlineTableEditing", "enableObjectResizing", "insertBrOnReturn"]; for (i = 0; i < commands.length; i++) IsCommandEnabled(commands[i]); // These are privileged, and available only to chrome. - commands = ["cut", "paste", "copy"]; + commands = ["paste"]; for (i = 0; i < commands.length; i++) { - IsCommandEnabled(commands[i]); + is(document.queryCommandEnabled(commands[i]), false, + "Command should not be enabled for non-privileged code"); + is(SpecialPowers.wrap(document).queryCommandEnabled(commands[i]), true, + "Command should be enabled for privileged code"); try { document.execCommand(commands[i], false, false); ok(false, "Thould have thrown: " + commands[i]); } catch (e) { ok(/insecure|denied/.test(e), "Threw correctly: " + commands[i] + " - " + e); } SpecialPowers.wrap(document).execCommand(commands[i], false, false); }
--- a/gfx/2d/Matrix.h +++ b/gfx/2d/Matrix.h @@ -148,17 +148,32 @@ public: { _11 *= aX; _12 *= aX; _21 *= aY; _22 *= aY; return *this; } - + + /** + * Similar to PostTranslate, but applies a scale instead of a translation. + */ + Matrix &PostScale(Float aScaleX, Float aScaleY) + { + _11 *= aScaleX; + _12 *= aScaleY; + _21 *= aScaleX; + _22 *= aScaleY; + _31 *= aScaleX; + _32 *= aScaleY; + + return *this; + } + GFX2D_API static Matrix Rotation(Float aAngle); /** * Similar to PreTranslate, but applies a rotation instead of a translation. */ Matrix &PreRotate(Float aAngle) { return *this = Matrix::Rotation(aAngle) * *this;
--- a/gfx/layers/LayerScope.cpp +++ b/gfx/layers/LayerScope.cpp @@ -221,105 +221,91 @@ StaticAutoPtr<LayerScopeWebSocketManager class DebugGLData: public LinkedListElement<DebugGLData> { public: explicit DebugGLData(Packet::DataType aDataType) : mDataType(aDataType) { } virtual ~DebugGLData() { } - Packet::DataType GetDataType() const { return mDataType; } - virtual bool Write() = 0; +protected: static bool WriteToStream(Packet& aPacket) { if (!WebSocketHelper::GetSocketManager()) return true; uint32_t size = aPacket.ByteSize(); auto data = MakeUnique<uint8_t[]>(size); aPacket.SerializeToArray(data.get(), size); return WebSocketHelper::GetSocketManager()->WriteAll(data.get(), size); } -protected: Packet::DataType mDataType; }; -class DebugGLFrameStatusData : public DebugGLData +class DebugGLFrameStatusData final: public DebugGLData { public: DebugGLFrameStatusData(Packet::DataType aDataType, int64_t aValue) : DebugGLData(aDataType), mFrameStamp(aValue) { } explicit DebugGLFrameStatusData(Packet::DataType aDataType) : DebugGLData(aDataType), mFrameStamp(0) { } - int64_t GetFrameStamp() const { return mFrameStamp; } - virtual bool Write() override { Packet packet; packet.set_type(mDataType); FramePacket* fp = packet.mutable_frame(); fp->set_value(static_cast<uint64_t>(mFrameStamp)); - if (!WriteToStream(packet)) - return false; - return true; + return WriteToStream(packet); } protected: int64_t mFrameStamp; }; -class DebugGLTextureData : public DebugGLData { +class DebugGLTextureData final: public DebugGLData { public: DebugGLTextureData(GLContext* cx, void* layerRef, GLenum target, GLuint name, DataSourceSurface* img) : DebugGLData(Packet::TEXTURE), - mLayerRef(layerRef), + mLayerRef(reinterpret_cast<uint64_t>(layerRef)), mTarget(target), mName(name), mContextAddress(reinterpret_cast<intptr_t>(cx)), mDatasize(0) { // pre-packing // DataSourceSurface may have locked buffer, // so we should compress now, and then it could // be unlocked outside. pack(img); } - const void* GetLayerRef() const { return mLayerRef; } - GLuint GetName() const { return mName; } - GLenum GetTextureTarget() const { return mTarget; } - intptr_t GetContextAddress() const { return mContextAddress; } - uint32_t GetDataSize() const { return mDatasize; } - virtual bool Write() override { - if (!WriteToStream(mPacket)) - return false; - return true; + return WriteToStream(mPacket); } private: void pack(DataSourceSurface* aImage) { mPacket.set_type(mDataType); TexturePacket* tp = mPacket.mutable_texture(); - tp->set_layerref(reinterpret_cast<uint64_t>(mLayerRef)); + tp->set_layerref(mLayerRef); tp->set_name(mName); tp->set_target(mTarget); tp->set_dataformat(LOCAL_GL_RGBA); tp->set_glcontext(static_cast<uint64_t>(mContextAddress)); if (aImage) { tp->set_width(aImage->GetSize().width); tp->set_height(aImage->GetSize().height); @@ -347,83 +333,74 @@ private: } else { tp->set_width(0); tp->set_height(0); tp->set_stride(0); } } protected: - void* mLayerRef; + uint64_t mLayerRef; GLenum mTarget; GLuint mName; intptr_t mContextAddress; uint32_t mDatasize; // Packet data Packet mPacket; }; -class DebugGLColorData : public DebugGLData { +class DebugGLColorData final: public DebugGLData { public: DebugGLColorData(void* layerRef, const gfxRGBA& color, int width, int height) : DebugGLData(Packet::COLOR), - mLayerRef(layerRef), + mLayerRef(reinterpret_cast<uint64_t>(layerRef)), mColor(color.Packed()), mSize(width, height) { } - const void* GetLayerRef() const { return mLayerRef; } - uint32_t GetColor() const { return mColor; } - const nsIntSize& GetSize() const { return mSize; } - virtual bool Write() override { Packet packet; packet.set_type(mDataType); ColorPacket* cp = packet.mutable_color(); - cp->set_layerref(reinterpret_cast<uint64_t>(mLayerRef)); + cp->set_layerref(mLayerRef); cp->set_color(mColor); cp->set_width(mSize.width); cp->set_height(mSize.height); - if (!WriteToStream(packet)) - return false; - return true; + return WriteToStream(packet); } protected: - void* mLayerRef; + uint64_t mLayerRef; uint32_t mColor; nsIntSize mSize; }; -class DebugGLLayersData : public DebugGLData { +class DebugGLLayersData final: public DebugGLData { public: explicit DebugGLLayersData(UniquePtr<Packet> aPacket) : DebugGLData(Packet::LAYERS), mPacket(Move(aPacket)) { } virtual bool Write() override { mPacket->set_type(mDataType); - - if (!WriteToStream(*mPacket)) - return false; - return true; + return WriteToStream(*mPacket); } protected: UniquePtr<Packet> mPacket; }; -class DebugGLMetaData : public DebugGLData +class DebugGLMetaData final: public DebugGLData { public: DebugGLMetaData(Packet::DataType aDataType, bool aValue) : DebugGLData(aDataType), mComposedByHwc(aValue) { } @@ -434,25 +411,79 @@ public: virtual bool Write() override { Packet packet; packet.set_type(mDataType); MetaPacket* mp = packet.mutable_meta(); mp->set_composedbyhwc(mComposedByHwc); - if (!WriteToStream(packet)) - return false; - return true; + return WriteToStream(packet); } protected: bool mComposedByHwc; }; +class DebugGLDrawData final: public DebugGLData { +public: + DebugGLDrawData(float aOffsetX, + float aOffsetY, + const gfx::Matrix4x4& aMVMatrix, + size_t aRects, + const gfx::Rect* aLayerRects, + void* aLayerRef) + : DebugGLData(Packet::DRAW), + mOffsetX(aOffsetX), + mOffsetY(aOffsetY), + mMVMatrix(aMVMatrix), + mRects(aRects), + mLayerRef(reinterpret_cast<uint64_t>(aLayerRef)) + { + for (size_t i = 0; i < mRects; i++){ + mLayerRects[i] = aLayerRects[i]; + } + } + + virtual bool Write() override { + Packet packet; + packet.set_type(mDataType); + + DrawPacket* dp = packet.mutable_draw(); + dp->set_layerref(mLayerRef); + + dp->set_offsetx(mOffsetX); + dp->set_offsety(mOffsetY); + + auto element = reinterpret_cast<Float *>(&mMVMatrix); + for (int i = 0; i < 16; i++) { + dp->add_mvmatrix(*element++); + } + dp->set_totalrects(mRects); + + MOZ_ASSERT(mRects > 0 && mRects < 4); + for (size_t i = 0; i < mRects; i++) { + layerscope::DrawPacket::Rect* pRect = dp->add_layerrect(); + pRect->set_x(mLayerRects[i].x); + pRect->set_y(mLayerRects[i].y); + pRect->set_w(mLayerRects[i].width); + pRect->set_h(mLayerRects[i].height); + } + + return WriteToStream(packet); + } + +protected: + float mOffsetX; + float mOffsetY; + gfx::Matrix4x4 mMVMatrix; + size_t mRects; + gfx::Rect mLayerRects[4]; + uint64_t mLayerRef; +}; class DebugListener : public nsIServerSocketListener { virtual ~DebugListener() { } public: NS_DECL_THREADSAFE_ISUPPORTS @@ -798,17 +829,16 @@ SenderHelper::SendEffectChain(GLContext* default: break; } //const Effect* secondaryEffect = aEffectChain.mSecondaryEffects[EffectTypes::MASK]; // TODO: } - // ---------------------------------------------- // LayerScopeWebSocketHandler implementation // ---------------------------------------------- void LayerScopeWebSocketHandler::OpenStream(nsISocketTransport* aTransport) { MOZ_ASSERT(aTransport); @@ -1291,26 +1321,117 @@ LayerScope::Init() return; } DebugOnly<nsresult> rv = NS_DispatchToMainThread(new CreateServerSocketRunnable()); MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to dispatch WebSocket Creation to main thread"); dispatched = true; } } +class DrawSession { +public: + NS_INLINE_DECL_REFCOUNTING(DrawSession) + + DrawSession() + : mOffsetX(0.0), + mOffsetY(0.0), + mRects(0) + { } + + float mOffsetX; + float mOffsetY; + gfx::Matrix4x4 mMVMatrix; + size_t mRects; + gfx::Rect mLayerRects[4]; +private: + ~DrawSession() {} +}; + +class DrawSessionHolder { +public: + static void setSession(DrawSession *aSession) { + mSession = aSession; + } + + static DrawSession& current() { + return *mSession; + } + +private: + static nsRefPtr<DrawSession> mSession; +}; + +nsRefPtr<DrawSession> DrawSessionHolder::mSession; + void -LayerScope::SendEffectChain(gl::GLContext* aGLContext, - const EffectChain& aEffectChain, - int aWidth, - int aHeight) +LayerScope::DrawBegin() +{ + if (!CheckSendable()) { + return; + } + + DrawSessionHolder::setSession(new DrawSession()); +} + +void LayerScope::SetRenderOffset(float aX, float aY) +{ + if (!CheckSendable()) { + return; + } + + DrawSessionHolder::current().mOffsetX = aX; + DrawSessionHolder::current().mOffsetY = aY; +} + +void LayerScope::SetLayerTransform(const gfx::Matrix4x4& aMatrix) +{ + if (!CheckSendable()) { + return; + } + + DrawSessionHolder::current().mMVMatrix = aMatrix; +} + +void LayerScope::SetLayerRects(size_t aRects, const gfx::Rect* aLayerRects) +{ + if (!CheckSendable()) { + return; + } + + MOZ_ASSERT(aRects > 0 && aRects <= 4); + MOZ_ASSERT(aLayerRects); + + DrawSessionHolder::current().mRects = aRects; + + for (size_t i = 0; i < aRects; i++){ + DrawSessionHolder::current().mLayerRects[i] = aLayerRects[i]; + } +} + +void +LayerScope::DrawEnd(gl::GLContext* aGLContext, + const EffectChain& aEffectChain, + int aWidth, + int aHeight) { // Protect this public function if (!CheckSendable()) { return; } + + // 1. Send parameters of draw call, such as uniforms and attributes of + // vertex adnd fragment shader. + DrawSession& draws = DrawSessionHolder::current(); + WebSocketHelper::GetSocketManager()->AppendDebugData( + new DebugGLDrawData(draws.mOffsetX, draws.mOffsetY, + draws.mMVMatrix, draws.mRects, + draws.mLayerRects, + aEffectChain.mLayerRef)); + + // 2. Send textures. SenderHelper::SendEffectChain(aGLContext, aEffectChain, aWidth, aHeight); } void LayerScope::SendLayer(LayerComposite* aLayer, int aWidth, int aHeight) { @@ -1354,17 +1475,16 @@ LayerScope::CheckSendable() void LayerScope::CleanLayer() { if (CheckSendable()) { WebSocketHelper::GetSocketManager()->CleanDebugData(); } } - void LayerScope::SetHWComposed() { if (CheckSendable()) { WebSocketHelper::GetSocketManager()->AppendDebugData( new DebugGLMetaData(Packet::META, true)); } }
--- a/gfx/layers/LayerScope.h +++ b/gfx/layers/LayerScope.h @@ -18,20 +18,25 @@ namespace layers { namespace layerscope { class Packet; } struct EffectChain; class LayerComposite; class LayerScope { public: - static void SendEffectChain(gl::GLContext* aGLContext, - const EffectChain& aEffectChain, - int aWidth, - int aHeight); + static void DrawBegin(); + static void SetRenderOffset(float aX, float aY); + static void SetLayerTransform(const gfx::Matrix4x4& aMatrix); + static void SetLayerRects(size_t aRects, const gfx::Rect* aLayerRects); + static void DrawEnd(gl::GLContext* aGLContext, + const EffectChain& aEffectChain, + int aWidth, + int aHeight); + static void SendLayer(LayerComposite* aLayer, int aWidth, int aHeight); static void SendLayerDump(UniquePtr<layerscope::Packet> aPacket); static bool CheckSendable(); static void CleanLayer(); static void SetHWComposed();
--- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -139,20 +139,49 @@ TextureHost::AsTextureHost(PTextureParen } PTextureParent* TextureHost::GetIPDLActor() { return mActor; } +bool +TextureHost::SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle) +{ + if (!aReleaseFenceHandle.IsValid()) { + // HWC might not provide Fence. + // In this case, HWC implicitly handles buffer's fence. + return false; + } + + mReleaseFenceHandle.Merge(aReleaseFenceHandle); + + return true; +} + FenceHandle TextureHost::GetAndResetReleaseFenceHandle() { - return FenceHandle(); + FenceHandle fence; + mReleaseFenceHandle.TransferToAnotherFenceHandle(fence); + return fence; +} + +void +TextureHost::SetAcquireFenceHandle(const FenceHandle& aAcquireFenceHandle) +{ + mAcquireFenceHandle = aAcquireFenceHandle; +} + +FenceHandle +TextureHost::GetAndResetAcquireFenceHandle() +{ + nsRefPtr<FenceHandle::FdObj> fdObj = mAcquireFenceHandle.GetAndResetFdObj(); + return FenceHandle(fdObj); } // implemented in TextureHostOGL.cpp TemporaryRef<TextureHost> CreateTextureHostOGL(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, TextureFlags aFlags); // implemented in TextureHostBasic.cpp
--- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -465,18 +465,16 @@ public: /** * Return a pointer to the IPDLActor. * * This is to be used with IPDL messages only. Do not store the returned * pointer. */ PTextureParent* GetIPDLActor(); - virtual FenceHandle GetAndResetReleaseFenceHandle(); - /** * Specific to B2G's Composer2D * XXX - more doc here */ virtual LayerRenderState GetRenderState() { // By default we return an empty render state, this should be overridden // by the TextureHost implementations that are used on B2G with Composer2D @@ -495,35 +493,54 @@ public: /** * Indicates whether the TextureHost implementation is backed by an * in-memory buffer. The consequence of this is that locking the * TextureHost does not contend with locking the texture on the client side. */ virtual bool HasInternalBuffer() const { return false; } - /** - * Cast to a TextureHost for each backend. - */ - virtual TextureHostOGL* AsHostOGL() { return nullptr; } - void AddCompositableRef() { ++mCompositableCount; } void ReleaseCompositableRef() { --mCompositableCount; MOZ_ASSERT(mCompositableCount >= 0); if (mCompositableCount == 0) { UnbindTextureSource(); } } int NumCompositableRefs() const { return mCompositableCount; } + /** + * Store a fence that will signal when the current buffer is no longer being read. + * Similar to android's GLConsumer::setReleaseFence() + */ + bool SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle); + + /** + * Return a releaseFence's Fence and clear a reference to the Fence. + */ + FenceHandle GetAndResetReleaseFenceHandle(); + + void SetAcquireFenceHandle(const FenceHandle& aAcquireFenceHandle); + + /** + * Return a acquireFence's Fence and clear a reference to the Fence. + */ + FenceHandle GetAndResetAcquireFenceHandle(); + + virtual void WaitAcquireFenceHandleSyncComplete() {}; + protected: + FenceHandle mReleaseFenceHandle; + + FenceHandle mAcquireFenceHandle; + void RecycleTexture(TextureFlags aFlags); PTextureParent* mActor; TextureFlags mFlags; int mCompositableCount; friend class TextureParent; };
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp +++ b/gfx/layers/ipc/CompositableTransactionParent.cpp @@ -174,20 +174,17 @@ CompositableParentManager::ReceiveCompos MOZ_ASSERT(tex.get()); compositable->UseTextureHost(tex); MaybeFence maybeFence = op.fence(); if (maybeFence.type() == MaybeFence::TFenceHandle) { FenceHandle fence = maybeFence.get_FenceHandle(); if (fence.IsValid() && tex) { - TextureHostOGL* hostOGL = tex->AsHostOGL(); - if (hostOGL) { - hostOGL->SetAcquireFence(fence); - } + tex->SetAcquireFenceHandle(fence); } } if (IsAsync() && compositable->GetLayer()) { ScheduleComposition(op); // Async layer updates don't trigger invalidation, manually tell the layer // that its content have changed. compositable->GetLayer()->SetInvalidRectToVisibleRegion();
--- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -427,16 +427,17 @@ CompositorOGL::BindAndDrawQuadWithTextur TextureSource *aTexture) { Rect layerRects[4]; Rect textureRects[4]; size_t rects = DecomposeIntoNoRepeatRects(aRect, aTexCoordRect, &layerRects, &textureRects); + BindAndDrawQuads(aProg, rects, layerRects, textureRects); } void CompositorOGL::PrepareViewport(const gfx::IntSize& aSize) { // Set the viewport correctly. mGLContext->fViewport(0, 0, aSize.width, aSize.height); @@ -914,34 +915,32 @@ CompositorOGL::DrawQuad(const Rect& aRec MOZ_ASSERT(mFrameInProgress, "frame not started"); MOZ_ASSERT(mCurrentRenderTarget, "No destination"); if (aEffectChain.mPrimaryEffect->mType == EffectTypes::VR_DISTORTION) { DrawVRDistortion(aRect, aClipRect, aEffectChain, aOpacity, aTransform); return; } + LayerScope::DrawBegin(); Rect clipRect = aClipRect; // aClipRect is in destination coordinate space (after all // transforms and offsets have been applied) so if our // drawing is going to be shifted by mRenderOffset then we need // to shift the clip rect by the same amount. if (!mTarget && mCurrentRenderTarget->IsWindow()) { clipRect.MoveBy(mRenderOffset.x, mRenderOffset.y); } IntRect intClipRect; clipRect.ToIntRect(&intClipRect); gl()->fScissor(intClipRect.x, FlipY(intClipRect.y + intClipRect.height), intClipRect.width, intClipRect.height); - LayerScope::SendEffectChain(mGLContext, aEffectChain, - aRect.width, aRect.height); - MaskType maskType; EffectMask* effectMask; TextureSourceOGL* sourceMask = nullptr; gfx::Matrix4x4 maskQuadTransform; if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) { effectMask = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get()); sourceMask = effectMask->mMaskTexture->AsSourceOGL(); @@ -1004,25 +1003,27 @@ CompositorOGL::DrawQuad(const Rect& aRec bool colorMatrix = aEffectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX]; ShaderConfigOGL config = GetShaderConfigFor(aEffectChain.mPrimaryEffect, maskType, blendMode, colorMatrix); config.SetOpacity(aOpacity != 1.f); ShaderProgramOGL *program = GetShaderProgramFor(config); ActivateProgram(program); program->SetProjectionMatrix(mProjMatrix); program->SetLayerTransform(aTransform); - + LayerScope::SetLayerTransform(aTransform); if (colorMatrix) { EffectColorMatrix* effectColorMatrix = static_cast<EffectColorMatrix*>(aEffectChain.mSecondaryEffects[EffectTypes::COLOR_MATRIX].get()); program->SetColorMatrix(effectColorMatrix->mColorMatrix); } IntPoint offset = mCurrentRenderTarget->GetOrigin(); program->SetRenderOffset(offset.x, offset.y); + LayerScope::SetRenderOffset(offset.x, offset.y); + if (aOpacity != 1.f) program->SetLayerOpacity(aOpacity); if (config.mFeatures & ENABLE_TEXTURE_RECT) { TexturedEffect* texturedEffect = static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get()); TextureSourceOGL* source = texturedEffect->mTexture->AsSourceOGL(); // This is used by IOSurface that use 0,0...w,h coordinate rather then 0,0..1,1. program->SetTexCoordMultiplier(source->GetSize().width, source->GetSize().height); @@ -1211,16 +1212,17 @@ CompositorOGL::DrawQuad(const Rect& aRec if (didSetBlendMode) { gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA, LOCAL_GL_ONE, LOCAL_GL_ONE); } // in case rendering has used some other GL context MakeCurrent(); + LayerScope::DrawEnd(mGLContext, aEffectChain, aRect.width, aRect.height); } void CompositorOGL::EndFrame() { PROFILER_LABEL("CompositorOGL", "EndFrame", js::ProfileEntry::Category::GRAPHICS); @@ -1472,16 +1474,17 @@ CompositorOGL::BindAndDrawQuads(ShaderPr aProg->SetLayerRects(aLayerRects); if (aProg->GetTextureCount() > 0) { aProg->SetTextureRects(aTextureRects); } // We are using GL_TRIANGLES here because the Mac Intel drivers fail to properly // process uniform arrays with GL_TRIANGLE_STRIP. Go figure. mGLContext->fDrawArrays(LOCAL_GL_TRIANGLES, 0, 6 * aQuads); + LayerScope::SetLayerRects(aQuads, aLayerRects); } GLBlitTextureImageHelper* CompositorOGL::BlitTextureImageHelper() { if (!mBlitTextureImageHelper) { mBlitTextureImageHelper = MakeUnique<GLBlitTextureImageHelper>(this); }
--- a/gfx/layers/opengl/GrallocTextureHost.cpp +++ b/gfx/layers/opengl/GrallocTextureHost.cpp @@ -3,27 +3,29 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "base/process.h" #include "GLContext.h" #include "gfx2DGlue.h" #include <ui/GraphicBuffer.h> #include "GrallocImages.h" // for GrallocImage +#include "GLLibraryEGL.h" // for GLLibraryEGL #include "mozilla/gfx/2D.h" #include "mozilla/gfx/DataSurfaceHelpers.h" #include "mozilla/layers/GrallocTextureHost.h" #include "mozilla/layers/SharedBufferManagerParent.h" #include "EGLImageHelpers.h" #include "GLReadTexImageHelper.h" namespace mozilla { namespace layers { using namespace android; +using namespace mozilla::gl; static gfx::SurfaceFormat SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat, TextureFlags aFlags) { bool swapRB = bool(aFlags & TextureFlags::RB_SWAPPED); switch (aFormat) { case android::PIXEL_FORMAT_BGRA_8888: @@ -258,22 +260,16 @@ GrallocTextureHostOGL::UnbindTextureSour // detached, Although decreasing the refcount of the TextureSource may lead // to the gl handle being destroyed, which would unlock the gralloc buffer. // That said, this method is called before another TextureHost attaches to the // TextureSource, which has the effect of unlocking the gralloc buffer. So when // this is called we know we are going to be unlocked soon. mGLTextureSource = nullptr; } -FenceHandle -GrallocTextureHostOGL::GetAndResetReleaseFenceHandle() -{ - return GetAndResetReleaseFence(); -} - GLenum GetTextureTarget(gl::GLContext* aGL, android::PixelFormat aFormat) { MOZ_ASSERT(aGL); if (aGL->Renderer() == gl::GLRenderer::SGX530 || aGL->Renderer() == gl::GLRenderer::SGX540) { // SGX has a quirk that only TEXTURE_EXTERNAL works and any other value will // result in black pixels when trying to draw from bound textures. // Unfortunately, using TEXTURE_EXTERNAL on Adreno has a terrible effect on // performance. @@ -377,16 +373,52 @@ GrallocTextureHostOGL::PrepareTextureSou gl->fEGLImageTargetTexture2D(textureTarget, mEGLImage); glSource->SetSize(mSize); glSource->SetFormat(mFormat); mGLTextureSource = glSource; } } +void +GrallocTextureHostOGL::WaitAcquireFenceHandleSyncComplete() +{ + if (!mAcquireFenceHandle.IsValid()) { + return; + } + + nsRefPtr<FenceHandle::FdObj> fence = mAcquireFenceHandle.GetAndResetFdObj(); + int fenceFd = fence->GetAndResetFd(); + + EGLint attribs[] = { + LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, + LOCAL_EGL_NONE + }; + + EGLSync sync = sEGLLibrary.fCreateSync(EGL_DISPLAY(), + LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, + attribs); + if (!sync) { + NS_WARNING("failed to create native fence sync"); + return; + } + + // Wait sync complete with timeout. + // If a source of the fence becomes invalid because of error, + // fene complete is not signaled. See Bug 1061435. + EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), + sync, + 0, + 400000000 /*400 usec*/); + if (status != LOCAL_EGL_CONDITION_SATISFIED) { + NS_ERROR("failed to wait native fence sync"); + } + MOZ_ALWAYS_TRUE( sEGLLibrary.fDestroySync(EGL_DISPLAY(), sync) ); +} + bool GrallocTextureHostOGL::BindTextureSource(CompositableTextureSourceRef& aTextureSource) { // This happens at composition time. // If mGLTextureSource is null it means PrepareTextureSource failed. if (!mGLTextureSource) { return false; @@ -395,15 +427,15 @@ GrallocTextureHostOGL::BindTextureSource // If Prepare didn't fail, we expect our TextureSource to be the same as aTextureSource, // otherwise it means something has fiddled with the TextureSource between Prepare and // now. MOZ_ASSERT(mGLTextureSource == aTextureSource); aTextureSource = mGLTextureSource.get(); #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 // Wait until it's ready. - WaitAcquireFenceSyncComplete(); + WaitAcquireFenceHandleSyncComplete(); #endif return true; } } // namepsace layers } // namepsace mozilla
--- a/gfx/layers/opengl/GrallocTextureHost.h +++ b/gfx/layers/opengl/GrallocTextureHost.h @@ -11,17 +11,16 @@ #include "mozilla/layers/TextureHostOGL.h" #include "mozilla/layers/ShadowLayerUtilsGralloc.h" #include <ui/GraphicBuffer.h> namespace mozilla { namespace layers { class GrallocTextureHostOGL : public TextureHost - , public TextureHostOGL { friend class GrallocBufferActor; public: GrallocTextureHostOGL(TextureFlags aFlags, const NewSurfaceDescriptorGralloc& aDescriptor); virtual ~GrallocTextureHostOGL(); @@ -46,26 +45,19 @@ public: virtual LayerRenderState GetRenderState() override; virtual void PrepareTextureSource(CompositableTextureSourceRef& aTextureSource) override; virtual bool BindTextureSource(CompositableTextureSourceRef& aTextureSource) override; virtual void UnbindTextureSource() override; - virtual FenceHandle GetAndResetReleaseFenceHandle() override; + virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() override; -#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 - virtual TextureHostOGL* AsHostOGL() override - { - return this; - } -#endif - - virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() override; + virtual void WaitAcquireFenceHandleSyncComplete() override; bool IsValid() const; virtual const char* Name() override { return "GrallocTextureHostOGL"; } gl::GLContext* GetGLContext() const { return mCompositor ? mCompositor->gl() : nullptr; } private:
--- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -106,87 +106,16 @@ FlagsToGLFlags(TextureFlags aFlags) result |= TextureImage::OriginBottomLeft; if (aFlags & TextureFlags::DISALLOW_BIGIMAGE) result |= TextureImage::DisallowBigImage; return static_cast<gl::TextureImage::Flags>(result); } bool -TextureHostOGL::SetReleaseFence(const FenceHandle& aReleaseFence) -{ - if (!aReleaseFence.IsValid()) { - // HWC might not provide Fence. - // In this case, HWC implicitly handles buffer's fence. - return false; - } - - mReleaseFence.Merge(aReleaseFence); - - return true; -} - -FenceHandle -TextureHostOGL::GetAndResetReleaseFence() -{ - FenceHandle fence; - mReleaseFence.TransferToAnotherFenceHandle(fence); - return fence; -} - -void -TextureHostOGL::SetAcquireFence(const FenceHandle& aAcquireFence) -{ - mAcquireFence = aAcquireFence; -} - -FenceHandle -TextureHostOGL::GetAndResetAcquireFence() -{ - nsRefPtr<FenceHandle::FdObj> fdObj = mAcquireFence.GetAndResetFdObj(); - return FenceHandle(fdObj); -} - -void -TextureHostOGL::WaitAcquireFenceSyncComplete() -{ - if (!mAcquireFence.IsValid()) { - return; - } - - nsRefPtr<FenceHandle::FdObj> fence = mAcquireFence.GetAndResetFdObj(); - int fenceFd = fence->GetAndResetFd(); - - EGLint attribs[] = { - LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, - LOCAL_EGL_NONE - }; - - EGLSync sync = sEGLLibrary.fCreateSync(EGL_DISPLAY(), - LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, - attribs); - if (!sync) { - NS_WARNING("failed to create native fence sync"); - return; - } - - // Wait sync complete with timeout. - // If a source of the fence becomes invalid because of error, - // fene complete is not signaled. See Bug 1061435. - EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), - sync, - 0, - 400000000 /*400 usec*/); - if (status != LOCAL_EGL_CONDITION_SATISFIED) { - NS_ERROR("failed to wait native fence sync"); - } - MOZ_ALWAYS_TRUE( sEGLLibrary.fDestroySync(EGL_DISPLAY(), sync) ); -} - -bool TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface, nsIntRegion* aDestRegion, gfx::IntPoint* aSrcOffset) { GLContext *gl = mCompositor->gl(); MOZ_ASSERT(gl); if (!gl) { NS_WARNING("trying to update TextureImageTextureSourceOGL without a GLContext");
--- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -118,48 +118,16 @@ public: void ClearCachedFilter() { mHasCachedFilter = false; } private: gfx::Filter mCachedFilter; bool mHasCachedFilter; }; /** - * TextureHostOGL provides the necessary API for platform specific composition. - */ -class TextureHostOGL -{ -public: - /** - * Store a fence that will signal when the current buffer is no longer being read. - * Similar to android's GLConsumer::setReleaseFence() - */ - virtual bool SetReleaseFence(const FenceHandle& aReleaseFence); - - /** - * Return a releaseFence's Fence and clear a reference to the Fence. - */ - virtual FenceHandle GetAndResetReleaseFence(); - - virtual void SetAcquireFence(const FenceHandle& aAcquireFence); - - /** - * Return a acquireFence's Fence and clear a reference to the Fence. - */ - virtual FenceHandle GetAndResetAcquireFence(); - - virtual void WaitAcquireFenceSyncComplete(); - -protected: - FenceHandle mReleaseFence; - - FenceHandle mAcquireFence; -}; - -/** * A TextureSource backed by a TextureImage. * * Depending on the underlying TextureImage, may support texture tiling, so * make sure to check AsBigImageIterator() and use the texture accordingly. * * This TextureSource can be used without a TextureHost and manage it's own * GL texture(s). */
--- a/gfx/layers/protobuf/LayerScopePacket.pb.cc +++ b/gfx/layers/protobuf/LayerScopePacket.pb.cc @@ -21,16 +21,18 @@ void protobuf_ShutdownFile_LayerScopePac delete LayersPacket::default_instance_; delete LayersPacket_Layer::default_instance_; delete LayersPacket_Layer_Size::default_instance_; delete LayersPacket_Layer_Rect::default_instance_; delete LayersPacket_Layer_Region::default_instance_; delete LayersPacket_Layer_Matrix::default_instance_; delete LayersPacket_Layer_Shadow::default_instance_; delete MetaPacket::default_instance_; + delete DrawPacket::default_instance_; + delete DrawPacket_Rect::default_instance_; delete Packet::default_instance_; delete CommandPacket::default_instance_; } void protobuf_AddDesc_LayerScopePacket_2eproto() { static bool already_here = false; if (already_here) return; already_here = true; @@ -42,29 +44,33 @@ void protobuf_AddDesc_LayerScopePacket_2 LayersPacket::default_instance_ = new LayersPacket(); LayersPacket_Layer::default_instance_ = new LayersPacket_Layer(); LayersPacket_Layer_Size::default_instance_ = new LayersPacket_Layer_Size(); LayersPacket_Layer_Rect::default_instance_ = new LayersPacket_Layer_Rect(); LayersPacket_Layer_Region::default_instance_ = new LayersPacket_Layer_Region(); LayersPacket_Layer_Matrix::default_instance_ = new LayersPacket_Layer_Matrix(); LayersPacket_Layer_Shadow::default_instance_ = new LayersPacket_Layer_Shadow(); MetaPacket::default_instance_ = new MetaPacket(); + DrawPacket::default_instance_ = new DrawPacket(); + DrawPacket_Rect::default_instance_ = new DrawPacket_Rect(); Packet::default_instance_ = new Packet(); CommandPacket::default_instance_ = new CommandPacket(); FramePacket::default_instance_->InitAsDefaultInstance(); ColorPacket::default_instance_->InitAsDefaultInstance(); TexturePacket::default_instance_->InitAsDefaultInstance(); LayersPacket::default_instance_->InitAsDefaultInstance(); LayersPacket_Layer::default_instance_->InitAsDefaultInstance(); LayersPacket_Layer_Size::default_instance_->InitAsDefaultInstance(); LayersPacket_Layer_Rect::default_instance_->InitAsDefaultInstance(); LayersPacket_Layer_Region::default_instance_->InitAsDefaultInstance(); LayersPacket_Layer_Matrix::default_instance_->InitAsDefaultInstance(); LayersPacket_Layer_Shadow::default_instance_->InitAsDefaultInstance(); MetaPacket::default_instance_->InitAsDefaultInstance(); + DrawPacket::default_instance_->InitAsDefaultInstance(); + DrawPacket_Rect::default_instance_->InitAsDefaultInstance(); Packet::default_instance_->InitAsDefaultInstance(); CommandPacket::default_instance_->InitAsDefaultInstance(); ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_LayerScopePacket_2eproto); } // Force AddDescriptors() to be called at static initialization time. struct StaticDescriptorInitializer_LayerScopePacket_2eproto { StaticDescriptorInitializer_LayerScopePacket_2eproto() { @@ -3187,91 +3193,688 @@ void MetaPacket::Swap(MetaPacket* other) ::std::string MetaPacket::GetTypeName() const { return "mozilla.layers.layerscope.MetaPacket"; } // =================================================================== +#ifndef _MSC_VER +const int DrawPacket_Rect::kXFieldNumber; +const int DrawPacket_Rect::kYFieldNumber; +const int DrawPacket_Rect::kWFieldNumber; +const int DrawPacket_Rect::kHFieldNumber; +#endif // !_MSC_VER + +DrawPacket_Rect::DrawPacket_Rect() + : ::google::protobuf::MessageLite() { + SharedCtor(); +} + +void DrawPacket_Rect::InitAsDefaultInstance() { +} + +DrawPacket_Rect::DrawPacket_Rect(const DrawPacket_Rect& from) + : ::google::protobuf::MessageLite() { + SharedCtor(); + MergeFrom(from); +} + +void DrawPacket_Rect::SharedCtor() { + _cached_size_ = 0; + x_ = 0; + y_ = 0; + w_ = 0; + h_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +DrawPacket_Rect::~DrawPacket_Rect() { + SharedDtor(); +} + +void DrawPacket_Rect::SharedDtor() { + if (this != default_instance_) { + } +} + +void DrawPacket_Rect::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const DrawPacket_Rect& DrawPacket_Rect::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_LayerScopePacket_2eproto(); return *default_instance_; +} + +DrawPacket_Rect* DrawPacket_Rect::default_instance_ = NULL; + +DrawPacket_Rect* DrawPacket_Rect::New() const { + return new DrawPacket_Rect; +} + +void DrawPacket_Rect::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + x_ = 0; + y_ = 0; + w_ = 0; + h_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +bool DrawPacket_Rect::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required float x = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &x_))); + set_has_x(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(21)) goto parse_y; + break; + } + + // required float y = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_y: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &y_))); + set_has_y(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_w; + break; + } + + // required float w = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_w: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &w_))); + set_has_w(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(37)) goto parse_h; + break; + } + + // required float h = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_h: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &h_))); + set_has_h(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag)); + break; + } + } + } + return true; +#undef DO_ +} + +void DrawPacket_Rect::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required float x = 1; + if (has_x()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->x(), output); + } + + // required float y = 2; + if (has_y()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->y(), output); + } + + // required float w = 3; + if (has_w()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->w(), output); + } + + // required float h = 4; + if (has_h()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(4, this->h(), output); + } + +} + +int DrawPacket_Rect::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required float x = 1; + if (has_x()) { + total_size += 1 + 4; + } + + // required float y = 2; + if (has_y()) { + total_size += 1 + 4; + } + + // required float w = 3; + if (has_w()) { + total_size += 1 + 4; + } + + // required float h = 4; + if (has_h()) { + total_size += 1 + 4; + } + + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void DrawPacket_Rect::CheckTypeAndMergeFrom( + const ::google::protobuf::MessageLite& from) { + MergeFrom(*::google::protobuf::down_cast<const DrawPacket_Rect*>(&from)); +} + +void DrawPacket_Rect::MergeFrom(const DrawPacket_Rect& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_x()) { + set_x(from.x()); + } + if (from.has_y()) { + set_y(from.y()); + } + if (from.has_w()) { + set_w(from.w()); + } + if (from.has_h()) { + set_h(from.h()); + } + } +} + +void DrawPacket_Rect::CopyFrom(const DrawPacket_Rect& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool DrawPacket_Rect::IsInitialized() const { + if ((_has_bits_[0] & 0x0000000f) != 0x0000000f) return false; + + return true; +} + +void DrawPacket_Rect::Swap(DrawPacket_Rect* other) { + if (other != this) { + std::swap(x_, other->x_); + std::swap(y_, other->y_); + std::swap(w_, other->w_); + std::swap(h_, other->h_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::std::string DrawPacket_Rect::GetTypeName() const { + return "mozilla.layers.layerscope.DrawPacket.Rect"; +} + + +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int DrawPacket::kOffsetXFieldNumber; +const int DrawPacket::kOffsetYFieldNumber; +const int DrawPacket::kMvMatrixFieldNumber; +const int DrawPacket::kTotalRectsFieldNumber; +const int DrawPacket::kLayerRectFieldNumber; +const int DrawPacket::kLayerrefFieldNumber; +#endif // !_MSC_VER + +DrawPacket::DrawPacket() + : ::google::protobuf::MessageLite() { + SharedCtor(); +} + +void DrawPacket::InitAsDefaultInstance() { +} + +DrawPacket::DrawPacket(const DrawPacket& from) + : ::google::protobuf::MessageLite() { + SharedCtor(); + MergeFrom(from); +} + +void DrawPacket::SharedCtor() { + _cached_size_ = 0; + offsetx_ = 0; + offsety_ = 0; + totalrects_ = 0u; + layerref_ = GOOGLE_ULONGLONG(0); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +DrawPacket::~DrawPacket() { + SharedDtor(); +} + +void DrawPacket::SharedDtor() { + if (this != default_instance_) { + } +} + +void DrawPacket::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const DrawPacket& DrawPacket::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_LayerScopePacket_2eproto(); return *default_instance_; +} + +DrawPacket* DrawPacket::default_instance_ = NULL; + +DrawPacket* DrawPacket::New() const { + return new DrawPacket; +} + +void DrawPacket::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + offsetx_ = 0; + offsety_ = 0; + totalrects_ = 0u; + layerref_ = GOOGLE_ULONGLONG(0); + } + mvmatrix_.Clear(); + layerrect_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +bool DrawPacket::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required float offsetX = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &offsetx_))); + set_has_offsetx(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(21)) goto parse_offsetY; + break; + } + + // required float offsetY = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_offsetY: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, &offsety_))); + set_has_offsety(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_mvMatrix; + break; + } + + // repeated float mvMatrix = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED32) { + parse_mvMatrix: + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + 1, 29, input, this->mutable_mvmatrix()))); + } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) + == ::google::protobuf::internal::WireFormatLite:: + WIRETYPE_LENGTH_DELIMITED) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< + float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>( + input, this->mutable_mvmatrix()))); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(29)) goto parse_mvMatrix; + if (input->ExpectTag(32)) goto parse_totalRects; + break; + } + + // required uint32 totalRects = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_totalRects: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>( + input, &totalrects_))); + set_has_totalrects(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(42)) goto parse_layerRect; + break; + } + + // repeated .mozilla.layers.layerscope.DrawPacket.Rect layerRect = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_layerRect: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_layerrect())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(42)) goto parse_layerRect; + if (input->ExpectTag(48)) goto parse_layerref; + break; + } + + // required uint64 layerref = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_layerref: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>( + input, &layerref_))); + set_has_layerref(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag)); + break; + } + } + } + return true; +#undef DO_ +} + +void DrawPacket::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required float offsetX = 1; + if (has_offsetx()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->offsetx(), output); + } + + // required float offsetY = 2; + if (has_offsety()) { + ::google::protobuf::internal::WireFormatLite::WriteFloat(2, this->offsety(), output); + } + + // repeated float mvMatrix = 3; + for (int i = 0; i < this->mvmatrix_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteFloat( + 3, this->mvmatrix(i), output); + } + + // required uint32 totalRects = 4; + if (has_totalrects()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt32(4, this->totalrects(), output); + } + + // repeated .mozilla.layers.layerscope.DrawPacket.Rect layerRect = 5; + for (int i = 0; i < this->layerrect_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessage( + 5, this->layerrect(i), output); + } + + // required uint64 layerref = 6; + if (has_layerref()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt64(6, this->layerref(), output); + } + +} + +int DrawPacket::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required float offsetX = 1; + if (has_offsetx()) { + total_size += 1 + 4; + } + + // required float offsetY = 2; + if (has_offsety()) { + total_size += 1 + 4; + } + + // required uint32 totalRects = 4; + if (has_totalrects()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt32Size( + this->totalrects()); + } + + // required uint64 layerref = 6; + if (has_layerref()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt64Size( + this->layerref()); + } + + } + // repeated float mvMatrix = 3; + { + int data_size = 0; + data_size = 4 * this->mvmatrix_size(); + total_size += 1 * this->mvmatrix_size() + data_size; + } + + // repeated .mozilla.layers.layerscope.DrawPacket.Rect layerRect = 5; + total_size += 1 * this->layerrect_size(); + for (int i = 0; i < this->layerrect_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->layerrect(i)); + } + + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void DrawPacket::CheckTypeAndMergeFrom( + const ::google::protobuf::MessageLite& from) { + MergeFrom(*::google::protobuf::down_cast<const DrawPacket*>(&from)); +} + +void DrawPacket::MergeFrom(const DrawPacket& from) { + GOOGLE_CHECK_NE(&from, this); + mvmatrix_.MergeFrom(from.mvmatrix_); + layerrect_.MergeFrom(from.layerrect_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_offsetx()) { + set_offsetx(from.offsetx()); + } + if (from.has_offsety()) { + set_offsety(from.offsety()); + } + if (from.has_totalrects()) { + set_totalrects(from.totalrects()); + } + if (from.has_layerref()) { + set_layerref(from.layerref()); + } + } +} + +void DrawPacket::CopyFrom(const DrawPacket& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool DrawPacket::IsInitialized() const { + if ((_has_bits_[0] & 0x0000002b) != 0x0000002b) return false; + + for (int i = 0; i < layerrect_size(); i++) { + if (!this->layerrect(i).IsInitialized()) return false; + } + return true; +} + +void DrawPacket::Swap(DrawPacket* other) { + if (other != this) { + std::swap(offsetx_, other->offsetx_); + std::swap(offsety_, other->offsety_); + mvmatrix_.Swap(&other->mvmatrix_); + std::swap(totalrects_, other->totalrects_); + layerrect_.Swap(&other->layerrect_); + std::swap(layerref_, other->layerref_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::std::string DrawPacket::GetTypeName() const { + return "mozilla.layers.layerscope.DrawPacket"; +} + + +// =================================================================== + bool Packet_DataType_IsValid(int value) { switch(value) { case 1: case 2: case 3: case 4: case 5: case 6: + case 7: return true; default: return false; } } #ifndef _MSC_VER const Packet_DataType Packet::FRAMESTART; const Packet_DataType Packet::FRAMEEND; const Packet_DataType Packet::COLOR; const Packet_DataType Packet::TEXTURE; const Packet_DataType Packet::LAYERS; const Packet_DataType Packet::META; +const Packet_DataType Packet::DRAW; const Packet_DataType Packet::DataType_MIN; const Packet_DataType Packet::DataType_MAX; const int Packet::DataType_ARRAYSIZE; #endif // _MSC_VER #ifndef _MSC_VER const int Packet::kTypeFieldNumber; const int Packet::kFrameFieldNumber; const int Packet::kColorFieldNumber; const int Packet::kTextureFieldNumber; const int Packet::kLayersFieldNumber; const int Packet::kMetaFieldNumber; +const int Packet::kDrawFieldNumber; #endif // !_MSC_VER Packet::Packet() : ::google::protobuf::MessageLite() { SharedCtor(); } void Packet::InitAsDefaultInstance() { frame_ = const_cast< ::mozilla::layers::layerscope::FramePacket*>(&::mozilla::layers::layerscope::FramePacket::default_instance()); color_ = const_cast< ::mozilla::layers::layerscope::ColorPacket*>(&::mozilla::layers::layerscope::ColorPacket::default_instance()); texture_ = const_cast< ::mozilla::layers::layerscope::TexturePacket*>(&::mozilla::layers::layerscope::TexturePacket::default_instance()); layers_ = const_cast< ::mozilla::layers::layerscope::LayersPacket*>(&::mozilla::layers::layerscope::LayersPacket::default_instance()); meta_ = const_cast< ::mozilla::layers::layerscope::MetaPacket*>(&::mozilla::layers::layerscope::MetaPacket::default_instance()); + draw_ = const_cast< ::mozilla::layers::layerscope::DrawPacket*>(&::mozilla::layers::layerscope::DrawPacket::default_instance()); } Packet::Packet(const Packet& from) : ::google::protobuf::MessageLite() { SharedCtor(); MergeFrom(from); } void Packet::SharedCtor() { _cached_size_ = 0; type_ = 1; frame_ = NULL; color_ = NULL; texture_ = NULL; layers_ = NULL; meta_ = NULL; + draw_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } Packet::~Packet() { SharedDtor(); } void Packet::SharedDtor() { if (this != default_instance_) { delete frame_; delete color_; delete texture_; delete layers_; delete meta_; + delete draw_; } } void Packet::SetCachedSize(int size) const { GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); _cached_size_ = size; GOOGLE_SAFE_CONCURRENT_WRITES_END(); } @@ -3298,16 +3901,19 @@ void Packet::Clear() { if (texture_ != NULL) texture_->::mozilla::layers::layerscope::TexturePacket::Clear(); } if (has_layers()) { if (layers_ != NULL) layers_->::mozilla::layers::layerscope::LayersPacket::Clear(); } if (has_meta()) { if (meta_ != NULL) meta_->::mozilla::layers::layerscope::MetaPacket::Clear(); } + if (has_draw()) { + if (draw_ != NULL) draw_->::mozilla::layers::layerscope::DrawPacket::Clear(); + } } ::memset(_has_bits_, 0, sizeof(_has_bits_)); } bool Packet::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { #define DO_(EXPRESSION) if (!(EXPRESSION)) return false ::google::protobuf::uint32 tag; @@ -3392,16 +3998,30 @@ bool Packet::MergePartialFromCodedStream if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { parse_meta: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_meta())); } else { goto handle_uninterpreted; } + if (input->ExpectTag(58)) goto parse_draw; + break; + } + + // optional .mozilla.layers.layerscope.DrawPacket draw = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_draw: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_draw())); + } else { + goto handle_uninterpreted; + } if (input->ExpectAtEnd()) return true; break; } default: { handle_uninterpreted: if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { @@ -3449,16 +4069,22 @@ void Packet::SerializeWithCachedSizes( } // optional .mozilla.layers.layerscope.MetaPacket meta = 6; if (has_meta()) { ::google::protobuf::internal::WireFormatLite::WriteMessage( 6, this->meta(), output); } + // optional .mozilla.layers.layerscope.DrawPacket draw = 7; + if (has_draw()) { + ::google::protobuf::internal::WireFormatLite::WriteMessage( + 7, this->draw(), output); + } + } int Packet::ByteSize() const { int total_size = 0; if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { // required .mozilla.layers.layerscope.Packet.DataType type = 1; if (has_type()) { @@ -3496,16 +4122,23 @@ int Packet::ByteSize() const { // optional .mozilla.layers.layerscope.MetaPacket meta = 6; if (has_meta()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( this->meta()); } + // optional .mozilla.layers.layerscope.DrawPacket draw = 7; + if (has_draw()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->draw()); + } + } GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); _cached_size_ = total_size; GOOGLE_SAFE_CONCURRENT_WRITES_END(); return total_size; } void Packet::CheckTypeAndMergeFrom( @@ -3529,16 +4162,19 @@ void Packet::MergeFrom(const Packet& fro mutable_texture()->::mozilla::layers::layerscope::TexturePacket::MergeFrom(from.texture()); } if (from.has_layers()) { mutable_layers()->::mozilla::layers::layerscope::LayersPacket::MergeFrom(from.layers()); } if (from.has_meta()) { mutable_meta()->::mozilla::layers::layerscope::MetaPacket::MergeFrom(from.meta()); } + if (from.has_draw()) { + mutable_draw()->::mozilla::layers::layerscope::DrawPacket::MergeFrom(from.draw()); + } } } void Packet::CopyFrom(const Packet& from) { if (&from == this) return; Clear(); MergeFrom(from); } @@ -3550,27 +4186,31 @@ bool Packet::IsInitialized() const { if (!this->color().IsInitialized()) return false; } if (has_texture()) { if (!this->texture().IsInitialized()) return false; } if (has_layers()) { if (!this->layers().IsInitialized()) return false; } + if (has_draw()) { + if (!this->draw().IsInitialized()) return false; + } return true; } void Packet::Swap(Packet* other) { if (other != this) { std::swap(type_, other->type_); std::swap(frame_, other->frame_); std::swap(color_, other->color_); std::swap(texture_, other->texture_); std::swap(layers_, other->layers_); std::swap(meta_, other->meta_); + std::swap(draw_, other->draw_); std::swap(_has_bits_[0], other->_has_bits_[0]); std::swap(_cached_size_, other->_cached_size_); } } ::std::string Packet::GetTypeName() const { return "mozilla.layers.layerscope.Packet"; }
--- a/gfx/layers/protobuf/LayerScopePacket.pb.h +++ b/gfx/layers/protobuf/LayerScopePacket.pb.h @@ -39,16 +39,18 @@ class TexturePacket; class LayersPacket; class LayersPacket_Layer; class LayersPacket_Layer_Size; class LayersPacket_Layer_Rect; class LayersPacket_Layer_Region; class LayersPacket_Layer_Matrix; class LayersPacket_Layer_Shadow; class MetaPacket; +class DrawPacket; +class DrawPacket_Rect; class Packet; class CommandPacket; enum LayersPacket_Layer_LayerType { LayersPacket_Layer_LayerType_UnknownLayer = 0, LayersPacket_Layer_LayerType_LayerManager = 1, LayersPacket_Layer_LayerType_ContainerLayer = 2, LayersPacket_Layer_LayerType_PaintedLayer = 3, @@ -87,21 +89,22 @@ const LayersPacket_Layer_Filter LayersPa const int LayersPacket_Layer_Filter_Filter_ARRAYSIZE = LayersPacket_Layer_Filter_Filter_MAX + 1; enum Packet_DataType { Packet_DataType_FRAMESTART = 1, Packet_DataType_FRAMEEND = 2, Packet_DataType_COLOR = 3, Packet_DataType_TEXTURE = 4, Packet_DataType_LAYERS = 5, - Packet_DataType_META = 6 + Packet_DataType_META = 6, + Packet_DataType_DRAW = 7 }; bool Packet_DataType_IsValid(int value); const Packet_DataType Packet_DataType_DataType_MIN = Packet_DataType_FRAMESTART; -const Packet_DataType Packet_DataType_DataType_MAX = Packet_DataType_META; +const Packet_DataType Packet_DataType_DataType_MAX = Packet_DataType_DRAW; const int Packet_DataType_DataType_ARRAYSIZE = Packet_DataType_DataType_MAX + 1; enum CommandPacket_CmdType { CommandPacket_CmdType_NO_OP = 0, CommandPacket_CmdType_LAYERS_TREE = 1, CommandPacket_CmdType_LAYERS_BUFFER = 2 }; bool CommandPacket_CmdType_IsValid(int value); @@ -1306,16 +1309,242 @@ class MetaPacket : public ::google::prot friend void protobuf_AssignDesc_LayerScopePacket_2eproto(); friend void protobuf_ShutdownFile_LayerScopePacket_2eproto(); void InitAsDefaultInstance(); static MetaPacket* default_instance_; }; // ------------------------------------------------------------------- +class DrawPacket_Rect : public ::google::protobuf::MessageLite { + public: + DrawPacket_Rect(); + virtual ~DrawPacket_Rect(); + + DrawPacket_Rect(const DrawPacket_Rect& from); + + inline DrawPacket_Rect& operator=(const DrawPacket_Rect& from) { + CopyFrom(from); + return *this; + } + + static const DrawPacket_Rect& default_instance(); + + void Swap(DrawPacket_Rect* other); + + // implements Message ---------------------------------------------- + + DrawPacket_Rect* New() const; + void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from); + void CopyFrom(const DrawPacket_Rect& from); + void MergeFrom(const DrawPacket_Rect& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::std::string GetTypeName() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required float x = 1; + inline bool has_x() const; + inline void clear_x(); + static const int kXFieldNumber = 1; + inline float x() const; + inline void set_x(float value); + + // required float y = 2; + inline bool has_y() const; + inline void clear_y(); + static const int kYFieldNumber = 2; + inline float y() const; + inline void set_y(float value); + + // required float w = 3; + inline bool has_w() const; + inline void clear_w(); + static const int kWFieldNumber = 3; + inline float w() const; + inline void set_w(float value); + + // required float h = 4; + inline bool has_h() const; + inline void clear_h(); + static const int kHFieldNumber = 4; + inline float h() const; + inline void set_h(float value); + + // @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.DrawPacket.Rect) + private: + inline void set_has_x(); + inline void clear_has_x(); + inline void set_has_y(); + inline void clear_has_y(); + inline void set_has_w(); + inline void clear_has_w(); + inline void set_has_h(); + inline void clear_has_h(); + + float x_; + float y_; + float w_; + float h_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; + + friend void protobuf_AddDesc_LayerScopePacket_2eproto(); + friend void protobuf_AssignDesc_LayerScopePacket_2eproto(); + friend void protobuf_ShutdownFile_LayerScopePacket_2eproto(); + + void InitAsDefaultInstance(); + static DrawPacket_Rect* default_instance_; +}; +// ------------------------------------------------------------------- + +class DrawPacket : public ::google::protobuf::MessageLite { + public: + DrawPacket(); + virtual ~DrawPacket(); + + DrawPacket(const DrawPacket& from); + + inline DrawPacket& operator=(const DrawPacket& from) { + CopyFrom(from); + return *this; + } + + static const DrawPacket& default_instance(); + + void Swap(DrawPacket* other); + + // implements Message ---------------------------------------------- + + DrawPacket* New() const; + void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from); + void CopyFrom(const DrawPacket& from); + void MergeFrom(const DrawPacket& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::std::string GetTypeName() const; + + // nested types ---------------------------------------------------- + + typedef DrawPacket_Rect Rect; + + // accessors ------------------------------------------------------- + + // required float offsetX = 1; + inline bool has_offsetx() const; + inline void clear_offsetx(); + static const int kOffsetXFieldNumber = 1; + inline float offsetx() const; + inline void set_offsetx(float value); + + // required float offsetY = 2; + inline bool has_offsety() const; + inline void clear_offsety(); + static const int kOffsetYFieldNumber = 2; + inline float offsety() const; + inline void set_offsety(float value); + + // repeated float mvMatrix = 3; + inline int mvmatrix_size() const; + inline void clear_mvmatrix(); + static const int kMvMatrixFieldNumber = 3; + inline float mvmatrix(int index) const; + inline void set_mvmatrix(int index, float value); + inline void add_mvmatrix(float value); + inline const ::google::protobuf::RepeatedField< float >& + mvmatrix() const; + inline ::google::protobuf::RepeatedField< float >* + mutable_mvmatrix(); + + // required uint32 totalRects = 4; + inline bool has_totalrects() const; + inline void clear_totalrects(); + static const int kTotalRectsFieldNumber = 4; + inline ::google::protobuf::uint32 totalrects() const; + inline void set_totalrects(::google::protobuf::uint32 value); + + // repeated .mozilla.layers.layerscope.DrawPacket.Rect layerRect = 5; + inline int layerrect_size() const; + inline void clear_layerrect(); + static const int kLayerRectFieldNumber = 5; + inline const ::mozilla::layers::layerscope::DrawPacket_Rect& layerrect(int index) const; + inline ::mozilla::layers::layerscope::DrawPacket_Rect* mutable_layerrect(int index); + inline ::mozilla::layers::layerscope::DrawPacket_Rect* add_layerrect(); + inline const ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >& + layerrect() const; + inline ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >* + mutable_layerrect(); + + // required uint64 layerref = 6; + inline bool has_layerref() const; + inline void clear_layerref(); + static const int kLayerrefFieldNumber = 6; + inline ::google::protobuf::uint64 layerref() const; + inline void set_layerref(::google::protobuf::uint64 value); + + // @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.DrawPacket) + private: + inline void set_has_offsetx(); + inline void clear_has_offsetx(); + inline void set_has_offsety(); + inline void clear_has_offsety(); + inline void set_has_totalrects(); + inline void clear_has_totalrects(); + inline void set_has_layerref(); + inline void clear_has_layerref(); + + float offsetx_; + float offsety_; + ::google::protobuf::RepeatedField< float > mvmatrix_; + ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect > layerrect_; + ::google::protobuf::uint64 layerref_; + ::google::protobuf::uint32 totalrects_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32]; + + friend void protobuf_AddDesc_LayerScopePacket_2eproto(); + friend void protobuf_AssignDesc_LayerScopePacket_2eproto(); + friend void protobuf_ShutdownFile_LayerScopePacket_2eproto(); + + void InitAsDefaultInstance(); + static DrawPacket* default_instance_; +}; +// ------------------------------------------------------------------- + class Packet : public ::google::protobuf::MessageLite { public: Packet(); virtual ~Packet(); Packet(const Packet& from); inline Packet& operator=(const Packet& from) { @@ -1354,16 +1583,17 @@ class Packet : public ::google::protobuf typedef Packet_DataType DataType; static const DataType FRAMESTART = Packet_DataType_FRAMESTART; static const DataType FRAMEEND = Packet_DataType_FRAMEEND; static const DataType COLOR = Packet_DataType_COLOR; static const DataType TEXTURE = Packet_DataType_TEXTURE; static const DataType LAYERS = Packet_DataType_LAYERS; static const DataType META = Packet_DataType_META; + static const DataType DRAW = Packet_DataType_DRAW; static inline bool DataType_IsValid(int value) { return Packet_DataType_IsValid(value); } static const DataType DataType_MIN = Packet_DataType_DataType_MIN; static const DataType DataType_MAX = Packet_DataType_DataType_MAX; static const int DataType_ARRAYSIZE = @@ -1413,40 +1643,51 @@ class Packet : public ::google::protobuf // optional .mozilla.layers.layerscope.MetaPacket meta = 6; inline bool has_meta() const; inline void clear_meta(); static const int kMetaFieldNumber = 6; inline const ::mozilla::layers::layerscope::MetaPacket& meta() const; inline ::mozilla::layers::layerscope::MetaPacket* mutable_meta(); inline ::mozilla::layers::layerscope::MetaPacket* release_meta(); + // optional .mozilla.layers.layerscope.DrawPacket draw = 7; + inline bool has_draw() const; + inline void clear_draw(); + static const int kDrawFieldNumber = 7; + inline const ::mozilla::layers::layerscope::DrawPacket& draw() const; + inline ::mozilla::layers::layerscope::DrawPacket* mutable_draw(); + inline ::mozilla::layers::layerscope::DrawPacket* release_draw(); + // @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.Packet) private: inline void set_has_type(); inline void clear_has_type(); inline void set_has_frame(); inline void clear_has_frame(); inline void set_has_color(); inline void clear_has_color(); inline void set_has_texture(); inline void clear_has_texture(); inline void set_has_layers(); inline void clear_has_layers(); inline void set_has_meta(); inline void clear_has_meta(); + inline void set_has_draw(); + inline void clear_has_draw(); ::mozilla::layers::layerscope::FramePacket* frame_; ::mozilla::layers::layerscope::ColorPacket* color_; ::mozilla::layers::layerscope::TexturePacket* texture_; ::mozilla::layers::layerscope::LayersPacket* layers_; ::mozilla::layers::layerscope::MetaPacket* meta_; + ::mozilla::layers::layerscope::DrawPacket* draw_; int type_; mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32]; + ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32]; friend void protobuf_AddDesc_LayerScopePacket_2eproto(); friend void protobuf_AssignDesc_LayerScopePacket_2eproto(); friend void protobuf_ShutdownFile_LayerScopePacket_2eproto(); void InitAsDefaultInstance(); static Packet* default_instance_; }; @@ -2732,16 +2973,250 @@ inline bool MetaPacket::composedbyhwc() } inline void MetaPacket::set_composedbyhwc(bool value) { set_has_composedbyhwc(); composedbyhwc_ = value; } // ------------------------------------------------------------------- +// DrawPacket_Rect + +// required float x = 1; +inline bool DrawPacket_Rect::has_x() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void DrawPacket_Rect::set_has_x() { + _has_bits_[0] |= 0x00000001u; +} +inline void DrawPacket_Rect::clear_has_x() { + _has_bits_[0] &= ~0x00000001u; +} +inline void DrawPacket_Rect::clear_x() { + x_ = 0; + clear_has_x(); +} +inline float DrawPacket_Rect::x() const { + return x_; +} +inline void DrawPacket_Rect::set_x(float value) { + set_has_x(); + x_ = value; +} + +// required float y = 2; +inline bool DrawPacket_Rect::has_y() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void DrawPacket_Rect::set_has_y() { + _has_bits_[0] |= 0x00000002u; +} +inline void DrawPacket_Rect::clear_has_y() { + _has_bits_[0] &= ~0x00000002u; +} +inline void DrawPacket_Rect::clear_y() { + y_ = 0; + clear_has_y(); +} +inline float DrawPacket_Rect::y() const { + return y_; +} +inline void DrawPacket_Rect::set_y(float value) { + set_has_y(); + y_ = value; +} + +// required float w = 3; +inline bool DrawPacket_Rect::has_w() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void DrawPacket_Rect::set_has_w() { + _has_bits_[0] |= 0x00000004u; +} +inline void DrawPacket_Rect::clear_has_w() { + _has_bits_[0] &= ~0x00000004u; +} +inline void DrawPacket_Rect::clear_w() { + w_ = 0; + clear_has_w(); +} +inline float DrawPacket_Rect::w() const { + return w_; +} +inline void DrawPacket_Rect::set_w(float value) { + set_has_w(); + w_ = value; +} + +// required float h = 4; +inline bool DrawPacket_Rect::has_h() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void DrawPacket_Rect::set_has_h() { + _has_bits_[0] |= 0x00000008u; +} +inline void DrawPacket_Rect::clear_has_h() { + _has_bits_[0] &= ~0x00000008u; +} +inline void DrawPacket_Rect::clear_h() { + h_ = 0; + clear_has_h(); +} +inline float DrawPacket_Rect::h() const { + return h_; +} +inline void DrawPacket_Rect::set_h(float value) { + set_has_h(); + h_ = value; +} + +// ------------------------------------------------------------------- + +// DrawPacket + +// required float offsetX = 1; +inline bool DrawPacket::has_offsetx() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void DrawPacket::set_has_offsetx() { + _has_bits_[0] |= 0x00000001u; +} +inline void DrawPacket::clear_has_offsetx() { + _has_bits_[0] &= ~0x00000001u; +} +inline void DrawPacket::clear_offsetx() { + offsetx_ = 0; + clear_has_offsetx(); +} +inline float DrawPacket::offsetx() const { + return offsetx_; +} +inline void DrawPacket::set_offsetx(float value) { + set_has_offsetx(); + offsetx_ = value; +} + +// required float offsetY = 2; +inline bool DrawPacket::has_offsety() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void DrawPacket::set_has_offsety() { + _has_bits_[0] |= 0x00000002u; +} +inline void DrawPacket::clear_has_offsety() { + _has_bits_[0] &= ~0x00000002u; +} +inline void DrawPacket::clear_offsety() { + offsety_ = 0; + clear_has_offsety(); +} +inline float DrawPacket::offsety() const { + return offsety_; +} +inline void DrawPacket::set_offsety(float value) { + set_has_offsety(); + offsety_ = value; +} + +// repeated float mvMatrix = 3; +inline int DrawPacket::mvmatrix_size() const { + return mvmatrix_.size(); +} +inline void DrawPacket::clear_mvmatrix() { + mvmatrix_.Clear(); +} +inline float DrawPacket::mvmatrix(int index) const { + return mvmatrix_.Get(index); +} +inline void DrawPacket::set_mvmatrix(int index, float value) { + mvmatrix_.Set(index, value); +} +inline void DrawPacket::add_mvmatrix(float value) { + mvmatrix_.Add(value); +} +inline const ::google::protobuf::RepeatedField< float >& +DrawPacket::mvmatrix() const { + return mvmatrix_; +} +inline ::google::protobuf::RepeatedField< float >* +DrawPacket::mutable_mvmatrix() { + return &mvmatrix_; +} + +// required uint32 totalRects = 4; +inline bool DrawPacket::has_totalrects() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void DrawPacket::set_has_totalrects() { + _has_bits_[0] |= 0x00000008u; +} +inline void DrawPacket::clear_has_totalrects() { + _has_bits_[0] &= ~0x00000008u; +} +inline void DrawPacket::clear_totalrects() { + totalrects_ = 0u; + clear_has_totalrects(); +} +inline ::google::protobuf::uint32 DrawPacket::totalrects() const { + return totalrects_; +} +inline void DrawPacket::set_totalrects(::google::protobuf::uint32 value) { + set_has_totalrects(); + totalrects_ = value; +} + +// repeated .mozilla.layers.layerscope.DrawPacket.Rect layerRect = 5; +inline int DrawPacket::layerrect_size() const { + return layerrect_.size(); +} +inline void DrawPacket::clear_layerrect() { + layerrect_.Clear(); +} +inline const ::mozilla::layers::layerscope::DrawPacket_Rect& DrawPacket::layerrect(int index) const { + return layerrect_.Get(index); +} +inline ::mozilla::layers::layerscope::DrawPacket_Rect* DrawPacket::mutable_layerrect(int index) { + return layerrect_.Mutable(index); +} +inline ::mozilla::layers::layerscope::DrawPacket_Rect* DrawPacket::add_layerrect() { + return layerrect_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >& +DrawPacket::layerrect() const { + return layerrect_; +} +inline ::google::protobuf::RepeatedPtrField< ::mozilla::layers::layerscope::DrawPacket_Rect >* +DrawPacket::mutable_layerrect() { + return &layerrect_; +} + +// required uint64 layerref = 6; +inline bool DrawPacket::has_layerref() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void DrawPacket::set_has_layerref() { + _has_bits_[0] |= 0x00000020u; +} +inline void DrawPacket::clear_has_layerref() { + _has_bits_[0] &= ~0x00000020u; +} +inline void DrawPacket::clear_layerref() { + layerref_ = GOOGLE_ULONGLONG(0); + clear_has_layerref(); +} +inline ::google::protobuf::uint64 DrawPacket::layerref() const { + return layerref_; +} +inline void DrawPacket::set_layerref(::google::protobuf::uint64 value) { + set_has_layerref(); + layerref_ = value; +} + +// ------------------------------------------------------------------- + // Packet // required .mozilla.layers.layerscope.Packet.DataType type = 1; inline bool Packet::has_type() const { return (_has_bits_[0] & 0x00000001u) != 0; } inline void Packet::set_has_type() { _has_bits_[0] |= 0x00000001u; @@ -2902,16 +3377,45 @@ inline ::mozilla::layers::layerscope::Me } inline ::mozilla::layers::layerscope::MetaPacket* Packet::release_meta() { clear_has_meta(); ::mozilla::layers::layerscope::MetaPacket* temp = meta_; meta_ = NULL; return temp; } +// optional .mozilla.layers.layerscope.DrawPacket draw = 7; +inline bool Packet::has_draw() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void Packet::set_has_draw() { + _has_bits_[0] |= 0x00000040u; +} +inline void Packet::clear_has_draw() { + _has_bits_[0] &= ~0x00000040u; +} +inline void Packet::clear_draw() { + if (draw_ != NULL) draw_->::mozilla::layers::layerscope::DrawPacket::Clear(); + clear_has_draw(); +} +inline const ::mozilla::layers::layerscope::DrawPacket& Packet::draw() const { + return draw_ != NULL ? *draw_ : *default_instance_->draw_; +} +inline ::mozilla::layers::layerscope::DrawPacket* Packet::mutable_draw() { + set_has_draw(); + if (draw_ == NULL) draw_ = new ::mozilla::layers::layerscope::DrawPacket; + return draw_; +} +inline ::mozilla::layers::layerscope::DrawPacket* Packet::release_draw() { + clear_has_draw(); + ::mozilla::layers::layerscope::DrawPacket* temp = draw_; + draw_ = NULL; + return temp; +} + // ------------------------------------------------------------------- // CommandPacket // required .mozilla.layers.layerscope.CommandPacket.CmdType type = 1; inline bool CommandPacket::has_type() const { return (_has_bits_[0] & 0x00000001u) != 0; }
--- a/gfx/layers/protobuf/LayerScopePacket.proto +++ b/gfx/layers/protobuf/LayerScopePacket.proto @@ -112,34 +112,52 @@ message LayersPacket { } repeated Layer layer = 1; } message MetaPacket { optional bool composedByHwc = 1; } +message DrawPacket { + message Rect { + required float x = 1; + required float y = 2; + required float w = 3; + required float h = 4; + } + + required float offsetX = 1; + required float offsetY = 2; + repeated float mvMatrix = 3; + required uint32 totalRects = 4; + repeated Rect layerRect = 5; + required uint64 layerref = 6; +} + // We only need to use this Packet. // Other packet definitions are just type defines message Packet { enum DataType { FRAMESTART = 1; FRAMEEND = 2; COLOR = 3; TEXTURE = 4; LAYERS = 5; META = 6; + DRAW = 7; } required DataType type = 1; optional FramePacket frame = 2; optional ColorPacket color = 3; optional TexturePacket texture = 4; optional LayersPacket layers = 5; optional MetaPacket meta = 6; + optional DrawPacket draw = 7; } // =============================== // Client to Server messages // =============================== message CommandPacket { enum CmdType {
--- a/gfx/qcms/transform-sse1.c +++ b/gfx/qcms/transform-sse1.c @@ -43,17 +43,17 @@ void qcms_transform_data_rgb_out_lut_sse const __m128 mat2 = _mm_load_ps(mat[2]); /* these values don't change, either */ const __m128 max = _mm_load_ps(clampMaxValueX4); const __m128 min = _mm_setzero_ps(); const __m128 scale = _mm_load_ps(floatScaleX4); /* working variables */ - __m128 vec_r, vec_g, vec_b, result, result_hi; + __m128 vec_r, vec_g, vec_b, result; /* CYA */ if (!length) return; /* one pixel is handled outside of the loop */ length--; @@ -79,33 +79,31 @@ void qcms_transform_data_rgb_out_lut_sse /* crunch, crunch, crunch */ vec_r = _mm_add_ps(vec_r, _mm_add_ps(vec_g, vec_b)); vec_r = _mm_max_ps(min, vec_r); vec_r = _mm_min_ps(max, vec_r); result = _mm_mul_ps(vec_r, scale); /* store calc'd output tables indices */ - /* Bug 1163740 temporary investigation: - * Write output[0] last, to keep |result| in a register in minidumps */ - result_hi = _mm_movehl_ps(result, result); - *((__m64 *)&output[2]) = _mm_cvtps_pi32(result_hi); *((__m64 *)&output[0]) = _mm_cvtps_pi32(result); + result = _mm_movehl_ps(result, result); + *((__m64 *)&output[2]) = _mm_cvtps_pi32(result) ; + + /* load for next loop while store completes */ + vec_r = _mm_load_ss(&igtbl_r[src[0]]); + vec_g = _mm_load_ss(&igtbl_g[src[1]]); + vec_b = _mm_load_ss(&igtbl_b[src[2]]); + src += 3; /* use calc'd indices to output RGB values */ dest[OUTPUT_R_INDEX] = otdata_r[output[0]]; dest[OUTPUT_G_INDEX] = otdata_g[output[1]]; dest[OUTPUT_B_INDEX] = otdata_b[output[2]]; dest += RGB_OUTPUT_COMPONENTS; - - /* load for next loop while store completes */ - vec_r = _mm_load_ss(&igtbl_r[src[0]]); - vec_g = _mm_load_ss(&igtbl_g[src[1]]); - vec_b = _mm_load_ss(&igtbl_b[src[2]]); - src += 3; } /* handle final (maybe only) pixel */ vec_r = _mm_shuffle_ps(vec_r, vec_r, 0); vec_g = _mm_shuffle_ps(vec_g, vec_g, 0); vec_b = _mm_shuffle_ps(vec_b, vec_b, 0); @@ -162,17 +160,17 @@ void qcms_transform_data_rgba_out_lut_ss const __m128 mat2 = _mm_load_ps(mat[2]); /* these values don't change, either */ const __m128 max = _mm_load_ps(clampMaxValueX4); const __m128 min = _mm_setzero_ps(); const __m128 scale = _mm_load_ps(floatScaleX4); /* working variables */ - __m128 vec_r, vec_g, vec_b, result, result_hi; + __m128 vec_r, vec_g, vec_b, result; unsigned char alpha; /* CYA */ if (!length) return; /* one pixel is handled outside of the loop */ length--; @@ -203,33 +201,32 @@ void qcms_transform_data_rgba_out_lut_ss alpha = src[3]; /* crunch, crunch, crunch */ vec_r = _mm_add_ps(vec_r, _mm_add_ps(vec_g, vec_b)); vec_r = _mm_max_ps(min, vec_r); vec_r = _mm_min_ps(max, vec_r); result = _mm_mul_ps(vec_r, scale); - /* Bug 1163740 temporary investigation: - * Write output[0] last, to keep |result| in a register in minidumps */ - result_hi = _mm_movehl_ps(result, result); - *((__m64 *)&output[2]) = _mm_cvtps_pi32(result_hi); + /* store calc'd output tables indices */ *((__m64 *)&output[0]) = _mm_cvtps_pi32(result); + result = _mm_movehl_ps(result, result); + *((__m64 *)&output[2]) = _mm_cvtps_pi32(result); + + /* load gamma values for next loop while store completes */ + vec_r = _mm_load_ss(&igtbl_r[src[0]]); + vec_g = _mm_load_ss(&igtbl_g[src[1]]); + vec_b = _mm_load_ss(&igtbl_b[src[2]]); + src += 4; /* use calc'd indices to output RGB values */ dest[OUTPUT_R_INDEX] = otdata_r[output[0]]; dest[OUTPUT_G_INDEX] = otdata_g[output[1]]; dest[OUTPUT_B_INDEX] = otdata_b[output[2]]; dest += 4; - - /* load gamma values for next loop while store completes */ - vec_r = _mm_load_ss(&igtbl_r[src[0]]); - vec_g = _mm_load_ss(&igtbl_g[src[1]]); - vec_b = _mm_load_ss(&igtbl_b[src[2]]); - src += 4; } /* handle final (maybe only) pixel */ vec_r = _mm_shuffle_ps(vec_r, vec_r, 0); vec_g = _mm_shuffle_ps(vec_g, vec_g, 0); vec_b = _mm_shuffle_ps(vec_b, vec_b, 0);
--- a/gfx/src/nsITheme.h +++ b/gfx/src/nsITheme.h @@ -19,20 +19,20 @@ struct nsIntMargin; class nsPresContext; class nsRenderingContext; class nsDeviceContext; class nsIFrame; class nsIAtom; class nsIWidget; // IID for the nsITheme interface -// {a21dd936-5960-46da-a724-7c114e421b41} +// {7329f760-08cb-450f-8225-dae729096dec} #define NS_ITHEME_IID \ -{ 0xa21dd936, 0x5960, 0x46da, \ - { 0xa7, 0x24, 0x7c, 0x11, 0x4e, 0x42, 0x1b, 0x41 } } +{ 0x7329f760, 0x08cb, 0x450f, \ + { 0x82, 0x25, 0xda, 0xe7, 0x29, 0x09, 0x6d, 0xec } } // {0ae05515-cf7a-45a8-9e02-6556de7685b1} #define NS_THEMERENDERER_CID \ { 0x0ae05515, 0xcf7a, 0x45a8, \ { 0x9e, 0x02, 0x65, 0x56, 0xde, 0x76, 0x85, 0xb1 } } /** * nsITheme is a service that provides platform-specific native * rendering for widgets. In other words, it provides the necessary @@ -131,17 +131,18 @@ public: NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, nsIAtom* aAttribute, bool* aShouldRepaint)=0; NS_IMETHOD ThemeChanged()=0; virtual bool WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType) { return false; } - virtual bool NeedToClearBackgroundBehindWidget(uint8_t aWidgetType) + virtual bool NeedToClearBackgroundBehindWidget(nsIFrame* aFrame, + uint8_t aWidgetType) { return false; } virtual bool WidgetProvidesFontSmoothingBackgroundColor(nsIFrame* aFrame, uint8_t aWidgetType, nscolor* aColor) { return false; } /** * ThemeGeometryType values are used for describing themed nsIFrames in
--- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -381,48 +381,57 @@ static const char *gPrefLangNames[] = { "x-orya", "x-telu", "x-knda", "x-sinh", "x-tibt", "x-unicode", }; -// this needs to match the list of pref font.default.xx entries listed in all.js! -// the order *must* match the order in eFontPrefLang -static nsIAtom* gPrefLangToLangGroups[] = { - nsGkAtoms::x_western, - nsGkAtoms::Japanese, - nsGkAtoms::Taiwanese, - nsGkAtoms::Chinese, - nsGkAtoms::HongKongChinese, - nsGkAtoms::ko, - nsGkAtoms::x_cyrillic, - nsGkAtoms::el, - nsGkAtoms::th, - nsGkAtoms::he, - nsGkAtoms::ar, - nsGkAtoms::x_devanagari, - nsGkAtoms::x_tamil, - nsGkAtoms::x_armn, - nsGkAtoms::x_beng, - nsGkAtoms::x_cans, - nsGkAtoms::x_ethi, - nsGkAtoms::x_geor, - nsGkAtoms::x_gujr, - nsGkAtoms::x_guru, - nsGkAtoms::x_khmr, - nsGkAtoms::x_mlym, - nsGkAtoms::x_orya, - nsGkAtoms::x_telu, - nsGkAtoms::x_knda, - nsGkAtoms::x_sinh, - nsGkAtoms::x_tibt, - nsGkAtoms::Unicode -}; +static nsIAtom* PrefLangToLangGroups(uint32_t aIndex) +{ + // This needs to match the list of pref font.default.xx entries listed in + // all.js! The order *must* match the order in eFontPrefLang. + // + // Having this array within a static function rather than at the top-level + // avoids a static constructor. + static nsIAtom* gPrefLangToLangGroups[] = { + nsGkAtoms::x_western, + nsGkAtoms::Japanese, + nsGkAtoms::Taiwanese, + nsGkAtoms::Chinese, + nsGkAtoms::HongKongChinese, + nsGkAtoms::ko, + nsGkAtoms::x_cyrillic, + nsGkAtoms::el, + nsGkAtoms::th, + nsGkAtoms::he, + nsGkAtoms::ar, + nsGkAtoms::x_devanagari, + nsGkAtoms::x_tamil, + nsGkAtoms::x_armn, + nsGkAtoms::x_beng, + nsGkAtoms::x_cans, + nsGkAtoms::x_ethi, + nsGkAtoms::x_geor, + nsGkAtoms::x_gujr, + nsGkAtoms::x_guru, + nsGkAtoms::x_khmr, + nsGkAtoms::x_mlym, + nsGkAtoms::x_orya, + nsGkAtoms::x_telu, + nsGkAtoms::x_knda, + nsGkAtoms::x_sinh, + nsGkAtoms::x_tibt, + nsGkAtoms::Unicode + }; + return aIndex < ArrayLength(gPrefLangToLangGroups) + ? gPrefLangToLangGroups[aIndex] + : nsGkAtoms::Unicode; +} gfxPlatform::gfxPlatform() : mTileWidth(-1) , mTileHeight(-1) , mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureBackendInfo) , mApzSupportCollector(this, &gfxPlatform::GetApzSupportInfo) { mAllowDownloadableFonts = UNINITIALIZED_VALUE; @@ -1519,20 +1528,17 @@ gfxPlatform::GetFontPrefLangFor(nsIAtom nsIAtom* gfxPlatform::GetLangGroupForPrefLang(eFontPrefLang aLang) { // the special CJK set pref lang should be resolved into separate // calls to individual CJK pref langs before getting here NS_ASSERTION(aLang != eFontPrefLang_CJKSet, "unresolved CJK set pref lang"); - if (uint32_t(aLang) < ArrayLength(gPrefLangToLangGroups)) { - return gPrefLangToLangGroups[uint32_t(aLang)]; - } - return nsGkAtoms::Unicode; + return PrefLangToLangGroups(uint32_t(aLang)); } const char* gfxPlatform::GetPrefLangName(eFontPrefLang aLang) { if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) { return gPrefLangNames[uint32_t(aLang)]; }
--- a/hal/gonk/GonkHal.cpp +++ b/hal/gonk/GonkHal.cpp @@ -1642,18 +1642,22 @@ PriorityClass::PriorityClass(ProcessPrio } if (EnsureMemCGroupExists(mGroup)) { mMemCGroupProcsFd = OpenMemCGroupProcs(); } } PriorityClass::~PriorityClass() { - close(mCpuCGroupProcsFd); - close(mMemCGroupProcsFd); + if (mCpuCGroupProcsFd != -1) { + close(mCpuCGroupProcsFd); + } + if (mMemCGroupProcsFd != -1) { + close(mMemCGroupProcsFd); + } } PriorityClass::PriorityClass(const PriorityClass& aOther) : mPriority(aOther.mPriority) , mOomScoreAdj(aOther.mOomScoreAdj) , mKillUnderKB(aOther.mKillUnderKB) , mGroup(aOther.mGroup) {
--- a/image/decoders/nsPNGDecoder.cpp +++ b/image/decoders/nsPNGDecoder.cpp @@ -106,16 +106,17 @@ nsPNGDecoder::AnimFrameInfo::AnimFrameIn const uint8_t nsPNGDecoder::pngSignatureBytes[] = { 137, 80, 78, 71, 13, 10, 26, 10 }; nsPNGDecoder::nsPNGDecoder(RasterImage* aImage) : Decoder(aImage), mPNG(nullptr), mInfo(nullptr), mCMSLine(nullptr), interlacebuf(nullptr), mInProfile(nullptr), mTransform(nullptr), + format(gfx::SurfaceFormat::UNKNOWN), mHeaderBytesRead(0), mCMSMode(0), mChannels(0), mFrameIsHidden(false), mDisablePremultipliedAlpha(false), mNumFrames(0) { } nsPNGDecoder::~nsPNGDecoder() @@ -631,16 +632,18 @@ nsPNGDecoder::info_callback(png_structp //---------------------------------------------------------------// // copy PNG info into imagelib structs (formerly png_set_dims()) // //---------------------------------------------------------------// if (channels == 1 || channels == 3) { decoder->format = gfx::SurfaceFormat::B8G8R8X8; } else if (channels == 2 || channels == 4) { decoder->format = gfx::SurfaceFormat::B8G8R8A8; + } else { + png_longjmp(decoder->mPNG, 1); // invalid number of channels } #ifdef PNG_APNG_SUPPORTED if (png_get_valid(png_ptr, info_ptr, PNG_INFO_acTL)) { png_set_progressive_frame_fn(png_ptr, nsPNGDecoder::frame_info_callback, nullptr); }
--- a/intl/locale/langGroups.properties +++ b/intl/locale/langGroups.properties @@ -209,16 +209,17 @@ x-cyrillic=x-cyrillic # zh-CN # ko # zh-TW x-tamil=x-tamil x-devanagari=x-devanagari x-unicode=x-unicode x-armn=x-armn x-geor=x-geor +x-math=x-math # These self-mappings are not necessary unless somebody use them to specify # lang in (X)HTML/XML documents, which they shouldn't. (see bug 256257) #x-beng=x-beng #x-cans=x-cans #x-ethi=x-ethi #x-guru=x-guru #x-gujr=x-gujr #x-khmr=x-khmr
--- a/js/src/builtin/AtomicsObject.cpp +++ b/js/src/builtin/AtomicsObject.cpp @@ -1223,18 +1223,21 @@ AtomicsObject::initClass(JSContext* cx, if (!JS_DefineFunctions(cx, Atomics, AtomicsMethods)) return nullptr; if (!JS_DefineConstDoubles(cx, Atomics, AtomicsConstants)) return nullptr; RootedValue AtomicsValue(cx, ObjectValue(*Atomics)); // Everything is set up, install Atomics on the global object. - if (!DefineProperty(cx, global, cx->names().Atomics, AtomicsValue, nullptr, nullptr, 0)) + if (!DefineProperty(cx, global, cx->names().Atomics, AtomicsValue, nullptr, nullptr, + JSPROP_RESOLVING)) + { return nullptr; + } global->setConstructor(JSProto_Atomics, AtomicsValue); return Atomics; } JSObject* js::InitAtomicsClass(JSContext* cx, HandleObject obj) {
--- a/js/src/builtin/Intl.cpp +++ b/js/src/builtin/Intl.cpp @@ -2044,18 +2044,21 @@ js::InitIntlClass(JSContext* cx, HandleO // called with this being "the standard built-in Intl object". The global // object reserves slots to track standard built-in objects, but doesn't // normally keep references to non-constructors. This makes sure there is one. RootedObject Intl(cx, global->getOrCreateIntlObject(cx)); if (!Intl) return nullptr; RootedValue IntlValue(cx, ObjectValue(*Intl)); - if (!DefineProperty(cx, global, cx->names().Intl, IntlValue, nullptr, nullptr, 0)) + if (!DefineProperty(cx, global, cx->names().Intl, IntlValue, nullptr, nullptr, + JSPROP_RESOLVING)) + { return nullptr; + } if (!JS_DefineFunctions(cx, Intl, intl_static_methods)) return nullptr; if (!InitCollatorClass(cx, Intl, global)) return nullptr; if (!InitNumberFormatClass(cx, Intl, global)) return nullptr;
--- a/js/src/builtin/Object.cpp +++ b/js/src/builtin/Object.cpp @@ -1127,17 +1127,18 @@ CreateObjectPrototype(JSContext* cx, JSP static bool FinishObjectClassInit(JSContext* cx, JS::HandleObject ctor, JS::HandleObject proto) { Rooted<GlobalObject*> self(cx, cx->global()); /* ES5 15.1.2.1. */ RootedId evalId(cx, NameToId(cx->names().eval)); - JSObject* evalobj = DefineFunction(cx, self, evalId, IndirectEval, 1, JSFUN_STUB_GSOPS); + JSObject* evalobj = DefineFunction(cx, self, evalId, IndirectEval, 1, + JSFUN_STUB_GSOPS | JSPROP_RESOLVING); if (!evalobj) return false; self->setOriginalEval(evalobj); RootedObject intrinsicsHolder(cx); bool isSelfHostingGlobal = cx->runtime()->isSelfHostingGlobal(self); if (isSelfHostingGlobal) { intrinsicsHolder = self;
--- a/js/src/builtin/SIMD.cpp +++ b/js/src/builtin/SIMD.cpp @@ -470,18 +470,21 @@ SIMDObject::initClass(JSContext* cx, Han RootedObject f64x2(cx); f64x2 = CreateAndBindSimdClass<Float64x2Defn>(cx, global, SIMD, cx->names().float64x2); if (!f64x2) return nullptr; global->setFloat64x2TypeDescr(*f64x2); // Everything is set up, install SIMD on the global object. RootedValue SIMDValue(cx, ObjectValue(*SIMD)); - if (!DefineProperty(cx, global, cx->names().SIMD, SIMDValue, nullptr, nullptr, 0)) + if (!DefineProperty(cx, global, cx->names().SIMD, SIMDValue, nullptr, nullptr, + JSPROP_RESOLVING)) + { return nullptr; + } global->setConstructor(JSProto_SIMD, SIMDValue); return SIMD; } JSObject* js::InitSIMDClass(JSContext* cx, HandleObject obj) {
--- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -1320,18 +1320,21 @@ GlobalObject::initTypedObjectModule(JSCo nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT)) { return false; } // Everything is setup, install module on the global object: RootedValue moduleValue(cx, ObjectValue(*module)); global->setConstructor(JSProto_TypedObject, moduleValue); - if (!DefineProperty(cx, global, cx->names().TypedObject, moduleValue, nullptr, nullptr, 0)) + if (!DefineProperty(cx, global, cx->names().TypedObject, moduleValue, nullptr, nullptr, + JSPROP_RESOLVING)) + { return false; + } return module; } JSObject* js::InitTypedObjectModuleObject(JSContext* cx, HandleObject obj) { MOZ_ASSERT(obj->is<GlobalObject>());
--- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -24,55 +24,18 @@ #include "vm/Interpreter-inl.h" using namespace js; using namespace js::jit; using JS::GenericNaN; using JS::ToInt32; -namespace { - -// Emulate a TypeSet logic from a Type object to avoid duplicating the guard -// logic. -class TypeWrapper { - TypeSet::Type t_; - - public: - explicit TypeWrapper(TypeSet::Type t) : t_(t) {} - - inline bool unknown() const { - return t_.isUnknown(); - } - inline bool hasType(TypeSet::Type t) const { - if (t == TypeSet::Int32Type()) - return t == t_ || t_ == TypeSet::DoubleType(); - return t == t_; - } - inline unsigned getObjectCount() const { - if (t_.isAnyObject() || t_.isUnknown() || !t_.isObject()) - return 0; - return 1; - } - inline JSObject* getSingletonNoBarrier(unsigned) const { - if (t_.isSingleton()) - return t_.singletonNoBarrier(); - return nullptr; - } - inline ObjectGroup* getGroupNoBarrier(unsigned) const { - if (t_.isGroup()) - return t_.groupNoBarrier(); - return nullptr; - } -}; - -} /* anonymous namespace */ - -template <typename Source, typename Set> void -MacroAssembler::guardTypeSet(const Source& address, const Set *types, BarrierKind kind, +template <typename Source> void +MacroAssembler::guardTypeSet(const Source& address, const TypeSet *types, BarrierKind kind, Register scratch, Label* miss) { MOZ_ASSERT(kind == BarrierKind::TypeTagOnly || kind == BarrierKind::TypeSet); MOZ_ASSERT(!types->unknown()); Label matched; TypeSet::Type tests[8] = { TypeSet::Int32Type(), @@ -159,18 +122,18 @@ MacroAssembler::guardTypeSetMightBeIncom loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch); load32(Address(scratch, ObjectGroup::offsetOfFlags()), scratch); branchTest32(Assembler::NonZero, scratch, Imm32(OBJECT_FLAG_UNKNOWN_PROPERTIES), label); and32(Imm32(OBJECT_FLAG_ADDENDUM_MASK), scratch); branch32(Assembler::Equal, scratch, Imm32(ObjectGroup::addendumOriginalUnboxedGroupValue()), label); } -template <typename Set> void -MacroAssembler::guardObjectType(Register obj, const Set *types, +void +MacroAssembler::guardObjectType(Register obj, const TypeSet *types, Register scratch, Label* miss) { MOZ_ASSERT(!types->unknown()); MOZ_ASSERT(!types->hasType(TypeSet::AnyObjectType())); MOZ_ASSERT(types->getObjectCount()); MOZ_ASSERT(scratch != InvalidReg); // Note: this method elides read barriers on values read from type sets, as @@ -231,58 +194,23 @@ MacroAssembler::guardObjectType(Register lastBranch.invertCondition(); lastBranch.relink(miss); lastBranch.emit(*this); bind(&matched); return; } -template <typename Source> void -MacroAssembler::guardType(const Source& address, TypeSet::Type type, - Register scratch, Label* miss) -{ - TypeWrapper wrapper(type); - guardTypeSet(address, &wrapper, BarrierKind::TypeSet, scratch, miss); -} - -template void MacroAssembler::guardTypeSet(const Address& address, const TemporaryTypeSet* types, - BarrierKind kind, Register scratch, Label* miss); -template void MacroAssembler::guardTypeSet(const ValueOperand& value, const TemporaryTypeSet* types, - BarrierKind kind, Register scratch, Label* miss); - -template void MacroAssembler::guardTypeSet(const Address& address, const HeapTypeSet* types, - BarrierKind kind, Register scratch, Label* miss); -template void MacroAssembler::guardTypeSet(const ValueOperand& value, const HeapTypeSet* types, - BarrierKind kind, Register scratch, Label* miss); -template void MacroAssembler::guardTypeSet(const TypedOrValueRegister& reg, const HeapTypeSet* types, - BarrierKind kind, Register scratch, Label* miss); - template void MacroAssembler::guardTypeSet(const Address& address, const TypeSet* types, BarrierKind kind, Register scratch, Label* miss); template void MacroAssembler::guardTypeSet(const ValueOperand& value, const TypeSet* types, BarrierKind kind, Register scratch, Label* miss); - -template void MacroAssembler::guardTypeSet(const Address& address, const TypeWrapper* types, - BarrierKind kind, Register scratch, Label* miss); -template void MacroAssembler::guardTypeSet(const ValueOperand& value, const TypeWrapper* types, +template void MacroAssembler::guardTypeSet(const TypedOrValueRegister& value, const TypeSet* types, BarrierKind kind, Register scratch, Label* miss); -template void MacroAssembler::guardObjectType(Register obj, const TemporaryTypeSet* types, - Register scratch, Label* miss); -template void MacroAssembler::guardObjectType(Register obj, const TypeSet* types, - Register scratch, Label* miss); -template void MacroAssembler::guardObjectType(Register obj, const TypeWrapper* types, - Register scratch, Label* miss); - -template void MacroAssembler::guardType(const Address& address, TypeSet::Type type, - Register scratch, Label* miss); -template void MacroAssembler::guardType(const ValueOperand& value, TypeSet::Type type, - Register scratch, Label* miss); - template<typename S, typename T> static void StoreToTypedFloatArray(MacroAssembler& masm, int arrayType, const S& value, const T& dest, unsigned numElems) { switch (arrayType) { case Scalar::Float32: masm.storeFloat32(value, dest);
--- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -326,22 +326,20 @@ class MacroAssembler : public MacroAssem void popRooted(VMFunction::RootType rootType, Register cellReg, const ValueOperand& valueReg); void adjustStack(int amount); public: // Emits a test of a value against all types in a TypeSet. A scratch // register is required. - template <typename Source, typename TypeSet> + template <typename Source> void guardTypeSet(const Source& address, const TypeSet* types, BarrierKind kind, Register scratch, Label* miss); - template <typename TypeSet> + void guardObjectType(Register obj, const TypeSet* types, Register scratch, Label* miss); - template <typename Source> - void guardType(const Source& address, TypeSet::Type type, Register scratch, Label* miss); void guardTypeSetMightBeIncomplete(Register obj, Register scratch, Label* label); void loadObjShape(Register objReg, Register dest) { loadPtr(Address(objReg, JSObject::offsetOfShape()), dest); } void loadObjGroup(Register objReg, Register dest) { loadPtr(Address(objReg, JSObject::offsetOfGroup()), dest);
--- a/js/src/jit/x86-shared/Assembler-x86-shared.h +++ b/js/src/jit/x86-shared/Assembler-x86-shared.h @@ -2761,17 +2761,17 @@ class AssemblerX86Shared : public Assemb case Operand::MEM_REG_DISP: masm.vinsertps_imr(mask, src1.disp(), src1.base(), src0.encoding(), dest.encoding()); break; default: MOZ_CRASH("unexpected operand kind"); } } unsigned blendpsMask(bool x, bool y, bool z, bool w) { - return x | (y << 1) | (z << 2) | (w << 3); + return (x << 0) | (y << 1) | (z << 2) | (w << 3); } void vblendps(unsigned mask, FloatRegister src1, FloatRegister src0, FloatRegister dest) { MOZ_ASSERT(HasSSE41()); masm.vblendps_irr(mask, src1.encoding(), src0.encoding(), dest.encoding()); } void vblendps(unsigned mask, const Operand& src1, FloatRegister src0, FloatRegister dest) { MOZ_ASSERT(HasSSE41()); switch (src1.kind()) {
--- a/js/src/jsapi-tests/testLookup.cpp +++ b/js/src/jsapi-tests/testLookup.cpp @@ -56,17 +56,17 @@ document_resolve(JSContext* cx, JS::Hand if (!flatStr) return false; if (JS_FlatStringEqualsAscii(flatStr, "all")) { JS::Rooted<JSObject*> docAll(cx, JS_NewObject(cx, &DocumentAllClass)); if (!docAll) return false; JS::Rooted<JS::Value> allValue(cx, JS::ObjectValue(*docAll)); - if (!JS_DefinePropertyById(cx, obj, id, allValue, 0)) + if (!JS_DefinePropertyById(cx, obj, id, allValue, JSPROP_RESOLVING)) return false; *resolvedp = true; return true; } } *resolvedp = false;
--- a/js/src/jsapi-tests/testResolveRecursion.cpp +++ b/js/src/jsapi-tests/testResolveRecursion.cpp @@ -6,17 +6,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "jsapi-tests/tests.h" /* * Test that resolve hook recursion for the same object and property is * prevented. */ - BEGIN_TEST(testResolveRecursion) { static const JSClass my_resolve_class = { "MyResolve", JSCLASS_HAS_PRIVATE, nullptr, // add nullptr, // delete nullptr, // get @@ -83,29 +82,29 @@ doResolve(JS::HandleObject obj, JS::Hand CHECK(str); JS::RootedValue v(cx); if (JS_FlatStringEqualsAscii(str, "x")) { if (obj == obj1) { /* First resolve hook invocation. */ CHECK_EQUAL(resolveEntryCount, 1); EVAL("obj2.y = true", &v); CHECK_SAME(v, JSVAL_TRUE); - CHECK(JS_DefinePropertyById(cx, obj, id, JS::FalseHandleValue, 0)); + CHECK(JS_DefinePropertyById(cx, obj, id, JS::FalseHandleValue, JSPROP_RESOLVING)); *resolvedp = true; return true; } if (obj == obj2) { CHECK_EQUAL(resolveEntryCount, 4); *resolvedp = false; return true; } } else if (JS_FlatStringEqualsAscii(str, "y")) { if (obj == obj2) { CHECK_EQUAL(resolveEntryCount, 2); - CHECK(JS_DefinePropertyById(cx, obj, id, JS::NullHandleValue, 0)); + CHECK(JS_DefinePropertyById(cx, obj, id, JS::NullHandleValue, JSPROP_RESOLVING)); EVAL("obj1.x", &v); CHECK(v.isUndefined()); EVAL("obj1.y", &v); CHECK_SAME(v, JSVAL_ZERO); *resolvedp = true; return true; } if (obj == obj1) { @@ -129,10 +128,54 @@ doResolve(JS::HandleObject obj, JS::Hand } static bool my_resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp) { return static_cast<cls_testResolveRecursion*>(JS_GetPrivate(obj))-> doResolve(obj, id, resolvedp); } +END_TEST(testResolveRecursion) -END_TEST(testResolveRecursion) +/* + * Test that JS_InitStandardClasses does not cause resolve hooks to be called. + * + * (XPConnect apparently does have global classes, such as the one created by + * nsMessageManagerScriptExecutor::InitChildGlobalInternal(), that have resolve + * hooks which can call back into JS, and on which JS_InitStandardClasses is + * called. Calling back into JS in the middle of resolving `undefined` is bad.) + */ +BEGIN_TEST(testResolveRecursion_InitStandardClasses) +{ + CHECK(JS_InitStandardClasses(cx, global)); + return true; +} + +const JSClass* getGlobalClass() override { + static const JSClass myGlobalClass = { + "testResolveRecursion_InitStandardClasses_myGlobalClass", + JSCLASS_GLOBAL_FLAGS, + nullptr, // add + nullptr, // delete + nullptr, // get + nullptr, // set + nullptr, // enumerate + my_resolve, + nullptr, // mayResolve + nullptr, // convert + nullptr, // finalize + nullptr, // call + nullptr, // hasInstance + nullptr, // construct + JS_GlobalObjectTraceHook + }; + + return &myGlobalClass; +} + +static bool +my_resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp) +{ + MOZ_ASSERT_UNREACHABLE("resolve hook should not be called from InitStandardClasses"); + JS_ReportError(cx, "FAIL"); + return false; +} +END_TEST(testResolveRecursion_InitStandardClasses)
--- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1226,19 +1226,18 @@ JS_ResolveStandardClass(JSContext* cx, H if (!rt->hasContexts() || !JSID_IS_ATOM(id)) return true; /* Check whether we're resolving 'undefined', and define it if so. */ JSAtom* idAtom = JSID_TO_ATOM(id); JSAtom* undefinedAtom = cx->names().undefined; if (idAtom == undefinedAtom) { *resolved = true; - return DefineProperty(cx, obj, undefinedAtom->asPropertyName(), - UndefinedHandleValue, nullptr, nullptr, - JSPROP_PERMANENT | JSPROP_READONLY); + return DefineProperty(cx, global, id, UndefinedHandleValue, nullptr, nullptr, + JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING); } /* Try for class constructors/prototypes named by well-known atoms. */ stdnm = LookupStdName(cx->names(), idAtom, standard_class_names); /* Try less frequently used top-level functions and constants. */ if (!stdnm) stdnm = LookupStdName(cx->names(), idAtom, builtin_property_names);
--- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -856,51 +856,65 @@ class MOZ_STACK_CLASS SourceBufferHolder have self-hosted functions that can only be defined after the initialization is already finished. */ #define JSFUN_STUB_GSOPS 0x200 /* use JS_PropertyStub getter/setter instead of defaulting to class gsops for property holding function */ #define JSFUN_CONSTRUCTOR 0x400 /* native that can be called as a ctor */ -#define JSPROP_REDEFINE_NONCONFIGURABLE 0x800 /* If set, will allow redefining a - non-configurable property, but - only on a non-DOM global. This - is a temporary hack that will - need to go away in bug - 1105518 */ - -#define JSPROP_IGNORE_ENUMERATE 0x1000 /* ignore the value in JSPROP_ENUMERATE. - This flag only valid when defining over - an existing property. */ -#define JSPROP_IGNORE_READONLY 0x2000 /* ignore the value in JSPROP_READONLY. - This flag only valid when defining over - an existing property. */ -#define JSPROP_IGNORE_PERMANENT 0x4000 /* ignore the value in JSPROP_PERMANENT. - This flag only valid when defining over - an existing property. */ -#define JSPROP_IGNORE_VALUE 0x8000 /* ignore the Value in the descriptor. Nothing was - specified when passed to Object.defineProperty - from script. */ - /* * Specify a generic native prototype methods, i.e., methods of a class * prototype that are exposed as static methods taking an extra leading * argument: the generic |this| parameter. * * If you set this flag in a JSFunctionSpec struct's flags initializer, then * that struct must live at least as long as the native static method object * created due to this flag by JS_DefineFunctions or JS_InitClass. Typically * JSFunctionSpec structs are allocated in static arrays. */ #define JSFUN_GENERIC_NATIVE 0x800 #define JSFUN_FLAGS_MASK 0xe00 /* | of all the JSFUN_* flags */ /* + * If set, will allow redefining a non-configurable property, but only on a + * non-DOM global. This is a temporary hack that will need to go away in bug + * 1105518. + */ +#define JSPROP_REDEFINE_NONCONFIGURABLE 0x1000 + +/* + * Resolve hooks and enumerate hooks must pass this flag when calling + * JS_Define* APIs to reify lazily-defined properties. + * + * JSPROP_RESOLVING is used only with property-defining APIs. It tells the + * engine to skip the resolve hook when performing the lookup at the beginning + * of property definition. This keeps the resolve hook from accidentally + * triggering itself: unchecked recursion. + * + * For enumerate hooks, triggering the resolve hook would be merely silly, not + * fatal, except in some cases involving non-configurable properties. + */ +#define JSPROP_RESOLVING 0x2000 + +#define JSPROP_IGNORE_ENUMERATE 0x4000 /* ignore the value in JSPROP_ENUMERATE. + This flag only valid when defining over + an existing property. */ +#define JSPROP_IGNORE_READONLY 0x8000 /* ignore the value in JSPROP_READONLY. + This flag only valid when defining over + an existing property. */ +#define JSPROP_IGNORE_PERMANENT 0x10000 /* ignore the value in JSPROP_PERMANENT. + This flag only valid when defining over + an existing property. */ +#define JSPROP_IGNORE_VALUE 0x20000 /* ignore the Value in the descriptor. Nothing was + specified when passed to Object.defineProperty + from script. */ + +/* * The first call to JS_CallOnce by any thread in a process will call 'func'. * Later calls to JS_CallOnce with the same JSCallOnceType object will be * suppressed. * * Equivalently: each distinct JSCallOnceType object will allow one JS_CallOnce * to invoke its JSInitCallback. */ extern JS_PUBLIC_API(bool) @@ -2558,16 +2572,17 @@ class PropertyDescriptorOperations MOZ_ASSERT((attributes() & ~(JSPROP_ENUMERATE | JSPROP_IGNORE_ENUMERATE | JSPROP_PERMANENT | JSPROP_IGNORE_PERMANENT | JSPROP_READONLY | JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED | JSPROP_REDEFINE_NONCONFIGURABLE | + JSPROP_RESOLVING | SHADOWABLE)) == 0); MOZ_ASSERT(!hasAll(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE)); MOZ_ASSERT(!hasAll(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT)); if (isAccessorDescriptor()) { MOZ_ASSERT(has(JSPROP_SHARED)); MOZ_ASSERT(!has(JSPROP_READONLY)); MOZ_ASSERT(!has(JSPROP_IGNORE_READONLY)); MOZ_ASSERT(!has(JSPROP_IGNORE_VALUE)); @@ -2576,29 +2591,36 @@ class PropertyDescriptorOperations MOZ_ASSERT_IF(!has(JSPROP_GETTER), !getter()); MOZ_ASSERT_IF(!has(JSPROP_SETTER), !setter()); } else { MOZ_ASSERT(!hasAll(JSPROP_IGNORE_READONLY | JSPROP_READONLY)); MOZ_ASSERT_IF(has(JSPROP_IGNORE_VALUE), value().isUndefined()); } MOZ_ASSERT(getter() != JS_PropertyStub); MOZ_ASSERT(setter() != JS_StrictPropertyStub); + + MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_ENUMERATE)); + MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_PERMANENT)); + MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_READONLY)); + MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_VALUE)); + MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_REDEFINE_NONCONFIGURABLE)); #endif } void assertComplete() const { #ifdef DEBUG assertValid(); MOZ_ASSERT((attributes() & ~(JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED | JSPROP_REDEFINE_NONCONFIGURABLE | + JSPROP_RESOLVING | SHADOWABLE)) == 0); MOZ_ASSERT_IF(isAccessorDescriptor(), has(JSPROP_GETTER) && has(JSPROP_SETTER)); #endif } void assertCompleteIfFound() const { #ifdef DEBUG if (object())
--- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -358,70 +358,63 @@ CallerSetter(JSContext* cx, unsigned arg } static const JSPropertySpec function_properties[] = { JS_PSGS("arguments", ArgumentsGetter, ArgumentsSetter, 0), JS_PSGS("caller", CallerGetter, CallerSetter, 0), JS_PS_END }; -static JSObject* -ResolveInterpretedFunctionPrototype(JSContext* cx, HandleObject obj) +static bool +ResolveInterpretedFunctionPrototype(JSContext* cx, HandleFunction fun, HandleId id) { -#ifdef DEBUG - JSFunction* fun = &obj->as<JSFunction>(); MOZ_ASSERT(fun->isInterpreted() || fun->isAsmJSNative()); MOZ_ASSERT(!fun->isFunctionPrototype()); -#endif + MOZ_ASSERT(id == NameToId(cx->names().prototype)); // Assert that fun is not a compiler-created function object, which // must never leak to script or embedding code and then be mutated. - // Also assert that obj is not bound, per the ES5 15.3.4.5 ref above. - MOZ_ASSERT(!IsInternalFunctionObject(obj)); - MOZ_ASSERT(!obj->isBoundFunction()); + // Also assert that fun is not bound, per the ES5 15.3.4.5 ref above. + MOZ_ASSERT(!IsInternalFunctionObject(fun)); + MOZ_ASSERT(!fun->isBoundFunction()); // Make the prototype object an instance of Object with the same parent as // the function object itself, unless the function is an ES6 generator. In // that case, per the 15 July 2013 ES6 draft, section 15.19.3, its parent is // the GeneratorObjectPrototype singleton. - bool isStarGenerator = obj->as<JSFunction>().isStarGenerator(); - Rooted<GlobalObject*> global(cx, &obj->global()); + bool isStarGenerator = fun->isStarGenerator(); + Rooted<GlobalObject*> global(cx, &fun->global()); RootedObject objProto(cx); if (isStarGenerator) objProto = GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx, global); else - objProto = obj->global().getOrCreateObjectPrototype(cx); + objProto = fun->global().getOrCreateObjectPrototype(cx); if (!objProto) return nullptr; RootedPlainObject proto(cx, NewObjectWithGivenProto<PlainObject>(cx, objProto, SingletonObject)); if (!proto) return nullptr; - // Per ES5 15.3.5.2 a user-defined function's .prototype property is - // initially non-configurable, non-enumerable, and writable. - RootedValue protoVal(cx, ObjectValue(*proto)); - if (!DefineProperty(cx, obj, cx->names().prototype, protoVal, nullptr, nullptr, - JSPROP_PERMANENT)) - { - return nullptr; - } - // Per ES5 13.2 the prototype's .constructor property is configurable, // non-enumerable, and writable. However, per the 15 July 2013 ES6 draft, // section 15.19.3, the .prototype of a generator function does not link // back with a .constructor. if (!isStarGenerator) { - RootedValue objVal(cx, ObjectValue(*obj)); + RootedValue objVal(cx, ObjectValue(*fun)); if (!DefineProperty(cx, proto, cx->names().constructor, objVal, nullptr, nullptr, 0)) return nullptr; } - return proto; + // Per ES5 15.3.5.2 a user-defined function's .prototype property is + // initially non-configurable, non-enumerable, and writable. + RootedValue protoVal(cx, ObjectValue(*proto)); + return DefineProperty(cx, fun, id, protoVal, nullptr, nullptr, + JSPROP_PERMANENT | JSPROP_RESOLVING); } static bool fun_mayResolve(const JSAtomState& names, jsid id, JSObject*) { if (!JSID_IS_ATOM(id)) return false; @@ -453,17 +446,17 @@ fun_resolve(JSContext* cx, HandleObject * Thus all of the following don't get a .prototype property: * - Methods (that are not class-constructors or generators) * - Arrow functions * - Function.prototype */ if (fun->isBuiltin() || !fun->isConstructor()) return true; - if (!ResolveInterpretedFunctionPrototype(cx, fun)) + if (!ResolveInterpretedFunctionPrototype(cx, fun, id)) return false; *resolvedp = true; return true; } bool isLength = JSID_IS_ATOM(id, cx->names().length); if (isLength || JSID_IS_ATOM(id, cx->names().name)) { @@ -496,18 +489,21 @@ fun_resolve(JSContext* cx, HandleObject v.setInt32(length); } else { if (fun->hasResolvedName()) return true; v.setString(fun->atom() == nullptr ? cx->runtime()->emptyString : fun->atom()); } - if (!NativeDefineProperty(cx, fun, id, v, nullptr, nullptr, JSPROP_READONLY)) + if (!NativeDefineProperty(cx, fun, id, v, nullptr, nullptr, + JSPROP_READONLY | JSPROP_RESOLVING)) + { return false; + } if (isLength) fun->setResolvedLength(); else fun->setResolvedName(); *resolvedp = true; return true;
--- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -1617,18 +1617,21 @@ js::InitMathClass(JSContext* cx, HandleO { RootedObject proto(cx, obj->as<GlobalObject>().getOrCreateObjectPrototype(cx)); if (!proto) return nullptr; RootedObject Math(cx, NewObjectWithGivenProto(cx, &MathClass, proto, SingletonObject)); if (!Math) return nullptr; - if (!JS_DefineProperty(cx, obj, js_Math_str, Math, 0, JS_STUBGETTER, JS_STUBSETTER)) + if (!JS_DefineProperty(cx, obj, js_Math_str, Math, JSPROP_RESOLVING, + JS_STUBGETTER, JS_STUBSETTER)) + { return nullptr; + } if (!JS_DefineFunctions(cx, Math, math_static_methods)) return nullptr; if (!JS_DefineConstDoubles(cx, Math, math_constants)) return nullptr; obj->as<GlobalObject>().setConstructor(JSProto_Math, ObjectValue(*Math)); return Math;
--- a/js/src/jsnum.cpp +++ b/js/src/jsnum.cpp @@ -452,18 +452,18 @@ js::num_parseInt(JSContext* cx, unsigned return false; } args.rval().setNumber(number); return true; } static const JSFunctionSpec number_functions[] = { - JS_SELF_HOSTED_FN(js_isNaN_str, "Global_isNaN", 1,0), - JS_SELF_HOSTED_FN(js_isFinite_str, "Global_isFinite", 1,0), + JS_SELF_HOSTED_FN(js_isNaN_str, "Global_isNaN", 1, JSPROP_RESOLVING), + JS_SELF_HOSTED_FN(js_isFinite_str, "Global_isFinite", 1, JSPROP_RESOLVING), JS_FS_END }; const Class NumberObject::class_ = { js_Number_str, JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Number) }; @@ -1171,40 +1171,42 @@ js::InitNumberClass(JSContext* cx, Handl if (!DefinePropertiesAndFunctions(cx, numberProto, nullptr, number_methods)) return nullptr; if (!JS_DefineFunctions(cx, global, number_functions)) return nullptr; /* Number.parseInt should be the same function object as global parseInt. */ RootedId parseIntId(cx, NameToId(cx->names().parseInt)); - JSFunction* parseInt = DefineFunction(cx, global, parseIntId, num_parseInt, 2, 0); - if(!parseInt) + JSFunction* parseInt = DefineFunction(cx, global, parseIntId, num_parseInt, 2, + JSPROP_RESOLVING); + if (!parseInt) return nullptr; RootedValue parseIntValue(cx, ObjectValue(*parseInt)); - if(!DefineProperty(cx, ctor, parseIntId, parseIntValue, nullptr, nullptr, 0)) + if (!DefineProperty(cx, ctor, parseIntId, parseIntValue, nullptr, nullptr, 0)) return nullptr; /* Number.parseFloat should be the same function object as global parseFloat. */ RootedId parseFloatId(cx, NameToId(cx->names().parseFloat)); - JSFunction* parseFloat = DefineFunction(cx, global, parseFloatId, num_parseFloat, 1, 0); - if(!parseFloat) + JSFunction* parseFloat = DefineFunction(cx, global, parseFloatId, num_parseFloat, 1, + JSPROP_RESOLVING); + if (!parseFloat) return nullptr; RootedValue parseFloatValue(cx, ObjectValue(*parseFloat)); - if(!DefineProperty(cx, ctor, parseFloatId, parseFloatValue, nullptr, nullptr, 0)) + if (!DefineProperty(cx, ctor, parseFloatId, parseFloatValue, nullptr, nullptr, 0)) return nullptr; RootedValue valueNaN(cx, cx->runtime()->NaNValue); RootedValue valueInfinity(cx, cx->runtime()->positiveInfinityValue); /* ES5 15.1.1.1, 15.1.1.2 */ if (!NativeDefineProperty(cx, global, cx->names().NaN, valueNaN, nullptr, nullptr, - JSPROP_PERMANENT | JSPROP_READONLY) || + JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING) || !NativeDefineProperty(cx, global, cx->names().Infinity, valueInfinity, nullptr, nullptr, - JSPROP_PERMANENT | JSPROP_READONLY)) + JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING)) { return nullptr; } if (!GlobalObject::initBuiltinConstructor(cx, global, JSProto_Number, ctor, numberProto)) return nullptr; return numberProto;
--- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -3235,16 +3235,17 @@ js::WatchGuts(JSContext* cx, JS::HandleO MarkTypePropertyNonData(cx, obj, id); } WatchpointMap* wpmap = cx->compartment()->watchpointMap; if (!wpmap) { wpmap = cx->runtime()->new_<WatchpointMap>(); if (!wpmap || !wpmap->init()) { ReportOutOfMemory(cx); + js_delete(wpmap); return false; } cx->compartment()->watchpointMap = wpmap; } return wpmap->watch(cx, obj, id, js::WatchHandler, callable); }
--- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -895,19 +895,21 @@ js::InitJSONClass(JSContext* cx, HandleO RootedObject proto(cx, global->getOrCreateObjectPrototype(cx)); if (!proto) return nullptr; RootedObject JSON(cx, NewObjectWithGivenProto(cx, &JSONClass, proto, SingletonObject)); if (!JSON) return nullptr; - if (!JS_DefineProperty(cx, global, js_JSON_str, JSON, 0, + if (!JS_DefineProperty(cx, global, js_JSON_str, JSON, JSPROP_RESOLVING, JS_STUBGETTER, JS_STUBSETTER)) + { return nullptr; + } if (!JS_DefineFunctions(cx, JSON, json_static_methods)) return nullptr; global->setConstructor(JSProto_JSON, ObjectValue(*JSON)); return JSON; }
--- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -357,43 +357,46 @@ str_uneval(JSContext* cx, unsigned argc, return false; args.rval().setString(str); return true; } #endif static const JSFunctionSpec string_functions[] = { - JS_FN(js_escape_str, str_escape, 1,0), - JS_FN(js_unescape_str, str_unescape, 1,0), + JS_FN(js_escape_str, str_escape, 1, JSPROP_RESOLVING), + JS_FN(js_unescape_str, str_unescape, 1, JSPROP_RESOLVING), #if JS_HAS_UNEVAL - JS_FN(js_uneval_str, str_uneval, 1,0), + JS_FN(js_uneval_str, str_uneval, 1, JSPROP_RESOLVING), #endif - JS_FN(js_decodeURI_str, str_decodeURI, 1,0), - JS_FN(js_encodeURI_str, str_encodeURI, 1,0), - JS_FN(js_decodeURIComponent_str, str_decodeURI_Component, 1,0), - JS_FN(js_encodeURIComponent_str, str_encodeURI_Component, 1,0), + JS_FN(js_decodeURI_str, str_decodeURI, 1, JSPROP_RESOLVING), + JS_FN(js_encodeURI_str, str_encodeURI, 1, JSPROP_RESOLVING), + JS_FN(js_decodeURIComponent_str, str_decodeURI_Component, 1, JSPROP_RESOLVING), + JS_FN(js_encodeURIComponent_str, str_encodeURI_Component, 1, JSPROP_RESOLVING), JS_FS_END }; static const unsigned STRING_ELEMENT_ATTRS = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT; static bool str_enumerate(JSContext* cx, HandleObject obj) { RootedString str(cx, obj->as<StringObject>().unbox()); RootedValue value(cx); for (size_t i = 0, length = str->length(); i < length; i++) { JSString* str1 = NewDependentString(cx, str, i, 1); if (!str1) return false; value.setString(str1); - if (!DefineElement(cx, obj, i, value, nullptr, nullptr, STRING_ELEMENT_ATTRS)) + if (!DefineElement(cx, obj, i, value, nullptr, nullptr, + STRING_ELEMENT_ATTRS | JSPROP_RESOLVING)) + { return false; + } } return true; } static bool str_mayResolve(const JSAtomState&, jsid id, JSObject*) { @@ -410,18 +413,21 @@ str_resolve(JSContext* cx, HandleObject RootedString str(cx, obj->as<StringObject>().unbox()); int32_t slot = JSID_TO_INT(id); if ((size_t)slot < str->length()) { JSString* str1 = cx->staticStrings().getUnitStringForElement(cx, str, size_t(slot)); if (!str1) return false; RootedValue value(cx, StringValue(str1)); - if (!DefineElement(cx, obj, uint32_t(slot), value, nullptr, nullptr, STRING_ELEMENT_ATTRS)) + if (!DefineElement(cx, obj, uint32_t(slot), value, nullptr, nullptr, + STRING_ELEMENT_ATTRS | JSPROP_RESOLVING)) + { return false; + } *resolvedp = true; } return true; } const Class StringObject::class_ = { js_String_str, JSCLASS_HAS_RESERVED_SLOTS(StringObject::RESERVED_SLOTS) |
--- a/js/src/proxy/Proxy.cpp +++ b/js/src/proxy/Proxy.cpp @@ -769,16 +769,14 @@ js::InitProxyClass(JSContext* cx, Handle Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>()); RootedFunction ctor(cx); ctor = global->createConstructor(cx, proxy, cx->names().Proxy, 2); if (!ctor) return nullptr; if (!JS_DefineFunctions(cx, ctor, static_methods)) return nullptr; - if (!JS_DefineProperty(cx, obj, "Proxy", ctor, 0, - JS_STUBGETTER, JS_STUBSETTER)) { + if (!JS_DefineProperty(cx, obj, "Proxy", ctor, JSPROP_RESOLVING, JS_STUBGETTER, JS_STUBSETTER)) return nullptr; - } global->setConstructor(JSProto_Proxy, ObjectValue(*ctor)); return ctor; }
--- a/js/src/vm/ArgumentsObject.cpp +++ b/js/src/vm/ArgumentsObject.cpp @@ -350,17 +350,17 @@ ArgSetter(JSContext* cx, HandleObject ob NativeDefineProperty(cx, argsobj, id, vp, nullptr, nullptr, attrs, result); } static bool args_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp) { Rooted<NormalArgumentsObject*> argsobj(cx, &obj->as<NormalArgumentsObject>()); - unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE; + unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE | JSPROP_RESOLVING; if (JSID_IS_INT(id)) { uint32_t arg = uint32_t(JSID_TO_INT(id)); if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg)) return true; attrs |= JSPROP_ENUMERATE; } else if (JSID_IS_ATOM(id, cx->names().length)) { if (argsobj->hasOverriddenLength()) @@ -485,16 +485,17 @@ strictargs_resolve(JSContext* cx, Handle if (!JSID_IS_ATOM(id, cx->names().callee) && !JSID_IS_ATOM(id, cx->names().caller)) return true; attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED; getter = CastAsGetterOp(argsobj->global().getThrowTypeError()); setter = CastAsSetterOp(argsobj->global().getThrowTypeError()); } + attrs |= JSPROP_RESOLVING; if (!NativeDefineProperty(cx, argsobj, id, UndefinedHandleValue, getter, setter, attrs)) return false; *resolvedp = true; return true; } static bool
--- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -324,17 +324,17 @@ GlobalObject::valueIsEval(Value val) return eval.isObject() && eval == val; } /* static */ bool GlobalObject::initStandardClasses(JSContext* cx, Handle<GlobalObject*> global) { /* Define a top-level property 'undefined' with the undefined value. */ if (!DefineProperty(cx, global, cx->names().undefined, UndefinedHandleValue, - nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY)) + nullptr, nullptr, JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING)) { return false; } for (size_t k = 0; k < JSProto_LIMIT; ++k) { if (!ensureConstructor(cx, global, static_cast<JSProtoKey>(k))) return false; }
--- a/js/src/vm/NativeObject.cpp +++ b/js/src/vm/NativeObject.cpp @@ -1243,36 +1243,27 @@ js::NativeDefineProperty(ExclusiveContex } } else if (obj->is<ArgumentsObject>()) { if (id == NameToId(cx->names().length)) { // Either we are resolving the .length property on this object, or // redefining it. In the latter case only, we must set a bit. To // distinguish the two cases, we note that when resolving, the // property won't already exist; whereas the first time it is // redefined, it will. - if (obj->containsPure(id)) + if ((desc_.attributes() & JSPROP_RESOLVING) == 0) obj->as<ArgumentsObject>().markLengthOverridden(); } } // 9.1.6.1 OrdinaryDefineOwnProperty steps 1-2. RootedShape shape(cx); - if (desc_.hasValue()) { - // If we did a normal lookup here, it would cause resolve hook recursion in - // the following case. Suppose the first script we run in a lazy global is - // |parseInt()|. - // - js::InitNumberClass is called to resolve parseInt. - // - js::InitNumberClass tries to define the Number constructor on the - // global. - // - We end up here. - // - This lookup for 'Number' triggers the global resolve hook. - // - js::InitNumberClass is called again, this time to resolve Number. - // - It creates a second Number constructor, which trips an assertion. - // - // Therefore we do a special lookup that does not call the resolve hook. + if (desc_.attributes() & JSPROP_RESOLVING) { + // We are being called from a resolve or enumerate hook to reify a + // lazily-resolved property. To avoid reentering the resolve hook and + // recursing forever, skip the resolve hook when doing this lookup. NativeLookupOwnPropertyNoResolve(cx, obj, id, &shape); } else { if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape)) return false; } // From this point, the step numbers refer to // 9.1.6.3, ValidateAndApplyPropertyDescriptor.
--- a/js/xpconnect/src/Sandbox.cpp +++ b/js/xpconnect/src/Sandbox.cpp @@ -27,22 +27,26 @@ #include "xpcprivate.h" #include "XPCWrapper.h" #include "XrayWrapper.h" #include "Crypto.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/BlobBinding.h" #include "mozilla/dom/CSSBinding.h" #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" +#include "mozilla/dom/Fetch.h" #include "mozilla/dom/FileBinding.h" #include "mozilla/dom/PromiseBinding.h" +#include "mozilla/dom/RequestBinding.h" +#include "mozilla/dom/ResponseBinding.h" #include "mozilla/dom/RTCIdentityProviderRegistrar.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/TextDecoderBinding.h" #include "mozilla/dom/TextEncoderBinding.h" +#include "mozilla/dom/UnionConversions.h" #include "mozilla/dom/URLBinding.h" #include "mozilla/dom/URLSearchParamsBinding.h" using namespace mozilla; using namespace JS; using namespace js; using namespace xpc; @@ -232,16 +236,94 @@ SandboxCreateRTCIdentityProvider(JSConte dom::RTCIdentityProviderRegistrar* registrar = new dom::RTCIdentityProviderRegistrar(nativeGlobal); JS::RootedObject wrapped(cx, registrar->WrapObject(cx, nullptr)); return JS_DefineProperty(cx, obj, "rtcIdentityProvider", wrapped, JSPROP_ENUMERATE); } static bool +SetFetchRequestFromValue(JSContext *cx, RequestOrUSVString& request, + const MutableHandleValue& requestOrUrl) +{ + RequestOrUSVStringArgument requestHolder(request); + bool noMatch = true; + if (requestOrUrl.isObject() && + !requestHolder.TrySetToRequest(cx, requestOrUrl, noMatch, false)) { + return false; + } + if (noMatch && + !requestHolder.TrySetToUSVString(cx, requestOrUrl, noMatch)) { + return false; + } + if (noMatch) { + return false; + } + return true; +} + +static bool +SandboxFetch(JSContext* cx, JS::HandleObject scope, const CallArgs& args) +{ + if (args.length() < 1) { + JS_ReportError(cx, "fetch requires at least 1 argument"); + return false; + } + + RequestOrUSVString request; + if (!SetFetchRequestFromValue(cx, request, args[0])) { + JS_ReportError(cx, "fetch requires a string or Request in argument 1"); + return false; + } + RootedDictionary<dom::RequestInit> options(cx); + if (!options.Init(cx, args.hasDefined(1) ? args[1] : JS::NullHandleValue, + "Argument 2 of fetch", false)) { + return false; + } + nsCOMPtr<nsIGlobalObject> global = xpc::NativeGlobal(scope); + if (!global) { + return false; + } + ErrorResult rv; + nsRefPtr<dom::Promise> response = + FetchRequest(global, Constify(request), Constify(options), rv); + rv.WouldReportJSException(); + if (rv.Failed()) { + return ThrowMethodFailedWithDetails(cx, rv, "Sandbox", "fetch"); + } + if (!GetOrCreateDOMReflector(cx, scope, response, args.rval())) { + return false; + } + return true; +} + +static bool SandboxFetchPromise(JSContext* cx, unsigned argc, jsval* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + RootedObject callee(cx, &args.callee()); + RootedObject scope(cx, JS::CurrentGlobalOrNull(cx)); + if (SandboxFetch(cx, scope, args)) { + return true; + } + return ConvertExceptionToPromise(cx, scope, args.rval()); +} + + +static bool +SandboxCreateFetch(JSContext* cx, HandleObject obj) +{ + MOZ_ASSERT(JS_IsGlobalObject(obj)); + + return JS_DefineFunction(cx, obj, "fetch", SandboxFetchPromise, 2, 0) && + dom::RequestBinding::GetConstructorObject(cx, obj) && + dom::ResponseBinding::GetConstructorObject(cx, obj) && + dom::HeadersBinding::GetConstructorObject(cx, obj); +} + +static bool SandboxIsProxy(JSContext* cx, unsigned argc, jsval* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() < 1) { JS_ReportError(cx, "Function requires at least 1 argument"); return false; } if (!args[0].isObject()) { @@ -813,16 +895,18 @@ xpc::GlobalProperties::Parse(JSContext* } else if (!strcmp(name.ptr(), "Blob")) { Blob = true; } else if (!strcmp(name.ptr(), "File")) { File = true; } else if (!strcmp(name.ptr(), "crypto")) { crypto = true; } else if (!strcmp(name.ptr(), "rtcIdentityProvider")) { rtcIdentityProvider = true; + } else if (!strcmp(name.ptr(), "fetch")) { + fetch = true; } else { JS_ReportError(cx, "Unknown property name: %s", name.ptr()); return false; } } return true; } @@ -873,16 +957,19 @@ xpc::GlobalProperties::Define(JSContext* return false; if (crypto && !SandboxCreateCrypto(cx, obj)) return false; if (rtcIdentityProvider && !SandboxCreateRTCIdentityProvider(cx, obj)) return false; + if (fetch && !SandboxCreateFetch(cx, obj)) + return false; + return true; } nsresult xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prinOrSop, SandboxOptions& options) { // Create the sandbox global object
--- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -314,17 +314,18 @@ nsXPCComponents_Interfaces::Resolve(nsIX RootedObject idobj(cx); if (holder && // Assign, not compare (idobj = holder->GetJSObject())) { *resolvedp = true; *_retval = JS_DefinePropertyById(cx, obj, id, idobj, JSPROP_ENUMERATE | JSPROP_READONLY | - JSPROP_PERMANENT); + JSPROP_PERMANENT | + JSPROP_RESOLVING); } } } } return NS_OK; } /***************************************************************************/ @@ -552,17 +553,18 @@ nsXPCComponents_InterfacesByID::Resolve( if (holder && // Assign, not compare (idobj = holder->GetJSObject())) { *resolvedp = true; *_retval = JS_DefinePropertyById(cx, obj, id, idobj, JSPROP_ENUMERATE | JSPROP_READONLY | - JSPROP_PERMANENT); + JSPROP_PERMANENT | + JSPROP_RESOLVING); } } } return NS_OK; } /***************************************************************************/ /***************************************************************************/ @@ -770,17 +772,18 @@ nsXPCComponents_Classes::Resolve(nsIXPCo RootedObject idobj(cx); if (holder && // Assign, not compare (idobj = holder->GetJSObject())) { *resolvedp = true; *_retval = JS_DefinePropertyById(cx, obj, id, idobj, JSPROP_ENUMERATE | JSPROP_READONLY | - JSPROP_PERMANENT); + JSPROP_PERMANENT | + JSPROP_RESOLVING); } } } } return NS_OK; } /***************************************************************************/ @@ -1008,17 +1011,18 @@ nsXPCComponents_ClassesByID::Resolve(nsI RootedObject idobj(cx); if (holder && // Assign, not compare (idobj = holder->GetJSObject())) { *resolvedp = true; *_retval = JS_DefinePropertyById(cx, obj, id, idobj, JSPROP_ENUMERATE | JSPROP_READONLY | - JSPROP_PERMANENT); + JSPROP_PERMANENT | + JSPROP_RESOLVING); } } } } return NS_OK; } @@ -1203,17 +1207,18 @@ nsXPCComponents_Results::Resolve(nsIXPCo const void* iter = nullptr; nsresult rv; while (nsXPCException::IterateNSResults(&rv, &rv_name, nullptr, &iter)) { if (!strcmp(name.ptr(), rv_name)) { *resolvedp = true; if (!JS_DefinePropertyById(cx, obj, id, (uint32_t)rv, JSPROP_ENUMERATE | JSPROP_READONLY | - JSPROP_PERMANENT)) { + JSPROP_PERMANENT | + JSPROP_RESOLVING)) { return NS_ERROR_UNEXPECTED; } } } } return NS_OK; }
--- a/js/xpconnect/src/XPCJSID.cpp +++ b/js/xpconnect/src/XPCJSID.cpp @@ -397,17 +397,17 @@ nsJSIID::Resolve(nsIXPConnectWrappedNati if (member && member->IsConstant()) { RootedValue val(cx); if (!member->GetConstantValue(ccx, iface, val.address())) return NS_ERROR_OUT_OF_MEMORY; *resolvedp = true; *_retval = JS_DefinePropertyById(cx, obj, id, val, JSPROP_ENUMERATE | JSPROP_READONLY | - JSPROP_PERMANENT); + JSPROP_PERMANENT | JSPROP_RESOLVING); } return NS_OK; } /* bool enumerate (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj); */ NS_IMETHODIMP nsJSIID::Enumerate(nsIXPConnectWrappedNative* wrapper,
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp +++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp @@ -194,16 +194,18 @@ DefinePropertyIfFound(XPCCallContext& cc unsigned propFlags, bool* resolved) { RootedId id(ccx, idArg); XPCJSRuntime* rt = ccx.GetRuntime(); bool found; const char* name; + propFlags |= JSPROP_RESOLVING; + if (set) { if (iface) found = true; else found = set->FindMember(id, &member, &iface); } else found = (nullptr != (member = iface->FindMember(id))); @@ -359,16 +361,17 @@ DefinePropertyIfFound(XPCCallContext& cc Rooted<JSPropertyDescriptor> desc(ccx); if (!xpc::InterposeProperty(ccx, obj, iface->GetIID(), id, &desc)) return false; if (desc.object()) { AutoResolveName arn(ccx, id); if (resolved) *resolved = true; + desc.attributesRef() |= JSPROP_RESOLVING; return JS_DefinePropertyById(ccx, obj, id, desc); } } if (id == rt->GetStringID(XPCJSRuntime::IDX_TO_STRING) || id == rt->GetStringID(XPCJSRuntime::IDX_TO_SOURCE) || (scriptableInfo && scriptableInfo->GetFlags().DontEnumQueryInterface() &&
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp +++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp @@ -205,17 +205,17 @@ XPCWrappedNativeScope::AttachComponentsO return false; RootedObject global(aCx, GetGlobalJSObject()); MOZ_ASSERT(js::IsObjectInContextCompartment(global, aCx)); // The global Components property is non-configurable if it's a full // nsXPCComponents object. That way, if it's an nsXPCComponentsBase, // enableUniversalXPConnect can upgrade it later. - unsigned attrs = JSPROP_READONLY; + unsigned attrs = JSPROP_READONLY | JSPROP_RESOLVING; nsCOMPtr<nsIXPCComponents> c = do_QueryInterface(mComponents); if (c) attrs |= JSPROP_PERMANENT; RootedId id(aCx, XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS)); return JS_DefinePropertyById(aCx, global, id, components, attrs); }
--- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -3395,16 +3395,17 @@ struct GlobalProperties { bool URL : 1; bool URLSearchParams : 1; bool atob : 1; bool btoa : 1; bool Blob : 1; bool File : 1; bool crypto : 1; bool rtcIdentityProvider : 1; + bool fetch : 1; }; // Infallible. already_AddRefed<nsIXPCComponents_utils_Sandbox> NewSandboxConstructor(); // Returns true if class of 'obj' is SandboxClass. bool
--- a/js/xpconnect/tests/mochitest/mochitest.ini +++ b/js/xpconnect/tests/mochitest/mochitest.ini @@ -100,8 +100,11 @@ skip-if= buildapp == 'mulet' [test_crossOriginObjects.html] [test_crosscompartment_weakmap.html] [test_frameWrapping.html] # The JS test component we use below is only available in debug builds. [test_getWebIDLCaller.html] skip-if = (debug == false || os == "android") [test_nac.xhtml] [test_sameOriginPolicy.html] +[test_sandbox_fetch.html] + support-files = + ../../../../dom/tests/mochitest/fetch/test_fetch_basic.js
new file mode 100644 --- /dev/null +++ b/js/xpconnect/tests/mochitest/test_sandbox_fetch.html @@ -0,0 +1,54 @@ +<!doctype html> +<html> +<head> + <title>Fetch in JS Sandbox</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"></link> + <script src="test_fetch_basic.js"></script> +</head> +<body> +<script type="application/javascript"> + +SimpleTest.waitForExplicitFinish(); + +function testHttpFetch(url) { + info('fetch: ' + url); + return fetch(new Request(url, { method: 'GET' })) + .then(response => { + is(response.status, 200, 'Response is 200'); + is(response.url, url, 'Response URL matches'); + }); +} + +function runSandboxTest(testFunc, argString) { + is(typeof testFunc, 'function'); + var resolvePromise; + var testPromise = new Promise(r => resolvePromise = r); + var finishFuncName = 'finish_' + testFunc.name; + SpecialPowers.Cu.exportFunction(_ => resolvePromise(), sb, + { defineAs: finishFuncName }); + SpecialPowers.Cu.evalInSandbox('(' + testFunc.toSource() + ')' + + '(' + argString + ')' + + '.then(' + finishFuncName + ');', sb); + return testPromise; +} + +var origin = 'https://example.com'; +var properties = ['fetch', 'Blob', 'URL']; +var sb = new SpecialPowers.Cu.Sandbox(origin, + { wantGlobalProperties: properties }); + +sb.ok = SpecialPowers.Cu.exportFunction(ok, sb); +sb.is = SpecialPowers.Cu.exportFunction(is, sb); +sb.info = SpecialPowers.Cu.exportFunction(info, sb); + +Promise.resolve() + .then(_ => runSandboxTest(testHttpFetch, '"' + origin + window.location.pathname + '"')) + .then(_ => runSandboxTest(testAboutURL)) + .then(_ => runSandboxTest(testDataURL)) + .then(_ => runSandboxTest(testSameOriginBlobURL)) + .then(_ => SimpleTest.finish()); + +</script> +</body> +</html>
--- a/js/xpconnect/wrappers/AddonWrapper.cpp +++ b/js/xpconnect/wrappers/AddonWrapper.cpp @@ -27,17 +27,18 @@ InterposeProperty(JSContext* cx, HandleO { // We only want to do interpostion on DOM instances and // wrapped natives. RootedObject unwrapped(cx, UncheckedUnwrap(target)); const js::Class* clasp = js::GetObjectClass(unwrapped); if (!mozilla::dom::IsDOMClass(clasp) && !IS_WN_CLASS(clasp) && !IS_PROTO_CLASS(clasp) && - clasp != &OuterWindowProxyClass) { + clasp != &OuterWindowProxyClass && + !jsipc::IsWrappedCPOW(unwrapped)) { return true; } XPCWrappedNativeScope* scope = ObjectScope(CurrentGlobalOrNull(cx)); MOZ_ASSERT(scope->HasInterposition()); nsCOMPtr<nsIAddonInterposition> interp = scope->GetInterposition(); JSAddonId* addonId = AddonIdOfObject(target);
--- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -2159,17 +2159,17 @@ nsDisplayBackgroundImage::AppendBackgrou } bgItemList.AppendNewToTop( new (aBuilder) nsDisplayBackgroundColor(aBuilder, aFrame, bg, drawBackgroundColor ? color : NS_RGBA(0, 0, 0, 0))); } if (isThemed) { nsITheme* theme = presContext->GetTheme(); - if (theme->NeedToClearBackgroundBehindWidget(aFrame->StyleDisplay()->mAppearance) && + if (theme->NeedToClearBackgroundBehindWidget(aFrame, aFrame->StyleDisplay()->mAppearance) && aBuilder->IsInRootChromeDocumentOrPopup() && !aBuilder->IsInTransform()) { bgItemList.AppendNewToTop( new (aBuilder) nsDisplayClearBackground(aBuilder, aFrame)); } nsDisplayThemedBackground* bgItem = new (aBuilder) nsDisplayThemedBackground(aBuilder, aFrame); bgItemList.AppendNewToTop(bgItem); aList->AppendToTop(&bgItemList); @@ -4691,21 +4691,16 @@ nsDisplayTransform::GetDeltaToTransformO nscoord offset = (index == 0) ? aFrame->GetPosition().x : aFrame->GetPosition().y; coords[index] -= NSAppUnitsToFloatPixels(offset, aAppUnitsPerPixel); } } coords[2] = NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(), aAppUnitsPerPixel); - if (aBoundsOverride) { - // Adjust based on the origin of the override: - coords[0] += NSAppUnitsToFloatPixels(aBoundsOverride->x, aAppUnitsPerPixel); - coords[1] += NSAppUnitsToFloatPixels(aBoundsOverride->y, aAppUnitsPerPixel); - } return Point3D(coords[0], coords[1], coords[2]); } /* Returns the delta specified by the -moz-perspective-origin property. * This is a positive delta, meaning that it indicates the direction to move * to get from (0, 0) of the frame to the perspective origin. This function is * called off the main thread. @@ -4909,16 +4904,27 @@ nsDisplayTransform::GetResultingTransfor Point3D(NSAppUnitsToFloatPixels(aOrigin.x, aAppUnitsPerPixel), NSAppUnitsToFloatPixels(aOrigin.y, aAppUnitsPerPixel), 0.0f); Point3D roundedOrigin(hasSVGTransforms ? newOrigin.x : NS_round(newOrigin.x), hasSVGTransforms ? newOrigin.y : NS_round(newOrigin.y), 0); Point3D offsetBetweenOrigins = roundedOrigin + aProperties.mToTransformOrigin; + if (aOffsetByOrigin) { + // We can fold the final translation by roundedOrigin into the first matrix + // basis change translation. This is more stable against variation due to + // insufficient floating point precision than reversing the translation + // afterwards. + result.Translate(-aProperties.mToTransformOrigin); + result.TranslatePost(offsetBetweenOrigins); + } else { + result.ChangeBasis(offsetBetweenOrigins); + } + if (frame && frame->Preserves3D()) { // Include the transform set on our parent NS_ASSERTION(frame->GetParent() && frame->GetParent()->IsTransformed() && frame->GetParent()->Preserves3DChildren(), "Preserve3D mismatch!"); FrameTransformProperties props(frame->GetParent(), aAppUnitsPerPixel, @@ -4928,37 +4934,19 @@ nsDisplayTransform::GetResultingTransfor // then we're not a reference frame so no offset to origin will be added. Our // parent transform however *is* the reference frame, so we pass true for // aOffsetByOrigin to convert into the correct coordinate space. gfx3DMatrix parent = GetResultingTransformMatrixInternal(props, aOrigin - frame->GetPosition(), aAppUnitsPerPixel, nullptr, aOutAncestor, !frame->IsTransformed()); - - if (aOffsetByOrigin) { - result.Translate(-aProperties.mToTransformOrigin); - result.TranslatePost(offsetBetweenOrigins); - } else { - result.ChangeBasis(offsetBetweenOrigins); - } result = result * parent; - return result; - } - - if (aOffsetByOrigin) { - // We can fold the final translation by roundedOrigin into the first matrix - // basis change translation. This is more stable against variation due to - // insufficient floating point precision than reversing the translation - // afterwards. - result.Translate(-aProperties.mToTransformOrigin); - result.TranslatePost(offsetBetweenOrigins); - } else { - result.ChangeBasis(offsetBetweenOrigins); - } + } + return result; } bool nsDisplayOpacity::CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) { if (ActiveLayerTracker::IsStyleAnimated(aBuilder, mFrame, eCSSProperty_opacity)) { return true;
--- a/layout/mathml/mathml.css +++ b/layout/mathml/mathml.css @@ -6,28 +6,26 @@ /**************************************************************************/ /* namespace for MathML elements */ /**************************************************************************/ @namespace url(http://www.w3.org/1998/Math/MathML); /**************************************************************************/ /* <math> - outermost math element */ -/* Put Cambria before Cambria Math as Cambria Math has neither bold nor */ -/* italic. */ /**************************************************************************/ math { writing-mode: horizontal-tb !important; direction: ltr; unicode-bidi: embed; display: inline; font-size: inherit; font-style: normal; - font-family: MathJax_Main, STIXGeneral, Cambria, Cambria Math, XITS, Latin Modern Math, DejaVu Serif, DejaVu Sans, Times, Lucida Sans Unicode, OpenSymbol, Standard Symbols L, serif; + font-family: serif; text-rendering: optimizeLegibility; -moz-float-edge: margin-box; -moz-math-display: inline; } math[mode="display"], math[display="block"] { display: block; text-align: -moz-center; -moz-math-display: block;
--- a/layout/mathml/nsMathMLChar.cpp +++ b/layout/mathml/nsMathMLChar.cpp @@ -1655,18 +1655,20 @@ nsMathMLChar::StretchInternal(nsPresCont if (!done) { // normal case // Use the css font-family but add preferred fallback fonts. font = mStyleContext->StyleFont()->mFont; NormalizeDefaultFont(font, aFontSizeInflation); // really shouldn't be doing things this way but for now // insert fallbacks into the list - nsAutoTArray<nsString, 10> mathFallbacks; - gfxFontUtils::GetPrefsFontList("font.mathfont-family", mathFallbacks); + nsAutoTArray<nsString, 16> mathFallbacks; + gfxFontUtils::GetPrefsFontList("font.name.serif.x-math", mathFallbacks); + gfxFontUtils::AppendPrefsFontList("font.name-list.serif.x-math", + mathFallbacks); InsertMathFallbacks(font.fontlist, mathFallbacks); #ifdef NOISY_SEARCH nsAutoString fontlistStr; font.fontlist.ToString(fontlistStr, false, true); printf("Searching in "%s" for a glyph of appropriate size for: 0x%04X:%c\n", NS_ConvertUTF16toUTF8(fontlistStr).get(), mData[0], mData[0]&0x00FF);
new file mode 100644 --- /dev/null +++ b/layout/reftests/mathml/default-font-ref.html @@ -0,0 +1,13 @@ +<html> + <head> + <title>default font</title> + <meta charset="utf-8"/> + </head> + <body style="font: 20px monospace;"> + + <math style="font-family: serif; font-size: 40px;"> + <mn>x-math language</mn> + </math> + + </body> +</html>
new file mode 100644 --- /dev/null +++ b/layout/reftests/mathml/default-font.html @@ -0,0 +1,14 @@ +<html> + <head> + <title>default font</title> + <meta charset="utf-8"/> + </head> + <body style="font: 20px monospace;"> + + <!-- font.minimum-size.x-math set to 40 --> + <math> + <mn>x-math language</mn> + </math> + + </body> +</html>
--- a/layout/reftests/mathml/reftest.list +++ b/layout/reftests/mathml/reftest.list @@ -34,17 +34,17 @@ skip-if((B2G&&browserIsRemote)||Mulet) r == mfenced-5b.xhtml mfenced-5-ref.xhtml == mfenced-5c.xhtml mfenced-5-ref.xhtml == mfenced-5d.xhtml mfenced-5-ref.xhtml == mfenced-6.html mfenced-6-ref.html == mfenced-7.html mfenced-7-ref.html != mfenced-8.html mfenced-8-ref.html == mfenced-9.html mfenced-9-ref.html fails-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) == mfenced-10.html mfenced-10-ref.html # Windows versions without Cambria Math, see bug 670592 -fails-if(winWidget&&d2d) == mfenced-11.html mfenced-11-ref.html +== mfenced-11.html mfenced-11-ref.html skip-if(Mulet) == mfenced-12.html mfenced-12-ref.html # MULET: Bug 1144079: Re-enable Mulet mochitests and reftests taskcluster-specific disables == mi-mathvariant-1.xhtml mi-mathvariant-1-ref.xhtml == mi-mathvariant-2.xhtml mi-mathvariant-2-ref.xhtml != mi-mathvariant-3.html mi-mathvariant-3-ref.html != non-spacing-accent-1.xhtml non-spacing-accent-1-ref.xhtml == overbar-width-1.xhtml overbar-width-1-ref.xhtml skip-if(B2G||Mulet) == quotes-1.xhtml quotes-1-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop != stretchy-underbar-1.xhtml stretchy-underbar-1-ref.xhtml @@ -134,19 +134,19 @@ random-if(winWidget&&!/^Windows\x20NT\x2 == mspace-1.html mspace-1-ref.html == mpadded-1.html mpadded-1-ref.html == mpadded-2.html mpadded-2-ref.html == mpadded-3.html mpadded-3-ref.html == mpadded-4.html mpadded-4-ref.html == mpadded-5.html mpadded-5-ref.html == mpadded-1-2.html mpadded-1-2-ref.html == mpadded-6.html mpadded-6-ref.html -fails-if(B2G||Mulet) == mpadded-7.html mpadded-7-ref.html # B2G: slight character width variation # MULET: Bug 1144079: Re-enable Mulet mochitests and reftests taskcluster-specific disables -fails-if(B2G) == mpadded-8.html mpadded-8-ref.html # B2G: slight character width variation -fails-if(B2G) == mpadded-9.html mpadded-9-ref.html # B2G: slight character width variation +fails-if(Mulet) == mpadded-7.html mpadded-7-ref.html # MULET: Bug 1144079: Re-enable Mulet mochitests and reftests taskcluster-specific disables +== mpadded-8.html mpadded-8-ref.html +== mpadded-9.html mpadded-9-ref.html == math-display.html math-display-ref.html == scriptlevel-1.html scriptlevel-1-ref.html == scriptlevel-movablelimits-1.html scriptlevel-movablelimits-1-ref.html == munderover-align-accent-false.html munderover-align-accent-false-ref.html == munderover-align-accent-true.html munderover-align-accent-true-ref.html == munder-mover-align-accent-true.html munder-mover-align-accent-true-ref.html == munder-mover-align-accent-false.html munder-mover-align-accent-false-ref.html == mfrac-linethickness-1.xhtml mfrac-linethickness-1-ref.xhtml @@ -193,17 +193,17 @@ skip-if(B2G||Mulet) == maction-dynamic-3 == whitespace-trim-3.html whitespace-trim-3-ref.html fails == whitespace-trim-4.html whitespace-trim-4-ref.html # Bug 787215 == whitespace-trim-5.html whitespace-trim-5-ref.html random-if(winWidget&&!d2d) == opentype-stretchy.html opentype-stretchy-ref.html == opentype-fraction-dynamic-linethickness.html opentype-fraction-dynamic-linethickness-ref.html == operator-1.xhtml operator-1-ref.xhtml == scriptshift-1.xhtml scriptshift-1-ref.xhtml == number-size-1.xhtml number-size-1-ref.xhtml -random-if((B2G&&browserIsRemote)||Mulet) == multiscripts-1.html multiscripts-1-ref.html # B2G - slight height variation from font metrics # Initial mulet triage: parity with B2G/B2G Desktop +random-if((B2G&&browserIsRemote)||Mulet) fails-if(winWidget&&/^Windows\x20NT\x205\.1/.test(http.oscpu)) == multiscripts-1.html multiscripts-1-ref.html # B2G - slight height variation from font metrics # Initial mulet triage: parity with B2G/B2G Desktop == mathml-mmultiscript-base.html mathml-mmultiscript-base-ref.html == mathml-mmultiscript-mprescript.html mathml-mmultiscript-mprescript-ref.html != menclose-1a.html menclose-1-ref.html != menclose-1b.html menclose-1-ref.html != menclose-1c.html menclose-1-ref.html != menclose-1d.html menclose-1-ref.html != menclose-1e.html menclose-1-ref.html != menclose-1f.html menclose-1-ref.html @@ -340,25 +340,26 @@ fails-if(B2G||Mulet||Android||/^Windows\ == mfrac-A-2.html mfrac-A-2-ref.html == mfrac-A-3.html mfrac-A-3-ref.html == mfrac-A-4.html mfrac-A-4-ref.html == mfrac-A-5.html mfrac-A-5-ref.html == mfrac-A-6.html mfrac-A-6-ref.html == mfrac-A-7.html mfrac-A-7-ref.html == mfrac-A-8.html mfrac-A-8-ref.html == mfrac-B-1.html mfrac-B-1-ref.html -random-if(winWidget&&!/^Windows\x20NT\x205\.1/.test(http.oscpu)) == mfrac-B-2.html mfrac-B-2-3-ref.html -random-if(winWidget&&!/^Windows\x20NT\x205\.1/.test(http.oscpu)) == mfrac-B-3.html mfrac-B-2-3-ref.html +fails-if(winWidget) == mfrac-B-2.html mfrac-B-2-3-ref.html +fails-if(winWidget) == mfrac-B-3.html mfrac-B-2-3-ref.html == mfrac-B-4.html mfrac-B-4-5-ref.html == mfrac-B-5.html mfrac-B-4-5-ref.html == mfrac-B-6.html mfrac-B-6-7-ref.html == mfrac-B-7.html mfrac-B-6-7-ref.html fuzzy-if(OSX,1,100) == mfrac-C-1.html mfrac-C-1-ref.html -random-if(winWidget&&!/^Windows\x20NT\x205\.1/.test(http.oscpu)) == mfrac-C-2.html mfrac-C-2-ref.html +fails-if(winWidget) == mfrac-C-2.html mfrac-C-2-ref.html == mfrac-C-3.html mfrac-C-3-ref.html == mfrac-C-4.html mfrac-C-4-ref.html fuzzy-if(OSX,1,100) == mfrac-D-1.html mfrac-D-1-ref.html -random-if(winWidget&&!/^Windows\x20NT\x205\.1/.test(http.oscpu)) == mfrac-D-2.html mfrac-D-2-ref.html +fails-if(winWidget) == mfrac-D-2.html mfrac-D-2-ref.html == mfrac-D-3.html mfrac-D-3-ref.html == mfrac-D-4.html mfrac-D-4-ref.html == mfrac-E-1.html mfrac-E-1-ref.html test-pref(dom.webcomponents.enabled,true) == shadow-dom-1.html shadow-dom-1-ref.html pref(font.size.inflation.emPerLine,25) == font-inflation-1.html font-inflation-1-ref.html +test-pref(font.minimum-size.x-math,40) == default-font.html default-font-ref.html
--- a/layout/style/TopLevelVideoDocument.css +++ b/layout/style/TopLevelVideoDocument.css @@ -19,13 +19,14 @@ video { position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; max-width: 100%; max-height: 100%; + -moz-user-select: none; } video:focus { outline-width: 0; }
--- a/layout/style/nsHTMLStyleSheet.cpp +++ b/layout/style/nsHTMLStyleSheet.cpp @@ -301,16 +301,23 @@ nsHTMLStyleSheet::RulesMatching(ElementR // http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#language // says that the xml:lang attribute overrides HTML's lang attribute, // so we need to do this after WalkContentStyleRules. nsString lang; if (aData->mElement->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang, lang)) { ruleWalker->Forward(LangRuleFor(lang)); } + + // Set the language to "x-math" on the <math> element, so that appropriate + // font settings are used for MathML. + if (aData->mElement->IsMathMLElement(nsGkAtoms::math)) { + nsGkAtoms::x_math->ToString(lang); + ruleWalker->Forward(LangRuleFor(lang)); + } } // Test if style is dependent on content state /* virtual */ nsRestyleHint nsHTMLStyleSheet::HasStateDependentStyle(StateRuleProcessorData* aData) { if (aData->mElement->IsHTMLElement(nsGkAtoms::a) && nsCSSRuleProcessor::IsLink(aData->mElement) &&
--- a/layout/style/nsHTMLStyleSheet.h +++ b/layout/style/nsHTMLStyleSheet.h @@ -127,16 +127,18 @@ private: virtual void MapRuleInfoInto(nsRuleData* aRuleData) override; }; public: // for mLangRuleTable structures only // Rule to handle xml:lang attributes, of which we have exactly one // per language string, maintained in mLangRuleTable. + // We also create one extra rule for the "x-math" language string, used on + // <math> elements. class LangRule final : public nsIStyleRule { private: ~LangRule() {} public: explicit LangRule(const nsSubstring& aLang) : mLang(aLang) {} NS_DECL_ISUPPORTS
--- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -65,32 +65,25 @@ struct nsTableReflowState { nsSize availSize; // Stationary x-offset nscoord x; // Running y-offset nscoord y; - nsTableReflowState(nsPresContext& aPresContext, - const nsHTMLReflowState& aReflowState, - nsTableFrame& aTableFrame, + nsTableReflowState(const nsHTMLReflowState& aReflowState, nscoord aAvailWidth, nscoord aAvailHeight) : reflowState(aReflowState) { - Init(aPresContext, aTableFrame, aAvailWidth, aAvailHeight); - } - - void Init(nsPresContext& aPresContext, - nsTableFrame& aTableFrame, - nscoord aAvailWidth, - nscoord aAvailHeight) - { - nsTableFrame* table = static_cast<nsTableFrame*>(aTableFrame.FirstInFlow()); + MOZ_ASSERT(reflowState.frame->GetType() == nsGkAtoms::tableFrame, + "nsTableReflowState should only be created for nsTableFrame"); + nsTableFrame* table = + static_cast<nsTableFrame*>(reflowState.frame->FirstInFlow()); nsMargin borderPadding = table->GetChildAreaOffset(&reflowState); x = borderPadding.left + table->GetColSpacing(-1); y = borderPadding.top; //cellspacing added during reflow availSize.width = aAvailWidth; if (NS_UNCONSTRAINEDSIZE != availSize.width) { int32_t colCount = table->GetColCount(); @@ -103,25 +96,16 @@ struct nsTableReflowState { availSize.height = aAvailHeight; if (NS_UNCONSTRAINEDSIZE != availSize.height) { availSize.height -= borderPadding.top + borderPadding.bottom + table->GetRowSpacing(-1) + table->GetRowSpacing(table->GetRowCount()); availSize.height = std::max(0, availSize.height); } } - - nsTableReflowState(nsPresContext& aPresContext, - const nsHTMLReflowState& aReflowState, - nsTableFrame& aTableFrame) - : reflowState(aReflowState) - { - Init(aPresContext, aTableFrame, aReflowState.AvailableWidth(), aReflowState.AvailableHeight()); - } - }; /******************************************************************************** ** nsTableFrame ** ********************************************************************************/ struct BCPropertyData { @@ -2048,17 +2032,17 @@ nsTableFrame::ReflowTable(nsHTMLReflowMe if (!GetPrevInFlow()) { mTableLayoutStrategy->ComputeColumnISizes(aReflowState); } // Constrain our reflow width to the computed table width (of the 1st in flow). // and our reflow height to our avail height minus border, padding, cellspacing aDesiredSize.Width() = aReflowState.ComputedWidth() + aReflowState.ComputedPhysicalBorderPadding().LeftRight(); - nsTableReflowState reflowState(*PresContext(), aReflowState, *this, + nsTableReflowState reflowState(aReflowState, aDesiredSize.Width(), aAvailHeight); ReflowChildren(reflowState, aStatus, aLastChildReflowed, aDesiredSize.mOverflowAreas); ReflowColGroups(aReflowState.rendContext); } nsIFrame*
--- a/memory/mozjemalloc/jemalloc.c +++ b/memory/mozjemalloc/jemalloc.c @@ -5833,21 +5833,16 @@ MALLOC_OUT: /* Take care to call atexit() only once. */ if (opt_print_stats) { #ifndef MOZ_MEMORY_WINDOWS /* Print statistics at exit. */ atexit(malloc_print_stats); #endif } -#if !defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN) - /* Prevent potential deadlock on malloc locks after fork. */ - pthread_atfork(_malloc_prefork, _malloc_postfork, _malloc_postfork); -#endif - #ifndef MALLOC_STATIC_SIZES /* Set variables according to the value of opt_small_max_2pow. */ if (opt_small_max_2pow < opt_quantum_2pow) opt_small_max_2pow = opt_quantum_2pow; small_max = (1U << opt_small_max_2pow); /* Set bin-related variables. */ bin_maxclass = (pagesize >> 1); @@ -6040,16 +6035,21 @@ MALLOC_OUT: #ifdef MALLOC_VALIDATE chunk_rtree = malloc_rtree_new((SIZEOF_PTR << 3) - opt_chunk_2pow); if (chunk_rtree == NULL) return (true); #endif malloc_initialized = true; +#if !defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN) + /* Prevent potential deadlock on malloc locks after fork. */ + pthread_atfork(_malloc_prefork, _malloc_postfork, _malloc_postfork); +#endif + #if defined(NEEDS_PTHREAD_MMAP_UNALIGNED_TSD) if (pthread_key_create(&mmap_unaligned_tsd, NULL) != 0) { malloc_printf("<jemalloc>: Error in pthread_key_create()\n"); } #endif #if defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_REPLACE_MALLOC) /*
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1838,17 +1838,20 @@ pref("intl.hyphenation-alias.bs-*", "sh" // Norwegian has two forms, Bokmål and Nynorsk, with "no" as a macrolanguage encompassing both. // For "no", we'll alias to "nb" (Bokmål) as that is the more widely used written form. pref("intl.hyphenation-alias.no", "nb"); pref("intl.hyphenation-alias.no-*", "nb"); pref("intl.hyphenation-alias.nb-*", "nb"); pref("intl.hyphenation-alias.nn-*", "nn"); -pref("font.mathfont-family", "Latin Modern Math, XITS Math, STIX Math, Cambria Math, Asana Math, TeX Gyre Bonum Math, TeX Gyre Pagella Math, TeX Gyre Termes Math, Neo Euler, Lucida Bright Math, MathJax_Main, STIXNonUnicode, STIXSizeOneSym, STIXGeneral, Standard Symbols L, DejaVu Sans"); +pref("font.name.serif.x-math", "Latin Modern Math"); +pref("font.name-list.serif.x-math", "Latin Modern Math, XITS Math, Cambria Math, TeX Gyre Bonum Math, TeX Gyre Pagella Math, TeX Gyre Schola, TeX Gyre Termes Math, STIX Math, Asana Math, MathJax_Main, STIXGeneral, DejaVu Serif, DejaVu Sans, Standard Symbols L, serif"); +pref("font.name.sans-serif.x-math", "sans-serif"); +pref("font.name.monospace.x-math", "monospace"); // Some CJK fonts have bad underline offset, their CJK character glyphs are overlapped (or adjoined) to its underline. // These fonts are ignored the underline offset, instead of it, the underline is lowered to bottom of its em descent. pref("font.blacklist.underline_offset", "FangSong,Gulim,GulimChe,MingLiU,MingLiU-ExtB,MingLiU_HKSCS,MingLiU-HKSCS-ExtB,MS Gothic,MS Mincho,MS PGothic,MS PMincho,MS UI Gothic,PMingLiU,PMingLiU-ExtB,SimHei,SimSun,SimSun-ExtB,Hei,Kai,Apple LiGothic,Apple LiSung,Osaka"); #ifdef MOZ_B2G // Whitelist of fonts that ship with B2G that do not include space lookups in // default features. This allows us to skip analyzing the GSUB/GPOS tables @@ -2623,16 +2626,20 @@ pref("font.minimum-size.zh-HK", 0); pref("font.size.variable.zh-HK", 16); pref("font.size.fixed.zh-HK", 16); pref("font.default.zh-TW", "sans-serif"); pref("font.minimum-size.zh-TW", 0); pref("font.size.variable.zh-TW", 16); pref("font.size.fixed.zh-TW", 16); +// mathml.css sets font-size to "inherit" and font-family to "serif" so only +// font.name.*.x-math and font.minimum-size.x-math are really relevant. +pref("font.minimum-size.x-math", 0); + /* * A value greater than zero enables font size inflation for * pan-and-zoom UIs, so that the fonts in a block are at least the size * that, if a block's width is scaled to match the device's width, the * fonts in the block are big enough that at most the pref value ems of * text fit in *the width of the device*. * * When both this pref and the next are set, the larger inflation is @@ -2945,18 +2952,22 @@ pref("font.name.sans-serif.x-tibt", "Tib pref("font.name.monospace.x-tibt", "Tibetan Machine Uni"); pref("font.name-list.serif.x-tibt", "Tibetan Machine Uni, Jomolhari, Microsoft Himalaya"); pref("font.name-list.sans-serif.x-tibt", "Tibetan Machine Uni, Jomolhari, Microsoft Himalaya"); pref("font.name-list.monospace.x-tibt", "Tibetan Machine Uni, Jomolhari, Microsoft Himalaya"); pref("font.minimum-size.th", 10); pref("font.default.x-devanagari", "sans-serif"); +pref("font.name.serif.x-math", "Latin Modern Math"); // We have special support for Monotype Symbol on Windows. -pref("font.mathfont-family", "MathJax_Main, STIXNonUnicode, STIXSizeOneSym, STIXGeneral, Asana Math, Symbol, DejaVu Sans, Cambria Math"); +pref("font.name-list.serif.x-math", "Latin Modern Math, XITS Math, Cambria Math, TeX Gyre Bonum Math, TeX Gyre Pagella Math, TeX Gyre Schola, TeX Gyre Termes Math, STIX Math, Asana Math, MathJax_Main, STIXGeneral, DejaVu Serif, DejaVu Sans, Symbol, Times New Roman"); +pref("font.name.sans-serif.x-math", "Arial"); +pref("font.name.monospace.x-math", "Courier New"); +pref("font.name.cursive.x-math", "Comic Sans MS"); // cleartype settings - false implies default system settings // use cleartype rendering for downloadable fonts (win xp only) pref("gfx.font_rendering.cleartype.use_for_downloadable_fonts", true); // use cleartype rendering for all fonts always (win xp only) pref("gfx.font_rendering.cleartype.always_use_for_content", false); @@ -3372,18 +3383,23 @@ pref("font.name-list.sans-serif.zh-HK", pref("font.name-list.monospace.zh-HK", "Courier,Heiti TC,LiHei Pro"); // XP_MACOSX changes to default font sizes pref("font.minimum-size.th", 10); pref("font.size.variable.zh-CN", 15); pref("font.size.variable.zh-HK", 15); pref("font.size.variable.zh-TW", 15); +pref("font.name.serif.x-math", "Latin Modern Math"); // Apple's Symbol is Unicode so use it -pref("font.mathfont-family", "Latin Modern Math, XITS Math, STIX Math, Cambria Math, Asana Math, TeX Gyre Bonum Math, TeX Gyre Pagella Math, TeX Gyre Termes Math, Neo Euler, Lucida Bright Math, MathJax_Main, STIXNonUnicode, STIXSizeOneSym, STIXGeneral, Symbol, DejaVu Sans"); +pref("font.name-list.serif.x-math", "Latin Modern Math, XITS Math, Cambria Math, TeX Gyre Bonum Math, TeX Gyre Pagella Math, TeX Gyre Schola, TeX Gyre Termes Math, STIX Math, Asana Math, MathJax_Main, STIXGeneral, DejaVu Serif, DejaVu Sans, Symbol, Times"); +pref("font.name.sans-serif.x-math", "Helvetica"); +pref("font.name.monospace.x-math", "Courier"); +pref("font.name.cursive.x-math", "Apple Chancery"); +pref("font.name.fantasy.x-math", "Papyrus"); // individual font faces to be treated as independent families // names are Postscript names of each face pref("font.single-face-list", "Osaka-Mono"); // optimization hint for fonts with localized names to be read in at startup, otherwise read in at lookup miss // names are canonical family names (typically English names) pref("font.preload-names-list", "Hiragino Kaku Gothic ProN,Hiragino Mincho ProN,STSong"); @@ -3554,16 +3570,19 @@ pref("print.print_landscape", false); pref("print.print_paper_size", 0); // print_extra_margin enables platforms to specify an extra gap or margin // around the content of the page for Print Preview only pref("print.print_extra_margin", 0); // twips // font names +pref("font.name.serif.ar", "serif"); +pref("font.name.sans-serif.ar", "sans-serif"); +pref("font.name.monospace.ar", "monospace"); pref("font.size.fixed.ar", 12); pref("font.name.serif.el", "serif"); pref("font.name.sans-serif.el", "sans-serif"); pref("font.name.monospace.el", "monospace"); pref("font.size.fixed.el", 12); pref("font.name.serif.he", "serif"); @@ -3576,45 +3595,109 @@ pref("font.name.sans-serif.ja", "sans-se pref("font.name.monospace.ja", "monospace"); pref("font.name.serif.ko", "serif"); pref("font.name.sans-serif.ko", "sans-serif"); pref("font.name.monospace.ko", "monospace"); pref("font.name.serif.th", "serif"); pref("font.name.sans-serif.th", "sans-serif"); +pref("font.name.monospace.th", "monospace"); pref("font.minimum-size.th", 13); -pref("font.name.monospace.th", "monospace"); + +pref("font.name.serif.x-armn", "serif"); +pref("font.name.sans-serif.x-armn", "sans-serif"); +pref("font.name.monospace.x-armn", "monospace"); + +pref("font.name.serif.x-beng", "serif"); +pref("font.name.sans-serif.x-beng", "sans-serif"); +pref("font.name.monospace.x-beng", "monospace"); + +pref("font.name.serif.x-cans", "serif"); +pref("font.name.sans-serif.x-cans", "sans-serif"); +pref("font.name.monospace.x-cans", "monospace"); pref("font.name.serif.x-cyrillic", "serif"); pref("font.name.sans-serif.x-cyrillic", "sans-serif"); pref("font.name.monospace.x-cyrillic", "monospace"); pref("font.size.fixed.x-cyrillic", 12); +pref("font.name.serif.x-devanagari", "serif"); +pref("font.name.sans-serif.x-devanagari", "sans-serif"); +pref("font.name.monospace.x-devanagari", "monospace"); + +pref("font.name.serif.x-ethi", "serif"); +pref("font.name.sans-serif.x-ethi", "sans-serif"); +pref("font.name.monospace.x-ethi", "monospace"); + +pref("font.name.serif.x-geor", "serif"); +pref("font.name.sans-serif.x-geor", "sans-serif"); +pref("font.name.monospace.x-geor", "monospace"); + +pref("font.name.serif.x-gujr", "serif"); +pref("font.name.sans-serif.x-gujr", "sans-serif"); +pref("font.name.monospace.x-gujr", "monospace"); + +pref("font.name.serif.x-guru", "serif"); +pref("font.name.sans-serif.x-guru", "sans-serif"); +pref("font.name.monospace.x-guru", "monospace"); + +pref("font.name.serif.x-khmr", "serif"); +pref("font.name.sans-serif.x-khmr", "sans-serif"); +pref("font.name.monospace.x-khmr", "monospace"); + +pref("font.name.serif.x-knda", "serif"); +pref("font.name.sans-serif.x-knda", "sans-serif"); +pref("font.name.monospace.x-knda", "monospace"); + +pref("font.name.serif.x-mlym", "serif"); +pref("font.name.sans-serif.x-mlym", "sans-serif"); +pref("font.name.monospace.x-mlym", "monospace"); + +pref("font.name.serif.x-orya", "serif"); +pref("font.name.sans-serif.x-orya", "sans-serif"); +pref("font.name.monospace.x-orya", "monospace"); + +pref("font.name.serif.x-sinh", "serif"); +pref("font.name.sans-serif.x-sinh", "sans-serif"); +pref("font.name.monospace.x-sinh", "monospace"); + +pref("font.name.serif.x-tamil", "serif"); +pref("font.name.sans-serif.x-tamil", "sans-serif"); +pref("font.name.monospace.x-tamil", "monospace"); + +pref("font.name.serif.x-telu", "serif"); +pref("font.name.sans-serif.x-telu", "sans-serif"); +pref("font.name.monospace.x-telu", "monospace"); + +pref("font.name.serif.x-tibt", "serif"); +pref("font.name.sans-serif.x-tibt", "sans-serif"); +pref("font.name.monospace.x-tibt", "monospace"); + pref("font.name.serif.x-unicode", "serif"); pref("font.name.sans-serif.x-unicode", "sans-serif"); pref("font.name.monospace.x-unicode", "monospace"); pref("font.size.fixed.x-unicode", 12); pref("font.name.serif.x-western", "serif"); pref("font.name.sans-serif.x-western", "sans-serif"); pref("font.name.monospace.x-western", "monospace"); pref("font.size.fixed.x-western", 12); pref("font.name.serif.zh-CN", "serif"); pref("font.name.sans-serif.zh-CN", "sans-serif"); pref("font.name.monospace.zh-CN", "monospace"); -// ming_uni.ttf (HKSCS-2001) -// http://www.info.gov.hk/digital21/eng/hkscs/download/uime.exe pref("font.name.serif.zh-HK", "serif"); pref("font.name.sans-serif.zh-HK", "sans-serif"); pref("font.name.monospace.zh-HK", "monospace"); -// zh-TW +pref("font.name.serif.zh-TW", "serif"); +pref("font.name.sans-serif.zh-TW", "sans-serif"); +pref("font.name.monospace.zh-TW", "monospace"); /* PostScript print module prefs */ // pref("print.postscript.enabled", true); pref("print.postscript.paper_size", "letter"); pref("print.postscript.orientation", "portrait"); pref("print.postscript.print_command", "lpr ${MOZ_PRINTER_NAME:+-P\"$MOZ_PRINTER_NAME\"}"); // On GTK2 platform, we should use topmost window level for the default window @@ -3727,16 +3810,21 @@ pref("font.name.sans-serif.zh-HK", "Fira pref("font.name.monospace.zh-HK", "Fira Mono"); pref("font.name-list.sans-serif.zh-HK", "Fira Sans,Droid Sans Fallback"); pref("font.name.serif.zh-TW", "Charis SIL Compact"); pref("font.name.sans-serif.zh-TW", "Fira Sans"); pref("font.name.monospace.zh-TW", "Fira Mono"); pref("font.name-list.sans-serif.zh-TW", "Fira Sans,Droid Sans Fallback"); +pref("font.name.serif.x-math", "Latin Modern Math"); +pref("font.name-list.serif.x-math", "Latin Modern Math, XITS Math, Cambria Math, TeX Gyre Bonum Math, TeX Gyre Pagella Math, TeX Gyre Schola, TeX Gyre Termes Math, STIX Math, Asana Math, MathJax_Main, STIXGeneral, DejaVu Serif, DejaVu Sans, Charis SIL Compact"); +pref("font.name.sans-serif.x-math", "Fira Sans"); +pref("font.name.monospace.x-math", "Fira Mono"); + #elif defined(ANDROID) // We use the bundled fonts for Firefox for Android // ar pref("font.name.serif.el", "Droid Serif"); // not Charis SIL Compact, only has a few Greek chars pref("font.name.sans-serif.el", "Clear Sans"); pref("font.name.monospace.el", "Droid Sans Mono"); @@ -3800,16 +3888,21 @@ pref("font.name-list.monospace.zh-HK", " pref("font.name.serif.zh-TW", "Charis SIL Compact"); pref("font.name.sans-serif.zh-TW", "Clear Sans"); pref("font.name.monospace.zh-TW", "Droid Sans Mono"); pref("font.name-list.serif.zh-TW", "Droid Serif, Droid Sans Fallback"); pref("font.name-list.sans-serif.zh-TW", "Roboto, Droid Sans, Noto Sans TC, Noto Sans SC, Droid Sans Fallback"); pref("font.name-list.monospace.zh-TW", "Droid Sans Fallback"); +pref("font.name.serif.x-math", "Latin Modern Math"); +pref("font.name-list.serif.x-math", "Latin Modern Math, XITS Math, Cambria Math, TeX Gyre Bonum Math, TeX Gyre Pagella Math, TeX Gyre Schola, TeX Gyre Termes Math, STIX Math, Asana Math, MathJax_Main, STIXGeneral, DejaVu Serif, DejaVu Sans, Charis SIL Compact"); +pref("font.name.sans-serif.x-math", "Clear Sans"); +pref("font.name.monospace.x-math", "Droid Sans Mono"); + #endif #if OS_ARCH==AIX // Override default Japanese fonts pref("font.name.serif.ja", "dt-interface system-jisx0208.1983-0"); pref("font.name.sans-serif.ja", "dt-interface system-jisx0208.1983-0"); pref("font.name.monospace.ja", "dt-interface user-jisx0208.1983-0");
--- a/mozilla-config.h.in +++ b/mozilla-config.h.in @@ -36,21 +36,18 @@ #pragma clang diagnostic pop #endif /* * Force-include Char16.h in order to define PRUnichar as char16_t everywhere. * Note that this should be the first #include to make sure that prtypes.h does * not attempt to define PRUnichar. This includes the following hunspell-specific * includes. - * - * We don't use this to build elfhack and elf-dynstr-gc since those builds happen - * during the export tier. Also, disable this when building assembly files too. */ -#if !defined(ELFHACK_BUILD) && !defined(__ASSEMBLER__) +#if !defined(__ASSEMBLER__) #include "mozilla/Char16.h" #endif /* * Force-include hunspell_alloc_hooks.h and hunspell_fopen_hooks.h for hunspell, * so that we don't need to modify them directly. * * HUNSPELL_STATIC is defined in extensions/spellcheck/hunspell/src/Makefile.in,
--- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -1227,16 +1227,21 @@ HttpChannelChild::Redirect3Complete() if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, NS_BINDING_ABORTED); if (NS_FAILED(rv)) NS_WARNING("CompleteRedirectSetup failed, HttpChannelChild already open?"); // Release ref to new channel. mRedirectChannelChild = nullptr; + + if (mInterceptListener) { + mInterceptListener->Cleanup(); + mInterceptListener = nullptr; + } } //----------------------------------------------------------------------------- // HttpChannelChild::nsIChildChannel //----------------------------------------------------------------------------- NS_IMETHODIMP HttpChannelChild::ConnectParent(uint32_t id)
--- a/storage/mozStorageAsyncStatementParams.cpp +++ b/storage/mozStorageAsyncStatementParams.cpp @@ -101,25 +101,27 @@ AsyncStatementParams::Resolve(nsIXPConne // prototype chain to be checked for the property. bool resolved = false; bool ok = true; if (JSID_IS_INT(aId)) { uint32_t idx = JSID_TO_INT(aId); // All indexes are good because we don't know how many parameters there // really are. - ok = ::JS_DefineElement(aCtx, scopeObj, idx, JS::UndefinedHandleValue, 0); + ok = ::JS_DefineElement(aCtx, scopeObj, idx, JS::UndefinedHandleValue, + JSPROP_RESOLVING); resolved = true; } else if (JSID_IS_STRING(aId)) { // We are unable to tell if there's a parameter with this name and so // we must assume that there is. This screws the rest of the prototype // chain, but people really shouldn't be depending on this anyways. JS::Rooted<jsid> id(aCtx, aId); - ok = ::JS_DefinePropertyById(aCtx, scopeObj, id, JS::UndefinedHandleValue, 0); + ok = ::JS_DefinePropertyById(aCtx, scopeObj, id, JS::UndefinedHandleValue, + JSPROP_RESOLVING); resolved = true; } *_retval = ok; *aResolvedp = resolved && ok; return NS_OK; }
--- a/storage/mozStorageStatementJSHelper.cpp +++ b/storage/mozStorageStatementJSHelper.cpp @@ -229,17 +229,17 @@ StatementJSHelper::Resolve(nsIXPConnectW bool *_retval) { if (!JSID_IS_STRING(aId)) return NS_OK; JS::RootedObject scope(aCtx, aScopeObj); if (::JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(aId), "step")) { *_retval = ::JS_DefineFunction(aCtx, scope, "step", stepFunc, - 0, 0) != nullptr; + 0, JSPROP_RESOLVING) != nullptr; *aResolvedp = true; return NS_OK; } return NS_OK; } //////////////////////////////////////////////////////////////////////////////// //// StatementJSObjectHolder
--- a/storage/mozStorageStatementParams.cpp +++ b/storage/mozStorageStatementParams.cpp @@ -144,33 +144,35 @@ StatementParams::Resolve(nsIXPConnectWra if (JSID_IS_INT(id)) { uint32_t idx = JSID_TO_INT(id); // Ensure that our index is within range. We do not care about the // prototype chain being checked here. if (idx >= mParamCount) return NS_ERROR_INVALID_ARG; - ok = ::JS_DefineElement(aCtx, scope, idx, JS::UndefinedHandleValue, JSPROP_ENUMERATE); + ok = ::JS_DefineElement(aCtx, scope, idx, JS::UndefinedHandleValue, + JSPROP_ENUMERATE | JSPROP_RESOLVING); resolved = true; } else if (JSID_IS_STRING(id)) { JSString *str = JSID_TO_STRING(id); nsAutoJSString autoStr; if (!autoStr.init(aCtx, str)) { return NS_ERROR_FAILURE; } // Check to see if there's a parameter with this name, and if not, let // the rest of the prototype chain be checked. NS_ConvertUTF16toUTF8 name(autoStr); uint32_t idx; nsresult rv = mStatement->GetParameterIndex(name, &idx); if (NS_SUCCEEDED(rv)) { - ok = ::JS_DefinePropertyById(aCtx, scope, id, JS::UndefinedHandleValue, JSPROP_ENUMERATE); + ok = ::JS_DefinePropertyById(aCtx, scope, id, JS::UndefinedHandleValue, + JSPROP_ENUMERATE | JSPROP_RESOLVING); resolved = true; } } *_retval = ok; *resolvedp = resolved && ok; return NS_OK; }
--- a/storage/mozStorageStatementRow.cpp +++ b/storage/mozStorageStatementRow.cpp @@ -137,17 +137,18 @@ StatementRow::Resolve(nsIXPConnectWrappe // It's highly likely that the name doesn't exist, so let the JS engine // check the prototype chain and throw if that doesn't have the property // either. *aResolvedp = false; return NS_OK; } JS::Rooted<jsid> id(aCtx, aId); - *_retval = ::JS_DefinePropertyById(aCtx, scopeObj, id, JS::UndefinedHandleValue, 0); + *_retval = ::JS_DefinePropertyById(aCtx, scopeObj, id, JS::UndefinedHandleValue, + JSPROP_RESOLVING); *aResolvedp = true; return NS_OK; } return NS_OK; } } // namespace storage
new file mode 100644 --- /dev/null +++ b/testing/docker/desktop-build/REGISTRY @@ -0,0 +1,1 @@ +quay.io/djmitche
--- a/testing/docker/desktop-build/VERSION +++ b/testing/docker/desktop-build/VERSION @@ -1,1 +1,1 @@ -0.0.7 +0.0.11
--- a/testing/docker/desktop-build/bin/build.sh +++ b/testing/docker/desktop-build/bin/build.sh @@ -65,17 +65,17 @@ tc-vcs checkout mozharness $MOZHARNESS_B # check out tools where mozharness expects it to be ($PWD/build/tools and $WORKSPACE/build/tools) tc-vcs checkout $WORKSPACE/build/tools $TOOLS_BASE_REPOSITORY $TOOLS_HEAD_REPOSITORY $TOOLS_REV if [ ! -d build ]; then mkdir -p build ln -s $WORKSPACE/build/tools build/tools fi # and check out mozilla-central where mozharness will use it as a cache (/builds/hg-shared) -tc-vcs checkout /builds/hg-shared/mozilla-central $GECKO_BASE_REPOSITORY $GECKO_HEAD_REPOSITORY $GECKO_REV +tc-vcs checkout $WORKSPACE/build/src $GECKO_BASE_REPOSITORY $GECKO_HEAD_REPOSITORY $GECKO_REV # run mozharness in XVfb, if necessary; this is an array to maintain the quoting in the -s argument if $NEED_XVFB; then # Some mozharness scripts set DISPLAY=:2 Xvfb :2 -screen 0 1024x768x24 & export DISPLAY=:2 xvfb_pid=$! # Only error code 255 matters, because it signifies that no @@ -126,21 +126,25 @@ set -x export TOOLTOOL_CACHE # support multiple, space delimited, config files config_cmds="" for cfg in $MOZHARNESS_CONFIG; do config_cmds="${config_cmds} --config ${cfg}" done +# Mozharness would ordinarily do the checkouts itself, but they are disabled +# here (--no-checkout-sources, --no-clone-tools) as the checkout is performed above. + ./${MOZHARNESS_SCRIPT} ${config_cmds} \ $debug_flag \ $custom_build_variant_cfg_flag \ --disable-mock \ --no-setup-mock \ + --no-checkout-sources \ --no-clone-tools \ --no-clobber \ --no-update \ --log-level=debug \ --work-dir=$WORKSPACE/build \ --no-action=generate-build-stats \ --branch=${MH_BRANCH} \ --build-pool=${MH_BUILD_POOL}
new file mode 100644 --- /dev/null +++ b/testing/docker/ubuntu-build/REPOSITORY @@ -0,0 +1,1 @@ +quay.io/djmitche
--- a/testing/taskcluster/tasks/branches/base_job_flags.yml +++ b/testing/taskcluster/tasks/branches/base_job_flags.yml @@ -20,16 +20,17 @@ flags: - flame-kk # b2g flame kitkat - flame-kk-eng # b2g flame eng build - dolphin - dolphin-eng - dolphin-512 - dolphin-512-eng - aries-nightly - aries-eng + - android-api-11 tests: - cppunit - crashtest - crashtest-ipc - gaia-build - gaia-build-unit - gaia-js-integration
--- a/testing/taskcluster/tasks/branches/try/job_flags.yml +++ b/testing/taskcluster/tasks/branches/try/job_flags.yml @@ -95,16 +95,22 @@ builds: opt: task: tasks/builds/b2g_dolphin_512_opt.yml dolphin-512-eng: platforms: - b2g types: opt: task: tasks/builds/b2g_dolphin_512_eng.yml + android-api-11: + platforms: + - Android + types: + opt: + task: tasks/builds/android_api_11.yml tests: cppunit: allowed_build_tasks: tasks/builds/b2g_emulator_ics_opt.yml: task: tasks/tests/b2g_emulator_cpp_unit.yml tasks/builds/b2g_emulator_ics_debug.yml: task: tasks/tests/b2g_emulator_cpp_unit.yml
new file mode 100644 --- /dev/null +++ b/testing/taskcluster/tasks/builds/android_api_11.yml @@ -0,0 +1,62 @@ +$inherits: + from: 'tasks/build.yml' + variables: + build_name: 'android' + build_type: 'opt' +task: + metadata: + name: '[TC] Android armv7 API 11+' + description: 'Android armv7 API 11+' + + workerType: b2g-desktop-opt + + routes: + - 'index.buildbot.branches.{{project}}.android-api-11' + - 'index.buildbot.revisions.{{head_rev}}.{{project}}.android-api-11' + + scopes: + - 'docker-worker:cache:build-android-api-11-workspace' + - 'docker-worker:cache:tooltool-cache' + + payload: + image: '{{#docker_image}}desktop-build{{/docker_image}}' + cache: + build-android-api-11-workspace: '/home/worker/workspace' + tooltool-cache: '/home/worker/tools/tooltool-cache' + + env: + # 1164623: rename this var + GECKO_REV: '{{head_rev}}' + # 1164623: rename these three vars + MOZHARNESS_BASE_REPOSITORY: '{{mozharness_repository}}' + MOZHARNESS_HEAD_REPOSITORY: '{{mozharness_repository}}' + MOZHARNESS_REV: '{{mozharness_rev}}' + + MOZHARNESS_SCRIPT: 'mozharness/scripts/fx_desktop_build.py' + MOZHARNESS_CONFIG: 'builds/releng_base_android_64_builds.py' + MH_CUSTOM_BUILD_VARIANT_CFG: api-11 + MH_BRANCH: {{project}} + MH_BUILD_POOL: taskcluster + + TOOLTOOL_CACHE: '/home/worker/tooltool-cache' + RELENGAPI_TOKEN: 'TODO' # 1164612: encrypt this secret + + maxRunTime: 36000 + + command: ["/bin/bash", "bin/build.sh"] + + extra: + treeherderEnv: + - production + - staging + treeherder: + machine: + # see https://github.com/mozilla/treeherder/blob/master/ui/js/values.js + platform: android-4-0-armv7-api11 + # Rather then enforcing particular conventions we require that all build + # tasks provide the "build" extra field to specify where the build and tests + # files are located. + locations: + build: 'public/build/target.linux-x86_64.tar.bz2' + tests: 'public/build/target.tests.zip' +
--- a/toolkit/components/addoncompat/tests/addon/bootstrap.js +++ b/toolkit/components/addoncompat/tests/addon/bootstrap.js @@ -533,16 +533,67 @@ function testProgressListener() gBrowser.removeTab(tab); gBrowser.removeProgressListener(globalListener); gBrowser.removeTabsProgressListener(tabsListener); resolve(); }); }); } +function testRootTreeItem() +{ + return new Promise(function(resolve, reject) { + const url = baseURL + "browser_addonShims_testpage.html"; + let tab = gBrowser.addTab(url); + gBrowser.selectedTab = tab; + let browser = tab.linkedBrowser; + addLoadListener(browser, function handler() { + let win = browser.contentWindow; + + // Add-ons love this crap. + let root = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIWebNavigation) + .QueryInterface(Components.interfaces.nsIDocShellTreeItem) + .rootTreeItem + .QueryInterface(Components.interfaces.nsIInterfaceRequestor) + .getInterface(Components.interfaces.nsIDOMWindow); + is(root, gWin, "got correct chrome window"); + + gBrowser.removeTab(tab); + resolve(); + }); + }); +} + +function testImportNode() +{ + return new Promise(function(resolve, reject) { + const url = baseURL + "browser_addonShims_testpage.html"; + let tab = gBrowser.addTab(url); + gBrowser.selectedTab = tab; + let browser = tab.linkedBrowser; + addLoadListener(browser, function handler() { + let node = gWin.document.createElement("div"); + let doc = browser.contentDocument; + let result; + try { + result = doc.importNode(node, false); + } catch (e) { + ok(false, "importing threw an exception"); + } + if (browser.isRemoteBrowser) { + is(result, node, "got expected import result"); + } + + gBrowser.removeTab(tab); + resolve(); + }); + }); +} + function runTests(win, funcs) { ok = funcs.ok; is = funcs.is; info = funcs.info; gWin = win; gBrowser = win.gBrowser; @@ -550,16 +601,18 @@ function runTests(win, funcs) return testContentWindow(). then(testListeners). then(testCapturing). then(testObserver). then(testSandbox). then(testAddonContent). then(testAboutModuleRegistration). then(testProgressListener). + then(testRootTreeItem). + then(testImportNode). then(Promise.resolve()); } /* bootstrap.js API */ function startup(aData, aReason)
--- a/toolkit/content/editMenuOverlay.js +++ b/toolkit/content/editMenuOverlay.js @@ -12,18 +12,17 @@ function goUpdateGlobalEditMenuItems() // cut, copy, and paste buttons been added to the toolbars) for performance. // This only works in applications/on platforms that set the gEditUIVisible // flag, so we check to see if that flag is defined before using it. if (typeof gEditUIVisible != "undefined" && !gEditUIVisible) return; goUpdateCommand("cmd_undo"); goUpdateCommand("cmd_redo"); - goUpdateCommand("cmd_cut"); - goUpdateCommand("cmd_copy"); + // don't update the cmd_cut or cmd_copy items - as we want them to always be enabled goUpdateCommand("cmd_paste"); goUpdateCommand("cmd_selectAll"); goUpdateCommand("cmd_delete"); goUpdateCommand("cmd_switchTextDirection"); } // update menu items that relate to undo/redo function goUpdateUndoEditMenuItems()
--- a/toolkit/content/globalOverlay.js +++ b/toolkit/content/globalOverlay.js @@ -88,17 +88,17 @@ function goUpdateCommand(aCommand) } } function goDoCommand(aCommand) { try { var controller = top.document.commandDispatcher .getControllerForCommand(aCommand); - if (controller && controller.isCommandEnabled(aCommand)) + if (controller) controller.doCommand(aCommand); } catch (e) { Components.utils.reportError("An error occurred executing the " + aCommand + " command: " + e); } }
--- a/toolkit/content/tests/chrome/bug366992_window.xul +++ b/toolkit/content/tests/chrome/bug366992_window.xul @@ -14,44 +14,44 @@ height="600" title="366992 test"> <commandset id="editMenuCommands"/> <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/> <script type="application/javascript"><![CDATA[ - // Without the fix for bug 366992, the copy command would be enabled + // Without the fix for bug 366992, the delete command would be enabled // for the textbox even though the textbox's controller for this command // disables it. var gShouldNotBeReachedController = { supportsCommand: function(aCommand) { - return aCommand == "cmd_copy"; + return aCommand == "cmd_delete"; }, isCommandEnabled: function(aCommand) { - return aCommand == "cmd_copy"; + return aCommand == "cmd_delete"; }, doCommand: function(aCommand) { } } function ok(condition, message) { window.opener.wrappedJSObject.SimpleTest.ok(condition, message); } function finish() { window.controllers.removeController(gShouldNotBeReachedController); window.close(); window.opener.wrappedJSObject.SimpleTest.finish(); } function onLoad() { document.getElementById("textbox").focus(); - var copyDisabled = document.getElementById("cmd_copy") - .getAttribute("disabled") == "true"; - ok(copyDisabled, - "cmd_copy should be disabled when the empty textbox is focused"); + var deleteDisabled = document.getElementById("cmd_delete") + .getAttribute("disabled") == "true"; + ok(deleteDisabled, + "cmd_delete should be disabled when the empty textbox is focused"); finish(); } window.controllers.appendController(gShouldNotBeReachedController); ]]></script> <textbox id="textbox"/> </window>
--- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -224,17 +224,17 @@ PuppetWidget::Resize(double aWidth, return NS_OK; } nsresult PuppetWidget::ConfigureChildren(const nsTArray<Configuration>& aConfigurations) { for (uint32_t i = 0; i < aConfigurations.Length(); ++i) { const Configuration& configuration = aConfigurations[i]; - PuppetWidget* w = static_cast<PuppetWidget*>(configuration.mChild); + PuppetWidget* w = static_cast<PuppetWidget*>(configuration.mChild.get()); NS_ASSERTION(w->GetParent() == this, "Configured widget is not a child"); w->SetWindowClipRegion(configuration.mClipRegion, true); nsIntRect bounds; w->GetBounds(bounds); if (bounds.Size() != configuration.mBounds.Size()) { w->Resize(configuration.mBounds.x, configuration.mBounds.y, configuration.mBounds.width, configuration.mBounds.height,
--- a/widget/TextEvents.h +++ b/widget/TextEvents.h @@ -543,16 +543,21 @@ public: } bool mSucceeded; bool mWasAsync; bool mUseNativeLineBreak; bool mWithFontRanges; struct { + uint32_t EndOffset() const + { + return mOffset + mLength; + } + uint32_t mOffset; uint32_t mLength; } mInput; struct Reply { void* mContentsRoot; uint32_t mOffset;
--- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -275,17 +275,17 @@ nsWindow::Destroy(void) return NS_OK; } NS_IMETHODIMP nsWindow::ConfigureChildren(const nsTArray<nsIWidget::Configuration>& config) { for (uint32_t i = 0; i < config.Length(); ++i) { - nsWindow *childWin = (nsWindow*) config[i].mChild; + nsWindow *childWin = (nsWindow*) config[i].mChild.get(); childWin->Resize(config[i].mBounds.x, config[i].mBounds.y, config[i].mBounds.width, config[i].mBounds.height, false); } return NS_OK;
--- a/widget/cocoa/VibrancyManager.h +++ b/widget/cocoa/VibrancyManager.h @@ -21,17 +21,18 @@ class nsIntRegion; namespace mozilla { enum class VibrancyType { LIGHT, DARK, TOOLTIP, MENU, - HIGHLIGHTED_MENUITEM + HIGHLIGHTED_MENUITEM, + SHEET }; /** * VibrancyManager takes care of updating the vibrant regions of a window. * Vibrancy is a visual look that was introduced on OS X starting with 10.10. * An app declares vibrant window regions to the window server, and the window * server will display a blurred rendering of the screen contents from behind * the window in these areas, behind the actual window contents. Consequently,
--- a/widget/cocoa/VibrancyManager.mm +++ b/widget/cocoa/VibrancyManager.mm @@ -185,16 +185,17 @@ static id AppearanceForVibrancyType(VibrancyType aType) { Class NSAppearanceClass = NSClassFromString(@"NSAppearance"); switch (aType) { case VibrancyType::LIGHT: case VibrancyType::TOOLTIP: case VibrancyType::MENU: case VibrancyType::HIGHLIGHTED_MENUITEM: + case VibrancyType::SHEET: return [NSAppearanceClass performSelector:@selector(appearanceNamed:) withObject:@"NSAppearanceNameVibrantLight"]; case VibrancyType::DARK: return [NSAppearanceClass performSelector:@selector(appearanceNamed:) withObject:@"NSAppearanceNameVibrantDark"]; } } @@ -212,18 +213,20 @@ enum { static NSUInteger VisualEffectStateForVibrancyType(VibrancyType aType) { switch (aType) { case VibrancyType::TOOLTIP: case VibrancyType::MENU: case VibrancyType::HIGHLIGHTED_MENUITEM: - // Tooltip and menu windows are never "key", so we need to tell the - // vibrancy effect to look active regardless of window state. + case VibrancyType::SHEET: + // Tooltip and menu windows are never "key" and sheets always looks + // active, so we need to tell the vibrancy effect to look active + // regardless of window state. return NSVisualEffectStateActive; default: return NSVisualEffectStateFollowsWindowActiveState; } } static BOOL HasVibrantForeground(VibrancyType aType)
--- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -2490,35 +2490,38 @@ static void MakeRegionsNonOverlapping(Re void nsChildView::UpdateVibrancy(const nsTArray<ThemeGeometry>& aThemeGeometries) { if (!VibrancyManager::SystemSupportsVibrancy()) { return; } + nsIntRegion sheetRegion = + GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeSheet); nsIntRegion vibrantLightRegion = GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeVibrancyLight); nsIntRegion vibrantDarkRegion = GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeVibrancyDark); nsIntRegion menuRegion = GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeMenu); nsIntRegion tooltipRegion = GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeTooltip); nsIntRegion highlightedMenuItemRegion = GatherThemeGeometryRegion(aThemeGeometries, nsNativeThemeCocoa::eThemeGeometryTypeHighlightedMenuItem); - MakeRegionsNonOverlapping(vibrantLightRegion, vibrantDarkRegion, menuRegion, - tooltipRegion, highlightedMenuItemRegion); + MakeRegionsNonOverlapping(sheetRegion, vibrantLightRegion, vibrantDarkRegion, + menuRegion, tooltipRegion, highlightedMenuItemRegion); auto& vm = EnsureVibrancyManager(); vm.UpdateVibrantRegion(VibrancyType::LIGHT, vibrantLightRegion); vm.UpdateVibrantRegion(VibrancyType::TOOLTIP, tooltipRegion); vm.UpdateVibrantRegion(VibrancyType::MENU, menuRegion); vm.UpdateVibrantRegion(VibrancyType::HIGHLIGHTED_MENUITEM, highlightedMenuItemRegion); + vm.UpdateVibrantRegion(VibrancyType::SHEET, sheetRegion); vm.UpdateVibrantRegion(VibrancyType::DARK, vibrantDarkRegion); } void nsChildView::ClearVibrantAreas() { if (VibrancyManager::SystemSupportsVibrancy()) { EnsureVibrancyManager().ClearVibrantAreas(); @@ -2534,16 +2537,18 @@ ThemeGeometryTypeToVibrancyType(nsITheme case nsNativeThemeCocoa::eThemeGeometryTypeVibrancyDark: return VibrancyType::DARK; case nsNativeThemeCocoa::eThemeGeometryTypeTooltip: return VibrancyType::TOOLTIP; case nsNativeThemeCocoa::eThemeGeometryTypeMenu: return VibrancyType::MENU; case nsNativeThemeCocoa::eThemeGeometryTypeHighlightedMenuItem: return VibrancyType::HIGHLIGHTED_MENUITEM; + case nsNativeThemeCocoa::eThemeGeometryTypeSheet: + return VibrancyType::SHEET; default: MOZ_CRASH(); } } NSColor* nsChildView::VibrancyFillColorForThemeGeometryType(nsITheme::ThemeGeometryType aThemeGeometryType) {
--- a/widget/cocoa/nsNativeThemeCocoa.h +++ b/widget/cocoa/nsNativeThemeCocoa.h @@ -34,16 +34,17 @@ public: eThemeGeometryTypeToolbox, eThemeGeometryTypeWindowButtons, eThemeGeometryTypeFullscreenButton, eThemeGeometryTypeMenu, eThemeGeometryTypeHighlightedMenuItem, eThemeGeometryTypeVibrancyLight, eThemeGeometryTypeVibrancyDark, eThemeGeometryTypeTooltip, + eThemeGeometryTypeSheet, }; nsNativeThemeCocoa(); NS_DECL_ISUPPORTS_INHERITED // The nsITheme interface. NS_IMETHOD DrawWidgetBackground(nsRenderingContext* aContext, @@ -70,17 +71,18 @@ public: NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, nsIAtom* aAttribute, bool* aShouldRepaint) override; NS_IMETHOD ThemeChanged() override; bool ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* aFrame, uint8_t aWidgetType) override; bool WidgetIsContainer(uint8_t aWidgetType) override; bool ThemeDrawsFocusForWidget(uint8_t aWidgetType) override; bool ThemeNeedsComboboxDropmarker() override; virtual bool WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType) override; - virtual bool NeedToClearBackgroundBehindWidget(uint8_t aWidgetType) override; + virtual bool NeedToClearBackgroundBehindWidget(nsIFrame* aFrame, + uint8_t aWidgetType) override; virtual bool WidgetProvidesFontSmoothingBackgroundColor(nsIFrame* aFrame, uint8_t aWidgetType, nscolor* aColor) override; virtual ThemeGeometryType ThemeGeometryTypeForWidget(nsIFrame* aFrame, uint8_t aWidgetType) override; virtual Transparency GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType) override; void DrawProgress(CGContextRef context, const HIRect& inBoxRect, bool inIsIndeterminate, bool inIsHorizontal, @@ -91,16 +93,17 @@ public: protected: virtual ~nsNativeThemeCocoa(); nsIntMargin DirectionAwareMargin(const nsIntMargin& aMargin, nsIFrame* aFrame); nsIFrame* SeparatorResponsibility(nsIFrame* aBefore, nsIFrame* aAfter); CGRect SeparatorAdjustedRect(CGRect aRect, nsIFrame* aLeft, nsIFrame* aCurrent, nsIFrame* aRight); + bool IsWindowSheet(nsIFrame* aFrame); // HITheme drawing routines void DrawFrame(CGContextRef context, HIThemeFrameKind inKind, const HIRect& inBoxRect, bool inReadOnly, mozilla::EventStates inState); void DrawMeter(CGContextRef context, const HIRect& inBoxRect, nsIFrame* aFrame); void DrawSegment(CGContextRef cgContext, const HIRect& inBoxRect,
--- a/widget/cocoa/nsNativeThemeCocoa.mm +++ b/widget/cocoa/nsNativeThemeCocoa.mm @@ -2393,18 +2393,29 @@ nsNativeThemeCocoa::DrawWidgetBackground //CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 1.0, 0.1); //CGContextFillRect(cgContext, bounds); #endif EventStates eventState = GetContentState(aFrame, aWidgetType); switch (aWidgetType) { case NS_THEME_DIALOG: { - HIThemeSetFill(kThemeBrushDialogBackgroundActive, NULL, cgContext, HITHEME_ORIENTATION); - CGContextFillRect(cgContext, macRect); + if (IsWindowSheet(aFrame)) { + if (VibrancyManager::SystemSupportsVibrancy()) { + ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); + DrawVibrancyBackground(cgContext, macRect, aFrame, type); + } else { + HIThemeSetFill(kThemeBrushSheetBackgroundTransparent, NULL, cgContext, HITHEME_ORIENTATION); + CGContextFillRect(cgContext, macRect); + } + } else { + HIThemeSetFill(kThemeBrushDialogBackgroundActive, NULL, cgContext, HITHEME_ORIENTATION); + CGContextFillRect(cgContext, macRect); + } + } break; case NS_THEME_MENUPOPUP: if (VibrancyManager::SystemSupportsVibrancy()) { DrawVibrancyBackground(cgContext, macRect, aFrame, eThemeGeometryTypeMenu, 4); } else { HIThemeMenuDrawInfo mdi; @@ -3762,26 +3773,41 @@ nsNativeThemeCocoa::WidgetAppearanceDepe case NS_THEME_RESIZER: return false; default: return true; } } bool -nsNativeThemeCocoa::NeedToClearBackgroundBehindWidget(uint8_t aWidgetType) +nsNativeThemeCocoa::IsWindowSheet(nsIFrame* aFrame) +{ + NSWindow* win = NativeWindowForFrame(aFrame); + id winDelegate = [win delegate]; + nsIWidget* widget = [(WindowDelegate *)winDelegate geckoWidget]; + if (!widget) { + return false; + } + return (widget->WindowType() == eWindowType_sheet); +} + +bool +nsNativeThemeCocoa::NeedToClearBackgroundBehindWidget(nsIFrame* aFrame, + uint8_t aWidgetType) { switch (aWidgetType) { case NS_THEME_MAC_VIBRANCY_LIGHT: case NS_THEME_MAC_VIBRANCY_DARK: case NS_THEME_TOOLTIP: case NS_THEME_MENUPOPUP: case NS_THEME_MENUITEM: case NS_THEME_CHECKMENUITEM: return true; + case NS_THEME_DIALOG: + return IsWindowSheet(aFrame); default: return false; } } static nscolor ConvertNSColor(NSColor* aColor) { NSColor* deviceColor = [aColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]; @@ -3798,17 +3824,21 @@ nsNativeThemeCocoa::WidgetProvidesFontSm { switch (aWidgetType) { case NS_THEME_MAC_VIBRANCY_LIGHT: case NS_THEME_MAC_VIBRANCY_DARK: case NS_THEME_TOOLTIP: case NS_THEME_MENUPOPUP: case NS_THEME_MENUITEM: case NS_THEME_CHECKMENUITEM: + case NS_THEME_DIALOG: { + if (aWidgetType == NS_THEME_DIALOG && !IsWindowSheet(aFrame)) { + return false; + } ChildView* childView = ChildViewForFrame(aFrame); if (childView) { ThemeGeometryType type = ThemeGeometryTypeForWidget(aFrame, aWidgetType); NSColor* color = [childView vibrancyFontSmoothingBackgroundColorForThemeGeometryType:type]; *aColor = ConvertNSColor(color); return true; } return false; @@ -3843,29 +3873,34 @@ nsNativeThemeCocoa::ThemeGeometryTypeFor return eThemeGeometryTypeMenu; case NS_THEME_MENUITEM: case NS_THEME_CHECKMENUITEM: { EventStates eventState = GetContentState(aFrame, aWidgetType); bool isDisabled = IsDisabled(aFrame, eventState); bool isSelected = !isDisabled && CheckBooleanAttr(aFrame, nsGkAtoms::menuactive); return isSelected ? eThemeGeometryTypeHighlightedMenuItem : eThemeGeometryTypeMenu; } + case NS_THEME_DIALOG: + return IsWindowSheet(aFrame) ? eThemeGeometryTypeSheet : eThemeGeometryTypeUnknown; default: return eThemeGeometryTypeUnknown; } } nsITheme::Transparency nsNativeThemeCocoa::GetWidgetTransparency(nsIFrame* aFrame, uint8_t aWidgetType) { switch (aWidgetType) { case NS_THEME_MENUPOPUP: case NS_THEME_TOOLTIP: return eTransparent; + case NS_THEME_DIALOG: + return IsWindowSheet(aFrame) ? eTransparent : eOpaque; + case NS_THEME_SCROLLBAR_SMALL: case NS_THEME_SCROLLBAR: return nsLookAndFeel::UseOverlayScrollbars() ? eTransparent : eOpaque; case NS_THEME_STATUSBAR: // Knowing that scrollbars and statusbars are opaque improves // performance, because we create layers for them. return eOpaque;
--- a/widget/gonk/HwcComposer2D.cpp +++ b/widget/gonk/HwcComposer2D.cpp @@ -853,21 +853,17 @@ HwcComposer2D::Commit() if (mHwcLayerMap.IsEmpty() || (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER)) { continue; } LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState(); if (!state.mTexture) { continue; } - TextureHostOGL* texture = state.mTexture->AsHostOGL(); - if (!texture) { - continue; - } - FenceHandle fence = texture->GetAndResetAcquireFence(); + FenceHandle fence = state.mTexture->GetAndResetAcquireFenceHandle(); if (fence.IsValid()) { nsRefPtr<FenceHandle::FdObj> fdObj = fence.GetAndResetFdObj(); mList->hwLayers[j].acquireFenceFd = fdObj->GetAndResetFd(); } } int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays); @@ -879,21 +875,17 @@ HwcComposer2D::Commit() mList->hwLayers[j].releaseFenceFd = -1; nsRefPtr<FenceHandle::FdObj> fdObj = new FenceHandle::FdObj(fd); FenceHandle fence(fdObj); LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState(); if (!state.mTexture) { continue; } - TextureHostOGL* texture = state.mTexture->AsHostOGL(); - if (!texture) { - continue; - } - texture->SetReleaseFence(fence); + state.mTexture->SetReleaseFenceHandle(fence); } } if (mList->retireFenceFd >= 0) { mPrevRetireFence = FenceHandle(new FenceHandle::FdObj(mList->retireFenceFd)); } mPrepared = false;
--- a/widget/gtk/mozgtk/mozgtk.c +++ b/widget/gtk/mozgtk/mozgtk.c @@ -204,16 +204,17 @@ STUB(gtk_file_chooser_set_current_folder STUB(gtk_file_chooser_set_current_name) STUB(gtk_file_chooser_set_do_overwrite_confirmation) STUB(gtk_file_chooser_set_filename) STUB(gtk_file_chooser_set_filter) STUB(gtk_file_chooser_set_local_only) STUB(gtk_file_chooser_set_preview_widget) STUB(gtk_file_chooser_set_preview_widget_active) STUB(gtk_file_chooser_set_select_multiple) +STUB(gtk_file_chooser_widget_get_type) STUB(gtk_file_filter_add_pattern) STUB(gtk_file_filter_new) STUB(gtk_file_filter_set_name) STUB(gtk_fixed_new) STUB(gtk_frame_new) STUB(gtk_grab_add) STUB(gtk_grab_remove) STUB(gtk_handle_box_new)
--- a/widget/gtk/nsFilePicker.cpp +++ b/widget/gtk/nsFilePicker.cpp @@ -160,17 +160,18 @@ MakeCaseInsensitiveShellGlob(const char* return result; } NS_IMPL_ISUPPORTS(nsFilePicker, nsIFilePicker) nsFilePicker::nsFilePicker() : mSelectedType(0), mRunning(false), - mAllowURLs(false) + mAllowURLs(false), + mFileChooserDelegate(nullptr) { } nsFilePicker::~nsFilePicker() { } void @@ -426,16 +427,37 @@ nsFilePicker::Open(nsIFilePickerShownCal // directories. defaultPath->AppendNative(defaultName); nsAutoCString path; defaultPath->GetNativePath(path); gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(file_chooser), path.get()); } else { nsAutoCString directory; defaultPath->GetNativePath(directory); + +#if (MOZ_WIDGET_GTK == 3) + // Workaround for problematic refcounting in GTK3 before 3.16. + // We need to keep a reference to the dialog's internal delegate. + // Otherwise, if our dialog gets destroyed, we'll lose the dialog's + // delegate by the time this gets processed in the event loop. + // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1166741 + GtkDialog *dialog = GTK_DIALOG(file_chooser); + GtkContainer *area = GTK_CONTAINER(gtk_dialog_get_content_area(dialog)); + gtk_container_forall(area, [](GtkWidget *widget, + gpointer data) { + if (GTK_IS_FILE_CHOOSER_WIDGET(widget)) { + auto result = static_cast<GtkFileChooserWidget**>(data); + *result = GTK_FILE_CHOOSER_WIDGET(widget); + } + }, &mFileChooserDelegate); + + if (mFileChooserDelegate) + g_object_ref(mFileChooserDelegate); +#endif + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_chooser), directory.get()); } } gtk_dialog_set_default_response(GTK_DIALOG(file_chooser), GTK_RESPONSE_ACCEPT); int32_t count = mFilters.Length(); @@ -543,16 +565,31 @@ nsFilePicker::Done(GtkWidget* file_choos // When response_id is GTK_RESPONSE_DELETE_EVENT or when called from // OnDestroy, the widget would be destroyed anyway but it is fine if // gtk_widget_destroy is called more than once. gtk_widget_destroy has // requests that any remaining references be released, but the reference // count will not be decremented again if GtkWindow's reference has already // been released. gtk_widget_destroy(file_chooser); +#if (MOZ_WIDGET_GTK == 3) + if (mFileChooserDelegate) { + // Properly deref our acquired reference. We call this after + // gtk_widget_destroy() to try and ensure that pending file info + // queries caused by updating the current folder have been cancelled. + // However, we do not know for certain when the callback will run after + // cancelled. + g_idle_add([](gpointer data) -> gboolean { + g_object_unref(data); + return G_SOURCE_REMOVE; + }, mFileChooserDelegate); + mFileChooserDelegate = nullptr; + } +#endif + if (mCallback) { mCallback->Done(result); mCallback = nullptr; } else { mResult = result; } NS_RELEASE_THIS(); }
--- a/widget/gtk/nsFilePicker.h +++ b/widget/gtk/nsFilePicker.h @@ -68,11 +68,13 @@ protected: nsString mDefault; nsString mDefaultExtension; nsTArray<nsCString> mFilters; nsTArray<nsCString> mFilterNames; private: static nsIFile *mPrevDisplayDirectory; + + GtkFileChooserWidget *mFileChooserDelegate; }; #endif
--- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -4124,17 +4124,17 @@ nsWindow::ConfigureChildren(const nsTArr // size information from a source other than our owner. Don't let our parent // update this information. if (mWindowType == eWindowType_plugin_ipc_chrome) { return NS_OK; } for (uint32_t i = 0; i < aConfigurations.Length(); ++i) { const Configuration& configuration = aConfigurations[i]; - nsWindow* w = static_cast<nsWindow*>(configuration.mChild); + nsWindow* w = static_cast<nsWindow*>(configuration.mChild.get()); NS_ASSERTION(w->GetParent() == this, "Configured widget is not a child"); w->SetWindowClipRegion(configuration.mClipRegion, true); if (w->mBounds.Size() != configuration.mBounds.Size()) { w->Resize(configuration.mBounds.x, configuration.mBounds.y, configuration.mBounds.width, configuration.mBounds.height, true); } else if (w->mBounds.TopLeft() != configuration.mBounds.TopLeft()) {
--- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -1454,17 +1454,17 @@ class nsIWidget : public nsISupports { */ virtual nsTransparencyMode GetTransparencyMode() = 0; /** * This represents a command to set the bounds and clip region of * a child widget. */ struct Configuration { - nsIWidget* mChild; + nsCOMPtr<nsIWidget> mChild; uintptr_t mWindowID; // e10s specific, the unique plugin port id bool mVisible; // e10s specific, widget visibility nsIntRect mBounds; nsTArray<nsIntRect> mClipRegion; }; /** * Sets the clip region of each mChild (which must actually be a child
--- a/widget/tests/test_imestate.html +++ b/widget/tests/test_imestate.html @@ -140,16 +140,42 @@ const kIMEEnabledSupported = navigator.p // We support to control IME open state on Windows and Mac actually. However, // we cannot test it on Mac if the current keyboard layout is not CJK. And also // we cannot test it on Win32 if the system didn't be installed IME. So, // currently we should not run the open state testing. const kIMEOpenSupported = false; function runBasicTest(aIsEditable, aInDesignMode, aDescription) { + var onIMEFocusBlurHandler = null; + var TIPCallback = function(aTIP, aNotification) { + switch (aNotification.type) { + case "request-to-commit": + aTIP.commitComposition(); + break; + case "request-to-cancel": + aTIP.cancelComposition(); + break; + case "notify-focus": + case "notify-blur": + if (onIMEFocusBlurHandler) { + onIMEFocusBlurHandler(aNotification); + } + break; + } + return true; + }; + + var TIP = Components.classes["@mozilla.org/text-input-processor;1"] + .createInstance(Components.interfaces.nsITextInputProcessor); + if (!TIP.beginInputTransactionForTests(window, TIPCallback)) { + ok(false, "runBasicTest(): failed to begin input transaction"); + return; + } + function test(aTest) { function moveFocus(aTest, aFocusEventHandler) { if (aInDesignMode) { if (document.activeElement) { document.activeElement.blur(); } @@ -166,32 +192,22 @@ function runBasicTest(aIsEditable, aInDe var subDocument = null; if (element.contentDocument) { focusEventTarget = element.contentDocument; subDocument = element.contentDocument; element = element.contentDocument.documentElement; } focusEventTarget.addEventListener("focus", aFocusEventHandler, true); - document.addEventListener("MozIMEFocusIn", aFocusEventHandler, true); - document.addEventListener("MozIMEFocusOut", aFocusEventHandler, true); - if (subDocument) { - subDocument.addEventListener("MozIMEFocusIn", aFocusEventHandler, true); - subDocument.addEventListener("MozIMEFocusOut", aFocusEventHandler, true); - } + onIMEFocusBlurHandler = aFocusEventHandler; element.focus(); focusEventTarget.removeEventListener("focus", aFocusEventHandler, true); - document.removeEventListener("MozIMEFocusIn", aFocusEventHandler, true); - document.removeEventListener("MozIMEFocusOut", aFocusEventHandler, true); - if (element.contentDocument) { - subDocument.removeEventListener("MozIMEFocusIn", aFocusEventHandler, true); - subDocument.removeEventListener("MozIMEFocusOut", aFocusEventHandler, true); - } + onIMEFocusBlurHandler = null; var focusedElement = gFM.focusedElement; if (focusedElement) { var bindingParent = document.getBindingParent(focusedElement); if (bindingParent) { focusedElement = bindingParent; } } @@ -217,101 +233,101 @@ function runBasicTest(aIsEditable, aInDe is(gUtils.IMEIsOpen, aTest.changeOpened ? aTest.expectedOpened : aOpened, message); } // IME Enabled state testing var enabled = gUtils.IME_STATUS_ENABLED; if (kIMEEnabledSupported) { var focusEventCount = 0; - var mozIMEFocusInCount = 0; - var mozIMEFocusOutCount = 0; + var IMEReceivesFocus = 0; + var IMEReceivesBlur = 0; var IMEHasFocus = false; function onFocus(aEvent) { switch (aEvent.type) { case "focus": focusEventCount++; is(gUtils.IMEStatus, aTest.expectedEnabled, aDescription + ": " + aTest.description + ", wrong enabled state at focus event"); break; - case "MozIMEFocusIn": - mozIMEFocusInCount++; + case "notify-focus": + IMEReceivesFocus++; IMEHasFocus = true; is(gUtils.IMEStatus, aTest.expectedEnabled, aDescription + ": " + aTest.description + - ", MozIMEFocusIn event must be fired after IME state is updated"); + ", IME should receive a focus notification after IME state is updated"); break; - case "MozIMEFocusOut": - mozIMEFocusOutCount++; + case "notify-blur": + IMEReceivesBlur++; IMEHasFocus = false; var changingStatus = !(aIsEditable && aTest.expectedEnabled == gUtils.IME_STATUS_ENABLED); if (aTest.toDesignModeEditor) { is(gUtils.IME_STATUS_ENABLED, aTest.expectedEnabled, aDescription + ": " + aTest.description + - ", MozIMEFocusOut event must be fired after IME state is updated"); + ", IME should receive a blur notification after IME state is updated"); } else if (changingStatus) { isnot(gUtils.IMEStatus, aTest.expectedEnabled, aDescription + ": " + aTest.description + - ", MozIMEFocusOut event must be fired before IME state is updated"); + ", IME should receive a blur notification before IME state is updated"); } else { is(gUtils.IMEStatus, aTest.expectedEnabled, aDescription + ": " + aTest.description + - ", MozIMEFocusOut event must be fired with expected IME state if the state isn't being changed"); + ", IME should receive a blur notification and its context has expected IME state if the state isn't being changed"); } break; } } if (!moveFocus(aTest, onFocus)) { return; } if (aTest.focusable) { if (!aTest.focusEventNotFired) { ok(focusEventCount > 0, aDescription + ": " + aTest.description + ", focus event is never fired"); if (aTest.expectedEnabled == gUtils.IME_STATUS_ENABLED || aTest.expectedEnabled == gUtils.IME_STATUS_PASSWORD) { - ok(mozIMEFocusInCount > 0, - aDescription + ": " + aTest.description + ", MozIMEFocusIn event should be fired"); + ok(IMEReceivesFocus > 0, + aDescription + ": " + aTest.description + ", IME should receive a focus notification"); if (aInDesignMode && !aTest.toDesignModeEditor) { - is(mozIMEFocusOutCount, 0, + is(IMEReceivesBlur, 0, aDescription + ": " + aTest.description + - ", MozIMEFocusOut event shouldn't be fired in designMode since focus isn't moved from another editor"); + ", IME shouldn't receive a blur notification in designMode since focus isn't moved from another editor"); } else { - ok(mozIMEFocusOutCount > 0, + ok(IMEReceivesBlur > 0, aDescription + ": " + aTest.description + - ", MozIMEFocusOut event should be fired for the previous focused editor"); + ", IME should receive a blur notification for the previous focused editor"); } ok(IMEHasFocus, aDescription + ": " + aTest.description + - ", The latest MozIMEFocus* event must be MozIMEFocusIn"); + ", IME should have focus right now"); } else { - is(mozIMEFocusInCount, 0, + is(IMEReceivesFocus, 0, aDescription + ": " + aTest.description + - ", MozIMEFocusIn event shouldn't be fired"); - ok(mozIMEFocusOutCount > 0, + ", IME shouldn't receive a focus notification"); + ok(IMEReceivesBlur > 0, aDescription + ": " + aTest.description + - ", MozIMEFocusOut event should be fired"); + ", IME should receive a blur notification"); ok(!IMEHasFocus, aDescription + ": " + aTest.description + - ", The latest MozIMEFocus* event must be MozIMEFocusOut"); + ", IME shouldn't have focus right now"); } } else { todo(focusEventCount > 0, aDescription + ": " + aTest.description + ", focus event should be fired"); } } else { - is(mozIMEFocusInCount, 0, + is(IMEReceivesFocus, 0, aDescription + ": " + aTest.description + - ", MozIMEFocusIn event shouldn't be fired at testing non-focusable element"); - is(mozIMEFocusOutCount, 0, + ", IME shouldn't receive a focus notification at testing non-focusable element"); + is(IMEReceivesBlur, 0, aDescription + ": " + aTest.description + - ", MozIMEFocusOut event shouldn't be fired at testing non-focusable element"); + ", IME shouldn't receive a blur notification at testing non-focusable element"); } enabled = gUtils.IMEStatus; inputtype = gUtils.focusedInputType; is(enabled, aTest.expectedEnabled, aDescription + ": " + aTest.description + ", wrong enabled state"); if (aTest.expectedType && !aInDesignMode) { is(inputtype, aTest.expectedType, @@ -1353,87 +1369,107 @@ function runTestPasswordFieldOnDialog() // Bug 580388 and bug 808287 function runEditorReframeTests(aCallback) { if (document.activeElement) { document.activeElement.blur(); } - var input = document.getElementById("text"); - input.focus(); - input.style.overflow = "visible"; - - var mozIMEFocusIn = 0; - var mozIMEFocusOut = 0; + var IMEFocus = 0; + var IMEBlur = 0; var IMEHasFocus = false; - - var handler = function (aEvent) { - switch (aEvent.type) { - case "MozIMEFocusIn": - mozIMEFocusIn++; + var TIPCallback = function(aTIP, aNotification) { + switch (aNotification.type) { + case "request-to-commit": + aTIP.commitComposition(); + break; + case "request-to-cancel": + aTIP.cancelComposition(); + break; + case "notify-focus": + IMEFocus++; IMEHasFocus = true; break; - case "MozIMEFocusOut": - mozIMEFocusOut++; + case "notify-blur": + IMEBlur++; IMEHasFocus = false; break; } + return true; }; + var TIP = Components.classes["@mozilla.org/text-input-processor;1"] + .createInstance(Components.interfaces.nsITextInputProcessor); + if (!TIP.beginInputTransactionForTests(window, TIPCallback)) { + ok(false, "runEditorReframeTests(): failed to begin input transaction"); + return; + } + + var input = document.getElementById("text"); + input.focus(); + + is(IMEFocus, 1, "runEditorReframeTests(): IME should receive a focus notification by a call of <input>.focus()"); + is(IMEBlur, 0, "runEditorReframeTests(): IME shouldn't receive a blur notification by a call of <input>.focus()"); + ok(IMEHasFocus, "runEditorReframeTests(): IME should have focus because <input>.focus() is called"); + + IMEFocus = IMEBlur = 0; + + input.style.overflow = "visible"; + var onInput = function (aEvent) { aEvent.target.style.overflow = "hidden"; } - - document.addEventListener("MozIMEFocusIn", handler, true); - document.addEventListener("MozIMEFocusOut", handler, true); input.addEventListener("input", onInput, true); - sendChar("a"); + var AKey = new KeyboardEvent("", { key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A }); + TIP.keydown(AKey); + TIP.keyup(AKey); hitEventLoop(function () { - ok(mozIMEFocusOut > 0, "runEditorReframeTests(): IME focus must be lost at reframing"); - ok(mozIMEFocusIn > 0, "runEditorReframeTests(): IME focus must be restored after reframing"); - ok(IMEHasFocus, "runEditorReframeTests(): IME must have focus after reframing"); + is(IMEFocus, 0, "runEditorReframeTests(): IME shouldn't receive a focus notification during reframing"); + is(IMEBlur, 0, "runEditorReframeTests(): IME shouldn't receive a blur notification during reframing"); + ok(IMEHasFocus, "runEditorReframeTests(): IME must have focus even after reframing"); - var focusQueryHandler = function(aEvent) { - // Perform a style change and query during focus to trigger reframing - input.style.overflow = "visible"; - synthesizeQuerySelectedText(); - } - document.addEventListener("MozIMEFocusIn", focusQueryHandler, true); - mozIMEFocusIn = mozIMEFocusOut = 0; + var onFocus = function(aEvent) { + // Perform a style change and query during focus to trigger reframing + input.style.overflow = "visible"; + synthesizeQuerySelectedText(); + }; + input.addEventListener("focus", onFocus); + IMEFocus = IMEBlur = 0; input.blur(); input.focus(); - sendChar("a"); + TIP.keydown(AKey); + TIP.keyup(AKey); hitEventLoop(function() { - ok(IMEHasFocus, "runEditorReframeTests(): IME must have focus after reframing during focus"); - ok(mozIMEFocusOut == mozIMEFocusIn, "runEditorReframeTests(): IME focus/blur (" + mozIMEFocusIn + "/" + mozIMEFocusOut + ") must match after reframing during focus"); + is(IMEFocus, 1, "runEditorReframeTests(): IME should receive a focus notification at focus but shouldn't receive it during reframing"); + is(IMEBlur, 1, "runEditorReframeTests(): IME should receive a blur notification at blur but shouldn't receive it during reframing"); + ok(IMEHasFocus, "runEditorReframeTests(): IME sould have focus after reframing during focus"); + + input.removeEventListener("input", onInput, true); + input.removeEventListener("focus", onFocus); - document.removeEventListener("MozIMEFocusIn", focusQueryHandler, true); - document.removeEventListener("MozIMEFocusIn", handler, true); - document.removeEventListener("MozIMEFocusOut", handler, true); - input.removeEventListener("input", onInput, true); + input.style.overflow = "visible"; + input.value = ""; - input.style.overflow = "visible"; - input.value = ""; + TIP = null; - hitEventLoop(aCallback, 20); + hitEventLoop(aCallback, 20); }, 20); }, 20); } function runTests() { if (!kIMEEnabledSupported && !kIMEOpenSupported) return; - SpecialPowers.pushPrefEnv({"set":[["test.IME", true]]}, function() { // test for normal contents. runBasicTest(false, false, "Testing of normal contents"); // test for plugin contents runPluginTest(); var container = document.getElementById("display"); // test for contentEditable="true" @@ -1473,17 +1509,16 @@ function runTests() // XXX temporary disable against failure //runTestPasswordFieldOnDialog(); // Asynchronous tests runEditorReframeTests(function () { // This will call onFinish(), so, this test must be the last. runEditableSubframeTests(); }); - }); } function onFinish() { SimpleTest.finish(); } </script>
--- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -6350,17 +6350,17 @@ nsWindow::ConfigureChildren(const nsTArr return NS_OK; } // XXXroc we could use BeginDeferWindowPos/DeferWindowPos/EndDeferWindowPos // here, if that helps in some situations. So far I haven't seen a // need. for (uint32_t i = 0; i < aConfigurations.Length(); ++i) { const Configuration& configuration = aConfigurations[i]; - nsWindow* w = static_cast<nsWindow*>(configuration.mChild); + nsWindow* w = static_cast<nsWindow*>(configuration.mChild.get()); NS_ASSERTION(w->GetParent() == this, "Configured widget is not a child"); nsresult rv = w->SetWindowClipRegion(configuration.mClipRegion, true); NS_ENSURE_SUCCESS(rv, rv); nsIntRect bounds; w->GetBounds(bounds); if (bounds.Size() != configuration.mBounds.Size()) { w->Resize(configuration.mBounds.x, configuration.mBounds.y,
--- a/xpcom/glue/nsBaseHashtable.h +++ b/xpcom/glue/nsBaseHashtable.h @@ -166,17 +166,17 @@ public: * @param aUserArg passed unchanged to the EnumReadFunction */ uint32_t EnumerateRead(EnumReadFunction aEnumFunc, void* aUserArg) const { NS_ASSERTION(this->mTable.IsInitialized(), "nsBaseHashtable was not initialized properly."); s_EnumReadArgs enumData = { aEnumFunc, aUserArg }; - return PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&this->mTable), + return PL_DHashTableEnumerate(const_cast<PLDHashTable*>(static_cast<const PLDHashTable*>(&this->mTable)), s_EnumReadStub, &enumData); } /** * function type provided by the application for enumeration. * @param aKey the key being enumerated * @param aData Reference to data being enumerated, may be altered. e.g. for
--- a/xpcom/glue/nsTHashtable.h +++ b/xpcom/glue/nsTHashtable.h @@ -81,18 +81,22 @@ PLDHashOperator PL_DHashStubEnumRemove(P template<class EntryType> class nsTHashtable { typedef mozilla::fallible_t fallible_t; public: // Separate constructors instead of default aInitLength parameter since // otherwise the default no-arg constructor isn't found. - nsTHashtable() { Init(PL_DHASH_DEFAULT_INITIAL_LENGTH); } - explicit nsTHashtable(uint32_t aInitLength) { Init(aInitLength); } + nsTHashtable() + : mTable(Ops(), sizeof(EntryType), PL_DHASH_DEFAULT_INITIAL_LENGTH) + {} + explicit nsTHashtable(uint32_t aInitLength) + : mTable(Ops(), sizeof(EntryType), aInitLength) + {} /** * destructor, cleans up and deallocates */ ~nsTHashtable(); nsTHashtable(nsTHashtable<EntryType>&& aOther); @@ -125,17 +129,17 @@ public: * key doesn't exist */ EntryType* GetEntry(KeyType aKey) const { NS_ASSERTION(mTable.IsInitialized(), "nsTHashtable was not initialized properly."); return static_cast<EntryType*>( - PL_DHashTableSearch(const_cast<PLDHashTable*>(&mTable), + PL_DHashTableSearch(const_cast<PLDHashTable*>(static_cast<const PLDHashTable*>(&mTable)), EntryType::KeyToPointer(aKey))); } /** * Return true if an entry for the given key exists, false otherwise. * @param aKey the key to retrieve * @return true if the key exists, false if the key doesn't exist */ @@ -319,17 +323,17 @@ public: NS_ASSERTION(mTable.IsInitialized(), "nsTHashtable was not initialized properly."); PL_DHashMarkTableImmutable(&mTable); } #endif protected: - PLDHashTable mTable; + PLDHashTable2 mTable; static const void* s_GetKey(PLDHashTable* aTable, PLDHashEntryHdr* aEntry); static PLDHashNumber s_HashKey(PLDHashTable* aTable, const void* aKey); static bool s_MatchEntry(PLDHashTable* aTable, const PLDHashEntryHdr* aEntry, const void* aKey); @@ -373,20 +377,19 @@ protected: static size_t s_SizeOfStub(PLDHashEntryHdr* aEntry, mozilla::MallocSizeOf aMallocSizeOf, void* aArg); private: // copy constructor, not implemented nsTHashtable(nsTHashtable<EntryType>& aToCopy) = delete; /** - * Initialize the table. - * @param aInitLength the initial number of buckets in the hashtable + * Gets the table's ops. */ - void Init(uint32_t aInitLength); + static const PLDHashTableOps* Ops(); /** * An implementation of SizeOfEntryExcludingThisFun that calls SizeOfExcludingThis() * on each entry. */ static size_t BasicSizeOfEntryExcludingThisFun(EntryType* aEntry, mozilla::MallocSizeOf aMallocSizeOf, void*); @@ -406,35 +409,34 @@ nsTHashtable<EntryType>::nsTHashtable(ns // aOther shouldn't touch mTable after this, because we've stolen the table's // pointers but not overwitten them. MOZ_MAKE_MEM_UNDEFINED(&aOther.mTable, sizeof(aOther.mTable)); } template<class EntryType> nsTHashtable<EntryType>::~nsTHashtable() { - if (mTable.IsInitialized()) { - PL_DHashTableFinish(&mTable); - } } template<class EntryType> -void -nsTHashtable<EntryType>::Init(uint32_t aInitLength) +/* static */ const PLDHashTableOps* +nsTHashtable<EntryType>::Ops() { + // If this variable is a global variable, we get strange start-up failures on + // WindowsCrtPatch.h (see bug 1166598 comment 20). But putting it inside a + // function avoids that problem. static const PLDHashTableOps sOps = { s_HashKey, s_MatchEntry, EntryType::ALLOW_MEMMOVE ? ::PL_DHashMoveEntryStub : s_CopyEntry, s_ClearEntry, s_InitEntry }; - - PL_DHashTableInit(&mTable, &sOps, sizeof(EntryType), aInitLength); + return &sOps; } // static template<class EntryType> size_t nsTHashtable<EntryType>::BasicSizeOfEntryExcludingThisFun(EntryType* aEntry, mozilla::MallocSizeOf aMallocSizeOf, void*)