mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +00:00
Merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
e7c657e009
@ -31,7 +31,7 @@ function getWindows() {
|
||||
* @return A generator that yields XUL windows exposing the
|
||||
* nsIDOMWindow interface.
|
||||
*/
|
||||
function windowIterator() {
|
||||
function* windowIterator() {
|
||||
// Bug 752631: We only pass already loaded window in order to avoid
|
||||
// breaking XUL windows DOM. DOM is broken when some JS code try
|
||||
// to access DOM during "uninitialized" state of the related document.
|
||||
@ -48,7 +48,7 @@ exports.windowIterator = windowIterator;
|
||||
* A generator that yields browser windows exposing the `nsIDOMWindow`
|
||||
* interface.
|
||||
*/
|
||||
function browserWindowIterator() {
|
||||
function* browserWindowIterator() {
|
||||
for (let window of windowIterator()) {
|
||||
if (isBrowser(window))
|
||||
yield window;
|
||||
|
@ -54,7 +54,7 @@ function clear(target) {
|
||||
}
|
||||
exports.clear = clear;
|
||||
|
||||
function iterator(target) {
|
||||
function* iterator(target) {
|
||||
let refs = getRefsFor(target);
|
||||
|
||||
for (let ref of refs) {
|
||||
@ -72,4 +72,4 @@ function iterator(target) {
|
||||
refs.delete(ref);
|
||||
}
|
||||
}
|
||||
exports.iterator = iterator;
|
||||
exports[Symbol.iterator] = iterator;
|
||||
|
@ -57,7 +57,7 @@ function Collection(array) {
|
||||
* Provides iteration over the collection. Items are yielded in the order
|
||||
* they were added.
|
||||
*/
|
||||
this.__iterator__ = function Collection___iterator__() {
|
||||
this[Symbol.iterator] = function* Collection___iterator__() {
|
||||
let items = array.slice();
|
||||
for (let i = 0; i < items.length; i++)
|
||||
yield items[i];
|
||||
|
@ -37,19 +37,6 @@ const listOptions = {
|
||||
toString: function toString() {
|
||||
return 'List(' + listNS(this).keyValueMap + ')';
|
||||
},
|
||||
/**
|
||||
* Custom iterator providing `List`s enumeration behavior.
|
||||
* We cant reuse `_iterator` that is defined by `Iterable` since it provides
|
||||
* iteration in an arbitrary order.
|
||||
* @see https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in
|
||||
* @param {Boolean} onKeys
|
||||
*/
|
||||
__iterator__: function __iterator__(onKeys, onKeyValue) {
|
||||
let array = listNS(this).keyValueMap.slice(0),
|
||||
i = -1;
|
||||
for (let element of array)
|
||||
yield onKeyValue ? [++i, element] : onKeys ? ++i : element;
|
||||
},
|
||||
};
|
||||
listOptions[Symbol.iterator] = function iterator() {
|
||||
return listNS(this).keyValueMap.slice(0)[Symbol.iterator]();
|
||||
|
@ -134,8 +134,12 @@
|
||||
el.remove();
|
||||
}
|
||||
|
||||
// Set sitename
|
||||
document.getElementById(error + "_sitename").textContent = getHostString();
|
||||
// Set sitename if necessary.
|
||||
let sitenameElem = document.getElementById(error + "_sitename");
|
||||
if (sitenameElem) {
|
||||
sitenameElem.textContent = getHostString();
|
||||
}
|
||||
|
||||
document.title = document.getElementById("errorTitleText_" + error)
|
||||
.innerHTML;
|
||||
|
||||
|
@ -90,8 +90,7 @@ var gSync = {
|
||||
},
|
||||
|
||||
init() {
|
||||
// Bail out if we're already initialized or for pop-up windows.
|
||||
if (this._initialized || !window.toolbar.visible) {
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1088,14 +1088,6 @@ function _loadURIWithFlags(browser, uri, params) {
|
||||
}
|
||||
|
||||
let mustChangeProcess = requiredRemoteType != currentRemoteType;
|
||||
let newFrameloader = false;
|
||||
if (browser.getAttribute("isPreloadBrowser") == "true" && uri != "about:newtab") {
|
||||
// Leaving about:newtab from a used to be preloaded browser should run the process
|
||||
// selecting algorithm again.
|
||||
mustChangeProcess = true;
|
||||
newFrameloader = true;
|
||||
browser.removeAttribute("isPreloadBrowser");
|
||||
}
|
||||
|
||||
// !requiredRemoteType means we're loading in the parent/this process.
|
||||
if (!requiredRemoteType) {
|
||||
@ -1130,8 +1122,7 @@ function _loadURIWithFlags(browser, uri, params) {
|
||||
referrer: referrer ? referrer.spec : null,
|
||||
referrerPolicy,
|
||||
remoteType: requiredRemoteType,
|
||||
postData,
|
||||
newFrameloader,
|
||||
postData
|
||||
}
|
||||
|
||||
if (params.userContextId) {
|
||||
@ -1176,11 +1167,6 @@ function LoadInOtherProcess(browser, loadOptions, historyIndex = -1) {
|
||||
// Called when a docshell has attempted to load a page in an incorrect process.
|
||||
// This function is responsible for loading the page in the correct process.
|
||||
function RedirectLoad({ target: browser, data }) {
|
||||
if (browser.getAttribute("isPreloadBrowser") == "true") {
|
||||
browser.removeAttribute("isPreloadBrowser");
|
||||
data.loadOptions.newFrameloader = true;
|
||||
}
|
||||
|
||||
if (data.loadOptions.reloadInFreshProcess) {
|
||||
// Convert the fresh process load option into a large allocation remote type
|
||||
// to use common processing from this point.
|
||||
@ -3207,6 +3193,10 @@ var BrowserOnClick = {
|
||||
title = gNavigatorBundle.getString("safebrowsing.reportedUnwantedSite");
|
||||
// There is no button for reporting errors since Google doesn't currently
|
||||
// provide a URL endpoint for these reports.
|
||||
} else if (reason === "harmful") {
|
||||
title = gNavigatorBundle.getString("safebrowsing.reportedHarmfulSite");
|
||||
// There is no button for reporting errors since Google doesn't currently
|
||||
// provide a URL endpoint for these reports.
|
||||
}
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox();
|
||||
|
@ -2118,10 +2118,6 @@
|
||||
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
|
||||
}
|
||||
|
||||
if (aParams.isPreloadBrowser) {
|
||||
b.setAttribute("isPreloadBrowser", "true");
|
||||
}
|
||||
|
||||
if (this.hasAttribute("selectmenulist"))
|
||||
b.setAttribute("selectmenulist", this.getAttribute("selectmenulist"));
|
||||
|
||||
|
@ -131,8 +131,6 @@ skip-if = true # browser_bug321000.js is disabled because newline handling is sh
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
[browser_bug419612.js]
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
[browser_bug422590.js]
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
[browser_bug423833.js]
|
||||
skip-if = true # bug 428712
|
||||
# DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
|
||||
|
@ -1,59 +0,0 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// test a normal browser window
|
||||
var newWin = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", "about:blank");
|
||||
ok(newWin, "got new normal window");
|
||||
|
||||
whenDelayedStartupFinished(newWin, function() {
|
||||
testCustomize(newWin, function() {
|
||||
newWin.close();
|
||||
testChromeless();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testChromeless() {
|
||||
// test a chromeless window
|
||||
var newWin = openDialog(getBrowserURL(), "_blank",
|
||||
"chrome,dialog=no,location=yes,toolbar=no", "about:blank");
|
||||
ok(newWin, "got new window");
|
||||
|
||||
whenDelayedStartupFinished(newWin, function() {
|
||||
// Check that the search bar is hidden
|
||||
var searchBar = newWin.BrowserSearch.searchBar;
|
||||
ok(searchBar, "got search bar");
|
||||
|
||||
var searchBarBO = searchBar.boxObject;
|
||||
is(searchBarBO.width, 0, "search bar hidden");
|
||||
is(searchBarBO.height, 0, "search bar hidden");
|
||||
|
||||
testCustomize(newWin, function() {
|
||||
newWin.close();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testCustomize(aWindow, aCallback) {
|
||||
var fileMenu = aWindow.document.getElementById("file-menu");
|
||||
ok(fileMenu, "got file menu");
|
||||
is(fileMenu.disabled, false, "file menu initially enabled");
|
||||
|
||||
openToolbarCustomizationUI(function() {
|
||||
// Can't use the property, since the binding may have since been removed
|
||||
// if the element is hidden (see bug 422590)
|
||||
is(fileMenu.getAttribute("disabled"), "true",
|
||||
"file menu is disabled during toolbar customization");
|
||||
|
||||
closeToolbarCustomizationUI(onClose, aWindow);
|
||||
}, aWindow);
|
||||
|
||||
function onClose() {
|
||||
is(fileMenu.getAttribute("disabled"), "false",
|
||||
"file menu is enabled after toolbar customization");
|
||||
|
||||
if (aCallback)
|
||||
aCallback();
|
||||
}
|
||||
}
|
@ -20,13 +20,11 @@ var tests = [
|
||||
location: "http://test1.example.org/",
|
||||
effectiveHost: "test1.example.org"
|
||||
},
|
||||
/* This part is perma-crashing, see: Bug 1315092
|
||||
{
|
||||
name: "view-source",
|
||||
location: "view-source:http://example.com/",
|
||||
effectiveHost: null
|
||||
},
|
||||
*/
|
||||
{
|
||||
name: "normal HTTPS",
|
||||
location: "https://example.com/",
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
add_task(async function() {
|
||||
let input = "i-definitely-dont-exist.example.com";
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank", false);
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
|
||||
// NB: CPOW usage because new tab pages can be preloaded, in which case no
|
||||
// load events fire.
|
||||
await BrowserTestUtils.waitForCondition(() => !tab.linkedBrowser.contentDocument.hidden)
|
||||
@ -29,7 +29,7 @@ add_task(async function() {
|
||||
add_task(async function() {
|
||||
let input = "To be or not to be-that is the question";
|
||||
await SpecialPowers.pushPrefEnv({set: [["keyword.enabled", false]]});
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank", false);
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
|
||||
// NB: CPOW usage because new tab pages can be preloaded, in which case no
|
||||
// load events fire.
|
||||
await BrowserTestUtils.waitForCondition(() => !tab.linkedBrowser.contentDocument.hidden)
|
||||
|
@ -203,6 +203,21 @@ CustomizeMode.prototype = {
|
||||
},
|
||||
|
||||
enter() {
|
||||
if (!this.window.toolbar.visible) {
|
||||
let w = this.window.getTopWin(true);
|
||||
if (w) {
|
||||
w.gCustomizeMode.enter();
|
||||
return;
|
||||
}
|
||||
let obs = () => {
|
||||
Services.obs.removeObserver(obs, "browser-delayed-startup-finished");
|
||||
w = this.window.getTopWin(true);
|
||||
w.gCustomizeMode.enter();
|
||||
};
|
||||
Services.obs.addObserver(obs, "browser-delayed-startup-finished");
|
||||
this.window.openUILinkIn("about:newtab", "window");
|
||||
return;
|
||||
}
|
||||
this._wantToBeInCustomizeMode = true;
|
||||
|
||||
if (this._customizing || this._handler.isEnteringCustomizeMode) {
|
||||
|
@ -156,5 +156,6 @@ tags = fullscreen
|
||||
[browser_editcontrols_update.js]
|
||||
subsuite = clipboard
|
||||
[browser_customization_context_menus.js]
|
||||
[browser_open_from_popup.js]
|
||||
[browser_sidebar_toggle.js]
|
||||
[browser_remote_tabs_button.js]
|
||||
|
@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Check that opening customize mode in a popup opens it in the main window.
|
||||
*/
|
||||
add_task(async function open_customize_mode_from_popup() {
|
||||
let promiseWindow = BrowserTestUtils.waitForNewWindow(true);
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
|
||||
content.window.open("about:blank", "_blank", "height=300,toolbar=no");
|
||||
});
|
||||
let win = await promiseWindow;
|
||||
let customizePromise = BrowserTestUtils.waitForEvent(gNavToolbox, "customizationready");
|
||||
win.gCustomizeMode.enter();
|
||||
await customizePromise;
|
||||
ok(document.documentElement.hasAttribute("customizing"),
|
||||
"Should have opened customize mode in the parent window");
|
||||
await endCustomizing();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
@ -349,7 +349,7 @@
|
||||
</menulist>
|
||||
</html:td>
|
||||
</html:tr>
|
||||
<html:tr>
|
||||
<html:tr class="tableGroup">
|
||||
<html:td class="label-cell">
|
||||
<label accesskey="&homepage2.accesskey;"
|
||||
control="browserHomePage">&homepage2.label;</label>
|
||||
@ -365,7 +365,7 @@
|
||||
preference="browser.startup.homepage"/>
|
||||
</html:td>
|
||||
</html:tr>
|
||||
<html:tr>
|
||||
<html:tr class="tableSubGroup">
|
||||
<html:td class="label-cell" />
|
||||
<html:td class="content-cell homepage-buttons">
|
||||
<button id="useCurrent"
|
||||
@ -756,7 +756,6 @@
|
||||
<!-- Update -->
|
||||
<groupbox id="updateApp" data-category="paneGeneral" hidden="true">
|
||||
<label>&updateApplicationDescription.label;</label>
|
||||
<separator/>
|
||||
<hbox align="start">
|
||||
<vbox flex="1">
|
||||
<description>
|
||||
@ -872,7 +871,6 @@
|
||||
</vbox>
|
||||
#endif
|
||||
|
||||
<separator/>
|
||||
#ifdef MOZ_UPDATER
|
||||
<description>&updateApplication.description;</description>
|
||||
<radiogroup id="updateRadioGroup">
|
||||
|
@ -493,6 +493,7 @@
|
||||
<hbox>
|
||||
<button id="trackingProtectionExceptions"
|
||||
class="accessory-button"
|
||||
flex="1"
|
||||
hidden="true"
|
||||
label="&trackingProtectionExceptions.label;"
|
||||
accesskey="&trackingProtectionExceptions.accesskey;"
|
||||
@ -506,6 +507,7 @@
|
||||
<hbox>
|
||||
<button id="changeBlockList"
|
||||
class="accessory-button"
|
||||
flex="1"
|
||||
label="&changeBlockList2.label;"
|
||||
accesskey="&changeBlockList2.accesskey;"
|
||||
preference="pref.privacy.disable_button.change_blocklist"
|
||||
|
@ -28,8 +28,8 @@
|
||||
|
||||
<!-- Default Search Engine -->
|
||||
<groupbox id="defaultEngineGroup" data-category="paneSearch">
|
||||
<caption label="&defaultSearchEngine.label;"/>
|
||||
<label>&chooseYourDefaultSearchEngine2.label;</label>
|
||||
<caption><label>&defaultSearchEngine.label;</label></caption>
|
||||
<description>&chooseYourDefaultSearchEngine2.label;</description>
|
||||
<hbox>
|
||||
<!-- Please don't remove the wrapping hbox/vbox/box for these elements. It's used to properly compute the search tooltip position. -->
|
||||
<hbox>
|
||||
@ -54,8 +54,8 @@
|
||||
</groupbox>
|
||||
|
||||
<groupbox id="oneClickSearchProvidersGroup" data-category="paneSearch">
|
||||
<caption label="&oneClickSearchEngines.label;"/>
|
||||
<label>&chooseWhichOneToDisplay2.label;</label>
|
||||
<caption><label>&oneClickSearchEngines.label;</label></caption>
|
||||
<description>&chooseWhichOneToDisplay2.label;</description>
|
||||
|
||||
<tree id="engineList" flex="1" rows="8" hidecolumnpicker="true" editable="true"
|
||||
seltype="single">
|
||||
@ -81,9 +81,6 @@
|
||||
disabled="true"
|
||||
/>
|
||||
</hbox>
|
||||
|
||||
<separator class="thin"/>
|
||||
|
||||
<hbox id="addEnginesBox" pack="start">
|
||||
<label id="addEngines" class="text-link">&findMoreSearchEngines.label;</label>
|
||||
</hbox>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<stringbundle id="searchResultBundle" src="chrome://browser/locale/preferences/preferences.properties"/>
|
||||
|
||||
<hbox id="header-searchResults"
|
||||
class="header"
|
||||
class="subcategory"
|
||||
hidden="true"
|
||||
data-category="paneSearchResults">
|
||||
<label class="header-name" flex="1">&paneSearchResults.title;</label>
|
||||
|
@ -202,20 +202,18 @@
|
||||
</label>
|
||||
</caption>
|
||||
<hbox id="fxaDeviceName">
|
||||
<textbox id="fxaSyncComputerName" disabled="true"/>
|
||||
<hbox>
|
||||
<button id="fxaChangeDeviceName"
|
||||
label="&changeSyncDeviceName2.label;"
|
||||
accesskey="&changeSyncDeviceName2.accesskey;"/>
|
||||
<button id="fxaCancelChangeDeviceName"
|
||||
label="&cancelChangeSyncDeviceName.label;"
|
||||
accesskey="&cancelChangeSyncDeviceName.accesskey;"
|
||||
hidden="true"/>
|
||||
<button id="fxaSaveChangeDeviceName"
|
||||
label="&saveChangeSyncDeviceName.label;"
|
||||
accesskey="&saveChangeSyncDeviceName.accesskey;"
|
||||
hidden="true"/>
|
||||
</hbox>
|
||||
<textbox id="fxaSyncComputerName" flex="1" disabled="true"/>
|
||||
<button id="fxaChangeDeviceName"
|
||||
label="&changeSyncDeviceName2.label;"
|
||||
accesskey="&changeSyncDeviceName2.accesskey;"/>
|
||||
<button id="fxaCancelChangeDeviceName"
|
||||
label="&cancelChangeSyncDeviceName.label;"
|
||||
accesskey="&cancelChangeSyncDeviceName.accesskey;"
|
||||
hidden="true"/>
|
||||
<button id="fxaSaveChangeDeviceName"
|
||||
label="&saveChangeSyncDeviceName.label;"
|
||||
accesskey="&saveChangeSyncDeviceName.accesskey;"
|
||||
hidden="true"/>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
<label class="fxaMobilePromo">
|
||||
|
@ -3,6 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.website-name {
|
||||
padding-inline-start: 7px;
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
|
@ -62,8 +62,10 @@
|
||||
display: inline-block;
|
||||
offset-inline-start: 39px;
|
||||
border-radius: 22px;
|
||||
padding: 5px 8px;
|
||||
width: 110px;
|
||||
padding: 5px 12px;
|
||||
min-width: 100px;
|
||||
max-width: 140px;
|
||||
white-space: pre-line;
|
||||
margin-inline-start: 3px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
@ -251,6 +253,8 @@
|
||||
line-height: 22px;
|
||||
padding-inline-start: 40px;
|
||||
padding-inline-end: 28px;
|
||||
max-height: 360px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.onboarding-tour-description > h1 {
|
||||
|
@ -492,12 +492,6 @@ class Onboarding {
|
||||
this.gotoPage(tourId);
|
||||
this._removeTourFromNotificationQueue(tourId);
|
||||
break;
|
||||
// These tours are tagged completed instantly upon showing.
|
||||
case "onboarding-tour-default-browser":
|
||||
case "onboarding-tour-sync":
|
||||
case "onboarding-tour-performance":
|
||||
this.setToursCompleted([ evt.target.id ]);
|
||||
break;
|
||||
}
|
||||
let classList = evt.target.classList;
|
||||
if (classList.contains("onboarding-tour-item")) {
|
||||
@ -557,6 +551,15 @@ class Onboarding {
|
||||
li.classList.remove("onboarding-active");
|
||||
}
|
||||
}
|
||||
|
||||
switch (tourId) {
|
||||
// These tours should tagged completed instantly upon showing.
|
||||
case "onboarding-tour-default-browser":
|
||||
case "onboarding-tour-sync":
|
||||
case "onboarding-tour-performance":
|
||||
this.setToursCompleted([tourId]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
isTourCompleted(tourId) {
|
||||
@ -827,7 +830,7 @@ class Onboarding {
|
||||
_renderOverlayButton() {
|
||||
let button = this._window.document.createElement("button");
|
||||
let tooltipStringId = this._tourType === "new" ?
|
||||
"onboarding.overlay-icon-tooltip" : "onboarding.overlay-icon-tooltip-updated";
|
||||
"onboarding.overlay-icon-tooltip2" : "onboarding.overlay-icon-tooltip-updated2";
|
||||
let tooltip = this._bundle.formatStringFromName(tooltipStringId, [BRAND_SHORT_NAME], 1);
|
||||
button.setAttribute("aria-label", tooltip);
|
||||
button.id = "onboarding-overlay-button";
|
||||
|
@ -8,10 +8,15 @@ onboarding.hidden-checkbox-label-text=Mark all as complete, and hide the tour
|
||||
onboarding.button.learnMore=Learn More
|
||||
# LOCALIZATION NOTE(onboarding.notification-icon-tool-tip): This string will be used to show the tooltip alongside the notification icon in the notification bar. %S is brandShortName.
|
||||
onboarding.notification-icon-tool-tip=New to %S?
|
||||
# LOCALIZATION NOTE(onboarding.overlay-icon-tooltip): This string will be used to show the tooltip alongside the notification icon in the overlay tour. %S is brandShortName.
|
||||
onboarding.overlay-icon-tooltip=New to %S? Let’s get started.
|
||||
# LOCALIZATION NOTE(onboarding.overlay-icon-tooltip-updated): %S is brandShortName.
|
||||
onboarding.overlay-icon-tooltip-updated=%S is all new. See what you can do!
|
||||
# LOCALIZATION NOTE(onboarding.overlay-icon-tooltip2): This string will be used
|
||||
# to show the tooltip alongside the notification icon in the overlay tour. %S is
|
||||
# brandShortName. The tooltip is designed to show in two lines. Please use \n to
|
||||
# do appropriate line breaking.
|
||||
onboarding.overlay-icon-tooltip2=New to %S?\nLet’s get started.
|
||||
# LOCALIZATION NOTE(onboarding.overlay-icon-tooltip-updated2): %S is
|
||||
# brandShortName. The tooltip is designed to show in two lines. Please use \n to
|
||||
# do appropriate line breaking.
|
||||
onboarding.overlay-icon-tooltip-updated2=%S is all new.\nSee what you can do!
|
||||
# LOCALIZATION NOTE(onboarding.overlay-close-button-tooltip): The overlay close button is an icon button. This tooltip would be shown when mousing hovering on the button.
|
||||
onboarding.overlay-close-button-tooltip=Close
|
||||
onboarding.notification-icon-tooltip-updated=See what’s new!
|
||||
|
@ -23,7 +23,7 @@ panelmultiview[mainViewId=PanelUI-pocketView] > .panel-viewcontainer > .panel-vi
|
||||
}
|
||||
|
||||
#pocket-button-box[open="true"] > #pocket-button {
|
||||
fill: rgb(213,32,20);
|
||||
fill: #ef4056;
|
||||
fill-opacity: 1;
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ panelmultiview[mainViewId=PanelUI-pocketView] > .panel-viewcontainer > .panel-vi
|
||||
animation-timing-function: steps(12);
|
||||
animation-duration: 200ms;
|
||||
background-image: url("chrome://pocket-shared/skin/pocket-animation.svg");
|
||||
fill: rgb(213,32,20);
|
||||
fill: #ef4056;
|
||||
-moz-context-properties: fill;
|
||||
width: 260px;
|
||||
}
|
||||
@ -122,11 +122,11 @@ panelmultiview[mainViewId=PanelUI-pocketView] > .panel-viewcontainer > .panel-vi
|
||||
fill: inherit;
|
||||
}
|
||||
50% {
|
||||
fill: rgb(213,32,20);
|
||||
fill: #ef4056;
|
||||
}
|
||||
to {
|
||||
transform: translateX(-1056px);
|
||||
fill: rgb(213,32,20);
|
||||
fill: #ef4056;
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,11 +139,11 @@ panelmultiview[mainViewId=PanelUI-pocketView] > .panel-viewcontainer > .panel-vi
|
||||
fill: inherit;
|
||||
}
|
||||
50% {
|
||||
fill: rgb(213,32,20);
|
||||
fill: #ef4056;
|
||||
}
|
||||
to {
|
||||
transform: scaleX(-1) translateX(-1056px);
|
||||
fill: rgb(213,32,20);
|
||||
fill: #ef4056;
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ panelmultiview[mainViewId=PanelUI-pocketView] > .panel-viewcontainer > .panel-vi
|
||||
then no transition will occur and thus no transitionend event. */
|
||||
@keyframes library-pocket-fade {
|
||||
from {
|
||||
fill: rgb(213,32,20);
|
||||
fill: #ef4056;
|
||||
}
|
||||
to {
|
||||
fill: inherit;
|
||||
@ -218,7 +218,7 @@ panelmultiview[mainViewId=PanelUI-pocketView] > .panel-viewcontainer > .panel-vi
|
||||
}
|
||||
|
||||
#pocket-button[cui-areatype="toolbar"][open] {
|
||||
fill: rgb(213,32,20);
|
||||
fill: #ef4056;
|
||||
}
|
||||
|
||||
@media not all and (min-resolution: 1.1dppx) {
|
||||
|
@ -549,6 +549,7 @@ safebrowsing.reportedAttackSite=Reported Attack Site!
|
||||
safebrowsing.notAnAttackButton.label=This isn’t an attack site…
|
||||
safebrowsing.notAnAttackButton.accessKey=A
|
||||
safebrowsing.reportedUnwantedSite=Reported Unwanted Software Site!
|
||||
safebrowsing.reportedHarmfulSite=Reported Harmful Site!
|
||||
|
||||
# Ctrl-Tab
|
||||
# LOCALIZATION NOTE (ctrlTab.listAllTabs.label): #1 represents the number
|
||||
|
@ -243,14 +243,6 @@ this.E10SUtils = {
|
||||
this.getRemoteTypeForURIObject(aURI, true, remoteType, webNav.currentURI);
|
||||
}
|
||||
|
||||
if (sessionHistory.count == 1 && webNav.currentURI.spec == "about:newtab") {
|
||||
// This is possibly a preloaded browser and we're about to navigate away for
|
||||
// the first time. On the child side there is no way to tell for sure if that
|
||||
// is the case, so let's redirect this request to the parent to decide if a new
|
||||
// process is needed.
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the URI can be loaded in the current process then continue
|
||||
return this.shouldLoadURIInThisProcess(aURI);
|
||||
},
|
||||
|
@ -861,12 +861,11 @@ html|span.ac-emphasize-text-url {
|
||||
This is why we can't have nice things: */
|
||||
/* Animations don't repaint properly without an X compositor. */
|
||||
animation-name: none !important;
|
||||
/* Opacity rounds to 0 or 1 on Linux without an X compositor so make the
|
||||
background be transparent in that case by having all alpha values < 0.5 */
|
||||
background-image: radial-gradient(50% 100%, rgba(0,149,220,0.3) 50%, rgba(0,149,220,0.49) 100%);
|
||||
/* The highlight isn't anti-aliased without an X compositor so make it thicker.
|
||||
Make it a darker color since we don't have the box-shadow in this case. */
|
||||
border: 4px solid rgb(0,149,220);
|
||||
/* Opacity rounds to 0 or 1 on Linux without an X compositor, making the
|
||||
background color not visible. Anti-aliasing is not available either. Make a
|
||||
thicker outline and cancel border-radius for that case. */
|
||||
outline: 4px solid rgb(0,200,215);
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
#UITourTooltipDescription {
|
||||
|
@ -4,11 +4,6 @@
|
||||
|
||||
%include ../../../shared/incontentprefs/preferences.inc.css
|
||||
|
||||
prefpane .groupbox-title {
|
||||
background: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.actionsMenu > .menulist-label-box > .menulist-icon {
|
||||
margin-top: 2px;
|
||||
margin-inline-start: 2px;
|
||||
@ -19,12 +14,10 @@ prefpane .groupbox-title {
|
||||
padding-inline-start: 3px;
|
||||
}
|
||||
|
||||
textbox + button {
|
||||
margin-inline-start: -4px;
|
||||
}
|
||||
|
||||
filefield + button {
|
||||
margin-inline-start: -8px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
#popupPolicyRow {
|
||||
|
@ -28,11 +28,6 @@ prefpane .groupbox-body {
|
||||
padding: 8px 4px 4px 4px;
|
||||
}
|
||||
|
||||
prefpane .groupbox-title {
|
||||
background: url("chrome://global/skin/50pct_transparent_grey.png") repeat-x bottom left;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
tabpanels {
|
||||
padding: 20px 7px 7px;
|
||||
}
|
||||
|
@ -5,9 +5,16 @@
|
||||
%endif
|
||||
@namespace html "http://www.w3.org/1999/xhtml";
|
||||
|
||||
* {
|
||||
-moz-user-select: text;
|
||||
}
|
||||
|
||||
:root {
|
||||
--in-content-category-background: #fafafc;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding-top: 0;
|
||||
background-color: #fafafc;
|
||||
}
|
||||
|
||||
.pane-container {
|
||||
@ -28,6 +35,10 @@
|
||||
font-size: 1.36rem;
|
||||
}
|
||||
|
||||
groupbox + groupbox {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
input,
|
||||
description.indent,
|
||||
.indent > description {
|
||||
@ -39,10 +50,6 @@ description.indent,
|
||||
color: #737373;
|
||||
}
|
||||
|
||||
* {
|
||||
-moz-user-select: text;
|
||||
}
|
||||
|
||||
button,
|
||||
treecol,
|
||||
html|option {
|
||||
@ -50,34 +57,29 @@ html|option {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
caption > label {
|
||||
font-size: 1.55rem;
|
||||
font-weight: 600;
|
||||
description,
|
||||
label {
|
||||
line-height: 30px;
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
#engineList treechildren::-moz-tree-image(engineShown, checked),
|
||||
#blocklistsTree treechildren::-moz-tree-image(selectionCol, checked) {
|
||||
list-style-image: url("chrome://global/skin/in-content/check.svg");
|
||||
-moz-context-properties: fill, stroke;
|
||||
fill: #2292d0;
|
||||
stroke: none;
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
description > checkbox {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
#engineList treechildren::-moz-tree-image(engineShown, checked, selected),
|
||||
#blocklistsTree treechildren::-moz-tree-image(selectionCol, checked, selected) {
|
||||
fill: white;
|
||||
stroke: #0095dd;
|
||||
.indent {
|
||||
margin-inline-start: 28px !important;
|
||||
}
|
||||
|
||||
#engineList treechildren::-moz-tree-row,
|
||||
#blocklistsTree treechildren::-moz-tree-row {
|
||||
min-height: 36px;
|
||||
separator.thin:not([orient="vertical"]) {
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
#selectionCol {
|
||||
min-width: 26px;
|
||||
.checkbox-check {
|
||||
margin-inline-end: 8px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.learnMore {
|
||||
@ -88,6 +90,15 @@ caption > label {
|
||||
|
||||
.accessory-button {
|
||||
min-width: 145px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.groupbox-title {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.groupbox-body {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Subcategory title */
|
||||
@ -109,24 +120,6 @@ caption > label {
|
||||
|
||||
/* Category List */
|
||||
|
||||
#categories {
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
#categories > scrollbox {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* We want the last category to always have non-0 getBoundingClientRect().bottom
|
||||
* so we can use the value to figure out the max-height of the list in
|
||||
* preferences.js, so use collapse instead of display: none; if it's hidden
|
||||
*/
|
||||
#categories > .category[hidden="true"] {
|
||||
display: -moz-box;
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#category-general > .category-icon {
|
||||
list-style-image: url("chrome://browser/skin/preferences/in-content-new/general.svg");
|
||||
}
|
||||
@ -143,15 +136,6 @@ caption > label {
|
||||
list-style-image: url("chrome://browser/skin/preferences/in-content-new/sync.svg");
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.category-name {
|
||||
display: none;
|
||||
}
|
||||
.help-button {
|
||||
font-size: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* header */
|
||||
.header {
|
||||
display: flex;
|
||||
@ -165,7 +149,12 @@ caption > label {
|
||||
|
||||
/* General Pane */
|
||||
|
||||
#startupGroup {
|
||||
margin-top: 0px !important;
|
||||
}
|
||||
|
||||
#startupTable {
|
||||
margin-top: 32px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
@ -173,8 +162,12 @@ caption > label {
|
||||
padding: 0; /* remove the padding from html.css */
|
||||
}
|
||||
|
||||
#startupTable > tr:not(:first-child) > td {
|
||||
padding-top: 0.5em; /* add a spacing between the rows */
|
||||
#startupTable > .tableGroup > td {
|
||||
padding-top: 32px;
|
||||
}
|
||||
|
||||
#startupTable > .tableSubGroup > td {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
#startupTable > tr > .label-cell {
|
||||
@ -182,6 +175,10 @@ caption > label {
|
||||
width: 0; /* make the column as small as possible */
|
||||
}
|
||||
|
||||
#startupTable > tr > .content-cell:not(:first-child) {
|
||||
padding-inline-start: 8px;
|
||||
}
|
||||
|
||||
#startupTable > tr > .label-cell > label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
@ -202,9 +199,8 @@ caption > label {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#useFirefoxSync {
|
||||
font-size: 90%;
|
||||
margin-inline-end: 8px !important;
|
||||
.content-cell-item {
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
#getStarted {
|
||||
@ -225,15 +221,34 @@ caption > label {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
#defaultFontSizeLabel {
|
||||
/* !important needed to override common !important rule */
|
||||
margin-inline-start: 4px !important;
|
||||
#updateApp > .groupbox-body > label {
|
||||
margin: 0 0 4px 0;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
/* Applications Pane Styles */
|
||||
#updateApp > .groupbox-body > description {
|
||||
line-height: 30px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#updateBox {
|
||||
margin-top: 8px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
#updateBox button {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#updateRadioGroup radio {
|
||||
height: 30px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
#filter {
|
||||
margin-inline-start: 0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
#handlersView {
|
||||
@ -266,7 +281,51 @@ caption > label {
|
||||
margin-inline-end: 8px !important;
|
||||
}
|
||||
|
||||
/* Privacy pane */
|
||||
/* Search Pane */
|
||||
|
||||
#defaultEngine {
|
||||
margin-top: 2px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
#engineList {
|
||||
margin: 2px 0 5px 0;
|
||||
}
|
||||
|
||||
#engineList > treechildren::-moz-tree-image(engineShown, checked),
|
||||
#blocklistsTree > treechildren::-moz-tree-image(selectionCol, checked) {
|
||||
list-style-image: url("chrome://global/skin/in-content/check.svg");
|
||||
-moz-context-properties: fill, stroke;
|
||||
fill: #2292d0;
|
||||
stroke: none;
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
#engineList > treechildren::-moz-tree-image(engineShown, checked, selected),
|
||||
#blocklistsTree > treechildren::-moz-tree-image(selectionCol, checked, selected) {
|
||||
fill: white;
|
||||
stroke: #0095dd;
|
||||
}
|
||||
|
||||
#engineList > treechildren::-moz-tree-row,
|
||||
#blocklistsTree > treechildren::-moz-tree-row {
|
||||
min-height: 36px;
|
||||
}
|
||||
|
||||
#selectionCol {
|
||||
min-width: 26px;
|
||||
}
|
||||
|
||||
#addEnginesBox {
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
|
||||
/* Privacy Pane */
|
||||
|
||||
#formAutofillGroup {
|
||||
margin-top: 28px;
|
||||
}
|
||||
|
||||
.doNotTrackLearnMore {
|
||||
margin-inline-start: calc(1em + 30px);
|
||||
@ -279,14 +338,28 @@ caption > label {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
#locationBarGroup > .text-link {
|
||||
margin-top: 6px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
#allowSmartSize {
|
||||
margin-top: 0;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
#doNotTrackLearnMoreBox {
|
||||
margin-top: 30px
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
#trackingProtectionAdvancedSettings {
|
||||
margin-inline-start: 15px;
|
||||
}
|
||||
|
||||
#historyPane {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Collapse the non-active vboxes in decks to use only the height the
|
||||
active vbox needs */
|
||||
#historyPane:not([selectedIndex="1"]) > #historyDontRememberPane,
|
||||
@ -297,16 +370,6 @@ caption > label {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
/* XXX This style is for bug 740213 and should be removed once that
|
||||
bug has a solution. */
|
||||
description > html|a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
description > checkbox {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#weavePrefsDeck > vbox > label,
|
||||
#weavePrefsDeck > vbox > groupbox,
|
||||
#weavePrefsDeck > vbox > description,
|
||||
@ -316,21 +379,10 @@ description > checkbox {
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
groupbox {
|
||||
/* Give more available space for displaying tooltip on scrollable groupbox */
|
||||
margin-top: 15px !important;
|
||||
}
|
||||
|
||||
#tabsElement {
|
||||
margin-inline-end: 4px; /* add the 4px end-margin of other elements */
|
||||
}
|
||||
|
||||
.indent {
|
||||
/* !important needed to override margin-inline-start:0 !important; rule
|
||||
define in common.css for labels */
|
||||
margin-inline-start: 33px !important;
|
||||
}
|
||||
|
||||
.text-link {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@ -374,6 +426,7 @@ groupbox {
|
||||
}
|
||||
|
||||
.dialogBox > .groupbox-title {
|
||||
margin-top: 0;
|
||||
padding: 3.5px 0;
|
||||
background-color: #F1F1F1;
|
||||
border-bottom: 1px solid #C1C1C1;
|
||||
@ -462,6 +515,11 @@ groupbox {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
#useFirefoxSync {
|
||||
font-size: 90%;
|
||||
margin-inline-end: 8px !important;
|
||||
}
|
||||
|
||||
#noFxaGroup {
|
||||
-moz-box-flex: 1;
|
||||
margin: 0;
|
||||
@ -481,8 +539,10 @@ groupbox {
|
||||
}
|
||||
|
||||
#fxaSyncComputerName {
|
||||
margin-inline-start: 0px;
|
||||
-moz-box-flex: 1;
|
||||
margin-top: 3px;
|
||||
margin-inline-start: -4px;
|
||||
margin-inline-end: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#tosPP-small-ToS {
|
||||
@ -622,24 +682,24 @@ groupbox {
|
||||
.help-button {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
/* Needs to have enough gap from the bottom to not
|
||||
get behind the status panel (bug 1357841). */
|
||||
bottom: 2rem;
|
||||
bottom: 36px;
|
||||
background-image: url("chrome://browser/skin/preferences/in-content-new/help.svg");
|
||||
-moz-context-properties: fill, fill-opacity;
|
||||
fill: currentColor;
|
||||
fill-opacity: 0.8;
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
background-position: 15px;
|
||||
padding-inline-start: 35px;
|
||||
height: 16px;
|
||||
background-position: 8px;
|
||||
padding-inline-start: 38px;
|
||||
margin-inline-start: 44px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.help-button:-moz-locale-dir(rtl) {
|
||||
background-position: right 8px top 0;
|
||||
left: auto;
|
||||
right: 0;
|
||||
background-position: right 15px top 0;
|
||||
}
|
||||
|
||||
.help-button:hover {
|
||||
@ -677,7 +737,7 @@ groupbox {
|
||||
|
||||
#searchInput {
|
||||
width: 250px;
|
||||
margin: 20px 0;
|
||||
margin: 20px 0 30px 0;
|
||||
}
|
||||
|
||||
#searchInput .textbox-search-icons:not([selectedIndex="1"]) {
|
||||
|
@ -142,9 +142,11 @@ ifeq (,$(findstring -j,$(MOZ_MAKE_FLAGS)))
|
||||
MOZ_MAKE_FLAGS += -j$(cores)
|
||||
endif
|
||||
|
||||
ifdef MOZ_AUTOMATION
|
||||
ifeq (4.0,$(firstword $(sort 4.0 $(MAKE_VERSION))))
|
||||
MOZ_MAKE_FLAGS += --output-sync=line
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef MOZ_BUILD_PROJECTS
|
||||
|
||||
|
@ -3,10 +3,20 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const URL = "data:text/html;charset=utf8,test for textbox context menu";
|
||||
// HTML inputs don't automatically get the 'edit' context menu, so we have
|
||||
// a helper on the toolbox to do so. Make sure that shows menu items in the
|
||||
// right state, and that it works for an input inside of a panel.
|
||||
|
||||
add_task(function* () {
|
||||
let toolbox = yield openNewTabAndToolbox(URL, "inspector");
|
||||
const URL = "data:text/html;charset=utf8,test for textbox context menu";
|
||||
const textboxToolId = "test-tool-1";
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
gDevTools.unregisterTool(textboxToolId);
|
||||
});
|
||||
|
||||
add_task(async function checkMenuEntryStates() {
|
||||
info("Checking the state of edit menuitems with an empty clipboard");
|
||||
let toolbox = await openNewTabAndToolbox(URL, "inspector");
|
||||
let textboxContextMenu = toolbox.textBoxContextMenuPopup;
|
||||
|
||||
emptyClipboard();
|
||||
@ -15,7 +25,7 @@ add_task(function* () {
|
||||
let inspector = toolbox.getPanel("inspector");
|
||||
let onFocus = once(inspector.searchBox, "focus");
|
||||
inspector.searchBox.focus();
|
||||
yield onFocus;
|
||||
await onFocus;
|
||||
|
||||
ok(textboxContextMenu, "The textbox context menu is loaded in the toolbox");
|
||||
|
||||
@ -30,7 +40,7 @@ add_task(function* () {
|
||||
|
||||
let onContextMenuPopup = once(textboxContextMenu, "popupshowing");
|
||||
textboxContextMenu.openPopupAtScreen(0, 0, true);
|
||||
yield onContextMenuPopup;
|
||||
await onContextMenuPopup;
|
||||
|
||||
is(cmdUndo.getAttribute("disabled"), "true", "cmdUndo is disabled");
|
||||
is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
|
||||
@ -41,11 +51,41 @@ add_task(function* () {
|
||||
is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
|
||||
is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
|
||||
is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
|
||||
|
||||
yield cleanup(toolbox);
|
||||
});
|
||||
|
||||
function* cleanup(toolbox) {
|
||||
yield toolbox.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
add_task(async function automaticallyBindTexbox() {
|
||||
info("Registering a tool with an input field and making sure the context menu works");
|
||||
gDevTools.registerTool({
|
||||
id: textboxToolId,
|
||||
isTargetSupported: () => true,
|
||||
url: "data:text/html;charset=utf8,<input />",
|
||||
label: "Context menu works without tool intervention",
|
||||
build: function (iframeWindow, toolbox) {
|
||||
this.panel = createTestPanel(iframeWindow, toolbox);
|
||||
return this.panel.open();
|
||||
},
|
||||
});
|
||||
|
||||
let toolbox = await openNewTabAndToolbox(URL, textboxToolId);
|
||||
is(toolbox.currentToolId, textboxToolId, "The custom tool has been opened");
|
||||
await checkTextBox(toolbox.getCurrentPanel().document.querySelector("input"), toolbox);
|
||||
});
|
||||
|
||||
async function checkTextBox(textBox, {textBoxContextMenuPopup}) {
|
||||
is(textBoxContextMenuPopup.state, "closed", "The menu is closed");
|
||||
|
||||
info("Simulating context click on the textbox and expecting the menu to open");
|
||||
let onContextMenu = once(textBoxContextMenuPopup, "popupshown");
|
||||
EventUtils.synthesizeMouse(textBox, 2, 2, {type: "contextmenu", button: 2},
|
||||
textBox.ownerDocument.defaultView);
|
||||
await onContextMenu;
|
||||
|
||||
is(textBoxContextMenuPopup.state, "open", "The menu is now visible");
|
||||
|
||||
info("Closing the menu");
|
||||
let onContextMenuHidden = once(textBoxContextMenuPopup, "popuphidden");
|
||||
textBoxContextMenuPopup.hidePopup();
|
||||
await onContextMenuHidden;
|
||||
|
||||
is(textBoxContextMenuPopup.state, "closed", "The menu is closed again");
|
||||
}
|
||||
|
@ -203,6 +203,7 @@ function DevToolPanel(iframeWindow, toolbox) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this._toolbox = toolbox;
|
||||
this._window = iframeWindow;
|
||||
}
|
||||
|
||||
DevToolPanel.prototype = {
|
||||
@ -218,6 +219,10 @@ DevToolPanel.prototype = {
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
get document() {
|
||||
return this._window.document;
|
||||
},
|
||||
|
||||
get target() {
|
||||
return this._toolbox.target;
|
||||
},
|
||||
|
@ -442,6 +442,13 @@ Toolbox.prototype = {
|
||||
this.doc.getElementById("toolbox-textbox-context-popup");
|
||||
this.textBoxContextMenuPopup.addEventListener("popupshowing",
|
||||
this._updateTextBoxMenuItems, true);
|
||||
this.doc.addEventListener("contextmenu", (e) => {
|
||||
if (e.originalTarget.closest("input") || e.originalTarget.closest("textarea")) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this.openTextBoxContextMenu(e.screenX, e.screenY);
|
||||
}
|
||||
}, true);
|
||||
|
||||
this.shortcuts = new KeyShortcuts({
|
||||
window: this.doc.defaultView
|
||||
|
@ -324,7 +324,6 @@ BoxModel.prototype = {
|
||||
this.store.dispatch(updateLayout(layout));
|
||||
}, e => console.error(e));
|
||||
},
|
||||
contextMenu: this.inspector.onTextBoxContextMenu,
|
||||
cssProperties: getCssProperties(this.inspector.toolbox)
|
||||
}, event);
|
||||
},
|
||||
|
@ -193,7 +193,6 @@ function CssComputedView(inspector, document, pageStyle) {
|
||||
this.element.addEventListener("click", this._onClick);
|
||||
this.element.addEventListener("contextmenu", this._onContextMenu);
|
||||
this.searchField.addEventListener("input", this._onFilterStyles);
|
||||
this.searchField.addEventListener("contextmenu", this.inspector.onTextBoxContextMenu);
|
||||
this.searchClearButton.addEventListener("click", this._onClearSearch);
|
||||
this.includeBrowserStylesCheckbox.addEventListener("input",
|
||||
this._onIncludeBrowserStyles);
|
||||
@ -781,8 +780,6 @@ CssComputedView.prototype = {
|
||||
this.styleDocument.removeEventListener("copy", this._onCopy);
|
||||
this.element.removeEventListener("contextmenu", this._onContextMenu);
|
||||
this.searchField.removeEventListener("input", this._onFilterStyles);
|
||||
this.searchField.removeEventListener("contextmenu",
|
||||
this.inspector.onTextBoxContextMenu);
|
||||
this.searchClearButton.removeEventListener("click", this._onClearSearch);
|
||||
this.includeBrowserStylesCheckbox.removeEventListener("input",
|
||||
this._onIncludeBrowserStyles);
|
||||
|
@ -7,7 +7,6 @@
|
||||
const { addons, createClass, createFactory, DOM: dom, PropTypes } =
|
||||
require("devtools/client/shared/vendor/react");
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
const { findDOMNode } = require("devtools/client/shared/vendor/react-dom");
|
||||
|
||||
const SearchBox = createFactory(require("devtools/client/shared/components/search-box"));
|
||||
const FontList = createFactory(require("./FontList"));
|
||||
@ -25,25 +24,10 @@ const App = createClass({
|
||||
fonts: PropTypes.arrayOf(PropTypes.shape(Types.font)).isRequired,
|
||||
onPreviewFonts: PropTypes.func.isRequired,
|
||||
onShowAllFont: PropTypes.func.isRequired,
|
||||
onTextBoxContextMenu: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
mixins: [ addons.PureRenderMixin ],
|
||||
|
||||
componentDidMount() {
|
||||
let { onTextBoxContextMenu } = this.props;
|
||||
|
||||
let searchInput = findDOMNode(this).querySelector(".devtools-textinput");
|
||||
searchInput.addEventListener("contextmenu", onTextBoxContextMenu);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
let { onTextBoxContextMenu } = this.props;
|
||||
|
||||
let searchInput = findDOMNode(this).querySelector(".devtools-textinput");
|
||||
searchInput.removeEventListener("contextmenu", onTextBoxContextMenu);
|
||||
},
|
||||
|
||||
render() {
|
||||
let {
|
||||
fonts,
|
||||
|
@ -47,7 +47,6 @@ FontInspector.prototype = {
|
||||
let app = App({
|
||||
onPreviewFonts: this.onPreviewFonts,
|
||||
onShowAllFont: this.onShowAllFont,
|
||||
onTextBoxContextMenu: this.inspector.onTextBoxContextMenu
|
||||
});
|
||||
|
||||
let provider = createElement(Provider, {
|
||||
|
@ -44,7 +44,6 @@ function InspectorSearch(inspector, input, clearBtn) {
|
||||
this._onClearSearch = this._onClearSearch.bind(this);
|
||||
this.searchBox.addEventListener("keydown", this._onKeyDown, true);
|
||||
this.searchBox.addEventListener("input", this._onInput, true);
|
||||
this.searchBox.addEventListener("contextmenu", this.inspector.onTextBoxContextMenu);
|
||||
this.searchClearButton.addEventListener("click", this._onClearSearch);
|
||||
|
||||
// For testing, we need to be able to wait for the most recent node request
|
||||
@ -65,8 +64,6 @@ InspectorSearch.prototype = {
|
||||
destroy: function () {
|
||||
this.searchBox.removeEventListener("keydown", this._onKeyDown, true);
|
||||
this.searchBox.removeEventListener("input", this._onInput, true);
|
||||
this.searchBox.removeEventListener("contextmenu",
|
||||
this.inspector.onTextBoxContextMenu);
|
||||
this.searchClearButton.removeEventListener("click", this._onClearSearch);
|
||||
this.searchBox = null;
|
||||
this.searchClearButton = null;
|
||||
|
@ -123,7 +123,6 @@ function Inspector(toolbox) {
|
||||
this.onSidebarHidden = this.onSidebarHidden.bind(this);
|
||||
this.onSidebarSelect = this.onSidebarSelect.bind(this);
|
||||
this.onSidebarShown = this.onSidebarShown.bind(this);
|
||||
this.onTextBoxContextMenu = this.onTextBoxContextMenu.bind(this);
|
||||
|
||||
this._target.on("will-navigate", this._onBeforeNavigate);
|
||||
this._detectingActorFeatures = this._detectActorFeatures();
|
||||
@ -1062,17 +1061,6 @@ Inspector.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* This is meant to be called by all the search, filter, inplace text boxes in the
|
||||
* inspector, and just calls through to the toolbox openTextBoxContextMenu helper.
|
||||
* @param {DOMEvent} e
|
||||
*/
|
||||
onTextBoxContextMenu: function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this.toolbox.openTextBoxContextMenu(e.screenX, e.screenY);
|
||||
},
|
||||
|
||||
_openMenu: function ({ target, screenX = 0, screenY = 0 } = { }) {
|
||||
let markupContainer = this.markup.getContainer(this.selection.nodeFront);
|
||||
|
||||
|
@ -69,7 +69,6 @@ function ElementEditor(container, node) {
|
||||
trigger: "dblclick",
|
||||
stopOnReturn: true,
|
||||
done: this.onTagEdit.bind(this),
|
||||
contextMenu: this.markup.inspector.onTextBoxContextMenu,
|
||||
cssProperties: this._cssProperties
|
||||
});
|
||||
}
|
||||
@ -97,7 +96,6 @@ function ElementEditor(container, node) {
|
||||
undoMods.apply();
|
||||
});
|
||||
},
|
||||
contextMenu: this.markup.inspector.onTextBoxContextMenu,
|
||||
cssProperties: this._cssProperties
|
||||
});
|
||||
|
||||
@ -402,7 +400,6 @@ ElementEditor.prototype = {
|
||||
undoMods.apply();
|
||||
});
|
||||
},
|
||||
contextMenu: this.markup.inspector.onTextBoxContextMenu,
|
||||
cssProperties: this._cssProperties
|
||||
});
|
||||
|
||||
|
@ -55,7 +55,6 @@ function TextEditor(container, node, type) {
|
||||
});
|
||||
},
|
||||
cssProperties: getCssProperties(this.markup.toolbox),
|
||||
contextMenu: this.markup.inspector.onTextBoxContextMenu
|
||||
});
|
||||
|
||||
this.update();
|
||||
|
@ -150,7 +150,6 @@ function CssRuleView(inspector, document, store, pageStyle) {
|
||||
this.element.addEventListener("contextmenu", this._onContextMenu);
|
||||
this.addRuleButton.addEventListener("click", this._onAddRule);
|
||||
this.searchField.addEventListener("input", this._onFilterStyles);
|
||||
this.searchField.addEventListener("contextmenu", this.inspector.onTextBoxContextMenu);
|
||||
this.searchClearButton.addEventListener("click", this._onClearSearch);
|
||||
this.pseudoClassToggle.addEventListener("click", this._onTogglePseudoClassPanel);
|
||||
this.classToggle.addEventListener("click", this._onToggleClassPanel);
|
||||
@ -701,8 +700,6 @@ CssRuleView.prototype = {
|
||||
this.element.removeEventListener("contextmenu", this._onContextMenu);
|
||||
this.addRuleButton.removeEventListener("click", this._onAddRule);
|
||||
this.searchField.removeEventListener("input", this._onFilterStyles);
|
||||
this.searchField.removeEventListener("contextmenu",
|
||||
this.inspector.onTextBoxContextMenu);
|
||||
this.searchClearButton.removeEventListener("click", this._onClearSearch);
|
||||
this.pseudoClassToggle.removeEventListener("click", this._onTogglePseudoClassPanel);
|
||||
this.classToggle.removeEventListener("click", this._onToggleClassPanel);
|
||||
|
@ -45,7 +45,7 @@ support-files =
|
||||
!/devtools/client/shared/test/test-actor-registry.js
|
||||
|
||||
[browser_rules_add-property-and-reselect.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
skip-if = stylo # Bug 1387445
|
||||
[browser_rules_add-property-cancel_01.js]
|
||||
[browser_rules_add-property-cancel_02.js]
|
||||
[browser_rules_add-property-cancel_03.js]
|
||||
@ -54,22 +54,14 @@ skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_add-property_02.js]
|
||||
[browser_rules_add-property-svg.js]
|
||||
[browser_rules_add-rule-and-property.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_add-rule-button-state.js]
|
||||
[browser_rules_add-rule-edit-selector.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_add-rule-iframes.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_add-rule-namespace-elements.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_add-rule-pseudo-class.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_add-rule-then-property-edit-selector.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_add-rule-with-menu.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_add-rule.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_authored.js]
|
||||
[browser_rules_authored_color.js]
|
||||
[browser_rules_authored_override.js]
|
||||
@ -116,7 +108,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
||||
[browser_rules_cubicbezier-commit-on-ENTER.js]
|
||||
[browser_rules_cubicbezier-revert-on-ESC.js]
|
||||
[browser_rules_custom.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
skip-if = stylo # Bug 1387445
|
||||
[browser_rules_cycle-angle.js]
|
||||
[browser_rules_cycle-color.js]
|
||||
[browser_rules_edit-display-grid-property.js]
|
||||
@ -127,7 +119,6 @@ skip-if = (os == "linux") # Bug 1356214
|
||||
[browser_rules_edit-property-computed.js]
|
||||
[browser_rules_edit-property-increments.js]
|
||||
[browser_rules_edit-property-order.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_edit-property-remove_01.js]
|
||||
[browser_rules_edit-property-remove_02.js]
|
||||
[browser_rules_edit-property-remove_03.js]
|
||||
@ -137,7 +128,7 @@ skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_edit-property_04.js]
|
||||
[browser_rules_edit-property_05.js]
|
||||
[browser_rules_edit-property_06.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
skip-if = stylo # Bug 1387445
|
||||
[browser_rules_edit-property_07.js]
|
||||
[browser_rules_edit-property_08.js]
|
||||
[browser_rules_edit-property_09.js]
|
||||
@ -145,16 +136,12 @@ skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_edit-selector-click-on-scrollbar.js]
|
||||
skip-if = os == "mac" # Bug 1245996 : click on scrollbar not working on OSX
|
||||
[browser_rules_edit-selector-commit.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_edit-selector_01.js]
|
||||
[browser_rules_edit-selector_02.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_edit-selector_03.js]
|
||||
[browser_rules_edit-selector_04.js]
|
||||
[browser_rules_edit-selector_05.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_edit-selector_06.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_edit-selector_07.js]
|
||||
[browser_rules_edit-selector_08.js]
|
||||
[browser_rules_edit-selector_09.js]
|
||||
@ -183,7 +170,6 @@ skip-if = (os == "win" && debug) # bug 963492: win.
|
||||
[browser_rules_grid-toggle_03.js]
|
||||
[browser_rules_grid-toggle_04.js]
|
||||
[browser_rules_guessIndentation.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_inherited-properties_01.js]
|
||||
[browser_rules_inherited-properties_02.js]
|
||||
[browser_rules_inherited-properties_03.js]
|
||||
@ -193,22 +179,21 @@ skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_invalid-source-map.js]
|
||||
[browser_rules_keybindings.js]
|
||||
[browser_rules_keyframes-rule_01.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
skip-if = stylo # Bug 1387445
|
||||
[browser_rules_keyframes-rule_02.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
skip-if = stylo # Bug 1387445
|
||||
[browser_rules_keyframeLineNumbers.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
skip-if = stylo # Bug 1387445
|
||||
[browser_rules_lineNumbers.js]
|
||||
[browser_rules_livepreview.js]
|
||||
[browser_rules_mark_overridden_01.js]
|
||||
[browser_rules_mark_overridden_02.js]
|
||||
[browser_rules_mark_overridden_03.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
skip-if = stylo # Bug 1387445
|
||||
[browser_rules_mark_overridden_04.js]
|
||||
[browser_rules_mark_overridden_05.js]
|
||||
[browser_rules_mark_overridden_06.js]
|
||||
[browser_rules_mark_overridden_07.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_mathml-element.js]
|
||||
[browser_rules_media-queries.js]
|
||||
[browser_rules_multiple-properties-duplicates.js]
|
||||
@ -234,7 +219,7 @@ skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_search-filter-overridden-property.js]
|
||||
[browser_rules_search-filter_01.js]
|
||||
[browser_rules_search-filter_02.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
skip-if = stylo # Bug 1387445
|
||||
[browser_rules_search-filter_03.js]
|
||||
[browser_rules_search-filter_04.js]
|
||||
[browser_rules_search-filter_05.js]
|
||||
@ -257,7 +242,6 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
||||
[browser_rules_selector-highlighter_04.js]
|
||||
[browser_rules_selector-highlighter_05.js]
|
||||
[browser_rules_selector_highlight.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_rules_shapes-toggle_01.js]
|
||||
[browser_rules_shapes-toggle_02.js]
|
||||
[browser_rules_shapes-toggle_03.js]
|
||||
|
@ -144,7 +144,6 @@ RuleEditor.prototype = {
|
||||
element: this.selectorText,
|
||||
done: this._onSelectorDone,
|
||||
cssProperties: this.rule.cssProperties,
|
||||
contextMenu: this.ruleView.inspector.onTextBoxContextMenu
|
||||
});
|
||||
}
|
||||
|
||||
@ -463,7 +462,6 @@ RuleEditor.prototype = {
|
||||
contentType: InplaceEditor.CONTENT_TYPES.CSS_PROPERTY,
|
||||
popup: this.ruleView.popup,
|
||||
cssProperties: this.rule.cssProperties,
|
||||
contextMenu: this.ruleView.inspector.onTextBoxContextMenu
|
||||
});
|
||||
|
||||
// Auto-close the input if multiple rules get pasted into new property.
|
||||
|
@ -228,7 +228,6 @@ TextPropertyEditor.prototype = {
|
||||
contentType: InplaceEditor.CONTENT_TYPES.CSS_PROPERTY,
|
||||
popup: this.popup,
|
||||
cssProperties: this.cssProperties,
|
||||
contextMenu: this.ruleView.inspector.onTextBoxContextMenu
|
||||
});
|
||||
|
||||
// Auto blur name field on multiple CSS rules get pasted in.
|
||||
@ -300,7 +299,6 @@ TextPropertyEditor.prototype = {
|
||||
multiline: true,
|
||||
maxWidth: () => this.container.getBoundingClientRect().width,
|
||||
cssProperties: this.cssProperties,
|
||||
contextMenu: this.ruleView.inspector.onTextBoxContextMenu
|
||||
});
|
||||
|
||||
this.ruleView.highlighters.on("hover-shape-point", this._onHoverShapePoint);
|
||||
|
@ -101,7 +101,6 @@ skip-if = e10s && debug # Bug 1252201 - Docshell leak on debug e10s
|
||||
[browser_styleeditor_sync.js]
|
||||
[browser_styleeditor_syncAddProperty.js]
|
||||
[browser_styleeditor_syncAddRule.js]
|
||||
skip-if = stylo # Bug 1384802 - Empty rules aren't returned
|
||||
[browser_styleeditor_syncAlreadyOpen.js]
|
||||
[browser_styleeditor_syncEditSelector.js]
|
||||
[browser_styleeditor_syncIntoRuleView.js]
|
||||
|
50
devtools/client/webconsole/new-console-output/test/README.md
Normal file
50
devtools/client/webconsole/new-console-output/test/README.md
Normal file
@ -0,0 +1,50 @@
|
||||
# Console Tests
|
||||
The console panel uses currently two different frameworks for tests:
|
||||
|
||||
* Mochitest - [Mochitest](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Mochitest) is an automated testing framework built on top of the MochiKit JavaScript libraries. It's just one of the automated regression testing frameworks used by Mozilla
|
||||
|
||||
* Mocha + Enzyme - [mocha](https://mochajs.org/) Mocha is JavaScript test framework running on Node.js
|
||||
[Enzyme](http://airbnb.io/enzyme/) is a JavaScript Testing utility for React that makes it easier to assert, manipulate, and traverse your React Components' output.
|
||||
|
||||
The team is leaning towards Enzyme since it's well known and suitable for React.
|
||||
It's also easier to contribute to tests written on top of Enzyme.
|
||||
|
||||
# Stubs
|
||||
Many tests depends on fix data structures (aka stubs) that mimic
|
||||
<abbr title="Remote Debugging Protocol">RDP<abbr> packets that represents Console logs.
|
||||
Stubs are stored in `test/fixtures` directory and you might automatically generate them.
|
||||
|
||||
## Append new Console API stubs
|
||||
See how to generate stubs for Console API calls.
|
||||
|
||||
* Append new entry into `consoleApiCommands` array. The array is defined in this module:
|
||||
`\test\fixtures\stub-generators\stub-snippets.js`
|
||||
* Generate stubs with existing mochitest:
|
||||
`\test\fixtures\stub-generators\browser_webconsole_check_stubs_console_api.js`
|
||||
|
||||
Run the generator using `mach` command.
|
||||
`./mach test devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/browser_webconsole_check_stubs_console_api.js`
|
||||
|
||||
## Append new CSS Messages stubs
|
||||
See how to generate stubs for CSS messages.
|
||||
|
||||
* Append new entry into `cssMessage` map into `stub-snippets.js`
|
||||
* Generate stubs with: `browser_webconsole_check_stubs_css_message.js`
|
||||
|
||||
## Append new Evaluation Result stubs
|
||||
See how to generate stubs for evaluation results.
|
||||
|
||||
* Append new entry into `evaluationResultCommands` map into `stub-snippets.js`
|
||||
* Generate stubs with: `browser_webconsole_check_stubs_evaluation_result.js`
|
||||
|
||||
## Append new Network Events stubs
|
||||
See how to generate stubs for network events
|
||||
|
||||
* Append new entry into `networkEvent` map into `stub-snippets.js`
|
||||
* Generate stubs with: `browser_webconsole_update_stubs_network_event.js`
|
||||
|
||||
## Append new Page Error stubs
|
||||
See how to generate stubs for page errors.
|
||||
|
||||
* Append new entry into `pageError` array into `stub-snippets.js`
|
||||
* Generate stubs with: `browser_webconsole_update_stubs_page_error.js`
|
@ -89,7 +89,7 @@ struct DevTools : public ::testing::Test {
|
||||
/* Create the global object. */
|
||||
JS::RootedObject newGlobal(cx);
|
||||
JS::CompartmentOptions options;
|
||||
options.behaviors().setVersion(JSVERSION_LATEST);
|
||||
options.behaviors().setVersion(JSVERSION_DEFAULT);
|
||||
newGlobal = JS_NewGlobalObject(cx, getGlobalClass(), nullptr,
|
||||
JS::FireOnNewGlobalHook, options);
|
||||
if (!newGlobal)
|
||||
|
@ -123,7 +123,8 @@ DOMImplementation::CreateDocument(const nsAString& aNamespaceURI,
|
||||
mDocumentURI, mBaseURI,
|
||||
mOwner->NodePrincipal(),
|
||||
true, scriptHandlingObject,
|
||||
DocumentFlavorLegacyGuess);
|
||||
DocumentFlavorLegacyGuess,
|
||||
mOwner->GetStyleBackendType());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// When DOMImplementation's createDocument method is invoked with
|
||||
@ -202,7 +203,8 @@ DOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
|
||||
doctype, mDocumentURI, mBaseURI,
|
||||
mOwner->NodePrincipal(),
|
||||
true, scriptHandlingObject,
|
||||
DocumentFlavorLegacyGuess);
|
||||
DocumentFlavorLegacyGuess,
|
||||
mOwner->GetStyleBackendType());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
|
||||
|
||||
|
@ -461,6 +461,13 @@ DOMParser::SetUpDocument(DocumentFlavor aFlavor, nsIDOMDocument** aResult)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Try to inherit a style backend.
|
||||
auto styleBackend = StyleBackendType::None;
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mScriptHandlingObject);
|
||||
if (window && window->GetExtantDoc()) {
|
||||
styleBackend = window->GetExtantDoc()->GetStyleBackendType();
|
||||
}
|
||||
|
||||
NS_ASSERTION(mPrincipal, "Must have principal by now");
|
||||
NS_ASSERTION(mDocumentURI, "Must have document URI by now");
|
||||
|
||||
@ -469,5 +476,6 @@ DOMParser::SetUpDocument(DocumentFlavor aFlavor, nsIDOMDocument** aResult)
|
||||
mPrincipal,
|
||||
true,
|
||||
scriptHandlingObject,
|
||||
aFlavor);
|
||||
aFlavor,
|
||||
styleBackend);
|
||||
}
|
||||
|
@ -5200,7 +5200,8 @@ nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
|
||||
principal,
|
||||
true,
|
||||
nullptr,
|
||||
DocumentFlavorHTML);
|
||||
DocumentFlavorHTML,
|
||||
StyleBackendType::None);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
|
||||
|
@ -9939,7 +9939,8 @@ nsDocument::GetTemplateContentsOwner()
|
||||
NodePrincipal(),
|
||||
true, // aLoadedAsData
|
||||
scriptObject, // aEventObject
|
||||
DocumentFlavorHTML);
|
||||
DocumentFlavorHTML,
|
||||
mStyleBackendType);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
mTemplateContentsOwner = do_QueryInterface(domDocument);
|
||||
@ -12603,6 +12604,12 @@ nsIDocument::Constructor(const GlobalObject& aGlobal,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto styleBackend = StyleBackendType::None;
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
|
||||
if (window && window->GetExtantDoc()) {
|
||||
styleBackend = window->GetExtantDoc()->GetStyleBackendType();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptObjectPrincipal> prin = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!prin) {
|
||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
@ -12627,7 +12634,8 @@ nsIDocument::Constructor(const GlobalObject& aGlobal,
|
||||
prin->GetPrincipal(),
|
||||
true,
|
||||
global,
|
||||
DocumentFlavorPlain);
|
||||
DocumentFlavorPlain,
|
||||
styleBackend);
|
||||
if (NS_FAILED(res)) {
|
||||
rv.Throw(res);
|
||||
return nullptr;
|
||||
|
@ -1662,7 +1662,7 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
|
||||
return;
|
||||
}
|
||||
|
||||
JS::CompileOptions options(cx, JSVERSION_LATEST);
|
||||
JS::CompileOptions options(cx, JSVERSION_DEFAULT);
|
||||
options.setFileAndLine(url.get(), 1);
|
||||
options.setNoScriptRval(true);
|
||||
|
||||
@ -1728,7 +1728,7 @@ nsMessageManagerScriptExecutor::InitChildGlobalInternal(
|
||||
|
||||
JS::CompartmentOptions options;
|
||||
options.creationOptions().setSystemZone();
|
||||
options.behaviors().setVersion(JSVERSION_LATEST);
|
||||
options.behaviors().setVersion(JSVERSION_DEFAULT);
|
||||
|
||||
if (xpc::SharedMemoryEnabled()) {
|
||||
options.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
|
||||
|
@ -2231,7 +2231,6 @@ GK_ATOM(DisplayPortMargins, "_displayportmargins")
|
||||
GK_ATOM(DisplayPortBase, "_displayportbase")
|
||||
GK_ATOM(AsyncScrollLayerCreationFailed, "_asyncscrolllayercreationfailed")
|
||||
GK_ATOM(forcemessagemanager, "forcemessagemanager")
|
||||
GK_ATOM(isPreloadBrowser, "isPreloadBrowser")
|
||||
|
||||
// Names for system metrics
|
||||
GK_ATOM(color_picker_available, "color-picker-available")
|
||||
|
@ -3634,7 +3634,8 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
|
||||
nsIPrincipal* aPrincipal,
|
||||
bool aLoadedAsData,
|
||||
nsIGlobalObject* aEventObject,
|
||||
DocumentFlavor aFlavor);
|
||||
DocumentFlavor aFlavor,
|
||||
mozilla::StyleBackendType aStyleBackend);
|
||||
|
||||
// This is used only for xbl documents created from the startup cache.
|
||||
// Non-cached documents are created in the same manner as xml documents.
|
||||
@ -3642,7 +3643,8 @@ nsresult
|
||||
NS_NewXBLDocument(nsIDOMDocument** aInstancePtrResult,
|
||||
nsIURI* aDocumentURI,
|
||||
nsIURI* aBaseURI,
|
||||
nsIPrincipal* aPrincipal);
|
||||
nsIPrincipal* aPrincipal,
|
||||
mozilla::StyleBackendType aStyleBackend);
|
||||
|
||||
nsresult
|
||||
NS_NewPluginDocument(nsIDocument** aInstancePtrResult);
|
||||
|
@ -1,7 +1,6 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
audio.ogg
|
||||
dummy.html
|
||||
empty.html
|
||||
file_audioLoop.html
|
||||
file_audioLoopInIframe.html
|
||||
@ -36,7 +35,6 @@ tags = mcb
|
||||
[browser_force_process_selector.js]
|
||||
skip-if = !e10s # this only makes sense with e10s-multi
|
||||
[browser_messagemanager_loadprocessscript.js]
|
||||
[browser_aboutnewtab_process_selection.js]
|
||||
[browser_messagemanager_targetframeloader.js]
|
||||
[browser_messagemanager_unload.js]
|
||||
[browser_pagehide_on_tab_close.js]
|
||||
|
@ -1,76 +0,0 @@
|
||||
const TEST_URL = "http://www.example.com/browser/dom/base/test/dummy.html";
|
||||
|
||||
var ppmm = Services.ppmm;
|
||||
|
||||
add_task(async function(){
|
||||
// We want to count processes in this test, so let's disable the pre-allocated process manager.
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.ipc.processPrelaunch.enabled", false],
|
||||
["dom.ipc.processCount", 10],
|
||||
["dom.ipc.keepProcessesAlive.web", 10],
|
||||
]});
|
||||
});
|
||||
|
||||
// Ensure that the preloaded browser exists, and it's finished loading.
|
||||
async function ensurePreloaded(gBrowser) {
|
||||
gBrowser._createPreloadBrowser();
|
||||
// We cannot use the regular BrowserTestUtils helper for waiting here, since that
|
||||
// would try to insert the preloaded browser, which would only break things.
|
||||
await BrowserTestUtils.waitForCondition( () => {
|
||||
return gBrowser._preloadedBrowser.contentDocument.readyState == "complete";
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function(){
|
||||
// This test is only relevant in e10s.
|
||||
if (!gMultiProcessBrowser)
|
||||
return;
|
||||
|
||||
ppmm.releaseCachedProcesses();
|
||||
|
||||
// Wait for the preloaded browser to load.
|
||||
await ensurePreloaded(gBrowser);
|
||||
|
||||
// Store the number of processes (note: +1 for the parent process).
|
||||
const { childCount: originalChildCount } = ppmm;
|
||||
|
||||
// Use the preloaded browser and create another one.
|
||||
BrowserOpenTab();
|
||||
let tab1 = gBrowser.selectedTab;
|
||||
await ensurePreloaded(gBrowser);
|
||||
|
||||
// Check that the process count did not change.
|
||||
is(ppmm.childCount, originalChildCount, "Preloaded browser should not create a new content process.")
|
||||
|
||||
// Let's do another round.
|
||||
BrowserOpenTab();
|
||||
let tab2 = gBrowser.selectedTab;
|
||||
await ensurePreloaded(gBrowser);
|
||||
|
||||
// Check that the process count did not change.
|
||||
is(ppmm.childCount, originalChildCount, "Preloaded browser should (still) not create a new content process.")
|
||||
|
||||
// Navigate to a content page from the parent side.
|
||||
tab2.linkedBrowser.loadURI(TEST_URL);
|
||||
await BrowserTestUtils.browserLoaded(tab2.linkedBrowser, false, TEST_URL);
|
||||
is(ppmm.childCount, originalChildCount + 1,
|
||||
"Navigating away from the preloaded browser (parent side) should create a new content process.")
|
||||
|
||||
// Navigate to a content page from the child side.
|
||||
await BrowserTestUtils.switchTab(gBrowser, tab1);
|
||||
await ContentTask.spawn(tab1.linkedBrowser, null, async function() {
|
||||
const TEST_URL = "http://www.example.com/browser/dom/base/test/dummy.html";
|
||||
content.location.href = TEST_URL;
|
||||
});
|
||||
await BrowserTestUtils.browserLoaded(tab1.linkedBrowser, false, TEST_URL);
|
||||
is(ppmm.childCount, originalChildCount + 2,
|
||||
"Navigating away from the preloaded browser (child side) should create a new content process.")
|
||||
|
||||
await BrowserTestUtils.removeTab(tab1);
|
||||
await BrowserTestUtils.removeTab(tab2);
|
||||
|
||||
// Since we kept alive all the processes, we can shut down the ones that do
|
||||
// not host any tabs reliably.
|
||||
ppmm.releaseCachedProcesses();
|
||||
is(ppmm.childCount, originalChildCount, "We're back to the original process count.");
|
||||
});
|
@ -1,9 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Dummy test page</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
|
||||
</head>
|
||||
<body>
|
||||
<p>Dummy test page</p>
|
||||
</body>
|
||||
</html>
|
@ -185,6 +185,11 @@ const kEventConstructors = {
|
||||
return new MediaQueryListEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
MediaRecorderErrorEvent: { create: function (aName, aProps) {
|
||||
aProps.error = new DOMException();
|
||||
return new MediaRecorderErrorEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
MediaStreamEvent: { create: function (aName, aProps) {
|
||||
return new MediaStreamEvent(aName, aProps);
|
||||
},
|
||||
@ -287,10 +292,6 @@ const kEventConstructors = {
|
||||
return new ProgressEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
RecordErrorEvent: { create: function (aName, aProps) {
|
||||
return new RecordErrorEvent(aName, aProps);
|
||||
},
|
||||
},
|
||||
RTCDataChannelEvent: { create: function (aName, aProps) {
|
||||
return new RTCDataChannelEvent(aName, aProps);
|
||||
},
|
||||
|
@ -53,11 +53,7 @@ function done() {
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestFlakyTimeout("untriaged");
|
||||
addLoadEvent(function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["browser.newtab.preload", false]
|
||||
]}, doTest);
|
||||
});
|
||||
addLoadEvent(doTest);
|
||||
|
||||
|
||||
</script>
|
||||
|
@ -1568,8 +1568,9 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
||||
editorFlags |= nsIPlaintextEditor::eEditorDisabledMask;
|
||||
|
||||
// Disable the selection if necessary.
|
||||
if (editorFlags & nsIPlaintextEditor::eEditorDisabledMask)
|
||||
if (newTextEditor->IsDisabled()) {
|
||||
mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_OFF);
|
||||
}
|
||||
|
||||
newTextEditor->SetFlags(editorFlags);
|
||||
}
|
||||
@ -2572,7 +2573,7 @@ nsTextEditorState::SetValue(const nsAString& aValue, const nsAString* aOldValue,
|
||||
mValueBeingSet = aValue;
|
||||
mIsCommittingComposition = true;
|
||||
RefPtr<TextEditor> textEditor = mTextEditor;
|
||||
nsresult rv = textEditor->ForceCompositionEnd();
|
||||
nsresult rv = textEditor->CommitComposition();
|
||||
if (!self.get()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -762,11 +762,11 @@ ContentParent::MinTabSelect(const nsTArray<ContentParent*>& aContentParents,
|
||||
/*static*/ already_AddRefed<ContentParent>
|
||||
ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
|
||||
ProcessPriority aPriority,
|
||||
ContentParent* aOpener,
|
||||
bool aPreferUsed)
|
||||
ContentParent* aOpener)
|
||||
{
|
||||
nsTArray<ContentParent*>& contentParents = GetOrCreatePool(aRemoteType);
|
||||
uint32_t maxContentParents = GetMaxProcessCount(aRemoteType);
|
||||
|
||||
if (aRemoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
|
||||
// We never want to re-use Large-Allocation processes.
|
||||
if (contentParents.Length() >= maxContentParents) {
|
||||
@ -775,18 +775,11 @@ ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
|
||||
aOpener);
|
||||
}
|
||||
} else {
|
||||
uint32_t numberOfParents = contentParents.Length();
|
||||
nsTArray<nsIContentProcessInfo*> infos(numberOfParents);
|
||||
nsTArray<nsIContentProcessInfo*> infos(contentParents.Length());
|
||||
for (auto* cp : contentParents) {
|
||||
infos.AppendElement(cp->mScriptableHelper);
|
||||
}
|
||||
|
||||
if (aPreferUsed && numberOfParents) {
|
||||
// For the preloaded browser we don't want to create a new process but reuse an
|
||||
// existing one.
|
||||
maxContentParents = numberOfParents;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentProcessProvider> cpp =
|
||||
do_GetService("@mozilla.org/ipc/processselector;1");
|
||||
nsIContentProcessInfo* openerInfo = aOpener ? aOpener->mScriptableHelper.get() : nullptr;
|
||||
@ -1138,13 +1131,6 @@ ContentParent::CreateBrowser(const TabContext& aContext,
|
||||
remoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
|
||||
}
|
||||
|
||||
bool isPreloadBrowser = false;
|
||||
nsAutoString isPreloadBrowserStr;
|
||||
if (aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::isPreloadBrowser,
|
||||
isPreloadBrowserStr)) {
|
||||
isPreloadBrowser = isPreloadBrowserStr.EqualsLiteral("true");
|
||||
}
|
||||
|
||||
RefPtr<nsIContentParent> constructorSender;
|
||||
if (isInContentProcess) {
|
||||
MOZ_ASSERT(aContext.IsMozBrowserElement() || aContext.IsJSPlugin());
|
||||
@ -1160,8 +1146,7 @@ ContentParent::CreateBrowser(const TabContext& aContext,
|
||||
initialPriority);
|
||||
} else {
|
||||
constructorSender =
|
||||
GetNewOrUsedBrowserProcess(remoteType, initialPriority,
|
||||
nullptr, isPreloadBrowser);
|
||||
GetNewOrUsedBrowserProcess(remoteType, initialPriority, nullptr);
|
||||
}
|
||||
if (!constructorSender) {
|
||||
return nullptr;
|
||||
|
@ -172,8 +172,7 @@ public:
|
||||
GetNewOrUsedBrowserProcess(const nsAString& aRemoteType = NS_LITERAL_STRING(NO_REMOTE_TYPE),
|
||||
hal::ProcessPriority aPriority =
|
||||
hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND,
|
||||
ContentParent* aOpener = nullptr,
|
||||
bool aPreferUsed = false);
|
||||
ContentParent* aOpener = nullptr);
|
||||
|
||||
/**
|
||||
* Get or create a content process for a JS plugin. aPluginID is the id of the JS plugin
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "mozilla/dom/AudioStreamTrack.h"
|
||||
#include "mozilla/dom/BlobEvent.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/RecordErrorEvent.h"
|
||||
#include "mozilla/dom/MediaRecorderErrorEvent.h"
|
||||
#include "mozilla/dom/VideoStreamTrack.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
@ -109,6 +109,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaRecorder,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSecurityDomException)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUnknownDomException)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
@ -116,6 +118,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaRecorder,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSecurityDomException)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mUnknownDomException)
|
||||
tmp->UnRegisterActivityObserver();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
@ -1055,6 +1059,9 @@ void
|
||||
MediaRecorder::Start(const Optional<int32_t>& aTimeSlice, ErrorResult& aResult)
|
||||
{
|
||||
LOG(LogLevel::Debug, ("MediaRecorder.Start %p", this));
|
||||
|
||||
InitializeDomExceptions();
|
||||
|
||||
if (mState != RecordingState::Inactive) {
|
||||
aResult.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
@ -1396,25 +1403,34 @@ MediaRecorder::NotifyError(nsresult aRv)
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
nsString errorMsg;
|
||||
switch (aRv) {
|
||||
case NS_ERROR_DOM_SECURITY_ERR:
|
||||
errorMsg = NS_LITERAL_STRING("SecurityError");
|
||||
break;
|
||||
case NS_ERROR_OUT_OF_MEMORY:
|
||||
errorMsg = NS_LITERAL_STRING("OutOfMemoryError");
|
||||
break;
|
||||
default:
|
||||
errorMsg = NS_LITERAL_STRING("GenericError");
|
||||
}
|
||||
|
||||
RecordErrorEventInit init;
|
||||
MediaRecorderErrorEventInit init;
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = false;
|
||||
init.mName = errorMsg;
|
||||
// These DOMExceptions have been created earlier so they can contain stack
|
||||
// traces. We attach the appropriate one here to be fired. We should have
|
||||
// exceptions here, but defensively check.
|
||||
switch (aRv) {
|
||||
case NS_ERROR_DOM_SECURITY_ERR:
|
||||
if (!mSecurityDomException) {
|
||||
LOG(LogLevel::Debug, ("MediaRecorder.NotifyError: "
|
||||
"mSecurityDomException was not initialized"));
|
||||
mSecurityDomException = DOMException::Create(NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
init.mError = mSecurityDomException.forget();
|
||||
break;
|
||||
default:
|
||||
if (!mUnknownDomException) {
|
||||
LOG(LogLevel::Debug, ("MediaRecorder.NotifyError: "
|
||||
"mUnknownDomException was not initialized"));
|
||||
mUnknownDomException = DOMException::Create(NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
}
|
||||
LOG(LogLevel::Debug, ("MediaRecorder.NotifyError: "
|
||||
"mUnknownDomException being fired for aRv: %X", uint32_t(aRv)));
|
||||
init.mError = mUnknownDomException.forget();
|
||||
}
|
||||
|
||||
RefPtr<RecordErrorEvent> event =
|
||||
RecordErrorEvent::Constructor(this, NS_LITERAL_STRING("error"), init);
|
||||
RefPtr<MediaRecorderErrorEvent> event = MediaRecorderErrorEvent::Constructor(
|
||||
this, NS_LITERAL_STRING("error"), init);
|
||||
event->SetTrusted(true);
|
||||
|
||||
bool dummy;
|
||||
@ -1459,6 +1475,13 @@ MediaRecorder::GetSourceMediaStream()
|
||||
return mPipeStream ? mPipeStream.get() : mAudioNode->GetStream();
|
||||
}
|
||||
|
||||
void
|
||||
MediaRecorder::InitializeDomExceptions()
|
||||
{
|
||||
mSecurityDomException = DOMException::Create(NS_ERROR_DOM_SECURITY_ERR);
|
||||
mUnknownDomException = DOMException::Create(NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
}
|
||||
|
||||
size_t
|
||||
MediaRecorder::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
|
@ -28,6 +28,7 @@ class GlobalObject;
|
||||
namespace dom {
|
||||
|
||||
class AudioNode;
|
||||
class DOMException;
|
||||
|
||||
/**
|
||||
* Implementation of https://dvcs.w3.org/hg/dap/raw-file/default/media-stream-capture/MediaRecorder.html
|
||||
@ -133,6 +134,12 @@ protected:
|
||||
void RemoveSession(Session* aSession);
|
||||
// Functions for Session to query input source info.
|
||||
MediaStream* GetSourceMediaStream();
|
||||
// Create DOMExceptions capturing the JS stack for async errors. These are
|
||||
// created ahead of time rather than on demand when firing an error as the JS
|
||||
// stack of the operation that started the async behavior will not be
|
||||
// available at the time the error event is fired. Note, depending on when
|
||||
// this is called there may not be a JS stack to capture.
|
||||
void InitializeDomExceptions();
|
||||
// DOM wrapper for source media stream. Will be null when input is audio node.
|
||||
RefPtr<DOMMediaStream> mDOMStream;
|
||||
// Source audio node. Will be null when input is a media stream.
|
||||
@ -159,6 +166,12 @@ protected:
|
||||
uint32_t mVideoBitsPerSecond;
|
||||
uint32_t mBitsPerSecond;
|
||||
|
||||
// DOMExceptions that are created early and possibly thrown in NotifyError.
|
||||
// Creating them early allows us to capture the JS stack for which cannot be
|
||||
// done at the time the error event is fired.
|
||||
RefPtr<DOMException> mSecurityDomException;
|
||||
RefPtr<DOMException> mUnknownDomException;
|
||||
|
||||
private:
|
||||
// Register MediaRecorder into Document to listen the activity changes.
|
||||
void RegisterActivityObserver();
|
||||
|
@ -21,7 +21,10 @@ function startTest() {
|
||||
|
||||
mediaRecorder.onerror = function (e) {
|
||||
is(callbackStep, 0, 'should fired onstop callback');
|
||||
is(e.name, 'GenericError', 'error name should be GenericError');
|
||||
is(e.error.name, 'UnknownError', 'error name should be UnknownError');
|
||||
ok(e.error.stack.includes('test_mediarecorder_creation_fail.html'),
|
||||
'Events fired from onerror should include an error with a stack trace indicating ' +
|
||||
'an error in this test');
|
||||
is(mediaRecorder.mimeType, '', 'mimetype should be empty');
|
||||
is(mediaRecorder.state, 'recording', 'state is recording');
|
||||
info('onerror callback fired');
|
||||
|
@ -30,7 +30,7 @@ SpecialPowers.pushPrefEnv({"set": [["media.ogg.enabled", false]]},
|
||||
//fires again, so set it to null to avoid failures
|
||||
mediaRecorder.ondataavailable = null;
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
mediaRecorder.ondataavailable = function(evt) {
|
||||
ondataavailableFired = true;
|
||||
ok(evt instanceof BlobEvent,
|
||||
@ -43,16 +43,21 @@ SpecialPowers.pushPrefEnv({"set": [["media.ogg.enabled", false]]},
|
||||
'Blob data received should have type = ' + expectedMimeType);
|
||||
is(evt.target.mimeType, expectedMimeType,
|
||||
'Mime type in ondataavailable = ' + expectedMimeType);
|
||||
}
|
||||
};
|
||||
mediaRecorder.onerror = function(evt) {
|
||||
ok(evt instanceof RecordErrorEvent,
|
||||
'Events fired from onerror should be RecordErrorEvent');
|
||||
ok(evt instanceof MediaRecorderErrorEvent,
|
||||
'Events fired from onerror should be MediaRecorderErrorEvent');
|
||||
is(evt.type, 'error',
|
||||
'Event type should onerror');
|
||||
is(evt.name, 'GenericError',
|
||||
'Event name is GenericError');
|
||||
'Event type is error');
|
||||
ok(evt.error instanceof DOMException,
|
||||
'Events fired from onerror should have a DOMException in their error member');
|
||||
is(evt.error.name, 'UnknownError', 'Error name should be UnknownError.');
|
||||
is(evt.error.message, 'The operation failed for an unknown transient reason');
|
||||
ok(evt.error.stack.includes('test_mediarecorder_getencodeddata.html'),
|
||||
'Events fired from onerror should include an error with a stack trace indicating ' +
|
||||
'an error in this test');
|
||||
onErrorFired = true;
|
||||
}
|
||||
};
|
||||
mediaRecorder.start(0);
|
||||
is(mediaRecorder.state, 'recording', 'Media recorder should be recording');
|
||||
is(mediaRecorder.stream, stream,
|
||||
|
@ -89,12 +89,17 @@ function testPrincipals(resource) {
|
||||
hasStopped = new Promise(resolve => rec.onstop = resolve);
|
||||
video.play();
|
||||
})
|
||||
.then(() => ok(true, msgNoThrow), e => is(e.name, null, msgNoThrow))
|
||||
.then(() => ok(true, msgNoThrow), e => is(e.error.name, null, msgNoThrow))
|
||||
.then(() => Promise.race([
|
||||
new Promise((_, reject) => rec.onerror = e => reject(new DOMException("", e.name))),
|
||||
new Promise((_, reject) => rec.onerror = e => reject(e.error)),
|
||||
hasEnded
|
||||
]))
|
||||
.then(() => ok(false, msgSecErr), e => is(e.name, "SecurityError", msgSecErr))
|
||||
.then(() => ok(false, msgSecErr), e => {
|
||||
is(e.name, "SecurityError", msgSecErr);
|
||||
ok(e.stack.includes('test_mediarecorder_principals.html'),
|
||||
'Events fired from onerror should include an error with a stack trace indicating ' +
|
||||
'an error in this test');
|
||||
})
|
||||
.then(() => Promise.race([hasStopped, hasEnded.then(() => Promise.reject())]))
|
||||
.then(() => ok(true, msgOnStop), e => ok(false, msgOnStop))
|
||||
.then(() => clearInterval(interval));
|
||||
|
@ -42,7 +42,10 @@ function startTest() {
|
||||
}
|
||||
}
|
||||
ok(callbackStep < 3, 'onerror callback fired as expected.');
|
||||
is(e.name, 'GenericError', 'Error name should be GenericError.');
|
||||
is(e.error.name, 'UnknownError', 'Error name should be UnknownError.');
|
||||
ok(e.error.stack.includes('test_mediarecorder_unsupported_src.html'),
|
||||
'Events fired from onerror should include an error with a stack trace indicating ' +
|
||||
'an error in this test');
|
||||
is(mediaRecorder.mimeType, '', 'mimetype should be empty');
|
||||
is(mediaRecorder.state, 'recording', 'state is recording');
|
||||
info('onerror callback fired');
|
||||
|
@ -27,7 +27,7 @@ function on_new_message(event, new_messages) {
|
||||
}
|
||||
}
|
||||
|
||||
function do_cleanup() {
|
||||
function* do_cleanup() {
|
||||
if (webconsole) {
|
||||
webconsole.ui.off("new-messages", on_new_message);
|
||||
}
|
||||
|
@ -15,15 +15,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=841850
|
||||
var blankTarget = document.getElementById("blankTarget");
|
||||
blankTarget.click();
|
||||
|
||||
var os = SpecialPowers.Cc["@mozilla.org/observer-service;1"].
|
||||
getService(SpecialPowers.Components.interfaces.nsIObserverService);
|
||||
var observer = {
|
||||
observe: function(subject, topic, data) {
|
||||
if(topic == "content-document-global-created" && data =="http://example.com") {
|
||||
parent.parent.postMessage({"test": "blankTarget", "msg": "opened an http link with target=_blank from a secure page"}, "http://mochi.test:8888");
|
||||
SpecialPowers.removeAsyncObserver(observer, "content-document-global-created");
|
||||
os.removeObserver(observer, "content-document-global-created");
|
||||
}
|
||||
}
|
||||
}
|
||||
SpecialPowers.addAsyncObserver(observer, "content-document-global-created");
|
||||
os.addObserver(observer, "content-document-global-created");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
// NOTE: This js file requires db_smilCSSPropertyList.js
|
||||
|
||||
const isServoEnabled = SpecialPowers.DOMWindowUtils.isStyledByServo;
|
||||
|
||||
// Lists of testcases for re-use across multiple properties of the same type
|
||||
var _fromByTestLists =
|
||||
{
|
||||
@ -24,17 +26,30 @@ var _fromByTestLists =
|
||||
{ midComp: "rgba(45, 48, 52, 0.6)",
|
||||
// (rgb(10, 20, 30) * 0.2 + rgb(50, 50, 50) * 1) / 1.0
|
||||
toComp: "rgb(52, 54, 56)"}),
|
||||
// Note: technically, the "from" and "by" values in the test case below
|
||||
// would overflow the maxium color-channel values when added together.
|
||||
|
||||
// The "from" and "by" values in the test case below overflow the maxium
|
||||
// color-channel values when added together.
|
||||
// (e.g. for red [ignoring alpha for now], 100 + 240 = 340 which is > 255)
|
||||
// The SVG Animation spec says we should clamp color values "as late as
|
||||
// possible," i.e. allow the channel overflow and clamp at paint-time.
|
||||
// But for now, we instead clamp the implicit "to" value for the animation
|
||||
// and interpolate up to that clamped result.
|
||||
// possible" i.e. allow the channel overflow and clamp at paint-time.
|
||||
//
|
||||
// Servo does this, and gives us:
|
||||
//
|
||||
// to-value = (rgb(100, 100, 100) * 0.6 + rgb(240, 240, 240) * 1.0)) * 1
|
||||
// = rgb(300, 300, 300)
|
||||
// midComp = (rgb(100, 100, 100) * 0.6 * 0.5 + rgb(300, 300, 300) * 1.0 * 0.5) * (1 / 0.8)
|
||||
// = rgb(225, 225, 225)
|
||||
//
|
||||
// Gecko, however, clamps the "to" value and interpolates up to that
|
||||
// clamped result giving:
|
||||
//
|
||||
// midComp = (rgb(100, 100, 100) * 0.6 * 0.5 + rgb(255, 255, 255) * 1.0 * 0.5) * (1 / 0.8)
|
||||
// = rgb(197, 197, 197)
|
||||
//
|
||||
new AnimTestcaseFromBy("rgba(100, 100, 100, 0.6)", "rgba(240, 240, 240, 1)",
|
||||
// (rgb(100, 100, 100) * 0.6 * 0.5 + rgb(255, 255, 255) * 1.0 * 0.5) * (1 / 0.8)
|
||||
{ midComp: "rgba(197, 197, 197, 0.8)",
|
||||
// (rgb(100, 100, 100) * 0.6 + rgb(240, 240, 240) is overflowed
|
||||
{ midComp:
|
||||
isServoEnabled ? "rgba(225, 225, 225, 0.8)"
|
||||
: "rgba(197, 197, 197, 0.8)",
|
||||
toComp: "rgb(255, 255, 255)"}),
|
||||
],
|
||||
lengthNoUnits: [
|
||||
|
@ -640,6 +640,8 @@ var interfaceNamesInGlobalScope =
|
||||
"MediaQueryListEvent",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"MediaRecorder",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"MediaRecorderErrorEvent",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"MediaSource",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
@ -786,8 +788,6 @@ var interfaceNamesInGlobalScope =
|
||||
"RadioNodeList",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Range",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"RecordErrorEvent",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Rect",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
21
dom/webidl/MediaRecorderErrorEvent.webidl
Normal file
21
dom/webidl/MediaRecorderErrorEvent.webidl
Normal file
@ -0,0 +1,21 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://w3c.github.io/mediacapture-record/
|
||||
*
|
||||
* Copyright © 2017 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark
|
||||
* and document use rules apply.
|
||||
*/
|
||||
|
||||
dictionary MediaRecorderErrorEventInit : EventInit {
|
||||
required DOMException error;
|
||||
};
|
||||
|
||||
[Exposed=Window,
|
||||
Constructor(DOMString type, MediaRecorderErrorEventInit eventInitDict)]
|
||||
interface MediaRecorderErrorEvent : Event {
|
||||
[SameObject] readonly attribute DOMException error;
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
[Constructor(DOMString type, optional RecordErrorEventInit eventInitDict)]
|
||||
interface RecordErrorEvent : Event
|
||||
{
|
||||
readonly attribute DOMString name;
|
||||
};
|
||||
|
||||
dictionary RecordErrorEventInit : EventInit
|
||||
{
|
||||
DOMString name = "";
|
||||
};
|
@ -1031,7 +1031,6 @@ WEBIDL_FILES += [
|
||||
'PopStateEvent.webidl',
|
||||
'PopupBlockedEvent.webidl',
|
||||
'ProgressEvent.webidl',
|
||||
'RecordErrorEvent.webidl',
|
||||
'StyleRuleChangeEvent.webidl',
|
||||
'StyleSheetApplicableStateChangeEvent.webidl',
|
||||
'StyleSheetChangeEvent.webidl',
|
||||
@ -1079,6 +1078,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
||||
'HiddenPluginEvent.webidl',
|
||||
'ImageCaptureErrorEvent.webidl',
|
||||
'MediaQueryListEvent.webidl',
|
||||
'MediaRecorderErrorEvent.webidl',
|
||||
'MediaStreamEvent.webidl',
|
||||
'MediaStreamTrackEvent.webidl',
|
||||
'OfflineAudioCompletionEvent.webidl',
|
||||
@ -1091,7 +1091,6 @@ GENERATED_EVENTS_WEBIDL_FILES = [
|
||||
'PresentationConnectionCloseEvent.webidl',
|
||||
'ProgressEvent.webidl',
|
||||
'PromiseRejectionEvent.webidl',
|
||||
'RecordErrorEvent.webidl',
|
||||
'ScrollViewChangeEvent.webidl',
|
||||
'StyleRuleChangeEvent.webidl',
|
||||
'StyleSheetApplicableStateChangeEvent.webidl',
|
||||
|
@ -2020,7 +2020,7 @@ RuntimeService::Init()
|
||||
if (!sDefaultJSSettings.gcSettings[0].IsSet()) {
|
||||
sDefaultJSSettings.contextOptions = JS::ContextOptions();
|
||||
sDefaultJSSettings.chrome.maxScriptRuntime = -1;
|
||||
sDefaultJSSettings.chrome.compartmentOptions.behaviors().setVersion(JSVERSION_LATEST);
|
||||
sDefaultJSSettings.chrome.compartmentOptions.behaviors().setVersion(JSVERSION_DEFAULT);
|
||||
sDefaultJSSettings.content.maxScriptRuntime = MAX_SCRIPT_RUN_TIME_SEC;
|
||||
#ifdef JS_GC_ZEAL
|
||||
sDefaultJSSettings.gcZealFrequency = JS_DEFAULT_ZEAL_FREQ;
|
||||
|
@ -1961,7 +1961,7 @@ ScriptExecutorRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
.setNoScriptRval(true);
|
||||
|
||||
if (mScriptLoader.mWorkerScriptType == DebuggerScript) {
|
||||
options.setVersion(JSVERSION_LATEST);
|
||||
options.setVersion(JSVERSION_DEFAULT);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(loadInfo.mMutedErrorFlag.isSome());
|
||||
|
@ -41,7 +41,6 @@ add_task(function setupPrefs() {
|
||||
return SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true],
|
||||
["browser.newtab.preload", false],
|
||||
]});
|
||||
});
|
||||
|
||||
|
@ -226,18 +226,15 @@ nsXBLDocumentInfo::ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocI
|
||||
nsContentUtils::GetSecurityManager()->
|
||||
GetSystemPrincipal(getter_AddRefs(principal));
|
||||
|
||||
auto styleBackend = aBoundDocument ? aBoundDocument->GetStyleBackendType()
|
||||
: StyleBackendType::Gecko;
|
||||
nsCOMPtr<nsIDOMDocument> domdoc;
|
||||
rv = NS_NewXBLDocument(getter_AddRefs(domdoc), aURI, nullptr, principal);
|
||||
rv = NS_NewXBLDocument(getter_AddRefs(domdoc), aURI, nullptr, principal, styleBackend);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
|
||||
NS_ASSERTION(doc, "Must have a document!");
|
||||
|
||||
// Set the style backend type immediately after creating the XBL document.
|
||||
// Assume gecko if there's no bound document.
|
||||
doc->SetStyleBackendType(aBoundDocument ? aBoundDocument->GetStyleBackendType()
|
||||
: StyleBackendType::Gecko);
|
||||
|
||||
RefPtr<nsXBLDocumentInfo> docInfo = new nsXBLDocumentInfo(doc);
|
||||
|
||||
while (1) {
|
||||
|
@ -434,7 +434,7 @@ nsXBLProtoImplField::InstallField(JS::Handle<JSObject*> aBoundNode,
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(uriSpec.get(), mLineNumber)
|
||||
.setVersion(JSVERSION_LATEST);
|
||||
.setVersion(JSVERSION_DEFAULT);
|
||||
JS::AutoObjectVector scopeChain(cx);
|
||||
if (!nsJSUtils::GetScopeChainForElement(cx, boundElement, scopeChain)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -193,7 +193,7 @@ nsXBLProtoImplMethod::CompileMember(AutoJSAPI& jsapi, const nsString& aClassStr,
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(functionUri.get(),
|
||||
uncompiledMethod->mBodyText.GetLineNumber())
|
||||
.setVersion(JSVERSION_LATEST);
|
||||
.setVersion(JSVERSION_DEFAULT);
|
||||
JS::Rooted<JSObject*> methodObject(cx);
|
||||
JS::AutoObjectVector emptyVector(cx);
|
||||
nsresult rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options, cname,
|
||||
|
@ -199,7 +199,7 @@ nsXBLProtoImplProperty::CompileMember(AutoJSAPI& jsapi, const nsString& aClassSt
|
||||
JSAutoCompartment ac(cx, aClassObject);
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(functionUri.get(), getterText->GetLineNumber())
|
||||
.setVersion(JSVERSION_LATEST);
|
||||
.setVersion(JSVERSION_DEFAULT);
|
||||
nsCString name = NS_LITERAL_CSTRING("get_") + NS_ConvertUTF16toUTF8(mName);
|
||||
JS::Rooted<JSObject*> getterObject(cx);
|
||||
JS::AutoObjectVector emptyVector(cx);
|
||||
@ -245,7 +245,7 @@ nsXBLProtoImplProperty::CompileMember(AutoJSAPI& jsapi, const nsString& aClassSt
|
||||
JSAutoCompartment ac(cx, aClassObject);
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(functionUri.get(), setterText->GetLineNumber())
|
||||
.setVersion(JSVERSION_LATEST);
|
||||
.setVersion(JSVERSION_DEFAULT);
|
||||
nsCString name = NS_LITERAL_CSTRING("set_") + NS_ConvertUTF16toUTF8(mName);
|
||||
JS::Rooted<JSObject*> setterObject(cx);
|
||||
JS::AutoObjectVector emptyVector(cx);
|
||||
|
@ -435,7 +435,7 @@ nsXBLPrototypeHandler::EnsureEventHandler(AutoJSAPI& jsapi, nsIAtom* aName,
|
||||
JSAutoCompartment ac(cx, scopeObject);
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(bindingURI.get(), mLineNumber)
|
||||
.setVersion(JSVERSION_LATEST);
|
||||
.setVersion(JSVERSION_DEFAULT);
|
||||
|
||||
JS::Rooted<JSObject*> handlerFun(cx);
|
||||
JS::AutoObjectVector emptyVector(cx);
|
||||
|
@ -186,6 +186,7 @@ XMLHttpRequestMainThread::XMLHttpRequestMainThread()
|
||||
mResponseType(XMLHttpRequestResponseType::_empty),
|
||||
mRequestObserver(nullptr),
|
||||
mState(State::unsent),
|
||||
mStyleBackend(StyleBackendType::None),
|
||||
mFlagSynchronous(false), mFlagAborted(false), mFlagParseBody(false),
|
||||
mFlagSyncLooping(false), mFlagBackgroundRequest(false),
|
||||
mFlagHadUploadListenersOnSend(false), mFlagACwithCredentials(false),
|
||||
@ -2162,7 +2163,8 @@ XMLHttpRequestMainThread::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
||||
emptyStr, emptyStr, nullptr, docURI,
|
||||
baseURI, requestingPrincipal, true, global,
|
||||
mIsHtml ? DocumentFlavorHTML :
|
||||
DocumentFlavorLegacyGuess);
|
||||
DocumentFlavorLegacyGuess,
|
||||
mStyleBackend);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mResponseXML = do_QueryInterface(responseDoc);
|
||||
mResponseXML->SetChromeXHRDocURI(chromeXHRDocURI);
|
||||
|
@ -200,8 +200,13 @@ public:
|
||||
nsILoadGroup* aLoadGroup = nullptr)
|
||||
{
|
||||
MOZ_ASSERT(aPrincipal);
|
||||
MOZ_ASSERT_IF(nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(
|
||||
aGlobalObject), win->IsInnerWindow());
|
||||
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aGlobalObject);
|
||||
if (win) {
|
||||
MOZ_ASSERT(win->IsInnerWindow());
|
||||
if (win->GetExtantDoc()) {
|
||||
mStyleBackend = win->GetExtantDoc()->GetStyleBackendType();
|
||||
}
|
||||
}
|
||||
mPrincipal = aPrincipal;
|
||||
BindToOwner(aGlobalObject);
|
||||
mBaseURI = aBaseURI;
|
||||
@ -743,6 +748,8 @@ protected:
|
||||
|
||||
State mState;
|
||||
|
||||
StyleBackendType mStyleBackend;
|
||||
|
||||
bool mFlagSynchronous;
|
||||
bool mFlagAborted;
|
||||
bool mFlagParseBody;
|
||||
|
@ -69,7 +69,8 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
|
||||
nsIPrincipal* aPrincipal,
|
||||
bool aLoadedAsData,
|
||||
nsIGlobalObject* aEventObject,
|
||||
DocumentFlavor aFlavor)
|
||||
DocumentFlavor aFlavor,
|
||||
StyleBackendType aStyleBackend)
|
||||
{
|
||||
// Note: can't require that aDocumentURI/aBaseURI/aPrincipal be non-null,
|
||||
// since at least one caller (XMLHttpRequest) doesn't have decent args to
|
||||
@ -128,6 +129,12 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If we were passed an explicit style backend for this document set it
|
||||
// immediately after creation, before any content is inserted.
|
||||
if (aStyleBackend != StyleBackendType::None) {
|
||||
d->SetStyleBackendType(aStyleBackend);
|
||||
}
|
||||
|
||||
if (isHTML) {
|
||||
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(d);
|
||||
NS_ASSERTION(htmlDoc, "HTML Document doesn't implement nsIHTMLDocument?");
|
||||
@ -209,13 +216,15 @@ nsresult
|
||||
NS_NewXBLDocument(nsIDOMDocument** aInstancePtrResult,
|
||||
nsIURI* aDocumentURI,
|
||||
nsIURI* aBaseURI,
|
||||
nsIPrincipal* aPrincipal)
|
||||
nsIPrincipal* aPrincipal,
|
||||
StyleBackendType aStyleBackend)
|
||||
{
|
||||
nsresult rv = NS_NewDOMDocument(aInstancePtrResult,
|
||||
NS_LITERAL_STRING("http://www.mozilla.org/xbl"),
|
||||
NS_LITERAL_STRING("bindings"), nullptr,
|
||||
aDocumentURI, aBaseURI, aPrincipal, false,
|
||||
nullptr, DocumentFlavorLegacyGuess);
|
||||
nullptr, DocumentFlavorLegacyGuess,
|
||||
aStyleBackend);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocument> idoc = do_QueryInterface(*aInstancePtrResult);
|
||||
|
@ -835,7 +835,7 @@ XULContentSinkImpl::OpenScript(const char16_t** aAttributes,
|
||||
const uint32_t aLineNumber)
|
||||
{
|
||||
bool isJavaScript = true;
|
||||
uint32_t version = JSVERSION_LATEST;
|
||||
uint32_t version = JSVERSION_DEFAULT;
|
||||
nsresult rv;
|
||||
|
||||
// Look for SRC attribute and look for a LANGUAGE attribute
|
||||
@ -861,14 +861,14 @@ XULContentSinkImpl::OpenScript(const char16_t** aAttributes,
|
||||
|
||||
if (nsContentUtils::IsJavascriptMIMEType(mimeType)) {
|
||||
isJavaScript = true;
|
||||
version = JSVERSION_LATEST;
|
||||
version = JSVERSION_DEFAULT;
|
||||
|
||||
// Get the version string, and ensure that JavaScript supports it.
|
||||
nsAutoString versionName;
|
||||
rv = parser.GetParameter("version", versionName);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
version = nsContentUtils::ParseJavascriptVersion(versionName);
|
||||
version = JSVERSION_UNKNOWN;
|
||||
} else if (rv != NS_ERROR_INVALID_ARG) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -232,16 +232,9 @@ nsSetDocumentStateCommand::DoCommandParams(const char *aCommandName,
|
||||
bool isReadOnly;
|
||||
nsresult rvRO = aParams->GetBooleanValue(STATE_ATTRIBUTE, &isReadOnly);
|
||||
NS_ENSURE_SUCCESS(rvRO, rvRO);
|
||||
|
||||
uint32_t flags;
|
||||
textEditor->GetFlags(&flags);
|
||||
if (isReadOnly) {
|
||||
flags |= nsIPlaintextEditor::eEditorReadonlyMask;
|
||||
} else {
|
||||
flags &= ~(nsIPlaintextEditor::eEditorReadonlyMask);
|
||||
}
|
||||
|
||||
return textEditor->SetFlags(flags);
|
||||
return isReadOnly ?
|
||||
textEditor->AddFlags(nsIPlaintextEditor::eEditorReadonlyMask) :
|
||||
textEditor->RemoveFlags(nsIPlaintextEditor::eEditorReadonlyMask);
|
||||
}
|
||||
|
||||
if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentUseCSS")) {
|
||||
|
@ -956,16 +956,8 @@ EditorBase::EndTransaction()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// These two routines are similar to the above, but do not use
|
||||
// the transaction managers batching feature. Instead we use
|
||||
// a placeholder transaction to wrap up any further transaction
|
||||
// while the batch is open. The advantage of this is that
|
||||
// placeholder transactions can later merge, if needed. Merging
|
||||
// is unavailable between transaction manager batches.
|
||||
|
||||
NS_IMETHODIMP
|
||||
EditorBase::BeginPlaceHolderTransaction(nsIAtom* aName)
|
||||
void
|
||||
EditorBase::BeginPlaceholderTransaction(nsIAtom* aTransactionName)
|
||||
{
|
||||
MOZ_ASSERT(mPlaceholderBatch >= 0, "negative placeholder batch count!");
|
||||
if (!mPlaceholderBatch) {
|
||||
@ -973,7 +965,7 @@ EditorBase::BeginPlaceHolderTransaction(nsIAtom* aName)
|
||||
// time to turn on the batch
|
||||
BeginUpdateViewBatch();
|
||||
mPlaceholderTransaction = nullptr;
|
||||
mPlaceholderName = aName;
|
||||
mPlaceholderName = aTransactionName;
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (selection) {
|
||||
mSelState.emplace();
|
||||
@ -989,12 +981,10 @@ EditorBase::BeginPlaceHolderTransaction(nsIAtom* aName)
|
||||
}
|
||||
}
|
||||
mPlaceholderBatch++;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EditorBase::EndPlaceHolderTransaction()
|
||||
void
|
||||
EditorBase::EndPlaceholderTransaction()
|
||||
{
|
||||
MOZ_ASSERT(mPlaceholderBatch > 0,
|
||||
"zero or negative placeholder batch count when ending batch!");
|
||||
@ -1057,8 +1047,6 @@ EditorBase::EndPlaceHolderTransaction()
|
||||
}
|
||||
}
|
||||
mPlaceholderBatch--;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1335,10 +1323,9 @@ EditorBase::RemoveAttribute(Element* aElement,
|
||||
bool
|
||||
EditorBase::OutputsMozDirty()
|
||||
{
|
||||
// Return true for Composer (!eEditorAllowInteraction) or mail
|
||||
// (eEditorMailMask), but false for webpages.
|
||||
return !(mFlags & nsIPlaintextEditor::eEditorAllowInteraction) ||
|
||||
(mFlags & nsIPlaintextEditor::eEditorMailMask);
|
||||
// Return true for Composer (!IsInteractionAllowed()) or mail
|
||||
// (IsMailEditor()), but false for webpages.
|
||||
return !IsInteractionAllowed() || IsMailEditor();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -2193,11 +2180,13 @@ EditorBase::EndIMEComposition()
|
||||
NS_IMETHODIMP
|
||||
EditorBase::ForceCompositionEnd()
|
||||
{
|
||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||
if (!ps) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
nsPresContext* pc = ps->GetPresContext();
|
||||
return CommitComposition();
|
||||
}
|
||||
|
||||
nsresult
|
||||
EditorBase::CommitComposition()
|
||||
{
|
||||
nsPresContext* pc = GetPresContext();
|
||||
if (!pc) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
@ -2342,7 +2331,7 @@ EditorBase::CloneAttributes(Element* aDest,
|
||||
{
|
||||
MOZ_ASSERT(aDest && aSource);
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
|
||||
// Use transaction system for undo only if destination is already in the
|
||||
// document
|
||||
@ -5002,8 +4991,7 @@ EditorBase::DetermineCurrentDirection()
|
||||
|
||||
// If we don't have an explicit direction, determine our direction
|
||||
// from the content's direction
|
||||
if (!(mFlags & (nsIPlaintextEditor::eEditorLeftToRight |
|
||||
nsIPlaintextEditor::eEditorRightToLeft))) {
|
||||
if (!IsRightToLeft() && !IsLeftToRight()) {
|
||||
nsIFrame* frame = rootElement->GetPrimaryFrame();
|
||||
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
||||
|
||||
@ -5029,14 +5017,14 @@ EditorBase::SwitchTextDirection()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Apply the opposite direction
|
||||
if (mFlags & nsIPlaintextEditor::eEditorRightToLeft) {
|
||||
NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorLeftToRight),
|
||||
if (IsRightToLeft()) {
|
||||
NS_ASSERTION(!IsLeftToRight(),
|
||||
"Unexpected mutually exclusive flag");
|
||||
mFlags &= ~nsIPlaintextEditor::eEditorRightToLeft;
|
||||
mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
|
||||
rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("ltr"), true);
|
||||
} else if (mFlags & nsIPlaintextEditor::eEditorLeftToRight) {
|
||||
NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorRightToLeft),
|
||||
} else if (IsLeftToRight()) {
|
||||
NS_ASSERTION(!IsRightToLeft(),
|
||||
"Unexpected mutually exclusive flag");
|
||||
mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
|
||||
mFlags &= ~nsIPlaintextEditor::eEditorLeftToRight;
|
||||
@ -5061,14 +5049,14 @@ EditorBase::SwitchTextDirectionTo(uint32_t aDirection)
|
||||
|
||||
// Apply the requested direction
|
||||
if (aDirection == nsIPlaintextEditor::eEditorLeftToRight &&
|
||||
(mFlags & nsIPlaintextEditor::eEditorRightToLeft)) {
|
||||
IsRightToLeft()) {
|
||||
NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorLeftToRight),
|
||||
"Unexpected mutually exclusive flag");
|
||||
mFlags &= ~nsIPlaintextEditor::eEditorRightToLeft;
|
||||
mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
|
||||
rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, NS_LITERAL_STRING("ltr"), true);
|
||||
} else if (aDirection == nsIPlaintextEditor::eEditorRightToLeft &&
|
||||
(mFlags & nsIPlaintextEditor::eEditorLeftToRight)) {
|
||||
IsLeftToRight()) {
|
||||
NS_ASSERTION(!(mFlags & nsIPlaintextEditor::eEditorRightToLeft),
|
||||
"Unexpected mutually exclusive flag");
|
||||
mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
|
||||
|
@ -251,6 +251,11 @@ public:
|
||||
already_AddRefed<nsIDOMDocument> GetDOMDocument();
|
||||
already_AddRefed<nsIDocument> GetDocument();
|
||||
already_AddRefed<nsIPresShell> GetPresShell();
|
||||
nsPresContext* GetPresContext()
|
||||
{
|
||||
RefPtr<nsIPresShell> presShell = GetPresShell();
|
||||
return presShell ? presShell->GetPresContext() : nullptr;
|
||||
}
|
||||
already_AddRefed<nsIWidget> GetWidget();
|
||||
nsISelectionController* GetSelectionController() const
|
||||
{
|
||||
@ -351,6 +356,15 @@ public:
|
||||
WidgetCompositionEvent* aCompositionChangeEvet) = 0;
|
||||
void EndIMEComposition();
|
||||
|
||||
/**
|
||||
* Commit composition if there is.
|
||||
* Note that when there is a composition, this requests to commit composition
|
||||
* to native IME. Therefore, when there is composition, this can do anything.
|
||||
* For example, the editor instance, the widget or the process itself may
|
||||
* be destroyed.
|
||||
*/
|
||||
nsresult CommitComposition();
|
||||
|
||||
void SwitchTextDirectionTo(uint32_t aDirection);
|
||||
|
||||
protected:
|
||||
@ -580,6 +594,18 @@ protected:
|
||||
nsresult GetSelection(SelectionType aSelectionType,
|
||||
nsISelection** aSelection);
|
||||
|
||||
/**
|
||||
* (Begin|End)PlaceholderTransaction() are called by AutoPlaceholderBatch.
|
||||
* This set of methods are similar to the (Begin|End)Transaction(), but do
|
||||
* not use the transaction managers batching feature. Instead we use a
|
||||
* placeholder transaction to wrap up any further transaction while the
|
||||
* batch is open. The advantage of this is that placeholder transactions
|
||||
* can later merge, if needed. Merging is unavailable between transaction
|
||||
* manager batches.
|
||||
*/
|
||||
void BeginPlaceholderTransaction(nsIAtom* aTransactionName);
|
||||
void EndPlaceholderTransaction();
|
||||
|
||||
public:
|
||||
/**
|
||||
* All editor operations which alter the doc should be prefaced
|
||||
@ -947,6 +973,36 @@ public:
|
||||
*/
|
||||
uint32_t Flags() const { return mFlags; }
|
||||
|
||||
nsresult AddFlags(uint32_t aFlags)
|
||||
{
|
||||
const uint32_t kOldFlags = Flags();
|
||||
const uint32_t kNewFlags = (kOldFlags | aFlags);
|
||||
if (kNewFlags == kOldFlags) {
|
||||
return NS_OK;
|
||||
}
|
||||
return SetFlags(kNewFlags); // virtual call and may be expensive.
|
||||
}
|
||||
nsresult RemoveFlags(uint32_t aFlags)
|
||||
{
|
||||
const uint32_t kOldFlags = Flags();
|
||||
const uint32_t kNewFlags = (kOldFlags & ~aFlags);
|
||||
if (kNewFlags == kOldFlags) {
|
||||
return NS_OK;
|
||||
}
|
||||
return SetFlags(kNewFlags); // virtual call and may be expensive.
|
||||
}
|
||||
nsresult AddAndRemoveFlags(uint32_t aAddingFlags, uint32_t aRemovingFlags)
|
||||
{
|
||||
MOZ_ASSERT(!(aAddingFlags & aRemovingFlags),
|
||||
"Same flags are specified both adding and removing");
|
||||
const uint32_t kOldFlags = Flags();
|
||||
const uint32_t kNewFlags = ((kOldFlags | aAddingFlags) & ~aRemovingFlags);
|
||||
if (kNewFlags == kOldFlags) {
|
||||
return NS_OK;
|
||||
}
|
||||
return SetFlags(kNewFlags); // virtual call and may be expensive.
|
||||
}
|
||||
|
||||
bool IsPlaintextEditor() const
|
||||
{
|
||||
return (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) != 0;
|
||||
@ -1250,6 +1306,7 @@ protected:
|
||||
bool mIsHTMLEditorClass;
|
||||
|
||||
friend bool NSCanUnload(nsISupports* serviceMgr);
|
||||
friend class AutoPlaceholderBatch;
|
||||
friend class AutoRules;
|
||||
friend class AutoSelectionRestorer;
|
||||
friend class AutoTransactionsConserveSelection;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "mozilla/EventListenerManager.h" // for EventListenerManager
|
||||
#include "mozilla/IMEStateManager.h" // for IMEStateManager
|
||||
#include "mozilla/Preferences.h" // for Preferences
|
||||
#include "mozilla/TextEditor.h" // for TextEditor
|
||||
#include "mozilla/TextEvents.h" // for WidgetCompositionEvent
|
||||
#include "mozilla/dom/Element.h" // for Element
|
||||
#include "mozilla/dom/Event.h" // for Event
|
||||
@ -36,11 +37,8 @@
|
||||
#include "nsIDOMMouseEvent.h" // for nsIDOMMouseEvent
|
||||
#include "nsIDOMNode.h" // for nsIDOMNode
|
||||
#include "nsIDocument.h" // for nsIDocument
|
||||
#include "nsIEditor.h" // for EditorBase::GetSelection, etc.
|
||||
#include "nsIEditorMailSupport.h" // for nsIEditorMailSupport
|
||||
#include "nsIFocusManager.h" // for nsIFocusManager
|
||||
#include "nsIFormControl.h" // for nsIFormControl, etc.
|
||||
#include "nsIHTMLEditor.h" // for nsIHTMLEditor
|
||||
#include "nsINode.h" // for nsINode, ::NODE_IS_EDITABLE, etc.
|
||||
#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc.
|
||||
#include "nsIPresShell.h" // for nsIPresShell
|
||||
@ -366,7 +364,7 @@ EditorEventListener::EnsureCommitCompoisition()
|
||||
{
|
||||
MOZ_ASSERT(!DetachedFromEditor());
|
||||
RefPtr<EditorBase> editorBase(mEditorBase);
|
||||
editorBase->ForceCompositionEnd();
|
||||
editorBase->CommitComposition();
|
||||
return !DetachedFromEditor();
|
||||
}
|
||||
|
||||
@ -711,19 +709,14 @@ EditorEventListener::HandleMiddleClickPaste(nsIDOMMouseEvent* aMouseEvent)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
RefPtr<EditorBase> editorBase(mEditorBase);
|
||||
RefPtr<Selection> selection = editorBase->GetSelection();
|
||||
RefPtr<TextEditor> textEditor = mEditorBase->AsTextEditor();
|
||||
MOZ_ASSERT(textEditor);
|
||||
|
||||
RefPtr<Selection> selection = textEditor->GetSelection();
|
||||
if (selection) {
|
||||
selection->Collapse(parent, offset);
|
||||
}
|
||||
|
||||
// If the ctrl key is pressed, we'll do paste as quotation.
|
||||
// Would've used the alt key, but the kde wmgr treats alt-middle specially.
|
||||
nsCOMPtr<nsIEditorMailSupport> mailEditor;
|
||||
if (clickEvent->IsControl()) {
|
||||
mailEditor = do_QueryObject(editorBase);
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
int32_t clipboard = nsIClipboard::kGlobalClipboard;
|
||||
nsCOMPtr<nsIClipboard> clipboardService =
|
||||
@ -736,10 +729,12 @@ EditorEventListener::HandleMiddleClickPaste(nsIDOMMouseEvent* aMouseEvent)
|
||||
}
|
||||
}
|
||||
|
||||
if (mailEditor) {
|
||||
mailEditor->PasteAsQuotation(clipboard);
|
||||
// If the ctrl key is pressed, we'll do paste as quotation.
|
||||
// Would've used the alt key, but the kde wmgr treats alt-middle specially.
|
||||
if (clickEvent->IsControl()) {
|
||||
textEditor->PasteAsQuotation(clipboard);
|
||||
} else {
|
||||
editorBase->Paste(clipboard);
|
||||
textEditor->Paste(clipboard);
|
||||
}
|
||||
|
||||
// Prevent the event from propagating up to be possibly handled
|
||||
@ -1191,11 +1186,8 @@ EditorEventListener::SpellCheckIfNeeded()
|
||||
// If the spell check skip flag is still enabled from creation time,
|
||||
// disable it because focused editors are allowed to spell check.
|
||||
RefPtr<EditorBase> editorBase(mEditorBase);
|
||||
uint32_t currentFlags = 0;
|
||||
editorBase->GetFlags(¤tFlags);
|
||||
if(currentFlags & nsIPlaintextEditor::eEditorSkipSpellCheck) {
|
||||
currentFlags ^= nsIPlaintextEditor::eEditorSkipSpellCheck;
|
||||
editorBase->SetFlags(currentFlags);
|
||||
if(editorBase->ShouldSkipSpellCheck()) {
|
||||
editorBase->RemoveFlags(nsIPlaintextEditor::eEditorSkipSpellCheck);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,52 +143,43 @@ EditActionCanceled(nsresult aRv = NS_OK)
|
||||
/***************************************************************************
|
||||
* stack based helper class for batching a collection of transactions inside a
|
||||
* placeholder transaction.
|
||||
* XXX This is used by mozInlineSpellChecker. Therefore, cannot use concrete
|
||||
* editor class.
|
||||
*/
|
||||
class MOZ_RAII AutoPlaceHolderBatch
|
||||
class MOZ_RAII AutoPlaceholderBatch final
|
||||
{
|
||||
private:
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
RefPtr<EditorBase> mEditorBase;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
public:
|
||||
AutoPlaceHolderBatch(nsIEditor* aEditor,
|
||||
nsIAtom* aAtom
|
||||
explicit AutoPlaceholderBatch(EditorBase* aEditorBase
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mEditorBase(aEditorBase)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
BeginPlaceholderTransaction(nullptr);
|
||||
}
|
||||
AutoPlaceholderBatch(EditorBase* aEditorBase,
|
||||
nsIAtom* aTransactionName
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mEditor(aEditor)
|
||||
: mEditorBase(aEditorBase)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
if (mEditor) {
|
||||
mEditor->BeginPlaceHolderTransaction(aAtom);
|
||||
}
|
||||
BeginPlaceholderTransaction(aTransactionName);
|
||||
}
|
||||
~AutoPlaceHolderBatch()
|
||||
~AutoPlaceholderBatch()
|
||||
{
|
||||
if (mEditor) {
|
||||
mEditor->EndPlaceHolderTransaction();
|
||||
if (mEditorBase) {
|
||||
mEditorBase->EndPlaceholderTransaction();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* stack based helper class for batching a collection of txns.
|
||||
* Note: I changed this to use placeholder batching so that we get
|
||||
* proper selection save/restore across undo/redo.
|
||||
*/
|
||||
class MOZ_RAII AutoEditBatch final : public AutoPlaceHolderBatch
|
||||
{
|
||||
private:
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
public:
|
||||
explicit AutoEditBatch(nsIEditor* aEditor
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoPlaceHolderBatch(aEditor, nullptr)
|
||||
void BeginPlaceholderTransaction(nsIAtom* aTransactionName)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
if (mEditorBase) {
|
||||
mEditorBase->BeginPlaceholderTransaction(aTransactionName);
|
||||
}
|
||||
}
|
||||
~AutoEditBatch() {}
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -53,7 +53,7 @@ using namespace dom;
|
||||
NS_IMETHODIMP
|
||||
HTMLEditor::AbsolutePositionSelection(bool aEnabled)
|
||||
{
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this,
|
||||
aEnabled ? EditAction::setAbsolutePosition :
|
||||
EditAction::removeAbsolutePosition,
|
||||
@ -180,7 +180,7 @@ HTMLEditor::SetElementZIndex(nsIDOMElement* aElement,
|
||||
NS_IMETHODIMP
|
||||
HTMLEditor::RelativeChangeZIndex(int32_t aChange)
|
||||
{
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this,
|
||||
(aChange < 0) ? EditAction::decreaseZIndex :
|
||||
EditAction::increaseZIndex,
|
||||
@ -466,7 +466,7 @@ HTMLEditor::SetFinalPosition(int32_t aX,
|
||||
y.AppendInt(newY);
|
||||
|
||||
// we want one transaction only from a user's point of view
|
||||
AutoEditBatch batchIt(this);
|
||||
AutoPlaceholderBatch batchIt(this);
|
||||
|
||||
nsCOMPtr<Element> absolutelyPositionedObject =
|
||||
do_QueryInterface(mAbsolutelyPositionedObject);
|
||||
@ -510,7 +510,7 @@ HTMLEditor::AbsolutelyPositionElement(nsIDOMElement* aElement,
|
||||
if (isPositioned == aEnabled)
|
||||
return NS_OK;
|
||||
|
||||
AutoEditBatch batchIt(this);
|
||||
AutoPlaceholderBatch batchIt(this);
|
||||
|
||||
if (aEnabled) {
|
||||
int32_t x, y;
|
||||
@ -613,7 +613,7 @@ HTMLEditor::SetElementPosition(Element& aElement,
|
||||
int32_t aX,
|
||||
int32_t aY)
|
||||
{
|
||||
AutoEditBatch batchIt(this);
|
||||
AutoPlaceholderBatch batchIt(this);
|
||||
mCSSEditUtils->SetCSSPropertyPixels(aElement, *nsGkAtoms::left, aX);
|
||||
mCSSEditUtils->SetCSSPropertyPixels(aElement, *nsGkAtoms::top, aY);
|
||||
}
|
||||
|
@ -1016,7 +1016,7 @@ HTMLEditor::TypedText(const nsAString& aString,
|
||||
{
|
||||
MOZ_ASSERT(!aString.IsEmpty() || aAction != eTypedText);
|
||||
|
||||
AutoPlaceHolderBatch batch(this, nsGkAtoms::TypingTxnName);
|
||||
AutoPlaceholderBatch batch(this, nsGkAtoms::TypingTxnName);
|
||||
|
||||
if (aAction == eTypedBR) {
|
||||
// only inserts a br node
|
||||
@ -1203,7 +1203,7 @@ HTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
ForceCompositionEnd();
|
||||
CommitComposition();
|
||||
|
||||
// Do not use AutoRules -- rules code won't let us insert in <head>. Use
|
||||
// the head node as a parent and delete/insert directly.
|
||||
@ -1230,7 +1230,7 @@ HTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
|
||||
// Mac linebreaks: Map any remaining CR to LF:
|
||||
inputString.ReplaceSubstring(u"\r", u"\n");
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
|
||||
// Get the first range in the selection, for context:
|
||||
RefPtr<nsRange> range = selection->GetRangeAt(0);
|
||||
@ -1273,7 +1273,7 @@ HTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
|
||||
NS_IMETHODIMP
|
||||
HTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString)
|
||||
{
|
||||
ForceCompositionEnd();
|
||||
CommitComposition();
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
@ -1318,7 +1318,7 @@ HTMLEditor::RebuildDocumentFromSource(const nsAString& aSourceString)
|
||||
}
|
||||
|
||||
// Time to change the document
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
|
||||
nsReadingIterator<char16_t> endtotal;
|
||||
aSourceString.EndReading(endtotal);
|
||||
@ -1537,8 +1537,8 @@ HTMLEditor::InsertElementAtSelection(nsIDOMElement* aElement,
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
|
||||
|
||||
ForceCompositionEnd();
|
||||
AutoEditBatch beginBatching(this);
|
||||
CommitComposition();
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::insertElement,
|
||||
nsIEditor::eNext);
|
||||
|
||||
@ -1997,7 +1997,7 @@ HTMLEditor::MakeOrChangeList(const nsAString& aListType,
|
||||
|
||||
bool cancel, handled;
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::makeList, nsIEditor::eNext);
|
||||
|
||||
// pre-process
|
||||
@ -2068,7 +2068,7 @@ HTMLEditor::RemoveList(const nsAString& aListType)
|
||||
|
||||
bool cancel, handled;
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::removeList, nsIEditor::eNext);
|
||||
|
||||
// pre-process
|
||||
@ -2103,7 +2103,7 @@ HTMLEditor::MakeDefinitionItem(const nsAString& aItemType)
|
||||
|
||||
bool cancel, handled;
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::makeDefListItem,
|
||||
nsIEditor::eNext);
|
||||
|
||||
@ -2136,7 +2136,7 @@ HTMLEditor::InsertBasicBlock(const nsAString& aBlockType)
|
||||
|
||||
bool cancel, handled;
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::makeBasicBlock,
|
||||
nsIEditor::eNext);
|
||||
|
||||
@ -2208,7 +2208,7 @@ HTMLEditor::Indent(const nsAString& aIndent)
|
||||
if (aIndent.LowerCaseEqualsLiteral("outdent")) {
|
||||
opID = EditAction::outdent;
|
||||
}
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, opID, nsIEditor::eNext);
|
||||
|
||||
// pre-process
|
||||
@ -2277,7 +2277,7 @@ HTMLEditor::Align(const nsAString& aAlignType)
|
||||
// Protect the edit rules object from dying
|
||||
nsCOMPtr<nsIEditRules> rules(mRules);
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::align, nsIEditor::eNext);
|
||||
|
||||
bool cancel, handled;
|
||||
@ -2689,7 +2689,7 @@ HTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
|
||||
// Set all attributes found on the supplied anchor element
|
||||
nsCOMPtr<nsIDOMMozNamedAttrMap> attrMap;
|
||||
@ -3272,7 +3272,10 @@ HTMLEditor::DoContentInserted(nsIDocument* aDocument,
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHTMLEditor> kungFuDeathGrip(this);
|
||||
// XXX Why do we need this? This method is a helper of mutation observer.
|
||||
// So, the callers of mutation observer should guarantee that this won't
|
||||
// be deleted at least during the call.
|
||||
RefPtr<HTMLEditor> kungFuDeathGrip(this);
|
||||
|
||||
if (ShouldReplaceRootElement()) {
|
||||
nsContentUtils::AddScriptRunner(
|
||||
@ -3322,7 +3325,10 @@ HTMLEditor::ContentRemoved(nsIDocument* aDocument,
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHTMLEditor> kungFuDeathGrip(this);
|
||||
// XXX Why do we need to do this? This method is a mutation observer's
|
||||
// method. Therefore, the caller should guarantee that this won't be
|
||||
// deleted during the call.
|
||||
RefPtr<HTMLEditor> kungFuDeathGrip(this);
|
||||
|
||||
if (SameCOMIdentity(aChild, mRootElement)) {
|
||||
nsContentUtils::AddScriptRunner(
|
||||
@ -3446,7 +3452,7 @@ HTMLEditor::StyleSheetLoaded(StyleSheet* aSheet,
|
||||
bool aWasAlternate,
|
||||
nsresult aStatus)
|
||||
{
|
||||
AutoEditBatch batchIt(this);
|
||||
AutoPlaceholderBatch batchIt(this);
|
||||
|
||||
if (!mLastStyleSheetURL.IsEmpty())
|
||||
RemoveStyleSheet(mLastStyleSheetURL);
|
||||
@ -3580,7 +3586,7 @@ HTMLEditor::SelectEntireDocument(Selection* aSelection)
|
||||
NS_IMETHODIMP
|
||||
HTMLEditor::SelectAll()
|
||||
{
|
||||
ForceCompositionEnd();
|
||||
CommitComposition();
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_STATE(selection);
|
||||
@ -4519,7 +4525,7 @@ nsresult
|
||||
HTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
|
||||
{
|
||||
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
|
||||
ForceCompositionEnd();
|
||||
CommitComposition();
|
||||
|
||||
// Protect the edit rules object from dying
|
||||
nsCOMPtr<nsIEditRules> rules(mRules);
|
||||
@ -4529,7 +4535,7 @@ HTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
|
||||
|
||||
bool isCollapsed = selection->Collapsed();
|
||||
|
||||
AutoEditBatch batchIt(this);
|
||||
AutoPlaceholderBatch batchIt(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::insertElement,
|
||||
nsIEditor::eNext);
|
||||
AutoSelectionRestorer selectionRestorer(selection, this);
|
||||
|
@ -46,7 +46,7 @@ class nsIDOMRange;
|
||||
class nsRange;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class AutoSelectionSetterAfterTableEdit;
|
||||
class HTMLEditorEventListener;
|
||||
class HTMLEditRules;
|
||||
class TextEditRules;
|
||||
@ -836,6 +836,30 @@ protected:
|
||||
|
||||
void SetElementPosition(Element& aElement, int32_t aX, int32_t aY);
|
||||
|
||||
/**
|
||||
* Reset a selected cell or collapsed selection (the caret) after table
|
||||
* editing.
|
||||
*
|
||||
* @param aTable A table in the document.
|
||||
* @param aRow The row ...
|
||||
* @param aCol ... and column defining the cell where we will try to
|
||||
* place the caret.
|
||||
* @param aSelected If true, we select the whole cell instead of setting
|
||||
* caret.
|
||||
* @param aDirection If cell at (aCol, aRow) is not found, search for
|
||||
* previous cell in the same column (aPreviousColumn) or
|
||||
* row (ePreviousRow) or don't search for another cell
|
||||
* (aNoSearch). If no cell is found, caret is place just
|
||||
* before table; and if that fails, at beginning of
|
||||
* document. Thus we generally don't worry about the
|
||||
* return value and can use the
|
||||
* AutoSelectionSetterAfterTableEdit stack-based object to
|
||||
* insure we reset the caret in a table-editing method.
|
||||
*/
|
||||
void SetSelectionAfterTableEdit(nsIDOMElement* aTable,
|
||||
int32_t aRow, int32_t aCol,
|
||||
int32_t aDirection, bool aSelected);
|
||||
|
||||
protected:
|
||||
nsTArray<OwningNonNull<nsIContentFilter>> mContentFilters;
|
||||
|
||||
@ -1022,6 +1046,7 @@ protected:
|
||||
ParagraphSeparator mDefaultParagraphSeparator;
|
||||
|
||||
public:
|
||||
friend class AutoSelectionSetterAfterTableEdit;
|
||||
friend class HTMLEditorEventListener;
|
||||
friend class HTMLEditRules;
|
||||
friend class TextEditRules;
|
||||
|
@ -102,8 +102,8 @@ HTMLEditor::LoadHTML(const nsAString& aInputString)
|
||||
NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
// force IME commit; set up rules sniffing and batching
|
||||
ForceCompositionEnd();
|
||||
AutoEditBatch beginBatching(this);
|
||||
CommitComposition();
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::loadHTML, nsIEditor::eNext);
|
||||
|
||||
// Get selection
|
||||
@ -197,8 +197,8 @@ HTMLEditor::DoInsertHTMLWithContext(const nsAString& aInputString,
|
||||
nsCOMPtr<nsIEditRules> rules(mRules);
|
||||
|
||||
// force IME commit; set up rules sniffing and batching
|
||||
ForceCompositionEnd();
|
||||
AutoEditBatch beginBatching(this);
|
||||
CommitComposition();
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::htmlPaste, nsIEditor::eNext);
|
||||
|
||||
// Get selection
|
||||
@ -1024,7 +1024,7 @@ HTMLEditor::BlobReader::OnResult(const nsACString& aResult)
|
||||
nsresult rv = ImgFromData(type, aResult, stuffToPaste);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AutoEditBatch beginBatching(mHTMLEditor);
|
||||
AutoPlaceholderBatch beginBatching(mHTMLEditor);
|
||||
rv = mHTMLEditor->DoInsertHTMLWithContext(stuffToPaste, EmptyString(),
|
||||
EmptyString(),
|
||||
NS_LITERAL_STRING(kFileMime),
|
||||
@ -1120,7 +1120,7 @@ HTMLEditor::InsertObject(const nsACString& aType,
|
||||
rv = ImgFromData(type, imageData, stuffToPaste);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
rv = DoInsertHTMLWithContext(stuffToPaste, EmptyString(), EmptyString(),
|
||||
NS_LITERAL_STRING(kFileMime),
|
||||
aSourceDoc,
|
||||
@ -1174,7 +1174,7 @@ HTMLEditor::InsertFromTransferable(nsITransferable* transferable,
|
||||
|
||||
rv = ParseCFHTML(cfhtml, getter_Copies(cffragment), getter_Copies(cfcontext));
|
||||
if (NS_SUCCEEDED(rv) && !cffragment.IsEmpty()) {
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
// If we have our private HTML flavor, we will only use the fragment
|
||||
// from the CF_HTML. The rest comes from the clipboard.
|
||||
if (havePrivateHTMLFlavor) {
|
||||
@ -1224,7 +1224,7 @@ HTMLEditor::InsertFromTransferable(nsITransferable* transferable,
|
||||
}
|
||||
|
||||
if (!stuffToPaste.IsEmpty()) {
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
if (bestFlavor.EqualsLiteral(kHTMLMime)) {
|
||||
rv = DoInsertHTMLWithContext(stuffToPaste,
|
||||
aContextStr, aInfoStr, flavor,
|
||||
@ -1308,7 +1308,7 @@ HTMLEditor::InsertFromDataTransfer(DataTransfer* aDataTransfer,
|
||||
|
||||
nsresult rv = ParseCFHTML(cfhtml, getter_Copies(cffragment), getter_Copies(cfcontext));
|
||||
if (NS_SUCCEEDED(rv) && !cffragment.IsEmpty()) {
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
|
||||
if (hasPrivateHTMLFlavor) {
|
||||
// If we have our private HTML flavor, we will only use the fragment
|
||||
@ -1337,7 +1337,7 @@ HTMLEditor::InsertFromDataTransfer(DataTransfer* aDataTransfer,
|
||||
GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLContext), aIndex, contextString);
|
||||
GetStringFromDataTransfer(aDataTransfer, NS_LITERAL_STRING(kHTMLInfo), aIndex, infoString);
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
if (type.EqualsLiteral(kHTMLMime)) {
|
||||
return DoInsertHTMLWithContext(text,
|
||||
contextString, infoString, type,
|
||||
@ -1354,7 +1354,7 @@ HTMLEditor::InsertFromDataTransfer(DataTransfer* aDataTransfer,
|
||||
nsAutoString text;
|
||||
GetStringFromDataTransfer(aDataTransfer, type, aIndex, text);
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
return InsertTextAt(text, aDestinationNode, aDestOffset, aDoDeleteSelection);
|
||||
}
|
||||
}
|
||||
@ -1494,7 +1494,7 @@ HTMLEditor::PasteNoFormatting(int32_t aSelectionType)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ForceCompositionEnd();
|
||||
CommitComposition();
|
||||
|
||||
// Get Clipboard Service
|
||||
nsresult rv;
|
||||
@ -1632,7 +1632,7 @@ NS_IMETHODIMP
|
||||
HTMLEditor::PasteAsCitedQuotation(const nsAString& aCitation,
|
||||
int32_t aSelectionType)
|
||||
{
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::insertQuotation,
|
||||
nsIEditor::eNext);
|
||||
|
||||
@ -1708,7 +1708,7 @@ HTMLEditor::PasteAsPlaintextQuotation(int32_t aSelectionType)
|
||||
nsAutoString stuffToPaste;
|
||||
textDataObj->GetData(stuffToPaste);
|
||||
NS_ASSERTION(stuffToPaste.Length() <= (len/2), "Invalid length!");
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
rv = InsertAsPlaintextQuotation(stuffToPaste, true, 0);
|
||||
}
|
||||
}
|
||||
@ -1835,7 +1835,7 @@ HTMLEditor::InsertAsPlaintextQuotation(const nsAString& aQuotedText,
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::insertQuotation,
|
||||
nsIEditor::eNext);
|
||||
|
||||
@ -1935,7 +1935,7 @@ HTMLEditor::InsertAsCitedQuotation(const nsAString& aQuotedText,
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
AutoEditBatch beginBatching(this);
|
||||
AutoPlaceholderBatch beginBatching(this);
|
||||
AutoRules beginRulesSniffing(this, EditAction::insertQuotation,
|
||||
nsIEditor::eNext);
|
||||
|
||||
|
@ -18,8 +18,6 @@
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIHTMLInlineTableEditor.h"
|
||||
#include "nsIHTMLObjectResizer.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsLiteralString.h"
|
||||
#include "nsQueryObject.h"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user