merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-03-16 10:56:14 +01:00
commit 71900c9741
505 changed files with 24426 additions and 8642 deletions

View File

@ -35,7 +35,7 @@ static const uint32_t kGenericAccType = 0;
* via the object attribute "xml-roles".
*/
static nsRoleMapEntry sWAIRoleMaps[] =
static const nsRoleMapEntry sWAIRoleMaps[] =
{
{ // alert
&nsGkAtoms::alert,
@ -760,7 +760,7 @@ static nsRoleMapEntry sWAIRoleMaps[] =
}
};
static nsRoleMapEntry sLandmarkRoleMap = {
static const nsRoleMapEntry sLandmarkRoleMap = {
&nsGkAtoms::_empty,
roles::NOTHING,
kUseNativeRole,
@ -861,7 +861,7 @@ struct RoleComparator
}
nsRoleMapEntry*
const nsRoleMapEntry*
aria::GetRoleMap(dom::Element* aEl)
{
nsAutoString roles;

View File

@ -210,7 +210,7 @@ extern nsRoleMapEntry gEmptyRoleMap;
* @return a pointer to the role map entry for the ARIA role, or nullptr
* if none
*/
nsRoleMapEntry* GetRoleMap(dom::Element* aEl);
const nsRoleMapEntry* GetRoleMap(dom::Element* aEl);
/**
* Return accessible state from ARIA universal states applied to the given

View File

@ -146,7 +146,7 @@ nsAccUtils::SetLiveContainerAttributes(nsIPersistentProperties *aAttributes,
// container-live, and container-live-role attributes
if (live.IsEmpty()) {
nsRoleMapEntry* role = nullptr;
const nsRoleMapEntry* role = nullptr;
if (ancestor->IsElement()) {
role = aria::GetRoleMap(ancestor->AsElement());
}

View File

@ -142,7 +142,7 @@ New_HTMLLink(nsIContent* aContent, Accessible* aContext)
{
// Only some roles truly enjoy life as HTMLLinkAccessibles, for details
// see closed bug 494807.
nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aContent->AsElement());
const nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aContent->AsElement());
if (roleMapEntry && roleMapEntry->role != roles::NOTHING &&
roleMapEntry->role != roles::LINK) {
return new HyperTextAccessibleWrap(aContent, aContext->Document());
@ -1132,7 +1132,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
return newAcc;
}
nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(content->AsElement());
const nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(content->AsElement());
// If the element is focusable or global ARIA attribute is applied to it or
// it is referenced by ARIA relationship then treat role="presentation" on
@ -1184,7 +1184,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
// expose their native roles.
if (!roleMapEntry && newAcc && aContext->HasStrongARIARole()) {
if (frame->AccessibleType() == eHTMLTableRowType) {
nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
const nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
if (!contextRoleMap->IsOfType(eTable))
roleMapEntry = &aria::gEmptyRoleMap;
@ -1196,7 +1196,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
nsGkAtoms::li,
nsGkAtoms::dd) ||
frame->AccessibleType() == eHTMLLiType) {
nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
const nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
if (!contextRoleMap->IsOfType(eList))
roleMapEntry = &aria::gEmptyRoleMap;
}

View File

@ -226,7 +226,7 @@ public:
/**
* Retrun ARIA role map if any.
*/
nsRoleMapEntry* ARIARoleMap() const { return mRoleMapEntry; }
const nsRoleMapEntry* ARIARoleMap() const { return mRoleMapEntry; }
/**
* Return accessible role specified by ARIA (see constants in
@ -372,7 +372,7 @@ public:
/**
* Set the ARIA role map entry for a new accessible.
*/
void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
void SetRoleMapEntry(const nsRoleMapEntry* aRoleMapEntry)
{ mRoleMapEntry = aRoleMapEntry; }
/**
@ -1188,7 +1188,7 @@ protected:
/**
* Non-null indicates author-supplied role; possibly state & value as well
*/
nsRoleMapEntry* mRoleMapEntry;
const nsRoleMapEntry* mRoleMapEntry;
private:
Accessible() = delete;

View File

@ -1282,7 +1282,7 @@ DocAccessible::GetAccessibleOrDescendant(nsINode* aNode) const
void
DocAccessible::BindToDocument(Accessible* aAccessible,
nsRoleMapEntry* aRoleMapEntry)
const nsRoleMapEntry* aRoleMapEntry)
{
// Put into DOM node cache.
if (aAccessible->IsNodeMapEntry())

View File

@ -314,7 +314,8 @@ public:
* @param aRoleMapEntry [in] the role map entry role the ARIA role or nullptr
* if none
*/
void BindToDocument(Accessible* aAccessible, nsRoleMapEntry* aRoleMapEntry);
void BindToDocument(Accessible* aAccessible,
const nsRoleMapEntry* aRoleMapEntry);
/**
* Remove from document and shutdown the given accessible.

View File

@ -353,7 +353,7 @@ DocAccessibleChild::RecvARIARoleAtom(const uint64_t& aID, nsString* aRole)
return true;
}
if (nsRoleMapEntry* roleMap = acc->ARIARoleMap()) {
if (const nsRoleMapEntry* roleMap = acc->ARIARoleMap()) {
if (nsIAtom* roleAtom = *(roleMap->roleAtom)) {
roleAtom->ToString(*aRole);
}

View File

@ -811,7 +811,7 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
// Now, deal with widget roles
nsIAtom* roleAtom = nullptr;
if (accWrap && accWrap->HasARIARole()) {
nsRoleMapEntry* roleMap = accWrap->ARIARoleMap();
const nsRoleMapEntry* roleMap = accWrap->ARIARoleMap();
roleAtom = *roleMap->roleAtom;
}
if (proxy)

View File

@ -6138,7 +6138,7 @@ function CanCloseWindow()
{
// Avoid redundant calls to canClose from showing multiple
// PermitUnload dialogs.
if (window.skipNextCanClose) {
if (Services.startup.shuttingDown || window.skipNextCanClose) {
return true;
}

View File

@ -1560,7 +1560,13 @@
// Unhook our progress listener.
let tab = this.getTabForBrowser(aBrowser);
let filter = this._tabFilters.get(tab);
let listener = this._tabListeners.get(tab);
aBrowser.webProgress.removeProgressListener(filter);
filter.removeProgressListener(listener);
// We'll be creating a new listener, so destroy the old one.
listener.destroy();
// Make sure the browser is destroyed so it unregisters from observer notifications
aBrowser.destroy();
@ -1582,6 +1588,13 @@
aBrowser.docShellIsActive = (aBrowser == this.selectedBrowser &&
window.windowState != window.STATE_MINIMIZED);
// Create a new tab progress listener for the new browser we just injected,
// since tab progress listeners have logic for handling the initial about:blank
// load
listener = this.mTabProgressListener(tab, aBrowser, false, false);
this._tabListeners.set(tab, listener);
filter.addProgressListener(listener, Ci.nsIWebProgress.NOTIFY_ALL);
// Restore the progress listener.
aBrowser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);

View File

@ -120,6 +120,8 @@ support-files =
xul_tooltiptext.xhtml
file_bug1045809_1.html
file_bug1045809_2.html
file_csp_block_all_mixedcontent.html
file_csp_block_all_mixedcontent.js
[browser_URLBarSetURI.js]
skip-if = (os == "linux" || os == "mac") && debug # bug 970052, bug 970053
@ -554,3 +556,5 @@ skip-if = !e10s || !crashreporter
skip-if = !e10s || !crashreporter
[browser_aboutTabCrashed_withoutDump.js]
skip-if = !e10s
[browser_csp_block_all_mixedcontent.js]
tags = mcb

View File

@ -0,0 +1,55 @@
/*
* Description of the Test:
* We load an https page which uses a CSP including block-all-mixed-content.
* The page tries to load a script over http. We make sure the UI is not
* influenced when blocking the mixed content. In particular the page
* should still appear fully encrypted with a green lock.
*/
const PRE_PATH = "https://example.com/browser/browser/base/content/test/general/";
var gTestBrowser = null;
//------------------------------------------------------
function cleanUpAfterTests() {
gBrowser.removeCurrentTab();
window.focus();
finish();
}
//------------------------------------------------------
function verifyUInotDegraded() {
// make sure that not mixed content is loaded and also not blocked
assertMixedContentBlockingState(
gTestBrowser,
{ activeLoaded: false,
activeBlocked: false,
passiveLoaded: false
}
);
// clean up and finish test
cleanUpAfterTests();
}
//------------------------------------------------------
function runTests() {
var newTab = gBrowser.addTab();
gBrowser.selectedTab = newTab;
gTestBrowser = gBrowser.selectedBrowser;
newTab.linkedBrowser.stop();
// Starting the test
BrowserTestUtils.browserLoaded(gTestBrowser).then(verifyUInotDegraded);
var url = PRE_PATH + "file_csp_block_all_mixedcontent.html";
gTestBrowser.loadURI(url);
}
//------------------------------------------------------
function test() {
// Performing async calls, e.g. 'onload', we have to wait till all of them finished
waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{ 'set': [["security.mixed_content.block_active_content", true]] },
function() { runTests(); }
);
}

View File

@ -1,4 +1,4 @@
function test() {
add_task(function* () {
gPrefService.setBoolPref("browser.ctrlTab.previews", true);
gBrowser.addTab();
@ -7,39 +7,39 @@ function test() {
checkTabs(4);
ctrlTabTest([2] , 1, 0);
ctrlTabTest([2, 3, 1], 2, 2);
ctrlTabTest([] , 4, 2);
yield ctrlTabTest([2] , 1, 0);
yield ctrlTabTest([2, 3, 1], 2, 2);
yield ctrlTabTest([] , 4, 2);
{
let selectedIndex = gBrowser.tabContainer.selectedIndex;
pressCtrlTab();
pressCtrlTab(true);
releaseCtrl();
yield pressCtrlTab();
yield pressCtrlTab(true);
yield releaseCtrl();
is(gBrowser.tabContainer.selectedIndex, selectedIndex,
"Ctrl+Tab -> Ctrl+Shift+Tab keeps the selected tab");
}
{ // test for bug 445369
let tabs = gBrowser.tabs.length;
pressCtrlTab();
EventUtils.synthesizeKey("w", { ctrlKey: true });
yield pressCtrlTab();
yield synthesizeCtrlW();
is(gBrowser.tabs.length, tabs - 1, "Ctrl+Tab -> Ctrl+W removes one tab");
releaseCtrl();
yield releaseCtrl();
}
{ // test for bug 667314
let tabs = gBrowser.tabs.length;
pressCtrlTab();
pressCtrlTab(true);
EventUtils.synthesizeKey("w", { ctrlKey: true });
yield pressCtrlTab();
yield pressCtrlTab(true);
yield synthesizeCtrlW();
is(gBrowser.tabs.length, tabs - 1, "Ctrl+Tab -> Ctrl+W removes the selected tab");
releaseCtrl();
yield releaseCtrl();
}
gBrowser.addTab();
checkTabs(3);
ctrlTabTest([2, 1, 0], 7, 1);
yield ctrlTabTest([2, 1, 0], 7, 1);
gBrowser.addTab();
checkTabs(4);
@ -50,22 +50,22 @@ function test() {
let selectedTab = gBrowser.selectedTab;
let tabToRemove = gBrowser.tabs[1];
pressCtrlTab();
pressCtrlTab();
EventUtils.synthesizeKey("w", { ctrlKey: true });
yield pressCtrlTab();
yield pressCtrlTab();
yield synthesizeCtrlW();
ok(!tabToRemove.parentNode,
"Ctrl+Tab*2 -> Ctrl+W removes the second most recently selected tab");
pressCtrlTab(true);
pressCtrlTab(true);
releaseCtrl();
yield pressCtrlTab(true);
yield pressCtrlTab(true);
yield releaseCtrl();
ok(selectedTab.selected,
"Ctrl+Tab*2 -> Ctrl+W -> Ctrl+Shift+Tab*2 keeps the selected tab");
}
gBrowser.removeTab(gBrowser.tabContainer.lastChild);
checkTabs(2);
ctrlTabTest([1], 1, 0);
yield ctrlTabTest([1], 1, 0);
gBrowser.removeTab(gBrowser.tabContainer.lastChild);
checkTabs(1);
@ -77,7 +77,7 @@ function test() {
eventConsumed = event.defaultPrevented;
};
document.addEventListener("keypress", detectKeyEvent, false);
pressCtrlTab();
yield pressCtrlTab();
document.removeEventListener("keypress", detectKeyEvent, false);
ok(eventConsumed, "Ctrl+Tab consumed by the tabbed browser if one tab is open");
is(focusedWindow, document.commandDispatcher.focusedWindow,
@ -90,18 +90,42 @@ function test() {
/* private utility functions */
function pressCtrlTab(aShiftKey) {
function* pressCtrlTab(aShiftKey) {
let promise;
if (!isOpen() && canOpen()) {
promise = BrowserTestUtils.waitForEvent(ctrlTab.panel, "popupshown");
} else {
promise = BrowserTestUtils.waitForEvent(document, "keyup");
}
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: !!aShiftKey });
return promise;
}
function releaseCtrl() {
function* releaseCtrl() {
let promise;
if (isOpen()) {
promise = BrowserTestUtils.waitForEvent(ctrlTab.panel, "popuphidden");
} else {
promise = BrowserTestUtils.waitForEvent(document, "keyup");
}
EventUtils.synthesizeKey("VK_CONTROL", { type: "keyup" });
return promise;
}
function* synthesizeCtrlW() {
let promise = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "TabClose");
EventUtils.synthesizeKey("w", { ctrlKey: true });
return promise;
}
function isOpen() {
return ctrlTab.isOpen;
}
function canOpen() {
return gPrefService.getBoolPref("browser.ctrlTab.previews") && gBrowser.tabs.length > 2;
}
function checkTabs(aTabs) {
var tabs = gBrowser.tabs.length;
if (tabs != aTabs) {
@ -117,7 +141,7 @@ function test() {
});
}
function ctrlTabTest(tabsToSelect, tabTimes, expectedIndex) {
function* ctrlTabTest(tabsToSelect, tabTimes, expectedIndex) {
selectTabs(tabsToSelect);
var indexStart = gBrowser.tabContainer.selectedIndex;
@ -127,7 +151,7 @@ function test() {
normalized + " tabs back in most-recently-selected order";
for (let i = 0; i < tabTimes; i++) {
pressCtrlTab();
yield pressCtrlTab();
if (tabCount > 2)
is(gBrowser.tabContainer.selectedIndex, indexStart,
@ -138,7 +162,7 @@ function test() {
ok(isOpen(),
"With " + tabCount + " tabs open, Ctrl+Tab opens the preview panel");
releaseCtrl();
yield releaseCtrl();
ok(!isOpen(),
"Releasing Ctrl closes the preview panel");
@ -151,4 +175,4 @@ function test() {
"With "+ tabCount +" tabs open and tab " + indexStart
+ " selected, Ctrl+Tab*" + tabTimes + " goes " + where);
}
}
});

View File

@ -0,0 +1,9 @@
<!DOCTYPE HTML>
<html><head><meta charset="utf-8">
<title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>
</head>
<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
<body>
<script src="http://example.com/browser/browser/base/content/test/general/file_csp_block_all_mixedcontent.js"/>
</body>
</html>

View File

@ -0,0 +1,3 @@
// empty script file just used for testing Bug 1122236.
// Making sure the UI is not degraded when blocking
// mixed content using the CSP directive: block-all-mixed-content.

View File

@ -9,6 +9,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
Cu.import("resource://gre/modules/AddonManager.jsm");
Cu.import("resource://gre/modules/AppConstants.jsm");
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@ -138,6 +139,25 @@ function promisePopupShown(popup) {
});
}
XPCOMUtils.defineLazyGetter(global, "stylesheets", () => {
let styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"]
.getService(Components.interfaces.nsIStyleSheetService);
let styleSheetURI = Services.io.newURI("chrome://browser/content/extension.css",
null, null);
let styleSheet = styleSheetService.preloadSheet(styleSheetURI,
styleSheetService.AGENT_SHEET);
let stylesheets = [styleSheet];
if (AppConstants.platform === "macosx") {
styleSheetURI = Services.io.newURI("chrome://browser/content/extension-mac.css",
null, null);
let macStyleSheet = styleSheetService.preloadSheet(styleSheetURI,
styleSheetService.AGENT_SHEET);
stylesheets.push(macStyleSheet);
}
return stylesheets;
});
class BasePopup {
constructor(extension, viewNode, popupURL) {
let popupURI = Services.io.newURI(popupURL, null, extension.baseURI);
@ -163,6 +183,7 @@ class BasePopup {
destroy() {
this.browserReady.then(() => {
this.browser.removeEventListener("DOMWindowCreated", this, true);
this.browser.removeEventListener("load", this, true);
this.browser.removeEventListener("DOMTitleChanged", this, true);
this.browser.removeEventListener("DOMWindowClose", this, true);
@ -190,6 +211,13 @@ class BasePopup {
this.destroy();
break;
case "DOMWindowCreated":
let winUtils = this.browser.contentWindow
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
for (let stylesheet of global.stylesheets) {
winUtils.addSheet(stylesheet, winUtils.AGENT_SHEET);
}
break;
case "DOMWindowClose":
if (event.target === this.browser.contentWindow) {
event.preventDefault();
@ -217,7 +245,6 @@ class BasePopup {
createBrowser(viewNode, popupURI) {
let document = viewNode.ownerDocument;
this.browser = document.createElementNS(XUL_NS, "browser");
this.browser.setAttribute("type", "content");
this.browser.setAttribute("disableglobalhistory", "true");
@ -259,6 +286,7 @@ class BasePopup {
GlobalManager.injectInDocShell(this.browser.docShell, this.extension, this.context);
this.browser.setAttribute("src", this.context.uri.spec);
this.browser.addEventListener("DOMWindowCreated", this, true);
this.browser.addEventListener("load", this, true);
this.browser.addEventListener("DOMTitleChanged", this, true);
this.browser.addEventListener("DOMWindowClose", this, true);

View File

@ -0,0 +1,11 @@
button,
select,
input[type="checkbox"] + label::before {
border-radius: 4px;
}
.panel-section-footer {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
overflow: hidden;
}

View File

@ -0,0 +1,572 @@
/* stylelint-disable property-no-vendor-prefix */
/* stylelint-disable property-no-vendor-prefix */
/* Base */
button,
select,
option,
input {
-moz-appearance: none;
}
/* Variables */
html,
body {
background-color: #fcfcfc;
box-sizing: border-box;
color: #222426;
cursor: default;
display: flex;
flex-direction: column;
font: caption;
margin: 0;
padding: 0;
-moz-user-select: none;
}
body * {
box-sizing: border-box;
text-align: start;
}
/* stylelint-disable property-no-vendor-prefix */
/* Buttons */
button,
select {
background-color: #fbfbfb;
border: 1px solid #b1b1b1;
box-shadow: 0 0 0 0 transparent;
font: caption;
height: 24px;
outline: 0 !important;
padding: 0 8px 0;
transition-duration: 250ms;
transition-property: box-shadow, border;
}
select {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg==);
background-position: calc(100% - 4px) center;
background-repeat: no-repeat;
-moz-padding-end: 24px;
text-overflow: ellipsis;
}
label {
font: caption;
}
button::-moz-focus-inner {
border: 0;
outline: 0;
}
/* Dropdowns */
select {
background-color: #fbfbfb;
border: 1px solid #b1b1b1;
box-shadow: 0 0 0 0 transparent;
font: caption;
height: 24px;
outline: 0 !important;
padding: 0 8px 0;
transition-duration: 250ms;
transition-property: box-shadow, border;
}
select {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg==);
background-position: calc(100% - 4px) center;
background-repeat: no-repeat;
-moz-padding-end: 24px;
text-overflow: ellipsis;
}
select:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #000;
}
select:-moz-focusring * {
color: #000;
text-shadow: none;
}
button.hover,
select.hover {
background-color: #ebebeb;
border: 1px solid #b1b1b1;
}
button.pressed,
select.pressed {
background-color: #d4d4d4;
border: 1px solid #858585;
}
button.disabled,
select.disabled {
color: #999;
opacity: .5;
}
button.focused,
select.focused {
border-color: #fff;
box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
}
button.default {
background-color: #0996f8;
border-color: #0670cc;
color: #fff;
}
button.default.hover {
background-color: #0670cc;
border-color: #005bab;
}
button.default.pressed {
background-color: #005bab;
border-color: #004480;
}
button.default.focused {
border-color: #fff;
}
/* Radio Buttons */
.radioItem {
margin-bottom: 6px;
text-align: left;
}
input[type="radio"] {
display: none;
}
input[type="radio"] + label {
-moz-user-select: none;
}
input[type="radio"] + label::before {
background-color: #fff;
background-position: center;
border: 1px solid #b1b1b1;
border-radius: 50%;
content: "";
display: inline-block;
height: 16px;
margin-right: 6px;
vertical-align: text-top;
width: 16px;
}
input[type="radio"]:hover + label::before,
.radioItem.hover input[type="radio"]:not(active) + label::before {
background-color: #fbfbfb;
border-color: #b1b1b1;
}
input[type="radio"]:hover:active + label::before,
.radioItem.pressed input[type="radio"]:not(active) + label::before {
background-color: #ebebeb;
border-color: #858585;
}
input[type="radio"]:checked + label::before {
background-color: #0996f8;
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8Y2lyY2xlIGN4PSI4IiBjeT0iOCIgcj0iNCIgZmlsbD0iI2ZmZiIgLz4KPC9zdmc+Cg==);
border-color: #0670cc;
}
input[type="radio"]:checked:hover + label::before,
.radioItem.hover input[type="radio"]:checked:not(active) + label::before {
background-color: #0670cc;
border-color: #005bab;
}
input[type="radio"]:checked:hover:active + label::before,
.radioItem.pressed input[type="radio"]:checked:not(active) + label::before {
background-color: #005bab;
border-color: #004480;
}
.radioItem.disabled input[type="radio"] + label,
.radioItem.disabled input[type="radio"]:hover + label,
.radioItem.disabled input[type="radio"]:hover:active + label {
color: #999;
opacity: .5;
}
.radioItem.focused input[type="radio"] + label::before {
border-color: #0996f8;
box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
}
.radioItem.focused input[type="radio"]:checked + label::before {
border-color: #fff;
}
/* Checkboxes */
.checkboxItem {
margin-bottom: 6px;
text-align: left;
}
input[type="checkbox"] {
display: none;
}
input[type="checkbox"] + label {
-moz-user-select: none;
}
input[type="checkbox"] + label::before {
background-color: #fff;
background-position: center;
border: 1px solid #b1b1b1;
content: "";
display: inline-block;
height: 16px;
margin-right: 6px;
vertical-align: text-top;
width: 16px;
}
input[type="checkbox"]:hover + label::before,
.checkboxItem.hover input[type="checkbox"]:not(active) + label::before {
background-color: #fbfbfb;
border-color: #b1b1b1;
}
input[type="checkbox"]:hover:active + label::before,
.checkboxItem.pressed input[type="checkbox"]:not(active) + label::before {
background-color: #ebebeb;
border-color: #858585;
}
input[type="checkbox"]:checked + label::before {
background-color: #0996f8;
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNNy43LDEyLjkgQzcuNCwxMy4zIDYuOCwxMy40IDYuNCwxMyBMMy4yLDkuOCBDMi44LDkuNCAyLjgsOC42IDMuMiw4LjIgQzMuNiw3LjggNC40LDcuOCA0LjgsOC4yIEw2LjksMTAuMyBMMTEuMSw0LjQgQzExLjUsMy45IDEyLjIsMy44IDEyLjcsNC4xIEMxMy4yLDQuNSAxMy4zLDUuMiAxMyw1LjcgTDcuNywxMi45IEw3LjcsMTIuOSBaIiBmaWxsPSIjZmZmIiAvPgo8L3N2Zz4K);
border-color: #0670cc;
}
input[type="checkbox"]:checked:hover + label::before,
.checkboxItem.hover input[type="checkbox"]:checked:not(active) + label::before {
background-color: #0670cc;
border-color: #005bab;
}
input[type="checkbox"]:checked:hover:active + label::before,
.checkboxItem.pressed input[type="checkbox"]:checked:not(active) + label::before {
background-color: #005bab;
border-color: #004480;
}
.checkboxItem.disabled input[type="checkbox"] + label,
.checkboxItem.disabled input[type="checkbox"]:hover + label,
.checkboxItem.disabled input[type="checkbox"]:hover:active + label {
color: #999;
opacity: .5;
}
.checkboxItem.focused input[type="checkbox"] + label::before {
border-color: #0996f8;
box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
}
.checkboxItem.focused input[type="checkbox"]:checked + label::before {
border-color: #fff;
}
/* Expander Button */
button.expander {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNOCwxMkwzLDcsNCw2bDQsNCw0LTQsMSwxWiIgZmlsbD0iIzZBNkE2QSIgLz4KPC9zdmc+Cg==);
background-position: center;
background-repeat: no-repeat;
height: 24px;
padding: 0;
width: 24px;
}
/* Interactive States */
button:hover:not(.pressed):not(.disabled):not(.focused),
select:hover:not(.pressed):not(.disabled):not(.focused) {
background-color: #ebebeb;
border: 1px solid #b1b1b1;
}
button:hover:active:not(.hover):not(.disabled):not(.focused),
select:hover:active:not(.hover):not(.disabled):not(.focused) {
background-color: #d4d4d4;
border: 1px solid #858585;
}
button.default:hover:not(.pressed):not(.disabled):not(.focused) {
background-color: #0670cc;
border-color: #005bab;
}
button.default:hover:active:not(.hover):not(.disabled):not(.focused) {
background-color: #005bab;
border-color: #004480;
}
button:focus:not(.disabled) {
border-color: #fff !important;
box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
}
/* Fields */
input[type="text"],
textarea {
background-color: #fff;
border: 1px solid #b1b1b1;
box-shadow: 0 0 0 0 rgba(97, 181, 255, 0);
font: caption;
padding: 0 6px 0;
transition-duration: 250ms;
transition-property: box-shadow;
}
input[type="text"] {
height: 24px;
}
input[type="text"].hover,
textarea.hover {
border: 1px solid #858585;
}
input[type="text"].disabled,
textarea.disabled {
color: #999;
opacity: .5;
}
input[type="text"].focused,
textarea.focused {
border-color: #0996f8;
box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
}
/* Interactive States */
input[type="text"]:not(disabled):hover,
textarea:not(disabled):hover {
border: 1px solid #858585;
}
input[type="text"]:focus,
input[type="text"]:focus:hover,
textarea:focus,
textarea:focus:hover {
border-color: #0996f8;
box-shadow: 0 0 0 2px rgba(97, 181, 255, 0.75);
}
/* stylelint-disable property-no-vendor-prefix */
.panel-section {
display: flex;
flex-direction: row;
}
.panel-section-separator {
background-color: rgba(0, 0, 0, 0.15);
min-height: 1px;
}
/* Panel Section - Header */
.panel-section-header {
border-bottom: 1px solid rgba(0, 0, 0, 0.15);
padding: 16px;
}
.panel-section-header > .icon-section-header {
background-position: center center;
background-repeat: no-repeat;
height: 32px;
margin-right: 16px;
position: relative;
width: 32px;
}
.panel-section-header > .text-section-header {
align-self: center;
font-size: 1.385em;
font-weight: lighter;
}
/* Panel Section - List */
.panel-section-list {
flex-direction: column;
padding: 4px 0;
}
.panel-list-item {
align-items: center;
display: flex;
flex-direction: row;
height: 24px;
padding: 0 16px;
}
.panel-list-item:not(.disabled):hover {
background-color: rgba(0, 0, 0, 0.06);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.panel-list-item:not(.disabled):hover:active {
background-color: rgba(0, 0, 0, 0.1);
}
.panel-list-item.disabled {
color: #999;
}
.panel-list-item > .icon {
flex-grow: 0;
flex-shrink: 0;
}
.panel-list-item > .text {
flex-grow: 10;
}
.panel-list-item > .text-shortcut {
color: #808080;
font-family: "Lucida Grande", caption;
font-size: .847em;
justify-content: flex-end;
}
.panel-section-list .panel-section-separator {
margin: 4px 0;
}
/* Panel Section - Form Elements */
.panel-section-formElements {
display: flex;
flex-direction: column;
padding: 16px;
}
.panel-formElements-item {
align-items: center;
display: flex;
flex-direction: row;
margin-bottom: 12px;
}
.panel-formElements-item:last-child {
margin-bottom: 0;
}
.panel-formElements-item label {
flex-shrink: 0;
margin-right: 6px;
text-align: right;
}
.panel-formElements-item input[type="text"],
.panel-formElements-item select {
flex-grow: 1;
}
/* Panel Section - Footer */
.panel-section-footer {
background-color: rgba(0, 0, 0, 0.06);
border-top: 1px solid rgba(0, 0, 0, 0.15);
color: #1a1a1a;
display: flex;
flex-direction: row;
height: 41px;
margin-top: -1px;
padding: 0;
}
.panel-section-footer-button {
flex: 1 1 auto;
height: 100%;
margin: 0 -1px;
padding: 12px;
text-align: center;
}
.panel-section-footer-button > .text-shortcut {
color: #808080;
font-family: "Lucida Grande", caption;
font-size: .847em;
}
.panel-section-footer-button:hover {
background-color: rgba(0, 0, 0, 0.06);
}
.panel-section-footer-button:hover:active {
background-color: rgba(0, 0, 0, 0.1);
}
.panel-section-footer-button.default {
background-color: #0996f8;
box-shadow: 0 1px 0 #0670cc inset;
color: #fff;
}
.panel-section-footer-button.default:hover {
background-color: #0670cc;
box-shadow: 0 1px 0 #005bab inset;
}
.panel-section-footer-button.default:hover:active {
background-color: #005bab;
box-shadow: 0 1px 0 #004480 inset;
}
.panel-section-footer-separator {
background-color: rgba(0, 0, 0, 0.1);
width: 1px;
z-index: 99;
}
/* Panel Section - Tabs */
.panel-section-tabs {
color: #1a1a1a;
display: flex;
flex-direction: row;
height: 41px;
margin-bottom: -1px;
padding: 0;
}
.panel-section-tabs-button {
flex: 1 1 auto;
height: 100%;
margin: 0 -1px;
padding: 12px;
text-align: center;
}
.panel-section-tabs-button:hover {
background-color: rgba(0, 0, 0, 0.06);
}
.panel-section-tabs-button:hover:active {
background-color: rgba(0, 0, 0, 0.1);
}
.panel-section-tabs-button.selected {
box-shadow: 0 -1px 0 #0670cc inset, 0 -4px 0 #0996f8 inset;
color: #0996f8;
}
.panel-section-tabs-button.selected:hover {
color: #0670cc;
}
.panel-section-tabs-separator {
background-color: rgba(0, 0, 0, 0.1);
width: 1px;
z-index: 99;
}

View File

@ -3,6 +3,8 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
browser.jar:
content/browser/extension.css
content/browser/extension-mac.css
content/browser/extension.svg
content/browser/ext-utils.js
content/browser/ext-commands.js

View File

@ -3,7 +3,7 @@
"use strict";
function* testInArea(area) {
let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head></html>`;
let scriptPage = url => `<html><head><meta charset="utf-8"><script src="${url}"></script></head><body>${url}</body></html>`;
let extension = ExtensionTestUtils.loadExtension({
manifest: {
@ -18,7 +18,13 @@ function* testInArea(area) {
files: {
"popup-a.html": scriptPage("popup-a.js"),
"popup-a.js": function() {
browser.runtime.sendMessage("from-popup-a");
window.onload = () => {
if (window.getComputedStyle(document.body).backgroundColor == "rgb(252, 252, 252)") {
browser.runtime.sendMessage("from-popup-a");
} else {
browser.runtime.sendMessage("popup-a-failed-style-check");
}
};
browser.runtime.onMessage.addListener(msg => {
if (msg == "close-popup") {
window.close();
@ -74,6 +80,8 @@ function* testInArea(area) {
browser.runtime.onMessage.addListener(msg => {
if (msg == "close-popup") {
return;
} else if (msg == "popup-a-failed-style-check") {
browser.test.fail("popup failed style check");
} else if (expect.popup) {
browser.test.assertEq(msg, `from-popup-${expect.popup}`,
"expected popup opened");

View File

@ -255,6 +255,14 @@ panelmultiview[nosubviews=true] > .panel-viewcontainer > .panel-viewstack > .pan
max-width: 800px;
}
.cui-widget-panel[viewId^=PanelUI-webext-] > .panel-arrowcontainer > .panel-arrowcontent {
padding: 0;
}
.cui-widget-panelview[id^=PanelUI-webext-] {
border-radius: 3.5px;
}
panelview:not([mainview]) .toolbarbutton-text,
.cui-widget-panel toolbarbutton > .toolbarbutton-text {
text-align: start;

View File

@ -49,7 +49,7 @@ def checking(what):
# use that value instead.
@template
def check_prog(var, progs, allow_missing=False):
option(env=var, nargs=1, help=var)
option(env=var, nargs=1, help='Path to the %s program' % var.lower())
not_found = 'not found'
progs = list(progs)

View File

@ -260,6 +260,7 @@ def wanted_mozconfig_variables(help):
'MOZ_BUILD_APP',
'PERL',
'RPMBUILD',
'TAR',
'UNZIP',
'XARGS',
'ZIP',
@ -404,6 +405,7 @@ def split_triplet(triplet):
kernel=canonical_kernel,
os=canonical_os,
raw_cpu=cpu,
raw_os=os,
)
@ -466,6 +468,9 @@ def target_variables(target):
if target.cpu in ('x86', 'x86_64'):
set_config('INTEL_ARCHITECTURE', '1')
set_config('TARGET_CPU', target.raw_cpu)
set_config('TARGET_OS', target.raw_os)
@depends(host)
def host_variables(host):
if host.kernel == 'kFreeBSD':

View File

@ -81,10 +81,10 @@ check_mozconfig_variables()
@depends('OLD_CONFIGURE', mozconfig, autoconf, check_build_environment, shell,
old_configure_assignments)
old_configure_assignments, build_project)
@advanced
def prepare_configure(old_configure, mozconfig, autoconf, build_env, shell,
old_configure_assignments):
old_configure_assignments, build_project):
import glob
import itertools
import subprocess
@ -98,6 +98,11 @@ def prepare_configure(old_configure, mozconfig, autoconf, build_env, shell,
# as $0, and backslashes there breaks autoconf's detection of the source
# directory.
old_configure = os.path.abspath(old_configure[0])
if build_project == 'js':
old_configure_dir = os.path.dirname(old_configure)
if not old_configure_dir.endswith('/js/src'):
old_configure = os.path.join(old_configure_dir, 'js', 'src',
os.path.basename(old_configure))
refresh = True
if os.path.exists(old_configure):
@ -137,6 +142,10 @@ def prepare_configure(old_configure, mozconfig, autoconf, build_env, shell,
for key in mozconfig[t]['removed'].keys():
print("unset %s" % key, file=out)
# Autoconf is special, because it might be passed from
# mozconfig['make_extra'], which we don't pass automatically above.
print('export AUTOCONF=%s' % quote(autoconf), file=out)
for assignment in old_configure_assignments:
print(assignment, file=out)

View File

@ -24,6 +24,10 @@ def main(argv):
if sandbox._help:
return 0
return config_status(config)
def config_status(config):
# Sanitize config data to feed config.status
sanitized_config = {}
sanitized_config['substs'] = {
@ -43,6 +47,10 @@ def main(argv):
with codecs.open('config.status', 'w', encoding) as fh:
fh.write('#!%s\n' % config['PYTHON'])
fh.write('# coding=%s\n' % encoding)
# Because we're serializing as JSON but reading as python, the values
# for True, False and None are true, false and null, which don't exist.
# Define them.
fh.write('true, false, null = True, False, None\n')
for k, v in sanitized_config.iteritems():
fh.write('%s = ' % k)
json.dump(v, fh, sort_keys=True, indent=4, ensure_ascii=False)
@ -69,5 +77,6 @@ if __name__ == '__main__':
return subprocess.call([config['PYTHON'], 'config.status'])
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv))

View File

@ -27,6 +27,7 @@ const POLICY_REPORT_ONLY = "report-only"
// special handling of directives
const DIR_UPGRADE_INSECURE = "upgrade-insecure-requests";
const DIR_BLOCK_ALL_MIXED_CONTENT = "block-all-mixed-content";
// special handling of sources
const SRC_UNSAFE_INLINE = "'unsafe-inline'";
@ -89,13 +90,15 @@ exports.items = [
// loop over all the directive-sources within that directive
var outSrcs = [];
// special case handling for upgrade-insecure-requests
// which does not have any srcs
if (dir === DIR_UPGRADE_INSECURE) {
// special case handling for the directives
// upgrade-insecure-requests and block-all-mixed-content
// which do not include any srcs
if (dir === DIR_UPGRADE_INSECURE ||
dir === DIR_BLOCK_ALL_MIXED_CONTENT) {
outSrcs.push({
icon: GOOD_IMG_SRC,
src: "", // no src for upgrade-insecure-requests
desc: "" // no description for upgrade-insecure-requests
src: "", // no src
desc: "" // no description
});
}

View File

@ -334,7 +334,9 @@ AutoJSAPI::InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread)
{
MOZ_ASSERT(aCx);
MOZ_ASSERT(aIsMainThread == NS_IsMainThread());
MOZ_ASSERT(!JS_IsExceptionPending(aCx));
#ifdef DEBUG
bool haveException = JS_IsExceptionPending(aCx);
#endif // DEBUG
mCx = aCx;
mIsMainThread = aIsMainThread;
@ -356,6 +358,72 @@ AutoJSAPI::InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread)
if (aIsMainThread) {
JS_SetErrorReporter(rt, xpc::SystemErrorReporter);
}
#ifdef DEBUG
if (haveException) {
JS::Rooted<JS::Value> exn(aCx);
JS_GetPendingException(aCx, &exn);
JS_ClearPendingException(aCx);
if (exn.isObject()) {
JS::Rooted<JSObject*> exnObj(aCx, &exn.toObject());
nsAutoJSString stack, filename, name, message;
int32_t line;
JS::Rooted<JS::Value> tmp(aCx);
if (!JS_GetProperty(aCx, exnObj, "filename", &tmp)) {
JS_ClearPendingException(aCx);
}
if (tmp.isUndefined()) {
if (!JS_GetProperty(aCx, exnObj, "fileName", &tmp)) {
JS_ClearPendingException(aCx);
}
}
if (!filename.init(aCx, tmp)) {
JS_ClearPendingException(aCx);
}
if (!JS_GetProperty(aCx, exnObj, "stack", &tmp) ||
!stack.init(aCx, tmp)) {
JS_ClearPendingException(aCx);
}
if (!JS_GetProperty(aCx, exnObj, "name", &tmp) ||
!name.init(aCx, tmp)) {
JS_ClearPendingException(aCx);
}
if (!JS_GetProperty(aCx, exnObj, "message", &tmp) ||
!message.init(aCx, tmp)) {
JS_ClearPendingException(aCx);
}
if (!JS_GetProperty(aCx, exnObj, "lineNumber", &tmp) ||
!JS::ToInt32(aCx, tmp, &line)) {
JS_ClearPendingException(aCx);
line = 0;
}
printf_stderr("PREEXISTING EXCEPTION OBJECT: '%s: %s'\n%s:%d\n%s\n",
NS_ConvertUTF16toUTF8(name).get(),
NS_ConvertUTF16toUTF8(message).get(),
NS_ConvertUTF16toUTF8(filename).get(), line,
NS_ConvertUTF16toUTF8(stack).get());
} else {
// It's a primitive... not much we can do other than stringify it.
nsAutoJSString exnStr;
if (!exnStr.init(aCx, exn)) {
JS_ClearPendingException(aCx);
}
printf_stderr("PREEXISTING EXCEPTION PRIMITIVE: %s\n",
NS_ConvertUTF16toUTF8(exnStr).get());
}
MOZ_ASSERT(false, "We had an exception; we should not have");
}
#endif // DEBUG
}
AutoJSAPI::AutoJSAPI(nsIGlobalObject* aGlobalObject,

View File

@ -197,7 +197,8 @@ TextInputProcessor::BeginInputTransactionInternal(
}
if (aForTests) {
rv = dispatcher->BeginInputTransactionForTests(this);
bool isAPZAware = gfxPrefs::TestEventsAsyncEnabled();
rv = dispatcher->BeginTestInputTransaction(this, isAPZAware);
} else {
rv = dispatcher->BeginInputTransaction(this);
}
@ -631,8 +632,11 @@ TextInputProcessor::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
const IMENotification& aNotification)
{
// If This is called while this is being initialized, ignore the call.
// In such case, this method should return NS_ERROR_NOT_IMPLEMENTED because
// we can say, TextInputProcessor doesn't implement any handlers of the
// requests and notifications.
if (!mDispatcher) {
return NS_ERROR_NOT_AVAILABLE;
return NS_ERROR_NOT_IMPLEMENTED;
}
MOZ_ASSERT(aTextEventDispatcher == mDispatcher,
"Wrong TextEventDispatcher notifies this");
@ -701,6 +705,16 @@ TextInputProcessor::OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher)
UnlinkFromTextEventDispatcher();
}
NS_IMETHODIMP_(void)
TextInputProcessor::WillDispatchKeyboardEvent(
TextEventDispatcher* aTextEventDispatcher,
WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aIndexOfKeypress,
void* aData)
{
// TextInputProcessor doesn't set alternative char code.
}
nsresult
TextInputProcessor::PrepareKeyboardEventToDispatch(
WidgetKeyboardEvent& aKeyboardEvent,
@ -776,23 +790,6 @@ TextInputProcessor::Keydown(nsIDOMKeyEvent* aDOMKeyEvent,
return KeydownInternal(*originalKeyEvent, aKeyFlags, true, *aConsumedFlags);
}
TextEventDispatcher::DispatchTo
TextInputProcessor::GetDispatchTo() const
{
// Support asynchronous tests.
if (mForTests) {
return gfxPrefs::TestEventsAsyncEnabled() ?
TextEventDispatcher::eDispatchToParentProcess :
TextEventDispatcher::eDispatchToCurrentProcess;
}
// Otherwise, TextInputProcessor supports only keyboard apps on B2G.
// Keyboard apps on B2G doesn't want to dispatch keyboard events to
// chrome process. Therefore, this should dispatch key events only in
// the current process.
return TextEventDispatcher::eDispatchToCurrentProcess;
}
nsresult
TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aKeyFlags,
@ -838,8 +835,7 @@ TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
nsEventStatus status = aConsumedFlags ? nsEventStatus_eConsumeNoDefault :
nsEventStatus_eIgnore;
if (!mDispatcher->DispatchKeyboardEvent(eKeyDown, keyEvent, status,
GetDispatchTo())) {
if (!mDispatcher->DispatchKeyboardEvent(eKeyDown, keyEvent, status)) {
// If keydown event isn't dispatched, we don't need to dispatch keypress
// events.
return NS_OK;
@ -850,8 +846,7 @@ TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
KEYEVENT_NOT_CONSUMED;
if (aAllowToDispatchKeypress &&
mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status,
GetDispatchTo())) {
mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status)) {
aConsumedFlags |=
(status == nsEventStatus_eConsumeNoDefault) ? KEYPRESS_IS_CONSUMED :
KEYEVENT_NOT_CONSUMED;
@ -920,7 +915,7 @@ TextInputProcessor::KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent,
nsEventStatus status = aDoDefault ? nsEventStatus_eIgnore :
nsEventStatus_eConsumeNoDefault;
mDispatcher->DispatchKeyboardEvent(eKeyUp, keyEvent, status, GetDispatchTo());
mDispatcher->DispatchKeyboardEvent(eKeyUp, keyEvent, status);
aDoDefault = (status != nsEventStatus_eConsumeNoDefault);
return NS_OK;
}

View File

@ -36,6 +36,12 @@ public:
NS_IMETHOD_(void)
OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) override;
NS_IMETHOD_(void) WillDispatchKeyboardEvent(
TextEventDispatcher* aTextEventDispatcher,
WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aIndexOfKeypress,
void* aData) override;
protected:
virtual ~TextInputProcessor();
@ -61,7 +67,6 @@ private:
nsresult KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aKeyFlags,
bool& aDoDefault);
TextEventDispatcher::DispatchTo GetDispatchTo() const;
nsresult IsValidStateForComposition();
void UnlinkFromTextEventDispatcher();
nsresult PrepareKeyboardEventToDispatch(WidgetKeyboardEvent& aKeyboardEvent,

View File

@ -1429,6 +1429,8 @@ nsIDocument::nsIDocument()
: nsINode(nullNodeInfo),
mReferrerPolicySet(false),
mReferrerPolicy(mozilla::net::RP_Default),
mBlockAllMixedContent(false),
mBlockAllMixedContentPreloads(false),
mUpgradeInsecureRequests(false),
mUpgradeInsecurePreloads(false),
mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
@ -2592,13 +2594,18 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
treeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
if (sameTypeParent) {
mUpgradeInsecureRequests =
sameTypeParent->GetDocument()->GetUpgradeInsecureRequests(false);
nsIDocument* doc = sameTypeParent->GetDocument();
mBlockAllMixedContent = doc->GetBlockAllMixedContent(false);
// if the parent document makes use of block-all-mixed-content
// then subdocument preloads should always be blocked.
mBlockAllMixedContentPreloads =
mBlockAllMixedContent || doc->GetBlockAllMixedContent(true);
mUpgradeInsecureRequests = doc->GetUpgradeInsecureRequests(false);
// if the parent document makes use of upgrade-insecure-requests
// then subdocument preloads should always be upgraded.
mUpgradeInsecurePreloads =
mUpgradeInsecureRequests ||
sameTypeParent->GetDocument()->GetUpgradeInsecureRequests(true);
mUpgradeInsecureRequests || doc->GetUpgradeInsecureRequests(true);
}
}
@ -2697,6 +2704,16 @@ nsDocument::ApplySettingsFromCSP(bool aSpeculative)
mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
mReferrerPolicySet = true;
}
// Set up 'block-all-mixed-content' if not already inherited
// from the parent context or set by any other CSP.
if (!mBlockAllMixedContent) {
rv = csp->GetBlockAllMixedContent(&mBlockAllMixedContent);
NS_ENSURE_SUCCESS_VOID(rv);
}
if (!mBlockAllMixedContentPreloads) {
mBlockAllMixedContentPreloads = mBlockAllMixedContent;
}
// Set up 'upgrade-insecure-requests' if not already inherited
// from the parent context or set by any other CSP.
@ -2712,12 +2729,17 @@ nsDocument::ApplySettingsFromCSP(bool aSpeculative)
}
// 2) apply settings from speculative csp
if (!mUpgradeInsecurePreloads) {
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
rv = NodePrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
NS_ENSURE_SUCCESS_VOID(rv);
if (preloadCsp) {
preloadCsp->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
rv = NodePrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
NS_ENSURE_SUCCESS_VOID(rv);
if (preloadCsp) {
if (!mBlockAllMixedContentPreloads) {
rv = preloadCsp->GetBlockAllMixedContent(&mBlockAllMixedContentPreloads);
NS_ENSURE_SUCCESS_VOID(rv);
}
if (!mUpgradeInsecurePreloads) {
rv = preloadCsp->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
NS_ENSURE_SUCCESS_VOID(rv);
}
}
}

View File

@ -401,50 +401,66 @@ nsHTMLContentSerializer::AppendElementEnd(Element* aElement,
}
static const uint16_t kValNBSP = 160;
static const char* kEntities[] = {
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "&amp;", nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
"&lt;", nullptr, "&gt;", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
"&nbsp;"
#define _ 0
// This table indexes into kEntityStrings[].
static const uint8_t kEntities[] = {
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, 2, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
3, _, 4, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
5
};
static const char* kAttrEntities[] = {
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, "&quot;", nullptr, nullptr, nullptr, "&amp;", nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
"&lt;", nullptr, "&gt;", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
"&nbsp;"
// This table indexes into kEntityStrings[].
static const uint8_t kAttrEntities[] = {
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, 1, _, _, _, 2, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
3, _, 4, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
5
};
#undef _
static const char* const kEntityStrings[] = {
/* 0 */ nullptr,
/* 1 */ "&quot;",
/* 2 */ "&amp;",
/* 3 */ "&lt;",
/* 4 */ "&gt;",
/* 5 */ "&nbsp;"
};
uint32_t FindNextBasicEntity(const nsAString& aStr,
const uint32_t aLen,
uint32_t aIndex,
const char** aEntityTable,
const uint8_t* aEntityTable,
const char** aEntity)
{
for (; aIndex < aLen; ++aIndex) {
@ -452,7 +468,7 @@ uint32_t FindNextBasicEntity(const nsAString& aStr,
// needs to be replaced
char16_t val = aStr[aIndex];
if (val <= kValNBSP && aEntityTable[val]) {
*aEntity = aEntityTable[val];
*aEntity = kEntityStrings[aEntityTable[val]];
return aIndex;
}
}
@ -478,7 +494,7 @@ nsHTMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
if (!nonBasicEntities &&
(mFlags & (nsIDocumentEncoder::OutputEncodeBasicEntities))) {
const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
const uint8_t* entityTable = mInAttribute ? kAttrEntities : kEntities;
uint32_t start = 0;
const uint32_t len = aStr.Length();
for (uint32_t i = 0; i < len; ++i) {
@ -510,7 +526,7 @@ nsHTMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
uint32_t advanceLength = 0;
nsReadingIterator<char16_t> iter;
const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
const uint8_t* entityTable = mInAttribute ? kAttrEntities : kEntities;
nsAutoCString entityReplacement;
for (aStr.BeginReading(iter);
@ -532,7 +548,7 @@ nsHTMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
for (; c < fragmentEnd; c++, advanceLength++) {
char16_t val = *c;
if (val <= kValNBSP && entityTable[val]) {
fullConstEntityText = entityTable[val];
fullConstEntityText = kEntityStrings[entityTable[val]];
break;
} else if (val > 127 &&
((val < 256 &&

View File

@ -316,6 +316,19 @@ public:
return GetReferrerPolicy();
}
/**
* If true, this flag indicates that all mixed content subresource
* loads for this document (and also embeded browsing contexts) will
* be blocked.
*/
bool GetBlockAllMixedContent(bool aPreload) const
{
if (aPreload) {
return mBlockAllMixedContentPreloads;
}
return mBlockAllMixedContent;
}
/**
* If true, this flag indicates that all subresource loads for this
* document need to be upgraded from http to https.
@ -2766,6 +2779,8 @@ protected:
bool mReferrerPolicySet;
ReferrerPolicyEnum mReferrerPolicy;
bool mBlockAllMixedContent;
bool mBlockAllMixedContentPreloads;
bool mUpgradeInsecureRequests;
bool mUpgradeInsecurePreloads;

View File

@ -1193,24 +1193,39 @@ nsXMLContentSerializer::AppendToString(const nsAString& aStr,
static const uint16_t kGTVal = 62;
static const char* kEntities[] = {
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "&amp;", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"&lt;", "", "&gt;"
#define _ 0
// This table indexes into kEntityStrings[].
static const uint8_t kEntities[] = {
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, 2, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
3, _, 4
};
static const char* kAttrEntities[] = {
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "&quot;", "", "", "", "&amp;", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"&lt;", "", "&gt;"
// This table indexes into kEntityStrings[].
static const uint8_t kAttrEntities[] = {
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, 1, _, _, _, 2, _,
_, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _,
3, _, 4
};
#undef _
static const char* const kEntityStrings[] = {
/* 0 */ nullptr,
/* 1 */ "&quot;",
/* 2 */ "&amp;",
/* 3 */ "&lt;",
/* 4 */ "&gt;",
};
bool
@ -1224,7 +1239,7 @@ nsXMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
uint32_t advanceLength = 0;
nsReadingIterator<char16_t> iter;
const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
const uint8_t* entityTable = mInAttribute ? kAttrEntities : kEntities;
for (aStr.BeginReading(iter);
iter != done_reading;
@ -1240,8 +1255,8 @@ nsXMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
// needs to be replaced
for (; c < fragmentEnd; c++, advanceLength++) {
char16_t val = *c;
if ((val <= kGTVal) && (entityTable[val][0] != 0)) {
entityText = entityTable[val];
if ((val <= kGTVal) && entityTable[val]) {
entityText = kEntityStrings[entityTable[val]];
break;
}
}

View File

@ -55,7 +55,7 @@
namespace mozilla {
namespace dom {
JSErrorFormatString ErrorFormatString[] = {
const JSErrorFormatString ErrorFormatString[] = {
#define MSG_DEF(_name, _argc, _exn, _str) \
{ #_name, _str, _argc, _exn },
#include "mozilla/dom/Errors.msg"

View File

@ -12,6 +12,7 @@
#include "GLContext.h"
#include "WebGLContext.h"
#include "WebGLTimerQuery.h"
#include "gfxPrefs.h"
namespace mozilla {
@ -117,6 +118,7 @@ WebGLExtensionDisjointTimerQuery::EndQueryEXT(GLenum target)
mContext->MakeContextCurrent();
mContext->GL()->fEndQuery(target);
mActiveQuery->QueueAvailablity();
mActiveQuery = nullptr;
}
@ -139,6 +141,7 @@ WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLTimerQuery* query,
mContext->MakeContextCurrent();
mContext->GL()->fQueryCounter(query->mGLName, target);
query->mTarget = LOCAL_GL_TIMESTAMP_EXT;
query->QueueAvailablity();
}
void
@ -221,7 +224,8 @@ WebGLExtensionDisjointTimerQuery::GetQueryObjectEXT(JSContext* cx,
mContext->GL()->fGetQueryObjectuiv(query->mGLName,
LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT,
&avail);
retval.set(JS::BooleanValue(bool(avail)));
bool canBeAvailable = query->CanBeAvailable() || gfxPrefs::WebGLImmediateQueries();
retval.set(JS::BooleanValue(bool(avail) && canBeAvailable));
break;
}
default:

View File

@ -118,7 +118,7 @@ ShaderOutput(gl::GLContext* gl)
}
}
return SH_GLSL_OUTPUT;
return SH_GLSL_COMPATIBILITY_OUTPUT;
}
webgl::ShaderValidator*
@ -129,7 +129,7 @@ WebGLContext::CreateShaderValidator(GLenum shaderType) const
ShShaderSpec spec = IsWebGL2() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC;
ShShaderOutput outputLanguage = gl->IsGLES() ? SH_ESSL_OUTPUT
: SH_GLSL_OUTPUT;
: SH_GLSL_COMPATIBILITY_OUTPUT;
// If we're using WebGL2 we want a more specific version of GLSL
if (IsWebGL2())

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "nsContentUtils.h"
#include "WebGLContext.h"
#include "nsThreadUtils.h"
namespace mozilla {
@ -23,6 +24,7 @@ WebGLTimerQuery::WebGLTimerQuery(WebGLContext* webgl, GLuint name)
: WebGLContextBoundObject(webgl)
, mGLName(name)
, mTarget(LOCAL_GL_NONE)
, mCanBeAvailable(false)
{
}
@ -53,6 +55,12 @@ WebGLTimerQuery::GetParentObject() const
return mContext;
}
void
WebGLTimerQuery::QueueAvailablity()
{
RefPtr<WebGLTimerQuery> self = this;
NS_DispatchToCurrentThread(NS_NewRunnableFunction([self] { self->mCanBeAvailable = true; }));
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTimerQuery)

View File

@ -24,6 +24,8 @@ public:
void Delete();
bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; }
bool CanBeAvailable() const { return mCanBeAvailable; }
void QueueAvailablity();
GLenum Target() const { return mTarget; }
WebGLContext* GetParentObject() const;
@ -41,6 +43,7 @@ private:
~WebGLTimerQuery();
GLenum mTarget;
bool mCanBeAvailable;
friend class WebGLExtensionDisjointTimerQuery;
};

View File

@ -15,7 +15,7 @@ fail-if = (os == 'android')
[webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html]
fail-if = (os == 'android')
[webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html]
fail-if = (os == 'android') || (os == 'mac') || (os == 'win')
fail-if = (os == 'android') || (os == 'mac') || (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
[webgl-mochitest/ensure-exts/test_EXT_frag_depth.html]
fail-if = (os == 'android')
[webgl-mochitest/ensure-exts/test_EXT_sRGB.html]

View File

@ -15,11 +15,11 @@
namespace mozilla {
namespace dom {
static const char* labelsEncodings[][3] = {
static const char* const labelsEncodings[][3] = {
#include "labelsencodings.properties.h"
};
static const char* encodingsGroups[][3] = {
static const char* const encodingsGroups[][3] = {
#include "encodingsgroups.properties.h"
};

View File

@ -15,15 +15,15 @@
namespace mozilla {
namespace dom {
static const char* localesFallbacks[][3] = {
static const char* const localesFallbacks[][3] = {
#include "localesfallbacks.properties.h"
};
static const char* domainsFallbacks[][3] = {
static const char* const domainsFallbacks[][3] = {
#include "domainsfallbacks.properties.h"
};
static const char* nonParticipatingDomains[][3] = {
static const char* const nonParticipatingDomains[][3] = {
#include "nonparticipatingdomains.properties.h"
};

View File

@ -85,9 +85,46 @@ private:
uint32_t mInitialCount;
};
static bool IsEventTargetChrome(EventTarget* aEventTarget,
nsIDocument** aDocument = nullptr)
{
if (aDocument) {
*aDocument = nullptr;
}
if (NS_WARN_IF(!aEventTarget)) {
return false;
}
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aEventTarget);
if (!doc) {
nsCOMPtr<nsINode> node = do_QueryInterface(aEventTarget);
if (node) {
doc = node->OwnerDoc();
} else {
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aEventTarget);
if (!window) {
return false;
}
doc = window->GetExtantDoc();
}
if (!doc) {
return false;
}
}
bool isChrome = nsContentUtils::IsChromeDoc(doc);
if (aDocument) {
doc.swap(*aDocument);
}
return isChrome;
}
#define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH (1 << 0)
#define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1)
#define NS_TARGET_CHAIN_MAY_HAVE_MANAGER (1 << 2)
#define NS_TARGET_CHAIN_CHECKED_IF_CHROME (1 << 3)
#define NS_TARGET_CHAIN_IS_CHROME_CONTENT (1 << 4)
// EventTargetChainItem represents a single item in the event target chain.
class EventTargetChainItem
@ -210,6 +247,11 @@ public:
if (aVisitor.mEvent->mFlags.mPropagationStopped) {
return;
}
if (aVisitor.mEvent->mFlags.mOnlySystemGroupDispatchInContent &&
!aVisitor.mEvent->mFlags.mInSystemGroup &&
!IsCurrentTargetChrome()) {
return;
}
if (!mManager) {
if (!MayHaveListenerManager() && !aCd.MayHaveNewListenerManager()) {
return;
@ -233,6 +275,7 @@ public:
*/
void PostHandleEvent(EventChainPostVisitor& aVisitor);
private:
nsCOMPtr<EventTarget> mTarget;
uint16_t mFlags;
uint16_t mItemFlags;
@ -241,6 +284,17 @@ public:
nsCOMPtr<EventTarget> mNewTarget;
// Cache mTarget's event listener manager.
RefPtr<EventListenerManager> mManager;
bool IsCurrentTargetChrome()
{
if (!(mFlags & NS_TARGET_CHAIN_CHECKED_IF_CHROME)) {
mFlags |= NS_TARGET_CHAIN_CHECKED_IF_CHROME;
if (IsEventTargetChrome(mTarget)) {
mFlags |= NS_TARGET_CHAIN_IS_CHROME_CONTENT;
}
}
return !!(mFlags & NS_TARGET_CHAIN_IS_CHROME_CONTENT);
}
};
EventTargetChainItem::EventTargetChainItem(EventTarget* aTarget)
@ -468,18 +522,9 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
}
if (aEvent->mFlags.mOnlyChromeDispatch) {
nsCOMPtr<nsINode> node = do_QueryInterface(aTarget);
if (!node) {
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aTarget);
if (win) {
node = win->GetExtantDoc();
}
}
NS_ENSURE_STATE(node);
nsIDocument* doc = node->OwnerDoc();
if (!nsContentUtils::IsChromeDoc(doc)) {
nsPIDOMWindowInner* win = doc ? doc->GetInnerWindow() : nullptr;
nsCOMPtr<nsIDocument> doc;
if (!IsEventTargetChrome(target, getter_AddRefs(doc)) && doc) {
nsPIDOMWindowInner* win = doc->GetInnerWindow();
// If we can't dispatch the event to chrome, do nothing.
EventTarget* piTarget = win ? win->GetParentTarget() : nullptr;
if (!piTarget) {
@ -490,6 +535,8 @@ EventDispatcher::Dispatch(nsISupports* aTarget,
aEvent->target = target;
// but use chrome event handler or TabChildGlobal for event target chain.
target = piTarget;
} else if (NS_WARN_IF(!doc)) {
return NS_ERROR_UNEXPECTED;
}
}

View File

@ -52,6 +52,7 @@ interface nsIContentSecurityPolicy : nsISerializable
const unsigned short WEB_MANIFEST_SRC_DIRECTIVE = 16;
const unsigned short UPGRADE_IF_INSECURE_DIRECTIVE = 17;
const unsigned short CHILD_SRC_DIRECTIVE = 18;
const unsigned short BLOCK_ALL_MIXED_CONTENT = 19;
/**
* Accessor method for a read-only string version of the policy at a given
@ -72,6 +73,15 @@ interface nsIContentSecurityPolicy : nsISerializable
*/
readonly attribute bool upgradeInsecureRequests;
/**
* Returns whether this policy uses the directive block-all-mixed-content.
* Please note that block-all-mixed-content takes presedence in case the
* directive upgrade-insecure-requests is defined in the same policy and
* will therefore block all mixed content without even trying to perform
* an upgrade.
*/
readonly attribute bool blockAllMixedContent;
/**
* Obtains the referrer policy (as integer) for this browsing context as
* specified in CSP. If there are multiple policies and...

View File

@ -68,6 +68,9 @@ hostNameMightBeKeyword = Interpreting %1$S as a hostname, not a keyword. If you
# LOCALIZATION NOTE (notSupportingDirective):
# directive is not supported (e.g. 'reflected-xss')
notSupportingDirective = Not supporting directive '%1$S'. Directive and values will be ignored.
# LOCALIZATION NOTE (blockAllMixedContent):
# %1$S is the URL of the blocked resource load.
blockAllMixedContent = Blocking insecure request '%1$S'.
# CSP Errors:
# LOCALIZATION NOTE (couldntParseInvalidSource):

View File

@ -1,12 +0,0 @@
#
# 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/.
INSTALL_TARGETS += FAKE_GMP_OPENH264_PLUGIN
FAKE_GMP_OPENH264_PLUGIN_DEST = $(DEPTH)/dist/bin/gmp-fakeopenh264/1.0
FAKE_GMP_OPENH264_PLUGIN_FILES = \
$(srcdir)/fakeopenh264.info \
$(srcdir)/fakeopenh264.voucher \
$(NULL)

View File

@ -7,6 +7,12 @@
# largely a copy of dom/media/gmp-fake/moz.build
FINAL_TARGET = 'dist/bin/gmp-fakeopenh264/1.0'
FINAL_TARGET_FILES += [
'fakeopenh264.info',
'fakeopenh264.voucher',
]
SOURCES += [
'gmp-fake-openh264.cpp',
]

View File

@ -1,13 +0,0 @@
#
# 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/.
INSTALL_TARGETS += FAKE_GMP_PLUGIN
FAKE_GMP_PLUGIN_DEST = $(DEPTH)/dist/bin/gmp-fake/1.0
FAKE_GMP_PLUGIN_FILES = \
$(SHARED_LIBRARY) \
$(srcdir)/fake.info \
$(srcdir)/fake.voucher
include $(topsrcdir)/config/rules.mk

View File

@ -4,7 +4,13 @@
# 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/.
DIST_INSTALL = False
FINAL_TARGET = 'dist/bin/gmp-fake/1.0'
FINAL_TARGET_FILES += [
'fake.info',
'fake.voucher',
]
SOURCES += [
'gmp-fake.cpp',
'gmp-test-decryptor.cpp',

View File

@ -124,6 +124,11 @@ mozilla::plugins::SetupBridge(uint32_t aPluginId,
return true;
}
PluginModuleChromeParent* chromeParent = static_cast<PluginModuleChromeParent*>(plugin->GetLibrary());
/*
* We can't accumulate BLOCKED_ON_PLUGIN_MODULE_INIT_MS until here because
* its histogram key is not available until *after* NP_Initialize.
*/
chromeParent->AccumulateModuleInitBlockedTime();
*rv = chromeParent->GetRunID(runID);
if (NS_FAILED(*rv)) {
return true;
@ -401,13 +406,16 @@ PluginModuleContentParent::LoadModule(uint32_t aPluginId,
dom::ContentChild* cp = dom::ContentChild::GetSingleton();
nsresult rv;
uint32_t runID;
TimeStamp sendLoadPluginStart = TimeStamp::Now();
if (!cp->SendLoadPlugin(aPluginId, &rv, &runID) ||
NS_FAILED(rv)) {
return nullptr;
}
TimeStamp sendLoadPluginEnd = TimeStamp::Now();
PluginModuleContentParent* parent = mapping->GetModule();
MOZ_ASSERT(parent);
parent->mTimeBlocked += (sendLoadPluginEnd - sendLoadPluginStart);
if (!mapping->IsChannelOpened()) {
// mapping is linked into PluginModuleMapping::sModuleListHead and is
@ -2626,6 +2634,18 @@ public:
}
};
void
PluginModuleParent::AccumulateModuleInitBlockedTime()
{
if (mPluginName.IsEmpty()) {
GetPluginDetails();
}
Telemetry::Accumulate(Telemetry::BLOCKED_ON_PLUGIN_MODULE_INIT_MS,
GetHistogramKey(),
static_cast<uint32_t>(mTimeBlocked.ToMilliseconds()));
mTimeBlocked = TimeDuration();
}
nsresult
PluginModuleParent::NPP_NewInternal(NPMIMEType pluginType, NPP instance,
uint16_t mode,
@ -2640,12 +2660,9 @@ PluginModuleParent::NPP_NewInternal(NPMIMEType pluginType, NPP instance,
* on plugin module initialization. As implemented, this is the sum of
* plugin-container launch + toolhelp32 snapshot + NP_Initialize.
* We don't accumulate its value until here because the plugin info
* is not available until *after* NP_Initialize.
* for its histogram key is not available until *after* NP_Initialize.
*/
Telemetry::Accumulate(Telemetry::BLOCKED_ON_PLUGIN_MODULE_INIT_MS,
GetHistogramKey(),
static_cast<uint32_t>(mTimeBlocked.ToMilliseconds()));
mTimeBlocked = TimeDuration();
AccumulateModuleInitBlockedTime();
}
nsCaseInsensitiveUTF8StringArrayComparator comparator;

View File

@ -136,6 +136,8 @@ public:
return mPluginName + mPluginVersion;
}
void AccumulateModuleInitBlockedTime();
virtual nsresult GetRunID(uint32_t* aRunID) override;
virtual void SetHasLocalInstance() override {
mHadLocalInstance = true;

View File

@ -308,6 +308,19 @@ nsCSPContext::GetUpgradeInsecureRequests(bool *outUpgradeRequest)
return NS_OK;
}
NS_IMETHODIMP
nsCSPContext::GetBlockAllMixedContent(bool *outBlockAllMixedContent)
{
*outBlockAllMixedContent = false;
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
if (mPolicies[i]->hasDirective(nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT)) {
*outBlockAllMixedContent = true;
return NS_OK;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsCSPContext::GetReferrerPolicy(uint32_t* outPolicy, bool* outIsSet)
{

View File

@ -1008,6 +1008,11 @@ nsCSPParser::directiveName()
return nullptr;
}
// special case handling for block-all-mixed-content
if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT)) {
return new nsBlockAllMixedContentDirective(CSP_StringToCSPDirective(mCurToken));
}
// special case handling for upgrade-insecure-requests
if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
return new nsUpgradeInsecureDirective(CSP_StringToCSPDirective(mCurToken));
@ -1059,6 +1064,20 @@ nsCSPParser::directive()
return;
}
// special case handling for block-all-mixed-content, which is only specified
// by a directive name but does not include any srcs.
if (cspDir->equals(nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT)) {
if (mCurDir.Length() > 1) {
const char16_t* params[] = { MOZ_UTF16("block-all-mixed-content") };
logWarningErrorToConsole(nsIScriptError::warningFlag,
"ignoreSrcForDirective",
params, ArrayLength(params));
}
// add the directive and return
mPolicy->addDirective(cspDir);
return;
}
// special case handling for upgrade-insecure-requests, which is only specified
// by a directive name but does not include any srcs.
if (cspDir->equals(nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {

View File

@ -902,6 +902,11 @@ nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const
outCSP.mForm_action.Value() = mozilla::Move(srcs);
return;
case nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT:
outCSP.mBlock_all_mixed_content.Construct();
// does not have any srcs
return;
case nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE:
outCSP.mUpgrade_insecure_requests.Construct();
// does not have any srcs
@ -987,6 +992,24 @@ bool nsCSPChildSrcDirective::equals(CSPDirective aDirective) const
return (aDirective == nsIContentSecurityPolicy::CHILD_SRC_DIRECTIVE);
}
/* =============== nsBlockAllMixedContentDirective ============= */
nsBlockAllMixedContentDirective::nsBlockAllMixedContentDirective(CSPDirective aDirective)
: nsCSPDirective(aDirective)
{
}
nsBlockAllMixedContentDirective::~nsBlockAllMixedContentDirective()
{
}
void
nsBlockAllMixedContentDirective::toString(nsAString& outStr) const
{
outStr.AppendASCII(CSP_CSPDirectiveToString(
nsIContentSecurityPolicy::BLOCK_ALL_MIXED_CONTENT));
}
/* =============== nsUpgradeInsecureDirective ============= */
nsUpgradeInsecureDirective::nsUpgradeInsecureDirective(CSPDirective aDirective)

View File

@ -88,7 +88,8 @@ static const char* CSPStrDirectives[] = {
"referrer", // REFERRER_DIRECTIVE
"manifest-src", // MANIFEST_SRC_DIRECTIVE
"upgrade-insecure-requests", // UPGRADE_IF_INSECURE_DIRECTIVE
"child-src" // CHILD_SRC_DIRECTIVE
"child-src", // CHILD_SRC_DIRECTIVE
"block-all-mixed-content" // BLOCK_ALL_MIXED_CONTENT
};
inline const char* CSP_CSPDirectiveToString(CSPDirective aDir)
@ -343,6 +344,29 @@ class nsCSPChildSrcDirective : public nsCSPDirective {
bool mHandleFrameSrc;
};
/* =============== nsBlockAllMixedContentDirective === */
class nsBlockAllMixedContentDirective : public nsCSPDirective {
public:
explicit nsBlockAllMixedContentDirective(CSPDirective aDirective);
~nsBlockAllMixedContentDirective();
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
bool aReportOnly, bool aUpgradeInsecure) const
{ return false; }
bool permits(nsIURI* aUri) const
{ return false; }
bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const
{ return false; }
void toString(nsAString& outStr) const;
void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs)
{ MOZ_ASSERT(false, "block-all-mixed-content does not hold any srcs"); }
};
/* =============== nsUpgradeInsecureDirective === */
/*

View File

@ -632,6 +632,35 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
return NS_OK;
}
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
NS_ENSURE_TRUE(docShell, NS_OK);
// The page might have set the CSP directive 'block-all-mixed-content' which
// should block not only active mixed content loads but in fact all mixed content
// loads, see https://www.w3.org/TR/mixed-content/#strict-checking
// Block all non secure loads in case the CSP directive is present. Please note
// that at this point we already know, based on |schemeSecure| that the load is
// not secure, so we can bail out early at this point.
if (docShell->GetDocument()->GetBlockAllMixedContent(isPreload)) {
// log a message to the console before returning.
nsAutoCString spec;
rv = aContentLocation->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
NS_ConvertUTF8toUTF16 reportSpec(spec);
const char16_t* params[] = { reportSpec.get()};
CSP_LogLocalizedStr(MOZ_UTF16("blockAllMixedContent"),
params, ArrayLength(params),
EmptyString(), // aSourceFile
EmptyString(), // aScriptSample
0, // aLineNumber
0, // aColumnNumber
nsIScriptError::errorFlag, "CSP",
docShell->GetDocument()->InnerWindowID());
*aDecision = REJECT_REQUEST;
return NS_OK;
}
// Disallow mixed content loads for workers, shared workers and service
// workers.
if (isWorkerType) {
@ -649,10 +678,6 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
return NS_OK;
}
// Determine if the rootDoc is https and if the user decided to allow Mixed Content
nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
NS_ENSURE_TRUE(docShell, NS_OK);
// The page might have set the CSP directive 'upgrade-insecure-requests'. In such
// a case allow the http: load to succeed with the promise that the channel will
// get upgraded to https before fetching any data from the netwerk.
@ -672,6 +697,7 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect,
return NS_OK;
}
// Determine if the rootDoc is https and if the user decided to allow Mixed Content
bool rootHasSecureConnection = false;
bool allowMixedContent = false;
bool isRootDocShell = false;

View File

@ -0,0 +1,53 @@
// custom *.sjs for Bug 1122236
// CSP: 'block-all-mixed-content'
const HEAD =
"<!DOCTYPE HTML>" +
"<html><head><meta charset=\"utf-8\">" +
"<title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>" +
"</head>";
const CSP_ALLOW =
"<meta http-equiv=\"Content-Security-Policy\" content=\"img-src *\">";
const CSP_BLOCK =
"<meta http-equiv=\"Content-Security-Policy\" content=\"block-all-mixed-content\">";
const BODY =
"<body>" +
"<img id=\"testimage\" src=\"http://mochi.test:8888/tests/image/test/mochitest/blue.png\"></img>" +
"<script type=\"application/javascript\">" +
" var myImg = document.getElementById(\"testimage\");" +
" myImg.onload = function(e) {" +
" window.parent.postMessage({result: \"img-loaded\"}, \"*\");" +
" };" +
" myImg.onerror = function(e) {" +
" window.parent.postMessage({result: \"img-blocked\"}, \"*\");" +
" };" +
"</script>" +
"</body>" +
"</html>";
function handleRequest(request, response)
{
// avoid confusing cache behaviors
response.setHeader("Cache-Control", "no-cache", false);
var queryString = request.queryString;
if (queryString === "csp-block") {
response.write(HEAD + CSP_BLOCK + BODY);
return;
}
if (queryString === "csp-allow") {
response.write(HEAD + CSP_ALLOW + BODY);
return;
}
if (queryString === "no-csp") {
response.write(HEAD + BODY);
return;
}
// we should never get here but just in case return something unexpected
response.write("do'h");
}

View File

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
<title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>
</head>
<body>
<b>user clicks and navigates from https://b.com to http://c.com</b>
<a id="navlink" href="http://example.com/tests/dom/security/test/csp/file_block_all_mixed_content_frame_navigation2.html">foo</a>
<script class="testbody" type="text/javascript">
// click the link to start the frame navigation
document.getElementById("navlink").click();
</script>
</body>
</html>

View File

@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>
</head>
<body>
<b>http://c.com loaded, let's tell the parent</b>
<script class="testbody" type="text/javascript">
window.parent.postMessage({result: "frame-navigated"}, "*");
</script>
</body>
</html>

View File

@ -156,6 +156,9 @@ support-files =
file_multipart_testserver.sjs
file_fontloader.sjs
file_fontloader.woff
file_block_all_mcb.sjs
file_block_all_mixed_content_frame_navigation1.html
file_block_all_mixed_content_frame_navigation2.html
[test_base-uri.html]
[test_blob_data_schemes.html]
@ -236,3 +239,7 @@ skip-if = toolkit == 'android' #investigate in bug 1250814
[test_docwrite_meta.html]
[test_multipartchannel.html]
[test_fontloader.html]
[test_block_all_mixed_content.html]
tags = mcb
[test_block_all_mixed_content_frame_navigation.html]
tags = mcb

View File

@ -0,0 +1,94 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<iframe style="width:100%;" id="testframe"></iframe>
<script class="testbody" type="text/javascript">
/* Description of the tests:
* Test 1:
* We load mixed display content in a frame using the CSP
* directive 'block-all-mixed-content' and observe that the image is blocked.
*
* Test 2:
* We load mixed display content in a frame using a CSP that allows the load
* and observe that the image is loaded.
*
* Test 3:
* We load mixed display content in a frame not using a CSP at all
* and observe that the image is loaded.
*
* Test 4:
* We load mixed display content in a frame using the CSP
* directive 'block-all-mixed-content' and observe that the image is blocked.
* Please note that Test 3 loads the image we are about to load in Test 4 into
* the img cache. Let's make sure the cached (mixed display content) image is
* not allowed to be loaded.
*/
const BASE_URI = "https://example.com/tests/dom/security/test/csp/";
const tests = [
{ // Test 1
query: "csp-block",
expected: "img-blocked",
description: "(csp-block) block-all-mixed content should block mixed display content"
},
{ // Test 2
query: "csp-allow",
expected: "img-loaded",
description: "(csp-allow) mixed display content should be loaded"
},
{ // Test 3
query: "no-csp",
expected: "img-loaded",
description: "(no-csp) mixed display content should be loaded"
},
{ // Test 4
query: "csp-block",
expected: "img-blocked",
description: "(csp-block) block-all-mixed content should block insecure cache loads"
},
];
var curTest;
var counter = -1;
function checkResults(result) {
is(result, curTest.expected, curTest.description);
loadNextTest();
}
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
checkResults(event.data.result);
}
function loadNextTest() {
counter++;
if (counter == tests.length) {
window.removeEventListener("message", receiveMessage, false);
SimpleTest.finish();
return;
}
curTest = tests[counter];
testframe.src = BASE_URI + "file_block_all_mcb.sjs?" + curTest.query;
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{ 'set': [["security.mixed_content.block_display_content", false]] },
function() { loadNextTest(); }
);
</script>
</body>
</html>

View File

@ -0,0 +1,46 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1122236 - CSP: Implement block-all-mixed-content</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<iframe style="width:100%;" id="testframe"></iframe>
<script class="testbody" type="text/javascript">
/* Description of the test:
*
* http://a.com embeds https://b.com.
* https://b.com has a CSP using 'block-all-mixed-content'.
* | site | http://a.com
* | embeds | https://b.com (uses block-all-mixed-content)
*
* The user navigates the embedded frame from
* https://b.com -> http://c.com.
* The test makes sure that such a navigation is not blocked
* by block-all-mixed-content.
*/
function checkResults(result) {
is(result, "frame-navigated", "frame should be allowed to be navigated");
window.removeEventListener("message", receiveMessage, false);
SimpleTest.finish();
}
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
checkResults(event.data.result);
}
SimpleTest.waitForExplicitFinish();
// http://a.com loads https://b.com
document.getElementById("testframe").src =
"https://example.com/tests/dom/security/test/csp/file_block_all_mixed_content_frame_navigation1.html";
</script>
</body>
</html>

View File

@ -27,6 +27,7 @@ dictionary CSP {
sequence<DOMString> manifest-src;
sequence<DOMString> upgrade-insecure-requests;
sequence<DOMString> child-src;
sequence<DOMString> block-all-mixed-content;
};
dictionary CSPPolicies {

View File

@ -556,22 +556,7 @@ nsXBLService::AttachGlobalKeyHandler(EventTarget* aTarget)
RefPtr<nsXBLWindowKeyHandler> handler =
NS_NewXBLWindowKeyHandler(elt, piTarget);
// listen to these events
manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keydown"),
TrustedEventsAtSystemGroupBubble());
manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keyup"),
TrustedEventsAtSystemGroupBubble());
manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keypress"),
TrustedEventsAtSystemGroupBubble());
// The capturing listener is only used for XUL keysets to properly handle
// shortcut keys in a multi-process environment.
manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keydown"),
TrustedEventsAtSystemGroupCapture());
manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keyup"),
TrustedEventsAtSystemGroupCapture());
manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keypress"),
TrustedEventsAtSystemGroupCapture());
handler->InstallKeyboardEventListenersTo(manager);
if (contentNode)
return contentNode->SetProperty(nsGkAtoms::listener,
@ -611,19 +596,8 @@ nsXBLService::DetachGlobalKeyHandler(EventTarget* aTarget)
if (!handler)
return NS_ERROR_FAILURE;
manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keydown"),
TrustedEventsAtSystemGroupBubble());
manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keyup"),
TrustedEventsAtSystemGroupBubble());
manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keypress"),
TrustedEventsAtSystemGroupBubble());
manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keydown"),
TrustedEventsAtSystemGroupCapture());
manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keyup"),
TrustedEventsAtSystemGroupCapture());
manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keypress"),
TrustedEventsAtSystemGroupCapture());
static_cast<nsXBLWindowKeyHandler*>(handler)->
RemoveKeyboardEventListenersFrom(manager);
contentNode->DeleteProperty(nsGkAtoms::listener);

View File

@ -23,6 +23,7 @@
#include "nsPIDOMWindow.h"
#include "nsIDocShell.h"
#include "nsIPresShell.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventStateManager.h"
#include "nsISelectionController.h"
#include "mozilla/Preferences.h"
@ -297,6 +298,82 @@ nsXBLWindowKeyHandler::WalkHandlers(nsIDOMKeyEvent* aKeyEvent, nsIAtom* aEventTy
return NS_OK;
}
void
nsXBLWindowKeyHandler::InstallKeyboardEventListenersTo(
EventListenerManager* aEventListenerManager)
{
// For marking each keyboard event as if it's reserved by chrome,
// nsXBLWindowKeyHandlers need to listen each keyboard events before
// web contents.
aEventListenerManager->AddEventListenerByType(
this, NS_LITERAL_STRING("keydown"),
TrustedEventsAtCapture());
aEventListenerManager->AddEventListenerByType(
this, NS_LITERAL_STRING("keyup"),
TrustedEventsAtCapture());
aEventListenerManager->AddEventListenerByType(
this, NS_LITERAL_STRING("keypress"),
TrustedEventsAtCapture());
// For reducing the IPC cost, preventing to dispatch reserved keyboard
// events into the content process.
aEventListenerManager->AddEventListenerByType(
this, NS_LITERAL_STRING("keydown"),
TrustedEventsAtSystemGroupCapture());
aEventListenerManager->AddEventListenerByType(
this, NS_LITERAL_STRING("keyup"),
TrustedEventsAtSystemGroupCapture());
aEventListenerManager->AddEventListenerByType(
this, NS_LITERAL_STRING("keypress"),
TrustedEventsAtSystemGroupCapture());
// Handle keyboard events in bubbling phase of the system event group.
aEventListenerManager->AddEventListenerByType(
this, NS_LITERAL_STRING("keydown"),
TrustedEventsAtSystemGroupBubble());
aEventListenerManager->AddEventListenerByType(
this, NS_LITERAL_STRING("keyup"),
TrustedEventsAtSystemGroupBubble());
aEventListenerManager->AddEventListenerByType(
this, NS_LITERAL_STRING("keypress"),
TrustedEventsAtSystemGroupBubble());
}
void
nsXBLWindowKeyHandler::RemoveKeyboardEventListenersFrom(
EventListenerManager* aEventListenerManager)
{
aEventListenerManager->RemoveEventListenerByType(
this, NS_LITERAL_STRING("keydown"),
TrustedEventsAtCapture());
aEventListenerManager->RemoveEventListenerByType(
this, NS_LITERAL_STRING("keyup"),
TrustedEventsAtCapture());
aEventListenerManager->RemoveEventListenerByType(
this, NS_LITERAL_STRING("keypress"),
TrustedEventsAtCapture());
aEventListenerManager->RemoveEventListenerByType(
this, NS_LITERAL_STRING("keydown"),
TrustedEventsAtSystemGroupCapture());
aEventListenerManager->RemoveEventListenerByType(
this, NS_LITERAL_STRING("keyup"),
TrustedEventsAtSystemGroupCapture());
aEventListenerManager->RemoveEventListenerByType(
this, NS_LITERAL_STRING("keypress"),
TrustedEventsAtSystemGroupCapture());
aEventListenerManager->RemoveEventListenerByType(
this, NS_LITERAL_STRING("keydown"),
TrustedEventsAtSystemGroupBubble());
aEventListenerManager->RemoveEventListenerByType(
this, NS_LITERAL_STRING("keyup"),
TrustedEventsAtSystemGroupBubble());
aEventListenerManager->RemoveEventListenerByType(
this, NS_LITERAL_STRING("keypress"),
TrustedEventsAtSystemGroupBubble());
}
NS_IMETHODIMP
nsXBLWindowKeyHandler::HandleEvent(nsIDOMEvent* aEvent)
{
@ -306,7 +383,11 @@ nsXBLWindowKeyHandler::HandleEvent(nsIDOMEvent* aEvent)
uint16_t eventPhase;
aEvent->GetEventPhase(&eventPhase);
if (eventPhase == nsIDOMEvent::CAPTURING_PHASE) {
HandleEventOnCapture(keyEvent);
if (aEvent->WidgetEventPtr()->mFlags.mInSystemGroup) {
HandleEventOnCaptureInSystemEventGroup(keyEvent);
} else {
HandleEventOnCaptureInDefaultEventGroup(keyEvent);
}
return NS_OK;
}
@ -319,12 +400,41 @@ nsXBLWindowKeyHandler::HandleEvent(nsIDOMEvent* aEvent)
}
void
nsXBLWindowKeyHandler::HandleEventOnCapture(nsIDOMKeyEvent* aEvent)
nsXBLWindowKeyHandler::HandleEventOnCaptureInDefaultEventGroup(
nsIDOMKeyEvent* aEvent)
{
WidgetKeyboardEvent* widgetKeyboardEvent =
aEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
if (widgetKeyboardEvent->mFlags.mOnlySystemGroupDispatchInContent) {
MOZ_RELEASE_ASSERT(
widgetKeyboardEvent->mFlags.mNoCrossProcessBoundaryForwarding);
return;
}
bool isReserved = false;
if (HasHandlerForEvent(aEvent, &isReserved) && isReserved) {
// For reserved commands (such as Open New Tab), we don't to wait for
// the content to answer (so mWantReplyFromContentProcess remains false),
// neither to give a chance for content to override its behavior.
widgetKeyboardEvent->mFlags.mNoCrossProcessBoundaryForwarding = true;
// If the key combination is reserved by chrome, we shouldn't expose the
// keyboard event to web contents because such keyboard events shouldn't be
// cancelable. So, it's not good behavior to fire keyboard events but
// to ignore the defaultPrevented attribute value in chrome.
widgetKeyboardEvent->mFlags.mOnlySystemGroupDispatchInContent = true;
}
}
void
nsXBLWindowKeyHandler::HandleEventOnCaptureInSystemEventGroup(
nsIDOMKeyEvent* aEvent)
{
WidgetKeyboardEvent* widgetEvent =
aEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
if (widgetEvent->mFlags.mNoCrossProcessBoundaryForwarding) {
if (widgetEvent->mFlags.mNoCrossProcessBoundaryForwarding ||
widgetEvent->mFlags.mOnlySystemGroupDispatchInContent) {
return;
}
@ -334,27 +444,19 @@ nsXBLWindowKeyHandler::HandleEventOnCapture(nsIDOMKeyEvent* aEvent)
return;
}
bool aReservedForChrome = false;
if (!HasHandlerForEvent(aEvent, &aReservedForChrome)) {
if (!HasHandlerForEvent(aEvent)) {
return;
}
if (aReservedForChrome) {
// For reserved commands (such as Open New Tab), we don't to wait for
// the content to answer (so mWantReplyFromContentProcess remains false),
// neither to give a chance for content to override its behavior.
widgetEvent->mFlags.mNoCrossProcessBoundaryForwarding = true;
} else {
// Inform the child process that this is a event that we want a reply
// from.
widgetEvent->mFlags.mWantReplyFromContentProcess = true;
// If this event hadn't been marked as mNoCrossProcessBoundaryForwarding
// yet, it means it wasn't processed by content. We'll not call any
// of the handlers at this moment, and will wait for the event to be
// redispatched with mNoCrossProcessBoundaryForwarding = 1 to process it.
aEvent->AsEvent()->StopPropagation();
}
// Inform the child process that this is a event that we want a reply
// from.
widgetEvent->mFlags.mWantReplyFromContentProcess = true;
// If this event hadn't been marked as mNoCrossProcessBoundaryForwarding
// yet, it means it wasn't processed by content. We'll not call any
// of the handlers at this moment, and will wait for the event to be
// redispatched with mNoCrossProcessBoundaryForwarding = 1 to process it.
// XXX Why not StopImmediatePropagation()?
aEvent->AsEvent()->StopPropagation();
}
//

View File

@ -17,6 +17,7 @@ class nsXBLSpecialDocInfo;
class nsXBLPrototypeHandler;
namespace mozilla {
class EventListenerManager;
namespace dom {
class Element;
class EventTarget;
@ -27,10 +28,16 @@ struct IgnoreModifierState;
class nsXBLWindowKeyHandler : public nsIDOMEventListener
{
typedef mozilla::dom::IgnoreModifierState IgnoreModifierState;
typedef mozilla::EventListenerManager EventListenerManager;
public:
nsXBLWindowKeyHandler(nsIDOMElement* aElement, mozilla::dom::EventTarget* aTarget);
void InstallKeyboardEventListenersTo(
EventListenerManager* aEventListenerManager);
void RemoveKeyboardEventListenersFrom(
EventListenerManager* aEventListenerManager);
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
@ -55,8 +62,10 @@ protected:
bool aExecute,
bool* aOutReservedForChrome = nullptr);
// HandleEvent function for the capturing phase.
void HandleEventOnCapture(nsIDOMKeyEvent* aEvent);
// HandleEvent function for the capturing phase in the default event group.
void HandleEventOnCaptureInDefaultEventGroup(nsIDOMKeyEvent* aEvent);
// HandleEvent function for the capturing phase in the system event group.
void HandleEventOnCaptureInSystemEventGroup(nsIDOMKeyEvent* aEvent);
// Check if any handler would handle the given event. Optionally returns
// whether the command handler for the event is marked with the "reserved"

View File

@ -11,6 +11,8 @@ MOCHITEST_MANIFESTS += [
MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
BROWSER_CHROME_MANIFESTS += ['tests/browser.ini']
UNIFIED_SOURCES += [
'ChangeAttributeTxn.cpp',
'ChangeStyleTxn.cpp',

View File

@ -0,0 +1,6 @@
[browser_bug527935.js]
skip-if = toolkit == 'android'
support-files = bug527935.html
[browser_bug629172.js]
skip-if = toolkit == 'android'
support-files = bug629172.html

View File

@ -0,0 +1,63 @@
add_task(function*() {
yield new Promise(resolve => waitForFocus(resolve, window));
const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug527935.html";
yield BrowserTestUtils.withNewTab({
gBrowser,
url: kPageURL
}, function*(aBrowser) {
var popupShown = false;
function listener() {
popupShown = true;
}
SpecialPowers.addAutoCompletePopupEventListener(window, "popupshowing", listener);
yield ContentTask.spawn(aBrowser, {}, function*() {
var window = content.window.wrappedJSObject;
var document = window.document;
var formTarget = document.getElementById("formTarget");
var initValue = document.getElementById("initValue");
window.loadPromise = new Promise(resolve => {
formTarget.onload = resolve;
});
initValue.focus();
initValue.value = "foo";
});
EventUtils.synthesizeKey("VK_RETURN", {});
yield ContentTask.spawn(aBrowser, {}, function*() {
var window = content.window.wrappedJSObject;
var document = window.document;
yield window.loadPromise;
var newInput = document.createElement("input");
newInput.setAttribute("name", "test");
document.body.appendChild(newInput);
var event = document.createEvent("KeyboardEvent");
event.initKeyEvent("keypress", true, true, null, false, false,
false, false, 0, "f".charCodeAt(0));
newInput.value = "";
newInput.focus();
newInput.dispatchEvent(event);
});
yield new Promise(resolve => hitEventLoop(resolve, 100));
ok(!popupShown, "Popup must not be opened");
SpecialPowers.removeAutoCompletePopupEventListener(window, "popupshowing", listener);
});
});
function hitEventLoop(func, times) {
if (times > 0) {
setTimeout(hitEventLoop, 0, func, times - 1);
} else {
setTimeout(func, 0);
}
}

View File

@ -0,0 +1,106 @@
add_task(function*() {
yield new Promise(resolve => waitForFocus(resolve, window));
const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug629172.html";
yield BrowserTestUtils.withNewTab({
gBrowser,
url: kPageURL
}, function*(aBrowser) {
yield ContentTask.spawn(aBrowser, {}, function*() {
var window = content.window.wrappedJSObject;
var document = window.document;
// Note: Using the with keyword, we would have been able to write this as:
//
// with (window) {
// Screenshots = {};
// // so on
// }
//
// However, browser-chrome tests are somehow forced to run in strict mode,
// which doesn't permit the usage of the with keyword, turning the following
// into the ugliest test you've ever seen. :(
var LTRRef = document.getElementById("ltr-ref");
var RTLRef = document.getElementById("rtl-ref");
window.Screenshots = {};
// generate the reference screenshots
LTRRef.style.display = "";
document.body.clientWidth;
window.Screenshots.ltr = window.snapshotWindow(window);
LTRRef.parentNode.removeChild(LTRRef);
RTLRef.style.display = "";
document.body.clientWidth;
window.Screenshots.rtl = window.snapshotWindow(window);
RTLRef.parentNode.removeChild(RTLRef);
window.Screenshots.get = function(dir, flip) {
if (flip) {
return this[dir == "rtl" ? "ltr" : "rtl"];
} else {
return this[dir];
}
};
});
function simulateCtrlShiftX(aBrowser) {
// In e10s, the keypress event will be dispatched to the content process,
// but in non-e10s it is handled by the browser UI code and hence won't
// reach the web page. As a result, we need to observe the event in
// the content process only in e10s mode.
var waitForKeypressContent = BrowserTestUtils.waitForContentEvent(aBrowser, "keypress");
EventUtils.synthesizeKey("x", {accelKey: true, shiftKey: true});
if (gMultiProcessBrowser) {
return waitForKeypressContent;
}
return Promise.resolve();
}
function* testDirection(initialDir, aBrowser) {
yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
var window = content.window.wrappedJSObject;
var document = window.document;
var t = window.t = document.createElement("textarea");
t.setAttribute("dir", initialDir);
t.value = "test.";
window.inputEventCount = 0;
t.oninput = function() { window.inputEventCount++; };
document.getElementById("content").appendChild(t);
document.body.clientWidth;
var s1 = window.snapshotWindow(window);
ok(window.compareSnapshots(s1, window.Screenshots.get(initialDir, false), true)[0],
"Textarea should appear correctly before switching the direction (" + initialDir + ")");
t.focus();
is(window.inputEventCount, 0, "input event count must be 0 before");
});
yield simulateCtrlShiftX(aBrowser);
yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
var window = content.window.wrappedJSObject;
is(window.t.getAttribute("dir"), initialDir == "ltr" ? "rtl" : "ltr", "The dir attribute must be correctly updated");
is(window.inputEventCount, 1, "input event count must be 1 after");
window.t.blur();
var s2 = window.snapshotWindow(window);
ok(window.compareSnapshots(s2, window.Screenshots.get(initialDir, true), true)[0],
"Textarea should appear correctly after switching the direction (" + initialDir + ")");
window.t.focus();
is(window.inputEventCount, 1, "input event count must be 1 before");
});
yield simulateCtrlShiftX(aBrowser);
yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
var window = content.window.wrappedJSObject;
is(window.inputEventCount, 2, "input event count must be 2 after");
is(window.t.getAttribute("dir"), initialDir == "ltr" ? "ltr" : "rtl", "The dir attribute must be correctly updated");
window.t.blur();
var s3 = window.snapshotWindow(window);
ok(window.compareSnapshots(s3, window.Screenshots.get(initialDir, false), true)[0],
"Textarea should appear correctly after switching back the direction (" + initialDir + ")");
window.t.parentNode.removeChild(window.t);
});
}
yield testDirection("ltr", aBrowser);
yield testDirection("rtl", aBrowser);
});
});

View File

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<body>
<div id="content">
<iframe id="formTarget" name="formTarget"></iframe>
<form action="data:text/html," target="formTarget">
<input name="test" id="initValue"><input type="submit">
</form>
</div>
</body>
</html

View File

@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
<style>
textarea { resize: none }
</style>
</head>
<body>
<div id="content">
<textarea id="ltr-ref" style="display: none">test.</textarea>
<textarea id="rtl-ref" style="display: none; direction: rtl">test.</textarea>
</div
</body>
</html>

View File

@ -58,8 +58,6 @@ skip-if = toolkit == 'android'
skip-if = toolkit == 'android'
[test_bug525389.html]
skip-if = toolkit == 'android'
[test_bug527935.html]
skip-if = toolkit == 'android' || e10s
[test_bug537046.html]
[test_bug549262.html]
skip-if = toolkit == 'android'
@ -102,8 +100,6 @@ skip-if = toolkit == 'android' #TIMED_OUT
[test_bug622371.html]
skip-if = toolkit == 'android' #bug 957797
[test_bug625452.html]
[test_bug629172.html]
skip-if = toolkit == 'android' || e10s
[test_bug629845.html]
[test_bug638596.html]
[test_bug640321.html]

View File

@ -1,74 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=527935
-->
<head>
<title>Test for Bug 527935</title>
<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>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=527935">Mozilla Bug 527935</a>
<p id="display"></p>
<div id="content">
<iframe id="formTarget" name="formTarget"></iframe>
<form action="data:text/html," target="formTarget">
<input name="test" id="initValue"><input type="submit">
</form>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 527935 **/
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
var formTarget = document.getElementById("formTarget");
var initValue = document.getElementById("initValue");
formTarget.addEventListener("load", function() {
var newInput = document.createElement("input");
newInput.setAttribute("name", "test");
document.body.appendChild(newInput);
setTimeout(function() {
var popupShown = false;
function listener() {
popupShown = true;
}
SpecialPowers.addAutoCompletePopupEventListener(window, "popupshowing", listener);
var event = document.createEvent("KeyboardEvent");
event.initKeyEvent("keypress", true, true, null, false, false,
false, false, 0, "f".charCodeAt(0));
newInput.value = "";
newInput.focus();
newInput.dispatchEvent(event);
hitEventLoop(function() {
ok(!popupShown, "Popup must not be opened");
SpecialPowers.removeAutoCompletePopupEventListener(window, "popupshowing", listener);
SimpleTest.finish();
}, 100);
}, 0);
}, false);
initValue.focus();
initValue.value = "foo";
synthesizeKey("VK_RETURN", {});
});
function hitEventLoop(func, times) {
if (times > 0) {
setTimeout(hitEventLoop, 0, func, times - 1);
} else {
setTimeout(func, 0);
}
}
</script>
</pre>
</body>
</html>

View File

@ -1,88 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=629172
-->
<head>
<title>Test for Bug 629172</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.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=629172">Mozilla Bug 629172</a>
<p id="display"></p>
<div id="content">
<textarea id="ltr-ref" style="display: none">test.</textarea>
<textarea id="rtl-ref" style="display: none; direction: rtl">test.</textarea>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 629172 **/
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
var LTRRef = document.getElementById("ltr-ref");
var RTLRef = document.getElementById("rtl-ref");
var Screenshots = {};
// generate the reference screenshots
LTRRef.style.display = "";
document.body.clientWidth;
Screenshots.ltr = snapshotWindow(window);
LTRRef.parentNode.removeChild(LTRRef);
RTLRef.style.display = "";
document.body.clientWidth;
Screenshots.rtl = snapshotWindow(window);
RTLRef.parentNode.removeChild(RTLRef);
Screenshots.get = function(dir, flip) {
if (flip) {
return this[dir == "rtl" ? "ltr" : "rtl"];
} else {
return this[dir];
}
};
function testDirection(initialDir) {
var t = document.createElement("textarea");
t.setAttribute("dir", initialDir);
t.value = "test.";
var inputEventCount = 0;
t.oninput = function() { inputEventCount++; };
document.getElementById("content").appendChild(t);
document.body.clientWidth;
var s1 = snapshotWindow(window);
ok(compareSnapshots(s1, Screenshots.get(initialDir, false), true)[0],
"Textarea should appear correctly before switching the direction (" + initialDir + ")");
t.focus();
is(inputEventCount, 0, "input event count must be 0 before");
synthesizeKey("x", {accelKey: true, shiftKey: true});
is(t.getAttribute("dir"), initialDir == "ltr" ? "rtl" : "ltr", "The dir attribute must be correctly updated");
is(inputEventCount, 1, "input event count must be 1 after");
t.blur();
var s2 = snapshotWindow(window);
ok(compareSnapshots(s2, Screenshots.get(initialDir, true), true)[0],
"Textarea should appear correctly after switching the direction (" + initialDir + ")");
t.focus();
is(inputEventCount, 1, "input event count must be 1 before");
synthesizeKey("x", {accelKey: true, shiftKey: true});
is(inputEventCount, 2, "input event count must be 2 after");
is(t.getAttribute("dir"), initialDir == "ltr" ? "ltr" : "rtl", "The dir attribute must be correctly updated");
t.blur();
var s3 = snapshotWindow(window);
ok(compareSnapshots(s3, Screenshots.get(initialDir, false), true)[0],
"Textarea should appear correctly after switching back the direction (" + initialDir + ")");
t.parentNode.removeChild(t);
}
testDirection("ltr");
testDirection("rtl");
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

View File

@ -15,24 +15,20 @@ angle_git_is_present = exec_script("src/commit_id.py",
angle_use_commit_id = angle_git_is_present == 1
gles_gypi = exec_script(
"//build/gypi_to_gn.py",
[ rebase_path("src/libGLESv2.gypi") ],
"scope",
[ "src/libGLESv2.gypi" ])
gles_gypi = exec_script("//build/gypi_to_gn.py",
[ rebase_path("src/libGLESv2.gypi") ],
"scope",
[ "src/libGLESv2.gypi" ])
compiler_gypi = exec_script(
"//build/gypi_to_gn.py",
[ rebase_path("src/compiler.gypi") ],
"scope",
[ "src/compiler.gypi" ])
compiler_gypi = exec_script("//build/gypi_to_gn.py",
[ rebase_path("src/compiler.gypi") ],
"scope",
[ "src/compiler.gypi" ])
# This config is exported to dependent targets (and also applied to internal
# ones).
config("external_config") {
include_dirs = [
"include",
]
include_dirs = [ "include" ]
}
# This config is applied to internal Angle targets (not pushed to dependents).
@ -45,8 +41,12 @@ config("internal_config") {
if (is_win) {
copy("copy_compiler_dll") {
sources = [ "$windows_sdk_path/Redist/D3D/$target_cpu/d3dcompiler_47.dll" ]
outputs = [ "$root_build_dir/d3dcompiler_47.dll" ]
sources = [
"$windows_sdk_path/Redist/D3D/$target_cpu/d3dcompiler_47.dll",
]
outputs = [
"$root_out_dir/d3dcompiler_47.dll",
]
}
}
@ -58,11 +58,6 @@ component("translator") {
defines = [ "ANGLE_TRANSLATOR_IMPLEMENTATION" ]
if (angle_enable_hlsl) {
sources += rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
defines += [ "ANGLE_ENABLE_HLSL" ]
}
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [
":internal_config",
@ -84,9 +79,9 @@ source_set("includes") {
"include/GLES2/gl2ext.h",
"include/GLES2/gl2platform.h",
"include/GLES3/gl3.h",
"include/GLES3/gl3platform.h",
"include/GLES3/gl31.h",
"include/GLES3/gl32.h",
"include/GLES3/gl3platform.h",
"include/GLSLANG/ShaderLang.h",
"include/KHR/khrplatform.h",
]
@ -106,12 +101,9 @@ config("translator_static_config") {
defines = [ "ANGLE_TRANSLATOR_STATIC" ]
}
config("debug_annotations_config") {
if (is_debug) {
defines = [
"ANGLE_ENABLE_DEBUG_ANNOTATIONS",
]
defines = [ "ANGLE_ENABLE_DEBUG_ANNOTATIONS" ]
}
}
@ -128,10 +120,24 @@ static_library("angle_common") {
static_library("translator_lib") {
sources = rebase_path(compiler_gypi.angle_translator_lib_sources, ".", "src")
defines = []
if (angle_enable_essl) {
sources +=
rebase_path(compiler_gypi.angle_translator_lib_essl_sources, ".", "src")
defines += [ "ANGLE_ENABLE_ESSL" ]
}
if (angle_enable_glsl) {
sources +=
rebase_path(compiler_gypi.angle_translator_lib_glsl_sources, ".", "src")
defines += [ "ANGLE_ENABLE_GLSL" ]
}
if (angle_enable_hlsl) {
sources += rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
defines = [ "ANGLE_ENABLE_HLSL" ]
sources +=
rebase_path(compiler_gypi.angle_translator_lib_hlsl_sources, ".", "src")
defines += [ "ANGLE_ENABLE_HLSL" ]
}
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [
@ -246,18 +252,13 @@ static_library("libANGLE") {
include_dirs = []
libs = []
defines = [
"LIBANGLE_IMPLEMENTATION",
]
defines = [ "LIBANGLE_IMPLEMENTATION" ]
# Shared D3D sources.
if (angle_enable_d3d9 || angle_enable_d3d11) {
sources += rebase_path(gles_gypi.libangle_d3d_shared_sources, ".", "src")
defines += [
"ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ " +
"\"d3dcompiler_47.dll\", \"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }",
]
defines += [ "ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES={ " + "\"d3dcompiler_47.dll\", \"d3dcompiler_46.dll\", \"d3dcompiler_43.dll\" }" ]
}
if (angle_enable_d3d9) {
@ -285,9 +286,7 @@ static_library("libANGLE") {
}
if (is_debug) {
defines += [
"ANGLE_GENERATE_SHADER_DEBUG_INFO",
]
defines += [ "ANGLE_GENERATE_SHADER_DEBUG_INFO" ]
}
configs -= [ "//build/config/compiler:chromium_code" ]
@ -300,10 +299,10 @@ static_library("libANGLE") {
]
deps = [
":angle_common",
":commit_id",
":includes",
":translator_static",
":angle_common",
]
if (is_win) {
@ -315,8 +314,8 @@ shared_library("libGLESv2") {
sources = rebase_path(gles_gypi.libglesv2_sources, ".", "src")
if (is_win) {
ldflags = [ "/DEF:" +
rebase_path("src/libGLESv2/libGLESv2.def", root_build_dir) ]
ldflags =
[ "/DEF:" + rebase_path("src/libGLESv2/libGLESv2.def", root_build_dir) ]
}
configs -= [ "//build/config/compiler:chromium_code" ]
@ -328,9 +327,7 @@ shared_library("libGLESv2") {
"//build/config/compiler:no_chromium_code",
]
defines = [
"LIBGLESV2_IMPLEMENTATION",
]
defines = [ "LIBGLESV2_IMPLEMENTATION" ]
deps = [
":includes",
@ -342,8 +339,7 @@ shared_library("libEGL") {
sources = rebase_path(gles_gypi.libegl_sources, ".", "src")
if (is_win) {
ldflags = [ "/DEF:" +
rebase_path("src/libEGL/libEGL.def", root_build_dir) ]
ldflags = [ "/DEF:" + rebase_path("src/libEGL/libEGL.def", root_build_dir) ]
}
configs -= [ "//build/config/compiler:chromium_code" ]
@ -355,9 +351,7 @@ shared_library("libEGL") {
"//build/config/compiler:no_chromium_code",
]
defines = [
"LIBEGL_IMPLEMENTATION",
]
defines = [ "LIBEGL_IMPLEMENTATION" ]
deps = [
":includes",
@ -365,11 +359,17 @@ shared_library("libEGL") {
]
}
util_gypi = exec_script(
"//build/gypi_to_gn.py",
[ rebase_path("util/util.gyp") ],
"scope",
[ "util/util.gyp" ])
util_gypi = exec_script("//build/gypi_to_gn.py",
[ rebase_path("util/util.gyp") ],
"scope",
[ "util/util.gyp" ])
config("angle_util_config") {
include_dirs = [ "util" ]
if (is_linux) {
libs = [ "X11" ]
}
}
static_library("angle_util") {
sources = rebase_path(util_gypi.util_sources, ".", "util")
@ -396,16 +396,15 @@ static_library("angle_util") {
"EGL_EGLEXT_PROTOTYPES",
]
configs += [
":internal_config",
":debug_annotations_config",
]
configs += [ ":debug_annotations_config" ]
include_dirs = [
"util",
public_configs = [
":angle_util_config",
":internal_config",
]
deps = [
":angle_common",
":libEGL",
":libGLESv2",
]

View File

@ -66,6 +66,40 @@ hooks = [
'-s', 'buildtools/linux64/clang-format.sha1',
],
},
# Pull GN binaries using checked-in hashes.
{
'name': 'gn_win',
'pattern': '.',
'action': [ 'download_from_google_storage',
'--no_resume',
'--platform=win32',
'--no_auth',
'--bucket', 'chromium-gn',
'-s', 'buildtools/win/gn.exe.sha1',
],
},
{
'name': 'gn_mac',
'pattern': '.',
'action': [ 'download_from_google_storage',
'--no_resume',
'--platform=darwin',
'--no_auth',
'--bucket', 'chromium-gn',
'-s', 'buildtools/mac/gn.sha1',
],
},
{
'name': 'gn_linux64',
'pattern': '.',
'action': [ 'download_from_google_storage',
'--no_resume',
'--platform=linux*',
'--no_auth',
'--bucket', 'chromium-gn',
'-s', 'buildtools/linux64/gn.sha1',
],
},
{
# A change to a .gyp, .gypi, or to GYP itself should run the generator.
"pattern": ".",

View File

@ -39,5 +39,6 @@ View the [Dev setup instructions](doc/DevSetup.md). For generating a Windows Sto
* Read about WebGL on the [Khronos WebGL Wiki](http://khronos.org/webgl/wiki/Main_Page).
* Learn about implementation details in the [OpenGL Insights chapter on ANGLE](http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-ANGLE.pdf) and this [ANGLE presentation](https://drive.google.com/file/d/0Bw29oYeC09QbbHoxNE5EUFh0RGs/view?usp=sharing).
* Learn about the past, present, and future of the ANGLE implementation in [this recent presentation](https://docs.google.com/presentation/d/1CucIsdGVDmdTWRUbg68IxLE5jXwCb2y1E9YVhQo0thg/pub?start=false&loop=false).
* Notes on [debugging ANGLE](doc/DebuggingTips.md).
* If you use ANGLE in your own project, we'd love to hear about it!

View File

@ -468,6 +468,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
#ifndef EGL_ANGLE_direct_composition
#define EGL_ANGLE_direct_composition 1
#define EGL_DIRECT_COMPOSITION_ANGLE 0x33A5
#endif /* EGL_ANGLE_direct_composition */
#ifndef EGL_ANGLE_platform_angle
#define EGL_ANGLE_platform_angle 1
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
@ -504,6 +509,26 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#define EGL_X11_VISUAL_ID_ANGLE 0x33A3
#endif /* EGL_ANGLE_x11_visual */
#ifndef EGL_ANGLE_flexible_surface_compatibility
#define EGL_ANGLE_flexible_surface_compatibility 1
#define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
#endif /* EGL_ANGLE_flexible_surface_compatibility */
#ifndef EGL_ANGLE_surface_orientation
#define EGL_ANGLE_surface_orientation
#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
#endif /* EGL_ANGLE_surface_orientation */
#ifndef EGL_ANGLE_experimental_present_path
#define EGL_ANGLE_experimental_present_path
#define EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE 0x33A4
#define EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE 0x33A9
#define EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE 0x33AA
#endif /* EGL_ANGLE_experimental_present_path */
#ifndef EGL_ARM_pixmap_multisample_discard
#define EGL_ARM_pixmap_multisample_discard 1
#define EGL_DISCARD_SAMPLES_ARM 0x3286

View File

@ -2920,6 +2920,21 @@ GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
#define GL_SHADER_BINARY_VIV 0x8FC4
#endif /* GL_VIV_shader_binary */
#ifndef GL_ANGLE_lossy_etc_decode
#define GL_ANGLE_lossy_etc_decode 1
#define GL_ETC1_RGB8_LOSSY_DECODE_ANGLE 0x9690
#define GL_COMPRESSED_R11_LOSSY_DECODE_EAC_ANGLE 0x9691
#define GL_COMPRESSED_SIGNED_R11_LOSSY_DECODE_EAC_ANGLE 0x9692
#define GL_COMPRESSED_RG11_LOSSY_DECODE_EAC_ANGLE 0x9693
#define GL_COMPRESSED_SIGNED_RG11_LOSSY_DECODE_EAC_ANGLE 0x9694
#define GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE 0x9695
#define GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE 0x9696
#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE 0x9697
#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE 0x9698
#define GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE 0x9699
#define GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE 0x969A
#endif /* GL_ANGLE_lossy_etc_decode */
#ifdef __cplusplus
}
#endif

View File

@ -48,7 +48,7 @@ typedef unsigned int GLenum;
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 140
#define ANGLE_SH_VERSION 143
typedef enum {
SH_GLES2_SPEC = 0x8B40,
@ -80,30 +80,35 @@ typedef enum {
SH_CSS_SHADERS_SPEC = 0x8B42
} ShShaderSpec;
typedef enum {
SH_ESSL_OUTPUT = 0x8B45,
// SH_GLSL_OUTPUT is deprecated. This is to not break the build.
SH_GLSL_OUTPUT = 0x8B46,
SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
// SH_GLSL_CORE_OUTPUT is deprecated.
SH_GLSL_CORE_OUTPUT = 0x8B47,
//Note: GL introduced core profiles in 1.5. However, for compatiblity with Chromium, we treat SH_GLSL_CORE_OUTPUT as GLSL_130_OUTPUT.
//TODO: Remove SH_GLSL_CORE_OUTPUT
SH_GLSL_130_OUTPUT = 0x8B47,
SH_GLSL_140_OUTPUT = 0x8B80,
SH_GLSL_150_CORE_OUTPUT = 0x8B81,
SH_GLSL_330_CORE_OUTPUT = 0x8B82,
SH_GLSL_400_CORE_OUTPUT = 0x8B83,
SH_GLSL_410_CORE_OUTPUT = 0x8B84,
SH_GLSL_420_CORE_OUTPUT = 0x8B85,
SH_GLSL_430_CORE_OUTPUT = 0x8B86,
SH_GLSL_440_CORE_OUTPUT = 0x8B87,
SH_GLSL_450_CORE_OUTPUT = 0x8B88,
typedef enum
{
// ESSL output only supported in some configurations.
SH_ESSL_OUTPUT = 0x8B45,
// HLSL output only supported in some configurations.
SH_HLSL_OUTPUT = 0x8B48,
SH_HLSL9_OUTPUT = 0x8B48,
SH_HLSL11_OUTPUT = 0x8B49
// GLSL output only supported in some configurations.
SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
// Note: GL introduced core profiles in 1.5.
SH_GLSL_130_OUTPUT = 0x8B47,
SH_GLSL_140_OUTPUT = 0x8B80,
SH_GLSL_150_CORE_OUTPUT = 0x8B81,
SH_GLSL_330_CORE_OUTPUT = 0x8B82,
SH_GLSL_400_CORE_OUTPUT = 0x8B83,
SH_GLSL_410_CORE_OUTPUT = 0x8B84,
SH_GLSL_420_CORE_OUTPUT = 0x8B85,
SH_GLSL_430_CORE_OUTPUT = 0x8B86,
SH_GLSL_440_CORE_OUTPUT = 0x8B87,
SH_GLSL_450_CORE_OUTPUT = 0x8B88,
// HLSL output only supported in some configurations.
// Deprecated:
SH_HLSL_OUTPUT = 0x8B48,
SH_HLSL9_OUTPUT = 0x8B48,
SH_HLSL11_OUTPUT = 0x8B49,
// Prefer using these to specify HLSL output type:
SH_HLSL_3_0_OUTPUT = 0x8B48, // D3D 9
SH_HLSL_4_1_OUTPUT = 0x8B49, // D3D 11
SH_HLSL_4_0_FL9_3_OUTPUT = 0x8B4A // D3D 11 feature level 9_3
} ShShaderOutput;
// Compile options.
@ -334,9 +339,9 @@ COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle ha
// type: Specifies the type of shader - GL_FRAGMENT_SHADER or GL_VERTEX_SHADER.
// spec: Specifies the language spec the compiler must conform to -
// SH_GLES2_SPEC or SH_WEBGL_SPEC.
// output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. Note: HLSL output is only
// supported in some configurations.
// output: Specifies the output code type - for example SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
// SH_HLSL_3_0_OUTPUT or SH_HLSL_4_1_OUTPUT. Note: Each output type may only
// be supported in some configurations.
// resources: Specifies the built-in resources.
COMPILER_EXPORT ShHandle ShConstructCompiler(
sh::GLenum type,

View File

@ -200,6 +200,9 @@ struct COMPILER_EXPORT InterfaceBlock
InterfaceBlock(const InterfaceBlock &other);
InterfaceBlock &operator=(const InterfaceBlock &other);
// Fields from blocks with non-empty instance names are prefixed with the block name.
std::string fieldPrefix() const;
std::string name;
std::string mappedName;
std::string instanceName;
@ -210,6 +213,6 @@ struct COMPILER_EXPORT InterfaceBlock
std::vector<InterfaceBlockField> fields;
};
}
} // namespace sh
#endif // GLSLANG_SHADERVARS_H_

View File

@ -108,7 +108,8 @@ SOURCES += [
'src/compiler/translator/glslang_tab.cpp',
]
if CONFIG['GNU_CXX'] or CONFIG['CLANG_CL']:
if CONFIG['GNU_CXX']:
CXXFLAGS += [
'-Wno-attributes',
'-Wno-shadow',
@ -116,16 +117,16 @@ if CONFIG['GNU_CXX'] or CONFIG['CLANG_CL']:
'-Wno-unknown-pragmas',
'-Wno-unreachable-code',
]
if CONFIG['GNU_CXX'] and not CONFIG['CLANG_CXX'] and not CONFIG['CLANG_CL']:
CXXFLAGS += [
'-Wno-shadow-compatible-local',
'-Wno-shadow-local',
]
if CONFIG['CLANG_CXX'] or CONFIG['CLANG_CL']:
CXXFLAGS += [
'-Wno-inconsistent-missing-override',
'-Wno-unused-private-field',
]
if CONFIG['CLANG_CXX']:
CXXFLAGS += [
'-Wno-inconsistent-missing-override',
'-Wno-unused-private-field',
]
else:
CXXFLAGS += [
'-Wno-shadow-compatible-local',
'-Wno-shadow-local',
]
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
@ -154,6 +155,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
DIRS += [ 'src/libANGLE', 'src/libGLESv2', 'src/libEGL' ]
DEFINES['ANGLE_ENABLE_HLSL'] = "1"
DEFINES['ANGLE_ENABLE_GLSL'] = "1"
DEFINES['ANGLE_ENABLE_ESSL'] = "1"
DEFINES['ANGLE_ENABLE_KEYEDMUTEX'] = "1"
EXPORTS.angle += [ 'include/GLSLANG/ShaderLang.h', 'include/GLSLANG/ShaderVars.h' ]

View File

@ -16,6 +16,8 @@
'angle_enable_d3d9%': 0,
'angle_enable_d3d11%': 0,
'angle_enable_gl%': 0,
'angle_enable_essl%': 1, # Enable this for all configs by default
'angle_enable_glsl%': 1, # Enable this for all configs by default
'angle_enable_hlsl%': 0,
'angle_link_glx%': 0,
'angle_gl_library_type%': 'shared_library',

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