зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to b2g-inbound
This commit is contained in:
Коммит
3d1c284b12
|
@ -206,6 +206,7 @@ DocAccessibleParent::RecvBindChildDoc(PDocAccessibleParent* aChildDoc, const uin
|
|||
MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
|
||||
|
||||
auto childDoc = static_cast<DocAccessibleParent*>(aChildDoc);
|
||||
childDoc->Unbind();
|
||||
bool result = AddChildDoc(childDoc, aID, false);
|
||||
MOZ_ASSERT(result);
|
||||
MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
|
||||
|
|
|
@ -64,7 +64,10 @@ public:
|
|||
void Unbind()
|
||||
{
|
||||
mParent = nullptr;
|
||||
ParentDoc()->mChildDocs.RemoveElement(this);
|
||||
if (DocAccessibleParent* parent = ParentDoc()) {
|
||||
parent->mChildDocs.RemoveElement(this);
|
||||
}
|
||||
|
||||
mParentDoc = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,8 +88,6 @@ this.AccessFu = { // jshint ignore:line
|
|||
Cu.import('resource://gre/modules/accessibility/PointerAdapter.jsm');
|
||||
Cu.import('resource://gre/modules/accessibility/Presentation.jsm');
|
||||
|
||||
Logger.info('Enabled');
|
||||
|
||||
for (let mm of Utils.AllMessageManagers) {
|
||||
this._addMessageListeners(mm);
|
||||
this._loadFrameScript(mm);
|
||||
|
@ -146,9 +144,7 @@ this.AccessFu = { // jshint ignore:line
|
|||
delete this.readyCallback;
|
||||
}
|
||||
|
||||
if (Utils.MozBuildApp !== 'mobile/android') {
|
||||
this.announce('screenReaderStarted');
|
||||
}
|
||||
Logger.info('AccessFu:Enabled');
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -161,14 +157,8 @@ this.AccessFu = { // jshint ignore:line
|
|||
|
||||
this._enabled = false;
|
||||
|
||||
Logger.info('Disabled');
|
||||
|
||||
Utils.win.document.removeChild(this.stylesheet.get());
|
||||
|
||||
if (Utils.MozBuildApp !== 'mobile/android') {
|
||||
this.announce('screenReaderStopped');
|
||||
}
|
||||
|
||||
for (let mm of Utils.AllMessageManagers) {
|
||||
mm.sendAsyncMessage('AccessFu:Stop');
|
||||
this._removeMessageListeners(mm);
|
||||
|
@ -200,6 +190,8 @@ this.AccessFu = { // jshint ignore:line
|
|||
this.doneCallback();
|
||||
delete this.doneCallback;
|
||||
}
|
||||
|
||||
Logger.info('AccessFu:Disabled');
|
||||
},
|
||||
|
||||
_enableOrDisable: function _enableOrDisable() {
|
||||
|
|
|
@ -14,42 +14,46 @@
|
|||
<script type="application/javascript">
|
||||
|
||||
function prefStart() {
|
||||
AccessFuTest.once_log("AccessFu:Enabled", () =>
|
||||
ok(AccessFu._enabled, "AccessFu was enabled again."));
|
||||
AccessFuTest.once_log("EventManager.start", AccessFuTest.nextTest);
|
||||
// Start AccessFu via pref.
|
||||
SpecialPowers.setIntPref("accessibility.accessfu.activate", 1);
|
||||
AccessFuTest.once_log("EventManager.start", AccessFuTest.nextTest);
|
||||
}
|
||||
|
||||
// Listen for 'EventManager.stop' and enable AccessFu again.
|
||||
function settingsStart() {
|
||||
ok(true, "EventManager was stopped.");
|
||||
isnot(AccessFu._enabled, true, "AccessFu was disabled.");
|
||||
AccessFuTest.once({
|
||||
"eventType": "announcement",
|
||||
"data": [{string: "screenReaderStarted"}]
|
||||
}, AccessFuTest.nextTest);
|
||||
// XXX: Bug 978076 - test start with SettingsManager.
|
||||
//navigator.mozSettings.createLock().set(
|
||||
// {'accessibility.screenreader': false});
|
||||
AccessFu._enable()
|
||||
AccessFuTest.once_log("EventManager.start", () => {
|
||||
ok(AccessFu._enabled, "AccessFu was enabled again.");
|
||||
AccessFuTest.nextTest();
|
||||
});
|
||||
AccessFu._enable();
|
||||
}
|
||||
|
||||
// Make sure EventManager is started again.
|
||||
function settingsStop() {
|
||||
ok(AccessFu._enabled, "AccessFu was enabled again.");
|
||||
AccessFuTest.once({
|
||||
"eventType": "announcement",
|
||||
"data": [{string: "screenReaderStopped"}]
|
||||
}, AccessFuTest.finish);
|
||||
// XXX: Bug 978076 - test stop with SettingsManager.
|
||||
//navigator.mozSettings.createLock().set(
|
||||
// {'accessibility.screenreader': false});
|
||||
AccessFuTest.once_log("EventManager.stop", () => {
|
||||
isnot(AccessFu._enabled, "AccessFu was disabled.");
|
||||
AccessFuTest.finish();
|
||||
});
|
||||
AccessFu._disable();
|
||||
}
|
||||
|
||||
// Listen for initial 'EventManager.start' and disable AccessFu.
|
||||
function prefStop() {
|
||||
ok(AccessFu._enabled, "AccessFu was started via preference.");
|
||||
AccessFuTest.once_log("AccessFu:Disabled", () =>
|
||||
isnot(AccessFu._enabled, true, "AccessFu was disabled."));
|
||||
AccessFuTest.once_log("EventManager.stop", AccessFuTest.nextTest);
|
||||
|
||||
SpecialPowers.setIntPref("accessibility.accessfu.activate", 0);
|
||||
}
|
||||
|
||||
|
@ -74,4 +78,4 @@
|
|||
Mozilla Bug 811307
|
||||
</a>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
@ -663,14 +663,15 @@ ia2Accessible::get_accessibleWithCaret(IUnknown** aAccessible,
|
|||
return S_FALSE;
|
||||
|
||||
Accessible* child = accWithCaret;
|
||||
while (child != acc)
|
||||
while (!child->IsDoc() && child != acc)
|
||||
child = child->Parent();
|
||||
|
||||
if (!child)
|
||||
if (child != acc)
|
||||
return S_FALSE;
|
||||
|
||||
*aAccessible = static_cast<IAccessible2*>(
|
||||
static_cast<AccessibleWrap*>(accWithCaret));
|
||||
(*aAccessible)->AddRef();
|
||||
*aCaretOffset = caretOffset;
|
||||
return S_OK;
|
||||
|
||||
|
|
|
@ -75,9 +75,11 @@ component {920400b1-cf8f-4760-a9c4-441417b15134} B2GAboutRedirector.js
|
|||
contract @mozilla.org/network/protocol/about;1?what=certerror {920400b1-cf8f-4760-a9c4-441417b15134}
|
||||
contract @mozilla.org/network/protocol/about;1?what=neterror {920400b1-cf8f-4760-a9c4-441417b15134}
|
||||
|
||||
#ifndef MOZ_GRAPHENE
|
||||
# FilePicker.js
|
||||
component {436ff8f9-0acc-4b11-8ec7-e293efba3141} FilePicker.js
|
||||
contract @mozilla.org/filepicker;1 {436ff8f9-0acc-4b11-8ec7-e293efba3141}
|
||||
#endif
|
||||
|
||||
# WebappsUpdateTimer.js
|
||||
component {637b0f77-2429-49a0-915f-abf5d0db8b9a} WebappsUpdateTimer.js
|
||||
|
|
|
@ -1667,3 +1667,8 @@ pref("dom.serviceWorkers.openWindow.enabled", true);
|
|||
// by about:newtab. These values are in CSS pixels.
|
||||
pref("toolkit.pageThumbs.minWidth", 280);
|
||||
pref("toolkit.pageThumbs.minHeight", 190);
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
// Enable speech synthesis, only Nightly for now
|
||||
pref("media.webspeech.synth.enabled", true);
|
||||
#endif
|
|
@ -1308,20 +1308,6 @@ toolbarpaletteitem[place="palette"][hidden] {
|
|||
animation-duration: 2s;
|
||||
}
|
||||
|
||||
#abouthome-search-panel > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 0;
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
#abouthome-search-panel-manage {
|
||||
padding: 4px 24px;
|
||||
}
|
||||
|
||||
#abouthome-search-panel-manage > label {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Combined context-menu items */
|
||||
#context-navigation > .menuitem-iconic > .menu-iconic-text,
|
||||
#context-navigation > .menuitem-iconic > .menu-accel-container {
|
||||
|
|
|
@ -261,14 +261,6 @@
|
|||
<box id="UITourHighlight"></box>
|
||||
</panel>
|
||||
|
||||
<panel id="abouthome-search-panel" orient="vertical" type="arrow" hidden="true"
|
||||
onclick="this.hidePopup()">
|
||||
<hbox id="abouthome-search-panel-manage"
|
||||
onclick="openPreferences('paneSearch')">
|
||||
<label>&changeSearchSettings.button;</label>
|
||||
</hbox>
|
||||
</panel>
|
||||
|
||||
<panel id="social-share-panel"
|
||||
class="social-panel"
|
||||
type="arrow"
|
||||
|
|
|
@ -119,7 +119,10 @@ for dirname, dirnames, filenames in os.walk('.'):
|
|||
|
||||
|
||||
def jsx_run_watcher(path):
|
||||
subprocess.call(append_arguments(run_command, ['-w', '-x', 'jsx', path, path]))
|
||||
# keep --target=es3 for now, as at least our UnsupportedBrowserView wants
|
||||
# to be able to render on IE8
|
||||
subprocess.call(append_arguments(run_command, ['--target=es3', '-w', '-x',
|
||||
'jsx', path, path]))
|
||||
|
||||
|
||||
def start_jsx_watcher_threads(dirs):
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<script type="text/javascript" src="loop/libs/l10n.js"></script>
|
||||
<script type="text/javascript" src="loop/js/otconfig.js"></script>
|
||||
<script type="text/javascript" src="loop/libs/sdk.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/react-0.12.2.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/react-0.13.3.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/lodash-3.9.3.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/backbone-1.2.1.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/classnames-2.2.0.js"></script>
|
||||
|
|
|
@ -262,12 +262,17 @@ body {
|
|||
|
||||
.room-list > .room-entry > h2 {
|
||||
display: inline-block;
|
||||
font-size: 1.3rem;
|
||||
line-height: 2.4rem;
|
||||
color: #000;
|
||||
vertical-align: middle;
|
||||
/* See .room-entry-context-item for the margin/size reductions.
|
||||
* An extra 16px to make space for the edit button. */
|
||||
width: calc(100% - 1rem - 32px);
|
||||
|
||||
font-size: 1.3rem;
|
||||
line-height: 2.4rem;
|
||||
color: #000;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.room-list > .room-entry.room-active:not(.room-opened) > h2 {
|
||||
|
|
|
@ -620,7 +620,7 @@ loop.panel = (function(_, mozL10n) {
|
|||
|
||||
/**
|
||||
* User profile prop can be either an object or null as per mozLoopAPI
|
||||
* and there is no way to express this with React 0.12.2
|
||||
* and there is no way to express this with React 0.13.3
|
||||
*/
|
||||
function userProfileValidator(props, propName, componentName) {
|
||||
if (Object.prototype.toString.call(props[propName]) !== "[object Object]" &&
|
||||
|
|
|
@ -620,7 +620,7 @@ loop.panel = (function(_, mozL10n) {
|
|||
|
||||
/**
|
||||
* User profile prop can be either an object or null as per mozLoopAPI
|
||||
* and there is no way to express this with React 0.12.2
|
||||
* and there is no way to express this with React 0.13.3
|
||||
*/
|
||||
function userProfileValidator(props, propName, componentName) {
|
||||
if (Object.prototype.toString.call(props[propName]) !== "[object Object]" &&
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<div id="main"></div>
|
||||
|
||||
<script type="text/javascript" src="loop/shared/libs/react-0.12.2.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/react-0.13.3.js"></script>
|
||||
<script type="text/javascript" src="loop/libs/l10n.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/lodash-3.9.3.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/libs/backbone-1.2.1.js"></script>
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -108,9 +108,9 @@ browser.jar:
|
|||
|
||||
# Shared libs
|
||||
#ifdef DEBUG
|
||||
content/browser/loop/shared/libs/react-0.12.2.js (content/shared/libs/react-0.12.2.js)
|
||||
content/browser/loop/shared/libs/react-0.13.3.js (content/shared/libs/react-0.13.3.js)
|
||||
#else
|
||||
content/browser/loop/shared/libs/react-0.12.2.js (content/shared/libs/react-0.12.2-prod.js)
|
||||
content/browser/loop/shared/libs/react-0.13.3.js (content/shared/libs/react-0.13.3-prod.js)
|
||||
#endif
|
||||
content/browser/loop/shared/libs/lodash-3.9.3.js (content/shared/libs/lodash-3.9.3.js)
|
||||
content/browser/loop/shared/libs/backbone-1.2.1.js (content/shared/libs/backbone-1.2.1.js)
|
||||
|
|
|
@ -41,7 +41,7 @@ if (typeof __PROD__ !== "undefined") {
|
|||
require("expose?classNames!classnames");
|
||||
} else {
|
||||
// our development server setup doesn't yet handle real modules, so for now...
|
||||
require("shared/libs/react-0.12.2.js");
|
||||
require("shared/libs/react-0.13.3.js");
|
||||
require("shared/libs/classnames-2.2.0.js");
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
"expose-loader": "0.7.x",
|
||||
"express": "4.x",
|
||||
"imports-loader": "0.6.x",
|
||||
"react": "0.12.x",
|
||||
"react": "0.13.3",
|
||||
"script-loader": "0.6.x",
|
||||
"webpack": "1.12.x"
|
||||
},
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
<!-- libs -->
|
||||
<script src="../../content/libs/l10n.js"></script>
|
||||
<script src="../../content/shared/libs/react-0.12.2.js"></script>
|
||||
<script src="../../content/shared/libs/react-0.13.3.js"></script>
|
||||
<script src="../../content/shared/libs/classnames-2.2.0.js"></script>
|
||||
<script src="../../content/shared/libs/lodash-3.9.3.js"></script>
|
||||
<script src="../../content/shared/libs/backbone-1.2.1.js"></script>
|
||||
|
|
|
@ -274,9 +274,10 @@ describe("loop.panel", function() {
|
|||
expect(node.textContent).to.eql("reallyreallylongtext@exa…");
|
||||
});
|
||||
|
||||
it("should throw an error when user profile is different from {} or null",
|
||||
it("should warn when user profile is different from {} or null",
|
||||
function() {
|
||||
var warnstub = sandbox.stub(console, "warn");
|
||||
|
||||
var view = TestUtils.renderIntoDocument(React.createElement(
|
||||
loop.panel.AccountLink, {
|
||||
fxAEnabled: false,
|
||||
|
@ -285,21 +286,21 @@ describe("loop.panel", function() {
|
|||
));
|
||||
|
||||
sinon.assert.calledOnce(warnstub);
|
||||
sinon.assert.calledWithExactly(warnstub, "Warning: Required prop `userProfile` was not correctly specified in `AccountLink`.");
|
||||
sinon.assert.calledWithMatch(warnstub, "Required prop `userProfile` was not correctly specified in `AccountLink`.");
|
||||
});
|
||||
|
||||
it("should throw an error when user profile is different from {} or null",
|
||||
it("should not warn when user profile is an object",
|
||||
function() {
|
||||
var warnstub = sandbox.stub(console, "warn");
|
||||
|
||||
var view = TestUtils.renderIntoDocument(React.createElement(
|
||||
loop.panel.AccountLink, {
|
||||
fxAEnabled: false,
|
||||
userProfile: function() {}
|
||||
userProfile: {}
|
||||
}
|
||||
));
|
||||
|
||||
sinon.assert.calledOnce(warnstub);
|
||||
sinon.assert.calledWithExactly(warnstub, "Warning: Required prop `userProfile` was not correctly specified in `AccountLink`.");
|
||||
sinon.assert.notCalled(warnstub);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ module.exports = function(config) {
|
|||
// List of files / patterns to load in the browser.
|
||||
baseConfig.files = baseConfig.files.concat([
|
||||
"content/libs/l10n.js",
|
||||
"content/shared/libs/react-0.12.2.js",
|
||||
"content/shared/libs/react-0.13.3.js",
|
||||
"content/shared/libs/classnames-2.2.0.js",
|
||||
"content/shared/libs/lodash-3.9.3.js",
|
||||
"content/shared/libs/backbone-1.2.1.js",
|
||||
|
|
|
@ -13,7 +13,7 @@ module.exports = function(config) {
|
|||
"standalone/content/libs/l10n-gaia-02ca67948fe8.js",
|
||||
"content/shared/libs/lodash-3.9.3.js",
|
||||
"content/shared/libs/backbone-1.2.1.js",
|
||||
"content/shared/libs/react-0.12.2.js",
|
||||
"content/shared/libs/react-0.13.3.js",
|
||||
"content/shared/libs/classnames-2.2.0.js",
|
||||
"content/shared/libs/sdk.js",
|
||||
"test/shared/vendor/*.js",
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
</script>
|
||||
|
||||
<!-- libs -->
|
||||
<script src="../../content/shared/libs/react-0.12.2.js"></script>
|
||||
<script src="../../content/shared/libs/react-0.13.3.js"></script>
|
||||
<script src="../../content/shared/libs/classnames-2.2.0.js"></script>
|
||||
<script src="../../content/shared/libs/lodash-3.9.3.js"></script>
|
||||
<script src="../../content/shared/libs/backbone-1.2.1.js"></script>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
</script>
|
||||
|
||||
<!-- libs -->
|
||||
<script src="../../content/shared/libs/react-0.12.2.js"></script>
|
||||
<script src="../../content/shared/libs/react-0.13.3.js"></script>
|
||||
<script src="../../content/shared/libs/classnames-2.2.0.js"></script>
|
||||
<script src="../../content/shared/libs/lodash-3.9.3.js"></script>
|
||||
<script src="../../content/shared/libs/backbone-1.2.1.js"></script>
|
||||
|
|
|
@ -65,7 +65,7 @@ var fakeRooms = [
|
|||
{
|
||||
"roomToken": "fjdkreFJDer",
|
||||
"decryptedContext": {
|
||||
"roomName": "Forth Room Name"
|
||||
"roomName": "Fourth Room Name"
|
||||
},
|
||||
"roomUrl": "http://localhost:3000/rooms/fjdkreFJDer",
|
||||
"roomOwner": "Alexis",
|
||||
|
@ -91,7 +91,7 @@ var fakeRooms = [
|
|||
{
|
||||
"roomToken": "preFLighdf",
|
||||
"decryptedContext": {
|
||||
"roomName": "Sixth Room Name"
|
||||
"roomName": "Sixth Room Name is a little longer to check the ellipsis"
|
||||
},
|
||||
"roomUrl": "http://localhost:3000/rooms/preFLighdf",
|
||||
"roomOwner": "Alexis",
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<div id="results"></div>
|
||||
<script src="fake-mozLoop.js"></script>
|
||||
<script src="fake-l10n.js"></script>
|
||||
<script src="../content/shared/libs/react-0.12.2.js"></script>
|
||||
<script src="../content/shared/libs/react-0.13.3.js"></script>
|
||||
<script src="../content/shared/libs/classnames-2.2.0.js"></script>
|
||||
<script src="../content/shared/libs/lodash-3.9.3.js"></script>
|
||||
<script src="../content/shared/libs/backbone-1.2.1.js"></script>
|
||||
|
|
|
@ -15,7 +15,15 @@ var gLanguagesDialog = {
|
|||
if (!this._availableLanguagesList.length)
|
||||
this._loadAvailableLanguages();
|
||||
},
|
||||
|
||||
|
||||
// Ugly hack used to trigger extra reflow in order to work around XUL bug 1194844;
|
||||
// see bug 1194346.
|
||||
forceReflow: function ()
|
||||
{
|
||||
this._activeLanguages.style.fontKerning = "none";
|
||||
setTimeout("gLanguagesDialog._activeLanguages.style.removeProperty('font-kerning')", 0);
|
||||
},
|
||||
|
||||
get _activeLanguages()
|
||||
{
|
||||
return document.getElementById("activeLanguages");
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
title="&languages.customize.Header;"
|
||||
dlgbuttons="accept,cancel,help"
|
||||
ondialoghelp="openPrefsHelp()"
|
||||
style="width: &window.width;;">
|
||||
style="width: &window.width;"
|
||||
# hack around XUL bug 1194844 by triggering extra reflow (see bug 1194346):
|
||||
onfocus="gLanguagesDialog.forceReflow()"
|
||||
onresize="gLanguagesDialog.forceReflow()">
|
||||
|
||||
<script type="application/javascript" src="chrome://browser/content/utilityOverlay.js"/>
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 1.1.551
|
||||
Current extension version is: 1.2.68
|
||||
|
|
|
@ -368,6 +368,12 @@ ChromeActions.prototype = {
|
|||
}
|
||||
return true;
|
||||
},
|
||||
supportedMouseWheelZoomModifierKeys: function() {
|
||||
return {
|
||||
ctrlKey: getIntPref('mousewheel.with_control.action', 3) === 3,
|
||||
metaKey: getIntPref('mousewheel.with_meta.action', 1) === 3,
|
||||
};
|
||||
},
|
||||
reportTelemetry: function (data) {
|
||||
var probeInfo = JSON.parse(data);
|
||||
switch (probeInfo.type) {
|
||||
|
@ -772,7 +778,7 @@ RequestListener.prototype.receive = function(event) {
|
|||
var response;
|
||||
if (sync) {
|
||||
response = actions[action].call(this.actions, data);
|
||||
event.detail.response = response;
|
||||
event.detail.response = makeContentReadable(response, doc.defaultView);
|
||||
} else {
|
||||
if (!event.detail.responseExpected) {
|
||||
doc.documentElement.removeChild(message);
|
||||
|
|
|
@ -22,8 +22,8 @@ if (typeof PDFJS === 'undefined') {
|
|||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
PDFJS.version = '1.1.551';
|
||||
PDFJS.build = '2a5616c';
|
||||
PDFJS.version = '1.2.68';
|
||||
PDFJS.build = '8079bdd';
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
|
@ -1326,6 +1326,8 @@ function loadJpegStream(id, imageUrl, objs) {
|
|||
}
|
||||
|
||||
|
||||
var DEFAULT_RANGE_CHUNK_SIZE = 65536; // 2^16 = 65536
|
||||
|
||||
/**
|
||||
* The maximum allowed image size in total pixels e.g. width * height. Images
|
||||
* above this value will not be drawn. Use -1 for no limit.
|
||||
|
@ -1520,6 +1522,9 @@ PDFJS.isEvalSupported = (PDFJS.isEvalSupported === undefined ?
|
|||
* @property {number} length - The PDF file length. It's used for progress
|
||||
* reports and range requests operations.
|
||||
* @property {PDFDataRangeTransport} range
|
||||
* @property {number} rangeChunkSize - Optional parameter to specify
|
||||
* maximum number of bytes fetched per range request. The default value is
|
||||
* 2^16 = 65536.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -1629,6 +1634,8 @@ PDFJS.getDocument = function getDocument(src,
|
|||
params[key] = source[key];
|
||||
}
|
||||
|
||||
params.rangeChunkSize = source.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
|
||||
|
||||
workerInitializedCapability = createPromiseCapability();
|
||||
transport = new WorkerTransport(workerInitializedCapability, source.range);
|
||||
workerInitializedCapability.promise.then(function transportInitialized() {
|
||||
|
@ -2526,6 +2533,9 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
}, this);
|
||||
|
||||
messageHandler.on('StartRenderPage', function transportRender(data) {
|
||||
if (this.destroyed) {
|
||||
return; // Ignore any pending requests if the worker was terminated.
|
||||
}
|
||||
var page = this.pageCache[data.pageIndex];
|
||||
|
||||
page.stats.timeEnd('Page Request');
|
||||
|
@ -2533,12 +2543,19 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
}, this);
|
||||
|
||||
messageHandler.on('RenderPageChunk', function transportRender(data) {
|
||||
if (this.destroyed) {
|
||||
return; // Ignore any pending requests if the worker was terminated.
|
||||
}
|
||||
var page = this.pageCache[data.pageIndex];
|
||||
|
||||
page._renderPageChunk(data.operatorList, data.intent);
|
||||
}, this);
|
||||
|
||||
messageHandler.on('commonobj', function transportObj(data) {
|
||||
if (this.destroyed) {
|
||||
return; // Ignore any pending requests if the worker was terminated.
|
||||
}
|
||||
|
||||
var id = data[0];
|
||||
var type = data[1];
|
||||
if (this.commonObjs.hasData(id)) {
|
||||
|
@ -2575,6 +2592,10 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
}, this);
|
||||
|
||||
messageHandler.on('obj', function transportObj(data) {
|
||||
if (this.destroyed) {
|
||||
return; // Ignore any pending requests if the worker was terminated.
|
||||
}
|
||||
|
||||
var id = data[0];
|
||||
var pageIndex = data[1];
|
||||
var type = data[2];
|
||||
|
@ -2606,6 +2627,10 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
}, this);
|
||||
|
||||
messageHandler.on('DocProgress', function transportDocProgress(data) {
|
||||
if (this.destroyed) {
|
||||
return; // Ignore any pending requests if the worker was terminated.
|
||||
}
|
||||
|
||||
var loadingTask = this.loadingTask;
|
||||
if (loadingTask.onProgress) {
|
||||
loadingTask.onProgress({
|
||||
|
@ -2616,6 +2641,10 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
}, this);
|
||||
|
||||
messageHandler.on('PageError', function transportError(data) {
|
||||
if (this.destroyed) {
|
||||
return; // Ignore any pending requests if the worker was terminated.
|
||||
}
|
||||
|
||||
var page = this.pageCache[data.pageNum - 1];
|
||||
var intentState = page.intentStates[data.intent];
|
||||
if (intentState.displayReadyCapability) {
|
||||
|
@ -2626,6 +2655,10 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
}, this);
|
||||
|
||||
messageHandler.on('JpegDecode', function(data) {
|
||||
if (this.destroyed) {
|
||||
return Promise.reject('Worker was terminated');
|
||||
}
|
||||
|
||||
var imageUrl = data[0];
|
||||
var components = data[1];
|
||||
if (components !== 3 && components !== 1) {
|
||||
|
@ -2665,7 +2698,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
};
|
||||
img.src = imageUrl;
|
||||
});
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
|
||||
fetchDocument: function WorkerTransport_fetchDocument(loadingTask, source) {
|
||||
|
@ -4521,16 +4554,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
var x = 0, i;
|
||||
for (i = 0; i < glyphsLength; ++i) {
|
||||
var glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
x += fontDirection * wordSpacing;
|
||||
continue;
|
||||
} else if (isNum(glyph)) {
|
||||
if (isNum(glyph)) {
|
||||
x += spacingDir * glyph * fontSize / 1000;
|
||||
continue;
|
||||
}
|
||||
|
||||
var restoreNeeded = false;
|
||||
var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
|
||||
var character = glyph.fontChar;
|
||||
var accent = glyph.accent;
|
||||
var scaledX, scaledY, scaledAccentX, scaledAccentY;
|
||||
|
@ -4574,7 +4604,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
}
|
||||
}
|
||||
|
||||
var charWidth = width * widthAdvanceScale + charSpacing * fontDirection;
|
||||
var charWidth = width * widthAdvanceScale + spacing * fontDirection;
|
||||
x += charWidth;
|
||||
|
||||
if (restoreNeeded) {
|
||||
|
@ -4619,18 +4649,14 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
|
||||
for (i = 0; i < glyphsLength; ++i) {
|
||||
glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
// word break
|
||||
this.ctx.translate(wordSpacing, 0);
|
||||
current.x += wordSpacing * textHScale;
|
||||
continue;
|
||||
} else if (isNum(glyph)) {
|
||||
if (isNum(glyph)) {
|
||||
spacingLength = spacingDir * glyph * fontSize / 1000;
|
||||
this.ctx.translate(spacingLength, 0);
|
||||
current.x += spacingLength * textHScale;
|
||||
continue;
|
||||
}
|
||||
|
||||
var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
|
||||
var operatorList = font.charProcOperatorList[glyph.operatorListId];
|
||||
if (!operatorList) {
|
||||
warn('Type3 character \"' + glyph.operatorListId +
|
||||
|
@ -4645,7 +4671,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||
this.restore();
|
||||
|
||||
var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
|
||||
width = transformed[0] * fontSize + charSpacing;
|
||||
width = transformed[0] * fontSize + spacing;
|
||||
|
||||
ctx.translate(width, 0);
|
||||
current.x += width * textHScale;
|
||||
|
|
|
@ -22,8 +22,8 @@ if (typeof PDFJS === 'undefined') {
|
|||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
PDFJS.version = '1.1.551';
|
||||
PDFJS.build = '2a5616c';
|
||||
PDFJS.version = '1.2.68';
|
||||
PDFJS.build = '8079bdd';
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
|
@ -1856,9 +1856,6 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
|
|||
})();
|
||||
|
||||
|
||||
// The maximum number of bytes fetched per range request
|
||||
var RANGE_CHUNK_SIZE = 65536;
|
||||
|
||||
// TODO(mack): Make use of PDFJS.Util.inherit() when it becomes available
|
||||
var BasePdfManager = (function BasePdfManagerClosure() {
|
||||
function BasePdfManager() {
|
||||
|
@ -1990,7 +1987,8 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
|
|||
disableAutoFetch: args.disableAutoFetch,
|
||||
initialData: args.initialData
|
||||
};
|
||||
this.streamManager = new ChunkedStreamManager(args.length, RANGE_CHUNK_SIZE,
|
||||
this.streamManager = new ChunkedStreamManager(args.length,
|
||||
args.rangeChunkSize,
|
||||
args.url, params);
|
||||
|
||||
this.pdfDocument = new PDFDocument(this, this.streamManager.getStream(),
|
||||
|
@ -10587,9 +10585,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
|
||||
for (var i = 0, ii = glyphs.length; i < ii; i++) {
|
||||
var glyph = glyphs[i];
|
||||
if (glyph === null) {
|
||||
continue;
|
||||
}
|
||||
buildPath(glyph.fontChar);
|
||||
|
||||
// If the glyph has an accent we need to build a path for its
|
||||
|
@ -11249,10 +11244,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
var defaultVMetrics = font.defaultVMetrics;
|
||||
for (var i = 0; i < glyphs.length; i++) {
|
||||
var glyph = glyphs[i];
|
||||
if (!glyph) { // Previous glyph was a space.
|
||||
width += textState.wordSpacing * textState.textHScale;
|
||||
continue;
|
||||
}
|
||||
var vMetricX = null;
|
||||
var vMetricY = null;
|
||||
var glyphWidth = null;
|
||||
|
@ -11288,11 +11279,14 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
// var x = pt[0];
|
||||
// var y = pt[1];
|
||||
|
||||
var charSpacing = 0;
|
||||
if (textChunk.str.length > 0) {
|
||||
// Apply char spacing only when there are chars.
|
||||
// As a result there is only spacing between glyphs.
|
||||
charSpacing = textState.charSpacing;
|
||||
var charSpacing = textState.charSpacing;
|
||||
if (glyph.isSpace) {
|
||||
var wordSpacing = textState.wordSpacing;
|
||||
charSpacing += wordSpacing;
|
||||
if (wordSpacing > 0) {
|
||||
addFakeSpaces(wordSpacing * 1000 / textState.fontSize,
|
||||
textChunk.str);
|
||||
}
|
||||
}
|
||||
|
||||
var tx = 0;
|
||||
|
@ -11326,6 +11320,22 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
return textChunk;
|
||||
}
|
||||
|
||||
function addFakeSpaces(width, strBuf) {
|
||||
var spaceWidth = textState.font.spaceWidth;
|
||||
if (spaceWidth <= 0) {
|
||||
return;
|
||||
}
|
||||
var fakeSpaces = width / spaceWidth;
|
||||
if (fakeSpaces > MULTI_SPACE_FACTOR) {
|
||||
fakeSpaces = Math.round(fakeSpaces);
|
||||
while (fakeSpaces--) {
|
||||
strBuf.push(' ');
|
||||
}
|
||||
} else if (fakeSpaces > SPACE_FACTOR) {
|
||||
strBuf.push(' ');
|
||||
}
|
||||
}
|
||||
|
||||
var timeSlotManager = new TimeSlotManager();
|
||||
|
||||
return new Promise(function next(resolve, reject) {
|
||||
|
@ -11404,29 +11414,26 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||
// In the default coordinate system, a positive adjustment
|
||||
// has the effect of moving the next glyph painted either to
|
||||
// the left or down by the given amount.
|
||||
var val = items[j] * textState.fontSize / 1000;
|
||||
var advance = items[j];
|
||||
var val = advance * textState.fontSize / 1000;
|
||||
if (textState.font.vertical) {
|
||||
offset = val * textState.textMatrix[3];
|
||||
textState.translateTextMatrix(0, offset);
|
||||
offset = val *
|
||||
(textState.textHScale * textState.textMatrix[2] +
|
||||
textState.textMatrix[3]);
|
||||
textState.translateTextMatrix(0, val);
|
||||
// Value needs to be added to height to paint down.
|
||||
textChunk.height += offset;
|
||||
} else {
|
||||
offset = val * textState.textHScale *
|
||||
textState.textMatrix[0];
|
||||
textState.translateTextMatrix(offset, 0);
|
||||
offset = val * (
|
||||
textState.textHScale * textState.textMatrix[0] +
|
||||
textState.textMatrix[1]);
|
||||
textState.translateTextMatrix(-val, 0);
|
||||
// Value needs to be subtracted from width to paint left.
|
||||
textChunk.width -= offset;
|
||||
advance = -advance;
|
||||
}
|
||||
if (items[j] < 0 && textState.font.spaceWidth > 0) {
|
||||
var fakeSpaces = -items[j] / textState.font.spaceWidth;
|
||||
if (fakeSpaces > MULTI_SPACE_FACTOR) {
|
||||
fakeSpaces = Math.round(fakeSpaces);
|
||||
while (fakeSpaces--) {
|
||||
textChunk.str.push(' ');
|
||||
}
|
||||
} else if (fakeSpaces > SPACE_FACTOR) {
|
||||
textChunk.str.push(' ');
|
||||
}
|
||||
if (advance > 0) {
|
||||
addFakeSpaces(advance, textChunk.str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12157,6 +12164,7 @@ var OperatorList = (function OperatorListClosure() {
|
|||
this.fnArray = [];
|
||||
this.argsArray = [];
|
||||
this.dependencies = {};
|
||||
this._totalLength = 0;
|
||||
this.pageIndex = pageIndex;
|
||||
this.intent = intent;
|
||||
}
|
||||
|
@ -12166,6 +12174,14 @@ var OperatorList = (function OperatorListClosure() {
|
|||
return this.argsArray.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {number} The total length of the entire operator list,
|
||||
* since `this.length === 0` after flushing.
|
||||
*/
|
||||
get totalLength() {
|
||||
return (this._totalLength + this.length);
|
||||
},
|
||||
|
||||
addOp: function(fn, args) {
|
||||
this.fnArray.push(fn);
|
||||
this.argsArray.push(args);
|
||||
|
@ -12214,12 +12230,15 @@ var OperatorList = (function OperatorListClosure() {
|
|||
new QueueOptimizer().optimize(this);
|
||||
}
|
||||
var transfers = getTransfers(this);
|
||||
var length = this.length;
|
||||
this._totalLength += length;
|
||||
|
||||
this.messageHandler.send('RenderPageChunk', {
|
||||
operatorList: {
|
||||
fnArray: this.fnArray,
|
||||
argsArray: this.argsArray,
|
||||
lastChunk: lastChunk,
|
||||
length: this.length
|
||||
length: length
|
||||
},
|
||||
pageIndex: this.pageIndex,
|
||||
intent: this.intent
|
||||
|
@ -16095,23 +16114,26 @@ function getFontType(type, subtype) {
|
|||
}
|
||||
|
||||
var Glyph = (function GlyphClosure() {
|
||||
function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId) {
|
||||
function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId,
|
||||
isSpace) {
|
||||
this.fontChar = fontChar;
|
||||
this.unicode = unicode;
|
||||
this.accent = accent;
|
||||
this.width = width;
|
||||
this.vmetric = vmetric;
|
||||
this.operatorListId = operatorListId;
|
||||
this.isSpace = isSpace;
|
||||
}
|
||||
|
||||
Glyph.prototype.matchesForCache =
|
||||
function(fontChar, unicode, accent, width, vmetric, operatorListId) {
|
||||
Glyph.prototype.matchesForCache = function(fontChar, unicode, accent, width,
|
||||
vmetric, operatorListId, isSpace) {
|
||||
return this.fontChar === fontChar &&
|
||||
this.unicode === unicode &&
|
||||
this.accent === accent &&
|
||||
this.width === width &&
|
||||
this.vmetric === vmetric &&
|
||||
this.operatorListId === operatorListId;
|
||||
this.operatorListId === operatorListId &&
|
||||
this.isSpace === isSpace;
|
||||
};
|
||||
|
||||
return Glyph;
|
||||
|
@ -18626,7 +18648,7 @@ var Font = (function FontClosure() {
|
|||
return width;
|
||||
},
|
||||
|
||||
charToGlyph: function Font_charToGlyph(charcode) {
|
||||
charToGlyph: function Font_charToGlyph(charcode, isSpace) {
|
||||
var fontCharCode, width, operatorListId;
|
||||
|
||||
var widthCode = charcode;
|
||||
|
@ -18669,9 +18691,9 @@ var Font = (function FontClosure() {
|
|||
var glyph = this.glyphCache[charcode];
|
||||
if (!glyph ||
|
||||
!glyph.matchesForCache(fontChar, unicode, accent, width, vmetric,
|
||||
operatorListId)) {
|
||||
operatorListId, isSpace)) {
|
||||
glyph = new Glyph(fontChar, unicode, accent, width, vmetric,
|
||||
operatorListId);
|
||||
operatorListId, isSpace);
|
||||
this.glyphCache[charcode] = glyph;
|
||||
}
|
||||
return glyph;
|
||||
|
@ -18707,22 +18729,16 @@ var Font = (function FontClosure() {
|
|||
charcode = c.charcode;
|
||||
var length = c.length;
|
||||
i += length;
|
||||
glyph = this.charToGlyph(charcode);
|
||||
// Space is char with code 0x20 and length 1 in multiple-byte codes.
|
||||
var isSpace = length === 1 && chars.charCodeAt(i - 1) === 0x20;
|
||||
glyph = this.charToGlyph(charcode, isSpace);
|
||||
glyphs.push(glyph);
|
||||
// placing null after each word break charcode (ASCII SPACE)
|
||||
// Ignore occurences of 0x20 in multiple-byte codes.
|
||||
if (length === 1 && chars.charCodeAt(i - 1) === 0x20) {
|
||||
glyphs.push(null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0, ii = chars.length; i < ii; ++i) {
|
||||
charcode = chars.charCodeAt(i);
|
||||
glyph = this.charToGlyph(charcode);
|
||||
glyph = this.charToGlyph(charcode, charcode === 0x20);
|
||||
glyphs.push(glyph);
|
||||
if (charcode === 0x20) {
|
||||
glyphs.push(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33808,7 +33824,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
|||
return;
|
||||
}
|
||||
source.length = length;
|
||||
if (length <= 2 * RANGE_CHUNK_SIZE) {
|
||||
if (length <= 2 * source.rangeChunkSize) {
|
||||
// The file size is smaller than the size of two chunks, so it does
|
||||
// not make any sense to abort the request and retry with a range
|
||||
// request.
|
||||
|
@ -34115,7 +34131,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
|||
finishWorkerTask(task);
|
||||
|
||||
info('page=' + pageNum + ' - getOperatorList: time=' +
|
||||
(Date.now() - start) + 'ms, len=' + operatorList.fnArray.length);
|
||||
(Date.now() - start) + 'ms, len=' + operatorList.totalLength);
|
||||
}, function(e) {
|
||||
finishWorkerTask(task);
|
||||
if (task.terminated) {
|
||||
|
|
|
@ -59,6 +59,22 @@
|
|||
.textLayer ::selection { background: rgb(0,0,255); }
|
||||
.textLayer ::-moz-selection { background: rgb(0,0,255); }
|
||||
|
||||
.textLayer .endOfContent {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 100%;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
z-index: -1;
|
||||
cursor: default;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.textLayer .endOfContent.active {
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
|
||||
.annotationLayer .annotLink > a:hover {
|
||||
opacity: 0.2;
|
||||
|
@ -420,9 +436,8 @@ html[dir='rtl'] #toolbarContainer, .findbar, .secondaryToolbar {
|
|||
}
|
||||
|
||||
@keyframes progressIndeterminate {
|
||||
0% { left: 0%; }
|
||||
50% { left: 100%; }
|
||||
100% { left: 100%; }
|
||||
0% { left: -142px; }
|
||||
100% { left: 0; }
|
||||
}
|
||||
|
||||
#loadingBar .progress.indeterminate {
|
||||
|
@ -430,18 +445,19 @@ html[dir='rtl'] #toolbarContainer, .findbar, .secondaryToolbar {
|
|||
transition: none;
|
||||
}
|
||||
|
||||
#loadingBar .indeterminate .glimmer {
|
||||
#loadingBar .progress.indeterminate .glimmer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 50px;
|
||||
width: calc(100% + 150px);
|
||||
|
||||
background-image: linear-gradient(to right, #999 0%, #fff 50%, #999 100%);
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
background: repeating-linear-gradient(135deg,
|
||||
#bbb 0, #999 5px,
|
||||
#999 45px, #ddd 55px,
|
||||
#ddd 95px, #bbb 100px);
|
||||
|
||||
animation: progressIndeterminate 2s linear infinite;
|
||||
animation: progressIndeterminate 950ms linear infinite;
|
||||
}
|
||||
|
||||
.findbar, .secondaryToolbar {
|
||||
|
@ -551,6 +567,13 @@ html[dir='ltr'] .doorHangerRight:before {
|
|||
margin-right: -9px;
|
||||
}
|
||||
|
||||
#findResultsCount {
|
||||
background-color: hsl(0, 0%, 85%);
|
||||
color: hsl(0, 0%, 32%);
|
||||
text-align: center;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
#findMsg {
|
||||
font-style: italic;
|
||||
color: #A6B7D0;
|
||||
|
|
|
@ -88,6 +88,7 @@ See https://github.com/adobe-type-tools/cmap-resources
|
|||
<label for="findHighlightAll" class="toolbarLabel" data-l10n-id="find_highlight">Highlight all</label>
|
||||
<input type="checkbox" id="findMatchCase" class="toolbarField" tabindex="95">
|
||||
<label for="findMatchCase" class="toolbarLabel" data-l10n-id="find_match_case_label">Match case</label>
|
||||
<span id="findResultsCount" class="toolbarLabel hidden"></span>
|
||||
<span id="findMsg" class="toolbarLabel"></span>
|
||||
</div> <!-- findbar -->
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf';
|
|||
var DEFAULT_SCALE_DELTA = 1.1;
|
||||
var MIN_SCALE = 0.25;
|
||||
var MAX_SCALE = 10.0;
|
||||
var VIEW_HISTORY_MEMORY = 20;
|
||||
var SCALE_SELECT_CONTAINER_PADDING = 8;
|
||||
var SCALE_SELECT_PADDING = 22;
|
||||
var PAGE_NUMBER_LOADING_INDICATOR = 'visiblePageIsLoading';
|
||||
|
@ -266,6 +265,55 @@ function binarySearchFirstItem(items, condition) {
|
|||
return minIndex; /* === maxIndex */
|
||||
}
|
||||
|
||||
/**
|
||||
* Approximates float number as a fraction using Farey sequence (max order
|
||||
* of 8).
|
||||
* @param {number} x - Positive float number.
|
||||
* @returns {Array} Estimated fraction: the first array item is a numerator,
|
||||
* the second one is a denominator.
|
||||
*/
|
||||
function approximateFraction(x) {
|
||||
// Fast paths for int numbers or their inversions.
|
||||
if (Math.floor(x) === x) {
|
||||
return [x, 1];
|
||||
}
|
||||
var xinv = 1 / x;
|
||||
var limit = 8;
|
||||
if (xinv > limit) {
|
||||
return [1, limit];
|
||||
} else if (Math.floor(xinv) === xinv) {
|
||||
return [1, xinv];
|
||||
}
|
||||
|
||||
var x_ = x > 1 ? xinv : x;
|
||||
// a/b and c/d are neighbours in Farey sequence.
|
||||
var a = 0, b = 1, c = 1, d = 1;
|
||||
// Limiting search to order 8.
|
||||
while (true) {
|
||||
// Generating next term in sequence (order of q).
|
||||
var p = a + c, q = b + d;
|
||||
if (q > limit) {
|
||||
break;
|
||||
}
|
||||
if (x_ <= p / q) {
|
||||
c = p; d = q;
|
||||
} else {
|
||||
a = p; b = q;
|
||||
}
|
||||
}
|
||||
// Select closest of the neighbours to x.
|
||||
if (x_ - a / b < c / d - x_) {
|
||||
return x_ === x ? [a, b] : [b, a];
|
||||
} else {
|
||||
return x_ === x ? [c, d] : [d, c];
|
||||
}
|
||||
}
|
||||
|
||||
function roundToDivide(x, div) {
|
||||
var r = x % div;
|
||||
return r === 0 ? x : Math.round(x - r + div);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic helper to find out what elements are visible within a scroll pane.
|
||||
*/
|
||||
|
@ -733,6 +781,8 @@ Preferences._readFromStorage = function (prefObj) {
|
|||
|
||||
|
||||
|
||||
var DEFAULT_VIEW_HISTORY_CACHE_SIZE = 20;
|
||||
|
||||
/**
|
||||
* View History - This is a utility for saving various view parameters for
|
||||
* recently opened files.
|
||||
|
@ -743,8 +793,9 @@ Preferences._readFromStorage = function (prefObj) {
|
|||
* - GENERIC or CHROME - uses localStorage, if it is available.
|
||||
*/
|
||||
var ViewHistory = (function ViewHistoryClosure() {
|
||||
function ViewHistory(fingerprint) {
|
||||
function ViewHistory(fingerprint, cacheSize) {
|
||||
this.fingerprint = fingerprint;
|
||||
this.cacheSize = cacheSize || DEFAULT_VIEW_HISTORY_CACHE_SIZE;
|
||||
this.isInitializedPromiseResolved = false;
|
||||
this.initializedPromise =
|
||||
this._readFromStorage().then(function (databaseStr) {
|
||||
|
@ -754,7 +805,7 @@ var ViewHistory = (function ViewHistoryClosure() {
|
|||
if (!('files' in database)) {
|
||||
database.files = [];
|
||||
}
|
||||
if (database.files.length >= VIEW_HISTORY_MEMORY) {
|
||||
if (database.files.length >= this.cacheSize) {
|
||||
database.files.shift();
|
||||
}
|
||||
var index;
|
||||
|
@ -836,6 +887,7 @@ var PDFFindBar = (function PDFFindBarClosure() {
|
|||
this.highlightAll = options.highlightAllCheckbox || null;
|
||||
this.caseSensitive = options.caseSensitiveCheckbox || null;
|
||||
this.findMsg = options.findMsg || null;
|
||||
this.findResultsCount = options.findResultsCount || null;
|
||||
this.findStatusIcon = options.findStatusIcon || null;
|
||||
this.findPreviousButton = options.findPreviousButton || null;
|
||||
this.findNextButton = options.findNextButton || null;
|
||||
|
@ -898,7 +950,8 @@ var PDFFindBar = (function PDFFindBarClosure() {
|
|||
return window.dispatchEvent(event);
|
||||
},
|
||||
|
||||
updateUIState: function PDFFindBar_updateUIState(state, previous) {
|
||||
updateUIState:
|
||||
function PDFFindBar_updateUIState(state, previous, matchCount) {
|
||||
var notFound = false;
|
||||
var findMsg = '';
|
||||
var status = '';
|
||||
|
@ -935,6 +988,26 @@ var PDFFindBar = (function PDFFindBarClosure() {
|
|||
|
||||
this.findField.setAttribute('data-status', status);
|
||||
this.findMsg.textContent = findMsg;
|
||||
|
||||
this.updateResultsCount(matchCount);
|
||||
},
|
||||
|
||||
updateResultsCount: function(matchCount) {
|
||||
if (!this.findResultsCount) {
|
||||
return; // no UI control is provided
|
||||
}
|
||||
|
||||
// If there are no matches, hide the counter
|
||||
if (!matchCount) {
|
||||
this.findResultsCount.classList.add('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the match counter
|
||||
this.findResultsCount.textContent = matchCount.toLocaleString();
|
||||
|
||||
// Show the counter
|
||||
this.findResultsCount.classList.remove('hidden');
|
||||
},
|
||||
|
||||
open: function PDFFindBar_open() {
|
||||
|
@ -991,6 +1064,7 @@ var PDFFindController = (function PDFFindControllerClosure() {
|
|||
this.active = false; // If active, find results will be highlighted.
|
||||
this.pageContents = []; // Stores the text for each page.
|
||||
this.pageMatches = [];
|
||||
this.matchCount = 0;
|
||||
this.selected = { // Currently selected match.
|
||||
pageIdx: -1,
|
||||
matchIdx: -1
|
||||
|
@ -1068,7 +1142,8 @@ var PDFFindController = (function PDFFindControllerClosure() {
|
|||
var queryLen = query.length;
|
||||
|
||||
if (queryLen === 0) {
|
||||
return; // Do nothing: the matches should be wiped out already.
|
||||
// Do nothing: the matches should be wiped out already.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!caseSensitive) {
|
||||
|
@ -1091,6 +1166,12 @@ var PDFFindController = (function PDFFindControllerClosure() {
|
|||
this.resumePageIdx = null;
|
||||
this.nextPageMatch();
|
||||
}
|
||||
|
||||
// Update the matches count
|
||||
if (matches.length > 0) {
|
||||
this.matchCount += matches.length;
|
||||
this.updateUIResultsCount();
|
||||
}
|
||||
},
|
||||
|
||||
extractText: function PDFFindController_extractText() {
|
||||
|
@ -1182,6 +1263,7 @@ var PDFFindController = (function PDFFindControllerClosure() {
|
|||
this.hadMatch = false;
|
||||
this.resumePageIdx = null;
|
||||
this.pageMatches = [];
|
||||
this.matchCount = 0;
|
||||
var self = this;
|
||||
|
||||
for (var i = 0; i < numPages; i++) {
|
||||
|
@ -1338,6 +1420,15 @@ var PDFFindController = (function PDFFindControllerClosure() {
|
|||
}
|
||||
},
|
||||
|
||||
updateUIResultsCount:
|
||||
function PDFFindController_updateUIResultsCount() {
|
||||
if (this.findBar === null) {
|
||||
throw new Error('PDFFindController is not initialized with a ' +
|
||||
'PDFFindBar instance.');
|
||||
}
|
||||
this.findBar.updateResultsCount(this.matchCount);
|
||||
},
|
||||
|
||||
updateUIState: function PDFFindController_updateUIState(state, previous) {
|
||||
if (this.integratedFind) {
|
||||
FirefoxCom.request('updateFindControlState',
|
||||
|
@ -1348,7 +1439,7 @@ var PDFFindController = (function PDFFindControllerClosure() {
|
|||
throw new Error('PDFFindController is not initialized with a ' +
|
||||
'PDFFindBar instance.');
|
||||
}
|
||||
this.findBar.updateUIState(state, previous);
|
||||
this.findBar.updateUIState(state, previous, this.matchCount);
|
||||
}
|
||||
};
|
||||
return PDFFindController;
|
||||
|
@ -3705,7 +3796,7 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||
var outputScale = getOutputScale(ctx);
|
||||
|
||||
if (PDFJS.useOnlyCssZoom) {
|
||||
var actualSizeViewport = viewport.clone({ scale: CSS_UNITS });
|
||||
var actualSizeViewport = viewport.clone({scale: CSS_UNITS});
|
||||
// Use a scale that will make the canvas be the original intended size
|
||||
// of the page.
|
||||
outputScale.sx *= actualSizeViewport.width / viewport.width;
|
||||
|
@ -3726,10 +3817,12 @@ var PDFPageView = (function PDFPageViewClosure() {
|
|||
}
|
||||
}
|
||||
|
||||
canvas.width = (Math.floor(viewport.width) * outputScale.sx) | 0;
|
||||
canvas.height = (Math.floor(viewport.height) * outputScale.sy) | 0;
|
||||
canvas.style.width = Math.floor(viewport.width) + 'px';
|
||||
canvas.style.height = Math.floor(viewport.height) + 'px';
|
||||
var sfx = approximateFraction(outputScale.sx);
|
||||
var sfy = approximateFraction(outputScale.sy);
|
||||
canvas.width = roundToDivide(viewport.width * outputScale.sx, sfx[0]);
|
||||
canvas.height = roundToDivide(viewport.height * outputScale.sy, sfy[0]);
|
||||
canvas.style.width = roundToDivide(viewport.width, sfx[1]) + 'px';
|
||||
canvas.style.height = roundToDivide(viewport.height, sfy[1]) + 'px';
|
||||
// Add the viewport so it's known what it was originally drawn with.
|
||||
canvas._viewport = viewport;
|
||||
|
||||
|
@ -3969,12 +4062,17 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() {
|
|||
this.viewport = options.viewport;
|
||||
this.textDivs = [];
|
||||
this.findController = options.findController || null;
|
||||
this._bindMouse();
|
||||
}
|
||||
|
||||
TextLayerBuilder.prototype = {
|
||||
_finishRendering: function TextLayerBuilder_finishRendering() {
|
||||
this.renderingDone = true;
|
||||
|
||||
var endOfContent = document.createElement('div');
|
||||
endOfContent.className = 'endOfContent';
|
||||
this.textLayerDiv.appendChild(endOfContent);
|
||||
|
||||
var event = document.createEvent('CustomEvent');
|
||||
event.initCustomEvent('textlayerrendered', true, true, {
|
||||
pageNumber: this.pageNumber
|
||||
|
@ -4310,7 +4408,30 @@ var TextLayerBuilder = (function TextLayerBuilderClosure() {
|
|||
this.matches = this.convertMatches(this.findController === null ?
|
||||
[] : (this.findController.pageMatches[this.pageIdx] || []));
|
||||
this.renderMatches(this.matches);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fixes text selection: adds additional div where mouse was clicked.
|
||||
* This reduces flickering of the content if mouse slowly dragged down/up.
|
||||
* @private
|
||||
*/
|
||||
_bindMouse: function TextLayerBuilder_bindMouse() {
|
||||
var div = this.textLayerDiv;
|
||||
div.addEventListener('mousedown', function (e) {
|
||||
var end = div.querySelector('.endOfContent');
|
||||
if (!end) {
|
||||
return;
|
||||
}
|
||||
end.classList.add('active');
|
||||
});
|
||||
div.addEventListener('mouseup', function (e) {
|
||||
var end = div.querySelector('.endOfContent');
|
||||
if (!end) {
|
||||
return;
|
||||
}
|
||||
end.classList.remove('active');
|
||||
});
|
||||
},
|
||||
};
|
||||
return TextLayerBuilder;
|
||||
})();
|
||||
|
@ -4930,6 +5051,10 @@ var PDFViewer = (function pdfViewer() {
|
|||
*/
|
||||
scrollPageIntoView: function PDFViewer_scrollPageIntoView(pageNumber,
|
||||
dest) {
|
||||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
|
||||
var pageView = this._pages[pageNumber - 1];
|
||||
|
||||
if (this.isInPresentationMode) {
|
||||
|
@ -6111,6 +6236,7 @@ var PDFViewerApplication = {
|
|||
highlightAllCheckbox: document.getElementById('findHighlightAll'),
|
||||
caseSensitiveCheckbox: document.getElementById('findMatchCase'),
|
||||
findMsg: document.getElementById('findMsg'),
|
||||
findResultsCount: document.getElementById('findResultsCount'),
|
||||
findStatusIcon: document.getElementById('findStatusIcon'),
|
||||
findPreviousButton: document.getElementById('findPrevious'),
|
||||
findNextButton: document.getElementById('findNext'),
|
||||
|
@ -6338,6 +6464,16 @@ var PDFViewerApplication = {
|
|||
return PDFJS.shadow(this, 'loadingBar', bar);
|
||||
},
|
||||
|
||||
get supportedMouseWheelZoomModifierKeys() {
|
||||
var support = {
|
||||
ctrlKey: true,
|
||||
metaKey: true,
|
||||
};
|
||||
support = FirefoxCom.requestSync('supportedMouseWheelZoomModifierKeys');
|
||||
|
||||
return PDFJS.shadow(this, 'supportedMouseWheelZoomModifierKeys', support);
|
||||
},
|
||||
|
||||
initPassiveLoading: function pdfViewInitPassiveLoading() {
|
||||
function FirefoxComDataRangeTransport(length, initialData) {
|
||||
PDFJS.PDFDataRangeTransport.call(this, length, initialData);
|
||||
|
@ -7624,6 +7760,11 @@ function handleMouseWheel(evt) {
|
|||
PDFViewerApplication.scrollPresentationMode(ticks *
|
||||
MOUSE_WHEEL_DELTA_FACTOR);
|
||||
} else if (evt.ctrlKey || evt.metaKey) {
|
||||
var support = PDFViewerApplication.supportedMouseWheelZoomModifierKeys;
|
||||
if ((evt.ctrlKey && !support.ctrlKey) ||
|
||||
(evt.metaKey && !support.metaKey)) {
|
||||
return;
|
||||
}
|
||||
// Only zoom the pages, not the entire viewer.
|
||||
evt.preventDefault();
|
||||
|
||||
|
|
|
@ -61,17 +61,6 @@ toolbar[brighttext] #downloads-button[attention] > #downloads-indicator-anchor >
|
|||
-moz-image-region: auto;
|
||||
}
|
||||
|
||||
%ifdef WINDOWS_AERO
|
||||
@media (-moz-os-version: windows-vista),
|
||||
(-moz-os-version: windows-win7) {
|
||||
%endif
|
||||
#downloads-button[cui-areatype="menu-panel"][attention] {
|
||||
list-style-image: url("chrome://browser/skin/downloads/download-glow-menuPanel-XPVista7.png");
|
||||
}
|
||||
%ifdef WINDOWS_AERO
|
||||
}
|
||||
%endif
|
||||
|
||||
/* In the next few rules, we use :not([counter]) as a shortcut that is
|
||||
equivalent to -moz-any([progress], [paused]). */
|
||||
|
||||
|
|
|
@ -331,6 +331,7 @@ browser.jar:
|
|||
% override chrome://browser/skin/toolbarbutton-dropdown-arrow.png chrome://browser/skin/toolbarbutton-dropdown-arrow-XPVista7.png os=WINNT osversion<=6.1
|
||||
% override chrome://browser/skin/urlbar-history-dropmarker.png chrome://browser/skin/urlbar-history-dropmarker-XPVista7.png os=WINNT osversion<=6.1
|
||||
% override chrome://browser/skin/urlbar-history-dropmarker@2x.png chrome://browser/skin/urlbar-history-dropmarker-XPVista7@2x.png os=WINNT osversion<=6.1
|
||||
% override chrome://browser/skin/downloads/download-glow-menuPanel.png chrome://browser/skin/downloads/download-glow-menuPanel-XPVista7.png os=WINNT osversion<=6.1
|
||||
% override chrome://browser/skin/places/autocomplete-star.png chrome://browser/skin/places/autocomplete-star-XPVista7.png os=WINNT osversion<=6.1
|
||||
% override chrome://browser/skin/tabbrowser/newtab.png chrome://browser/skin/tabbrowser/newtab-XPVista7.png os=WINNT osversion<=6.1
|
||||
% override chrome://browser/skin/tabbrowser/newtab@2x.png chrome://browser/skin/tabbrowser/newtab-XPVista7@2x.png os=WINNT osversion<=6.1
|
||||
|
|
|
@ -988,7 +988,7 @@ bool
|
|||
nsScriptSecurityManager::ScriptAllowed(JSObject *aGlobal)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT(JS_IsGlobalObject(aGlobal) || js::IsOuterObject(aGlobal));
|
||||
MOZ_ASSERT(JS_IsGlobalObject(aGlobal) || js::IsWindowProxy(aGlobal));
|
||||
|
||||
// Check the bits on the compartment private.
|
||||
return xpc::Scriptability::Get(aGlobal).Allowed();
|
||||
|
|
|
@ -30,7 +30,7 @@ import sys
|
|||
from check_utils import get_all_toplevel_filenames
|
||||
|
||||
architecture_independent = set([ 'generic' ])
|
||||
all_architecture_names = set([ 'x86', 'x64', 'arm', 'arm64', 'mips32' ])
|
||||
all_architecture_names = set([ 'x86', 'x64', 'arm', 'arm64', 'mips32', 'mips64' ])
|
||||
all_shared_architecture_names = set([ 'x86_shared', 'mips_shared', 'arm', 'arm64' ])
|
||||
|
||||
reBeforeArg = "(?<=[(,\s])"
|
||||
|
|
|
@ -504,10 +504,8 @@ endif
|
|||
|
||||
ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
|
||||
OUTOPTION = -Fo# eol
|
||||
PREPROCESS_OPTION = -P -Fi# eol
|
||||
else
|
||||
OUTOPTION = -o # eol
|
||||
PREPROCESS_OPTION = -E -o #eol
|
||||
endif # WINNT && !GNU_CC
|
||||
|
||||
ifneq (,$(filter ml%,$(AS)))
|
||||
|
|
12
configure.in
12
configure.in
|
@ -9144,6 +9144,18 @@ HAVE_SYS_VFS_H
|
|||
HAVE_SYS_MOUNT_H
|
||||
"
|
||||
|
||||
dnl ========================================================
|
||||
dnl Determine options to use for running the preprocessor.
|
||||
dnl ========================================================
|
||||
|
||||
if test -z "$GNU_CC" -a "$OS_ARCH" = "WINNT"; then
|
||||
PREPROCESS_OPTION="-P -Fi"
|
||||
else
|
||||
PREPROCESS_OPTION="-E -o "
|
||||
fi
|
||||
|
||||
AC_SUBST(PREPROCESS_OPTION)
|
||||
|
||||
dnl ========================================================
|
||||
dnl ICU Support
|
||||
dnl ========================================================
|
||||
|
|
|
@ -663,7 +663,7 @@ Animation::CanThrottle() const
|
|||
return true;
|
||||
}
|
||||
|
||||
return IsRunningOnCompositor();
|
||||
return mEffect->CanThrottle();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1172,28 +1172,17 @@ Animation::GetRenderedDocument() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Element* targetElement;
|
||||
nsCSSPseudoElements::Type pseudoType;
|
||||
mEffect->GetTarget(targetElement, pseudoType);
|
||||
if (!targetElement) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return targetElement->GetComposedDoc();
|
||||
return mEffect->GetRenderedDocument();
|
||||
}
|
||||
|
||||
nsPresContext*
|
||||
Animation::GetPresContext() const
|
||||
{
|
||||
nsIDocument* doc = GetRenderedDocument();
|
||||
if (!doc) {
|
||||
if (!mEffect) {
|
||||
return nullptr;
|
||||
}
|
||||
nsIPresShell* shell = doc->GetShell();
|
||||
if (!shell) {
|
||||
return nullptr;
|
||||
}
|
||||
return shell->GetPresContext();
|
||||
|
||||
return mEffect->GetPresContext();
|
||||
}
|
||||
|
||||
AnimationCollection*
|
||||
|
|
|
@ -295,6 +295,8 @@ public:
|
|||
|
||||
void NotifyEffectTimingUpdated();
|
||||
|
||||
AnimationCollection* GetCollection() const;
|
||||
|
||||
protected:
|
||||
void SilentlySetCurrentTime(const TimeDuration& aNewCurrentTime);
|
||||
void SilentlySetPlaybackRate(double aPlaybackRate);
|
||||
|
@ -355,7 +357,6 @@ protected:
|
|||
nsIDocument* GetRenderedDocument() const;
|
||||
nsPresContext* GetPresContext() const;
|
||||
virtual CommonAnimationManager* GetAnimationManager() const = 0;
|
||||
AnimationCollection* GetCollection() const;
|
||||
|
||||
RefPtr<AnimationTimeline> mTimeline;
|
||||
RefPtr<KeyframeEffectReadOnly> mEffect;
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
#include "mozilla/dom/KeyframeEffectBinding.h"
|
||||
#include "mozilla/dom/PropertyIndexedKeyframesBinding.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/LookAndFeel.h" // For LookAndFeel::GetInt
|
||||
#include "mozilla/StyleAnimationValue.h"
|
||||
#include "AnimationCommon.h"
|
||||
#include "Layers.h" // For Layer
|
||||
#include "nsCSSParser.h"
|
||||
#include "nsCSSPropertySet.h"
|
||||
#include "nsCSSProps.h" // For nsCSSProps::PropHasFlags
|
||||
|
@ -466,6 +468,19 @@ KeyframeEffectReadOnly::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
KeyframeEffectReadOnly::IsPropertyRunningOnCompositor(
|
||||
nsCSSProperty aProperty) const
|
||||
{
|
||||
const auto& info = LayerAnimationInfo::sRecords;
|
||||
for (size_t i = 0; i < ArrayLength(mIsPropertyRunningOnCompositor); i++) {
|
||||
if (info[i].mProperty == aProperty) {
|
||||
return mIsPropertyRunningOnCompositor[i];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
KeyframeEffectReadOnly::IsRunningOnCompositor() const
|
||||
{
|
||||
|
@ -1710,5 +1725,272 @@ KeyframeEffectReadOnly::GetFrames(JSContext*& aCx,
|
|||
}
|
||||
}
|
||||
|
||||
/* static */ const TimeDuration
|
||||
KeyframeEffectReadOnly::OverflowRegionRefreshInterval()
|
||||
{
|
||||
// The amount of time we can wait between updating throttled animations
|
||||
// on the main thread that influence the overflow region.
|
||||
static const TimeDuration kOverflowRegionRefreshInterval =
|
||||
TimeDuration::FromMilliseconds(200);
|
||||
|
||||
return kOverflowRegionRefreshInterval;
|
||||
}
|
||||
|
||||
bool
|
||||
KeyframeEffectReadOnly::CanThrottle() const
|
||||
{
|
||||
// Animation::CanThrottle checks for not in effect animations
|
||||
// before calling this.
|
||||
MOZ_ASSERT(IsInEffect(), "Effect should be in effect");
|
||||
|
||||
// Unthrottle if this animation is not current (i.e. it has passed the end).
|
||||
// In future we may be able to throttle this case too, but we should only get
|
||||
// occasional ticks while the animation is in this state so it doesn't matter
|
||||
// too much.
|
||||
if (!IsCurrent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIFrame* frame = GetAnimationFrame();
|
||||
if (!frame) {
|
||||
// There are two possible cases here.
|
||||
// a) No target element
|
||||
// b) The target element has no frame, e.g. because it is in a display:none
|
||||
// subtree.
|
||||
// In either case we can throttle the animation because there is no
|
||||
// need to update on the main thread.
|
||||
return true;
|
||||
}
|
||||
|
||||
// First we need to check layer generation and transform overflow
|
||||
// prior to the IsPropertyRunningOnCompositor check because we should
|
||||
// occasionally unthrottle these animations even if the animations are
|
||||
// already running on compositor.
|
||||
for (const LayerAnimationInfo::Record& record :
|
||||
LayerAnimationInfo::sRecords) {
|
||||
// Skip properties that are overridden in the cascade.
|
||||
// (GetAnimationOfProperty, as called by HasAnimationOfProperty,
|
||||
// only returns an animation if it currently wins in the cascade.)
|
||||
if (!HasAnimationOfProperty(record.mProperty)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AnimationCollection* collection = GetCollection();
|
||||
MOZ_ASSERT(collection,
|
||||
"CanThrottle should be called on an effect associated with an animation");
|
||||
layers::Layer* layer =
|
||||
FrameLayerBuilder::GetDedicatedLayer(frame, record.mLayerType);
|
||||
// Unthrottle if the layer needs to be brought up to date with the animation.
|
||||
if (!layer ||
|
||||
collection->mAnimationGeneration > layer->GetAnimationGeneration()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is a transform animation that affects the overflow region,
|
||||
// we should unthrottle the animation periodically.
|
||||
if (record.mProperty == eCSSProperty_transform &&
|
||||
!CanThrottleTransformChanges(*frame)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (!IsPropertyRunningOnCompositor(property.mProperty)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
KeyframeEffectReadOnly::CanThrottleTransformChanges(nsIFrame& aFrame) const
|
||||
{
|
||||
// If we know that the animation cannot cause overflow,
|
||||
// we can just disable flushes for this animation.
|
||||
|
||||
// If we don't show scrollbars, we don't care about overflow.
|
||||
if (LookAndFeel::GetInt(LookAndFeel::eIntID_ShowHideScrollbars) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
// CanThrottleTransformChanges is only called as part of a refresh driver tick
|
||||
// in which case we expect to has a pres context.
|
||||
MOZ_ASSERT(presContext);
|
||||
|
||||
TimeStamp now =
|
||||
presContext->RefreshDriver()->MostRecentRefresh();
|
||||
|
||||
AnimationCollection* collection = GetCollection();
|
||||
MOZ_ASSERT(collection,
|
||||
"CanThrottleTransformChanges should be involved with animation collection");
|
||||
TimeStamp styleRuleRefreshTime = collection->mStyleRuleRefreshTime;
|
||||
// If this animation can cause overflow, we can throttle some of the ticks.
|
||||
if (!styleRuleRefreshTime.IsNull() &&
|
||||
(now - styleRuleRefreshTime) < OverflowRegionRefreshInterval()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the nearest scrollable ancestor has overflow:hidden,
|
||||
// we don't care about overflow.
|
||||
nsIScrollableFrame* scrollable =
|
||||
nsLayoutUtils::GetNearestScrollableFrame(&aFrame);
|
||||
if (!scrollable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ScrollbarStyles ss = scrollable->GetScrollbarStyles();
|
||||
if (ss.mVertical == NS_STYLE_OVERFLOW_HIDDEN &&
|
||||
ss.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN &&
|
||||
scrollable->GetLogicalScrollPosition() == nsPoint(0, 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
KeyframeEffectReadOnly::GetAnimationFrame() const
|
||||
{
|
||||
if (!mTarget) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIFrame* frame = mTarget->GetPrimaryFrame();
|
||||
if (!frame) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mPseudoType == nsCSSPseudoElements::ePseudo_before) {
|
||||
frame = nsLayoutUtils::GetBeforeFrame(frame);
|
||||
} else if (mPseudoType == nsCSSPseudoElements::ePseudo_after) {
|
||||
frame = nsLayoutUtils::GetAfterFrame(frame);
|
||||
} else {
|
||||
MOZ_ASSERT(mPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement,
|
||||
"unknown mPseudoType");
|
||||
}
|
||||
if (!frame) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nsLayoutUtils::GetStyleFrame(frame);
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
KeyframeEffectReadOnly::GetRenderedDocument() const
|
||||
{
|
||||
if (!mTarget) {
|
||||
return nullptr;
|
||||
}
|
||||
return mTarget->GetComposedDoc();
|
||||
}
|
||||
|
||||
nsPresContext*
|
||||
KeyframeEffectReadOnly::GetPresContext() const
|
||||
{
|
||||
nsIDocument* doc = GetRenderedDocument();
|
||||
if (!doc) {
|
||||
return nullptr;
|
||||
}
|
||||
nsIPresShell* shell = doc->GetShell();
|
||||
if (!shell) {
|
||||
return nullptr;
|
||||
}
|
||||
return shell->GetPresContext();
|
||||
}
|
||||
|
||||
AnimationCollection *
|
||||
KeyframeEffectReadOnly::GetCollection() const
|
||||
{
|
||||
return mAnimation ? mAnimation->GetCollection() : nullptr;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
KeyframeEffectReadOnly::IsGeometricProperty(
|
||||
const nsCSSProperty aProperty)
|
||||
{
|
||||
switch (aProperty) {
|
||||
case eCSSProperty_bottom:
|
||||
case eCSSProperty_height:
|
||||
case eCSSProperty_left:
|
||||
case eCSSProperty_right:
|
||||
case eCSSProperty_top:
|
||||
case eCSSProperty_width:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
KeyframeEffectReadOnly::CanAnimateTransformOnCompositor(
|
||||
const nsIFrame* aFrame,
|
||||
const nsIContent* aContent)
|
||||
{
|
||||
if (aFrame->Combines3DTransformWithAncestors() ||
|
||||
aFrame->Extend3DContext()) {
|
||||
if (aContent) {
|
||||
nsCString message;
|
||||
message.AppendLiteral("Gecko bug: Async animation of 'preserve-3d' "
|
||||
"transforms is not supported. See bug 779598");
|
||||
AnimationCollection::LogAsyncAnimationFailure(message, aContent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Note that testing BackfaceIsHidden() is not a sufficient test for
|
||||
// what we need for animating backface-visibility correctly if we
|
||||
// remove the above test for Extend3DContext(); that would require
|
||||
// looking at backface-visibility on descendants as well.
|
||||
if (aFrame->StyleDisplay()->BackfaceIsHidden()) {
|
||||
if (aContent) {
|
||||
nsCString message;
|
||||
message.AppendLiteral("Gecko bug: Async animation of "
|
||||
"'backface-visibility: hidden' transforms is not supported."
|
||||
" See bug 1186204.");
|
||||
AnimationCollection::LogAsyncAnimationFailure(message, aContent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (aFrame->IsSVGTransformed()) {
|
||||
if (aContent) {
|
||||
nsCString message;
|
||||
message.AppendLiteral("Gecko bug: Async 'transform' animations of "
|
||||
"aFrames with SVG transforms is not supported. See bug 779599");
|
||||
AnimationCollection::LogAsyncAnimationFailure(message, aContent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
KeyframeEffectReadOnly::CanAnimatePropertyOnCompositor(
|
||||
const nsIFrame* aFrame,
|
||||
nsCSSProperty aProperty)
|
||||
{
|
||||
bool shouldLog = nsLayoutUtils::IsAnimationLoggingEnabled();
|
||||
|
||||
if (IsGeometricProperty(aProperty)) {
|
||||
if (shouldLog) {
|
||||
nsCString message;
|
||||
message.AppendLiteral("Performance warning: Async animation of "
|
||||
"'transform' or 'opacity' not possible due to animation of geometric"
|
||||
"properties on the same element");
|
||||
AnimationCollection::LogAsyncAnimationFailure(message,
|
||||
aFrame->GetContent());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (aProperty == eCSSProperty_transform) {
|
||||
if (!CanAnimateTransformOnCompositor(aFrame,
|
||||
shouldLog ? aFrame->GetContent() : nullptr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -25,9 +25,14 @@
|
|||
|
||||
struct JSContext;
|
||||
class nsCSSPropertySet;
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
class nsIFrame;
|
||||
class nsPresContext;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct AnimationCollection;
|
||||
class AnimValuesStyleRule;
|
||||
|
||||
namespace dom {
|
||||
|
@ -273,9 +278,22 @@ public:
|
|||
// Any updated properties are added to |aSetProperties|.
|
||||
void ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
|
||||
nsCSSPropertySet& aSetProperties);
|
||||
// Returns true if |aProperty| is currently being animated on compositor.
|
||||
bool IsPropertyRunningOnCompositor(nsCSSProperty aProperty) const;
|
||||
// Returns true if at least one property is being animated on compositor.
|
||||
bool IsRunningOnCompositor() const;
|
||||
void SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning);
|
||||
|
||||
bool CanThrottle() const;
|
||||
|
||||
// Returns true |aProperty| can be run on compositor for |aFrame|.
|
||||
static bool CanAnimatePropertyOnCompositor(const nsIFrame* aFrame,
|
||||
nsCSSProperty aProperty);
|
||||
nsIDocument* GetRenderedDocument() const;
|
||||
nsPresContext* GetPresContext() const;
|
||||
|
||||
inline AnimationCollection* GetCollection() const;
|
||||
|
||||
protected:
|
||||
virtual ~KeyframeEffectReadOnly();
|
||||
void ResetIsRunningOnCompositor();
|
||||
|
@ -307,6 +325,21 @@ protected:
|
|||
// restyle is performed, this member may temporarily become false even if
|
||||
// the animation remains on the layer after the restyle.
|
||||
bool mIsPropertyRunningOnCompositor[LayerAnimationInfo::kRecords];
|
||||
|
||||
private:
|
||||
nsIFrame* GetAnimationFrame() const;
|
||||
|
||||
bool CanThrottleTransformChanges(nsIFrame& aFrame) const;
|
||||
|
||||
// Returns true unless Gecko limitations prevent performing transform
|
||||
// animations for |aFrame|. Any limitations that are encountered are
|
||||
// logged using |aContent| to describe the affected content.
|
||||
// If |aContent| is nullptr, no logging is performed
|
||||
static bool CanAnimateTransformOnCompositor(const nsIFrame* aFrame,
|
||||
const nsIContent* aContent);
|
||||
static bool IsGeometricProperty(const nsCSSProperty aProperty);
|
||||
|
||||
static const TimeDuration OverflowRegionRefreshInterval();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -70,6 +70,64 @@ test(function(t) {
|
|||
}, 'Animation starts playing when its parent element is shown from ' +
|
||||
'"display:none" state');
|
||||
|
||||
test(function(t) {
|
||||
var div = addDiv(t, { style: 'animation: move 100s forwards' });
|
||||
assert_equals(div.getAnimations().length, 1,
|
||||
'display:initial element has animations');
|
||||
|
||||
var animation = div.getAnimations()[0];
|
||||
animation.finish();
|
||||
assert_equals(div.getAnimations().length, 1,
|
||||
'Element has finished animation if the animation ' +
|
||||
'fill-mode is forwards');
|
||||
|
||||
div.style.display = 'none';
|
||||
assert_equals(animation.playState, 'idle',
|
||||
'The animation.playState should be idle');
|
||||
|
||||
assert_equals(div.getAnimations().length, 0,
|
||||
'display:none element has no animations');
|
||||
|
||||
div.style.display = '';
|
||||
assert_equals(div.getAnimations().length, 1,
|
||||
'Element which is no longer display:none has animations ' +
|
||||
'again');
|
||||
assert_not_equals(div.getAnimations()[0], animation,
|
||||
'Restarted animation is a newly-generated animation');
|
||||
|
||||
}, 'Animation which has already finished starts playing when the element ' +
|
||||
'gets shown from "display:none" state');
|
||||
|
||||
test(function(t) {
|
||||
var parentElement = addDiv(t);
|
||||
var div = addDiv(t, { style: 'animation: move 100s forwards' });
|
||||
parentElement.appendChild(div);
|
||||
assert_equals(div.getAnimations().length, 1,
|
||||
'display:initial element has animations');
|
||||
|
||||
var animation = div.getAnimations()[0];
|
||||
animation.finish();
|
||||
assert_equals(div.getAnimations().length, 1,
|
||||
'Element has finished animation if the animation ' +
|
||||
'fill-mode is forwards');
|
||||
|
||||
parentElement.style.display = 'none';
|
||||
assert_equals(animation.playState, 'idle',
|
||||
'The animation.playState should be idle');
|
||||
assert_equals(div.getAnimations().length, 0,
|
||||
'Element in display:none subtree has no animations');
|
||||
|
||||
parentElement.style.display = '';
|
||||
assert_equals(div.getAnimations().length, 1,
|
||||
'Element which is no longer in display:none subtree has ' +
|
||||
'animations again');
|
||||
|
||||
assert_not_equals(div.getAnimations()[0], animation,
|
||||
'Restarted animation is a newly-generated animation');
|
||||
|
||||
}, 'Animation which has already finished starts playing when its parent ' +
|
||||
'element is shown from "display:none" state');
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -573,8 +573,6 @@ WebappsApplication.prototype = {
|
|||
|
||||
launch: function(aStartPoint) {
|
||||
let request = this.createRequest();
|
||||
this.addMessageListeners(["Webapps:Launch:Return:OK",
|
||||
"Webapps:Launch:Return:KO"]);
|
||||
cpmm.sendAsyncMessage("Webapps:Launch", { origin: this.origin,
|
||||
manifestURL: this.manifestURL,
|
||||
startPoint: aStartPoint || "",
|
||||
|
@ -582,6 +580,9 @@ WebappsApplication.prototype = {
|
|||
topId: this._topId,
|
||||
timestamp: Date.now(),
|
||||
requestID: this.getRequestId(request) });
|
||||
Services.obs.notifyObservers(null, "will-launch-app", null);
|
||||
this.addMessageListeners(["Webapps:Launch:Return:OK",
|
||||
"Webapps:Launch:Return:KO"]);
|
||||
return request;
|
||||
},
|
||||
|
||||
|
|
|
@ -1876,20 +1876,20 @@ Element::GetSMILOverrideStyle()
|
|||
return slots->mSMILOverrideStyle;
|
||||
}
|
||||
|
||||
css::StyleRule*
|
||||
Element::GetSMILOverrideStyleRule()
|
||||
css::Declaration*
|
||||
Element::GetSMILOverrideStyleDeclaration()
|
||||
{
|
||||
Element::nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
return slots ? slots->mSMILOverrideStyleRule.get() : nullptr;
|
||||
return slots ? slots->mSMILOverrideStyleDeclaration.get() : nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Element::SetSMILOverrideStyleRule(css::StyleRule* aStyleRule,
|
||||
bool aNotify)
|
||||
Element::SetSMILOverrideStyleDeclaration(css::Declaration* aDeclaration,
|
||||
bool aNotify)
|
||||
{
|
||||
Element::nsDOMSlots *slots = DOMSlots();
|
||||
|
||||
slots->mSMILOverrideStyleRule = aStyleRule;
|
||||
slots->mSMILOverrideStyleDeclaration = aDeclaration;
|
||||
|
||||
if (aNotify) {
|
||||
nsIDocument* doc = GetComposedDoc();
|
||||
|
@ -1924,18 +1924,18 @@ Element::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
|
|||
return false;
|
||||
}
|
||||
|
||||
css::StyleRule*
|
||||
Element::GetInlineStyleRule()
|
||||
css::Declaration*
|
||||
Element::GetInlineStyleDeclaration()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Element::SetInlineStyleRule(css::StyleRule* aStyleRule,
|
||||
const nsAString* aSerialized,
|
||||
bool aNotify)
|
||||
Element::SetInlineStyleDeclaration(css::Declaration* aDeclaration,
|
||||
const nsAString* aSerialized,
|
||||
bool aNotify)
|
||||
{
|
||||
NS_NOTYETIMPLEMENTED("Element::SetInlineStyleRule");
|
||||
NS_NOTYETIMPLEMENTED("Element::SetInlineStyleDeclaration");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -222,31 +222,31 @@ public:
|
|||
void ClearStyleStateLocks();
|
||||
|
||||
/**
|
||||
* Get the inline style rule, if any, for this element.
|
||||
* Get the inline style declaration, if any, for this element.
|
||||
*/
|
||||
virtual css::StyleRule* GetInlineStyleRule();
|
||||
virtual css::Declaration* GetInlineStyleDeclaration();
|
||||
|
||||
/**
|
||||
* Set the inline style rule for this element. This will send an appropriate
|
||||
* AttributeChanged notification if aNotify is true.
|
||||
* Set the inline style declaration for this element. This will send
|
||||
* an appropriate AttributeChanged notification if aNotify is true.
|
||||
*/
|
||||
virtual nsresult SetInlineStyleRule(css::StyleRule* aStyleRule,
|
||||
const nsAString* aSerialized,
|
||||
bool aNotify);
|
||||
virtual nsresult SetInlineStyleDeclaration(css::Declaration* aDeclaration,
|
||||
const nsAString* aSerialized,
|
||||
bool aNotify);
|
||||
|
||||
/**
|
||||
* Get the SMIL override style rule for this element. If the rule hasn't been
|
||||
* created, this method simply returns null.
|
||||
* Get the SMIL override style declaration for this element. If the
|
||||
* rule hasn't been created, this method simply returns null.
|
||||
*/
|
||||
virtual css::StyleRule* GetSMILOverrideStyleRule();
|
||||
virtual css::Declaration* GetSMILOverrideStyleDeclaration();
|
||||
|
||||
/**
|
||||
* Set the SMIL override style rule for this element. If aNotify is true, this
|
||||
* method will notify the document's pres context, so that the style changes
|
||||
* will be noticed.
|
||||
* Set the SMIL override style declaration for this element. If
|
||||
* aNotify is true, this method will notify the document's pres
|
||||
* context, so that the style changes will be noticed.
|
||||
*/
|
||||
virtual nsresult SetSMILOverrideStyleRule(css::StyleRule* aStyleRule,
|
||||
bool aNotify);
|
||||
virtual nsresult SetSMILOverrideStyleDeclaration(css::Declaration* aDeclaration,
|
||||
bool aNotify);
|
||||
|
||||
/**
|
||||
* Returns a new nsISMILAttr that allows the caller to animate the given
|
||||
|
|
|
@ -614,7 +614,7 @@ FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) c
|
|||
// - mStyle
|
||||
// - mDataSet
|
||||
// - mSMILOverrideStyle
|
||||
// - mSMILOverrideStyleRule
|
||||
// - mSMILOverrideStyleDeclaration
|
||||
// - mChildrenList
|
||||
// - mClassList
|
||||
|
||||
|
|
|
@ -286,9 +286,9 @@ public:
|
|||
nsCOMPtr<nsICSSDeclaration> mSMILOverrideStyle;
|
||||
|
||||
/**
|
||||
* Holds any SMIL override style rules for this element.
|
||||
* Holds any SMIL override style declaration for this element.
|
||||
*/
|
||||
RefPtr<mozilla::css::StyleRule> mSMILOverrideStyleRule;
|
||||
RefPtr<mozilla::css::Declaration> mSMILOverrideStyleDeclaration;
|
||||
|
||||
/**
|
||||
* An object implementing nsIDOMMozNamedAttrMap for this content (attributes)
|
||||
|
|
|
@ -2253,7 +2253,7 @@ Navigator::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
|||
|
||||
JS::Rooted<JSObject*> naviObj(aCx,
|
||||
js::CheckedUnwrap(aObject,
|
||||
/* stopAtOuter = */ false));
|
||||
/* stopAtWindowProxy = */ false));
|
||||
if (!naviObj) {
|
||||
return Throw(aCx, NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "nsIAtom.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/css/StyleRule.h"
|
||||
#include "mozilla/css/Declaration.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
|
@ -73,13 +72,13 @@ void
|
|||
MiscContainer::Cache()
|
||||
{
|
||||
// Not implemented for anything else yet.
|
||||
MOZ_ASSERT(mType == nsAttrValue::eCSSStyleRule);
|
||||
MOZ_ASSERT(mType == nsAttrValue::eCSSDeclaration);
|
||||
MOZ_ASSERT(IsRefCounted());
|
||||
MOZ_ASSERT(mValue.mRefCount > 0);
|
||||
MOZ_ASSERT(!mValue.mCached);
|
||||
|
||||
css::StyleRule* rule = mValue.mCSSStyleRule;
|
||||
nsHTMLCSSStyleSheet* sheet = rule->GetHTMLCSSStyleSheet();
|
||||
css::Declaration* declaration = mValue.mCSSDeclaration;
|
||||
nsHTMLCSSStyleSheet* sheet = declaration->GetHTMLCSSStyleSheet();
|
||||
if (!sheet) {
|
||||
return;
|
||||
}
|
||||
|
@ -94,17 +93,14 @@ MiscContainer::Cache()
|
|||
mValue.mCached = 1;
|
||||
|
||||
// This has to be immutable once it goes into the cache.
|
||||
css::Declaration* decl = rule->GetDeclaration();
|
||||
if (decl) {
|
||||
decl->SetImmutable();
|
||||
}
|
||||
declaration->SetImmutable();
|
||||
}
|
||||
|
||||
void
|
||||
MiscContainer::Evict()
|
||||
{
|
||||
// Not implemented for anything else yet.
|
||||
MOZ_ASSERT(mType == nsAttrValue::eCSSStyleRule);
|
||||
MOZ_ASSERT(mType == nsAttrValue::eCSSDeclaration);
|
||||
MOZ_ASSERT(IsRefCounted());
|
||||
MOZ_ASSERT(mValue.mRefCount == 0);
|
||||
|
||||
|
@ -112,8 +108,8 @@ MiscContainer::Evict()
|
|||
return;
|
||||
}
|
||||
|
||||
css::StyleRule* rule = mValue.mCSSStyleRule;
|
||||
nsHTMLCSSStyleSheet* sheet = rule->GetHTMLCSSStyleSheet();
|
||||
css::Declaration* declaration = mValue.mCSSDeclaration;
|
||||
nsHTMLCSSStyleSheet* sheet = declaration->GetHTMLCSSStyleSheet();
|
||||
MOZ_ASSERT(sheet);
|
||||
|
||||
nsString str;
|
||||
|
@ -149,7 +145,7 @@ nsAttrValue::nsAttrValue(nsIAtom* aValue)
|
|||
SetTo(aValue);
|
||||
}
|
||||
|
||||
nsAttrValue::nsAttrValue(css::StyleRule* aValue, const nsAString* aSerialized)
|
||||
nsAttrValue::nsAttrValue(css::Declaration* aValue, const nsAString* aSerialized)
|
||||
: mBits(0)
|
||||
{
|
||||
SetTo(aValue, aSerialized);
|
||||
|
@ -314,7 +310,7 @@ nsAttrValue::SetTo(const nsAttrValue& aOther)
|
|||
cont->mValue.mColor = otherCont->mValue.mColor;
|
||||
break;
|
||||
}
|
||||
case eCSSStyleRule:
|
||||
case eCSSDeclaration:
|
||||
{
|
||||
MOZ_CRASH("These should be refcounted!");
|
||||
}
|
||||
|
@ -421,12 +417,12 @@ nsAttrValue::SetTo(double aValue, const nsAString* aSerialized)
|
|||
}
|
||||
|
||||
void
|
||||
nsAttrValue::SetTo(css::StyleRule* aValue, const nsAString* aSerialized)
|
||||
nsAttrValue::SetTo(css::Declaration* aValue, const nsAString* aSerialized)
|
||||
{
|
||||
MiscContainer* cont = EnsureEmptyMiscContainer();
|
||||
MOZ_ASSERT(cont->mValue.mRefCount == 0);
|
||||
NS_ADDREF(cont->mValue.mCSSStyleRule = aValue);
|
||||
cont->mType = eCSSStyleRule;
|
||||
NS_ADDREF(cont->mValue.mCSSDeclaration = aValue);
|
||||
cont->mType = eCSSDeclaration;
|
||||
NS_ADDREF(cont);
|
||||
SetMiscAtomOrString(aSerialized);
|
||||
MOZ_ASSERT(cont->mValue.mRefCount == 1);
|
||||
|
@ -639,12 +635,11 @@ nsAttrValue::ToString(nsAString& aResult) const
|
|||
|
||||
break;
|
||||
}
|
||||
case eCSSStyleRule:
|
||||
case eCSSDeclaration:
|
||||
{
|
||||
aResult.Truncate();
|
||||
MiscContainer *container = GetMiscContainer();
|
||||
css::Declaration *decl =
|
||||
container->mValue.mCSSStyleRule->GetDeclaration();
|
||||
css::Declaration *decl = container->mValue.mCSSDeclaration;
|
||||
if (decl) {
|
||||
decl->ToString(aResult);
|
||||
}
|
||||
|
@ -889,9 +884,9 @@ nsAttrValue::HashValue() const
|
|||
{
|
||||
return cont->mValue.mColor;
|
||||
}
|
||||
case eCSSStyleRule:
|
||||
case eCSSDeclaration:
|
||||
{
|
||||
return NS_PTR_TO_INT32(cont->mValue.mCSSStyleRule);
|
||||
return NS_PTR_TO_INT32(cont->mValue.mCSSDeclaration);
|
||||
}
|
||||
// Intentionally identical, so that loading the image does not change the
|
||||
// hash code.
|
||||
|
@ -998,9 +993,10 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const
|
|||
}
|
||||
break;
|
||||
}
|
||||
case eCSSStyleRule:
|
||||
case eCSSDeclaration:
|
||||
{
|
||||
return thisCont->mValue.mCSSStyleRule == otherCont->mValue.mCSSStyleRule;
|
||||
return thisCont->mValue.mCSSDeclaration ==
|
||||
otherCont->mValue.mCSSDeclaration;
|
||||
}
|
||||
case eURL:
|
||||
{
|
||||
|
@ -1690,13 +1686,12 @@ nsAttrValue::ParseStyleAttribute(const nsAString& aString,
|
|||
css::Loader* cssLoader = ownerDoc->CSSLoader();
|
||||
nsCSSParser cssParser(cssLoader);
|
||||
|
||||
RefPtr<css::StyleRule> rule;
|
||||
cssParser.ParseStyleAttribute(aString, docURI, baseURI,
|
||||
aElement->NodePrincipal(),
|
||||
getter_AddRefs(rule));
|
||||
if (rule) {
|
||||
rule->SetHTMLCSSStyleSheet(sheet);
|
||||
SetTo(rule, &aString);
|
||||
RefPtr<css::Declaration> declaration =
|
||||
cssParser.ParseStyleAttribute(aString, docURI, baseURI,
|
||||
aElement->NodePrincipal());
|
||||
if (declaration) {
|
||||
declaration->SetHTMLCSSStyleSheet(sheet);
|
||||
SetTo(declaration, &aString);
|
||||
if (cachingAllowed) {
|
||||
MiscContainer* cont = GetMiscContainer();
|
||||
cont->Cache();
|
||||
|
@ -1716,13 +1711,13 @@ nsAttrValue::SetMiscAtomOrString(const nsAString* aValue)
|
|||
"Trying to re-set atom or string!");
|
||||
if (aValue) {
|
||||
uint32_t len = aValue->Length();
|
||||
// * We're allowing eCSSStyleRule attributes to store empty strings as it
|
||||
// * We're allowing eCSSDeclaration attributes to store empty strings as it
|
||||
// can be beneficial to store an empty style attribute as a parsed rule.
|
||||
// * We're allowing enumerated values because sometimes the empty
|
||||
// string corresponds to a particular enumerated value, especially
|
||||
// for enumerated values that are not limited enumerated.
|
||||
// Add other types as needed.
|
||||
NS_ASSERTION(len || Type() == eCSSStyleRule || Type() == eEnum,
|
||||
NS_ASSERTION(len || Type() == eCSSDeclaration || Type() == eEnum,
|
||||
"Empty string?");
|
||||
MiscContainer* cont = GetMiscContainer();
|
||||
if (len <= NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM) {
|
||||
|
@ -1786,12 +1781,12 @@ nsAttrValue::ClearMiscContainer()
|
|||
}
|
||||
else {
|
||||
switch (cont->mType) {
|
||||
case eCSSStyleRule:
|
||||
case eCSSDeclaration:
|
||||
{
|
||||
MOZ_ASSERT(cont->mValue.mRefCount == 1);
|
||||
cont->Release();
|
||||
cont->Evict();
|
||||
NS_RELEASE(cont->mValue.mCSSStyleRule);
|
||||
NS_RELEASE(cont->mValue.mCSSDeclaration);
|
||||
break;
|
||||
}
|
||||
case eURL:
|
||||
|
@ -1927,10 +1922,10 @@ nsAttrValue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
|||
n += str ? str->SizeOfIncludingThisIfUnshared(aMallocSizeOf) : 0;
|
||||
}
|
||||
|
||||
if (Type() == eCSSStyleRule && container->mValue.mCSSStyleRule) {
|
||||
// TODO: mCSSStyleRule might be owned by another object which would
|
||||
if (Type() == eCSSDeclaration && container->mValue.mCSSDeclaration) {
|
||||
// TODO: mCSSDeclaration might be owned by another object which would
|
||||
// make us count them twice, bug 677493.
|
||||
//n += container->mCSSStyleRule->SizeOfIncludingThis(aMallocSizeOf);
|
||||
//n += container->mCSSDeclaration->SizeOfIncludingThis(aMallocSizeOf);
|
||||
} else if (Type() == eAtomArray && container->mValue.mAtomArray) {
|
||||
// Don't measure each nsIAtom, they are measured separatly.
|
||||
n += container->mValue.mAtomArray->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
||||
|
|
|
@ -35,7 +35,7 @@ struct MiscContainer;
|
|||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
class StyleRule;
|
||||
class Declaration;
|
||||
struct URLValue;
|
||||
struct ImageValue;
|
||||
} // namespace css
|
||||
|
@ -94,7 +94,7 @@ public:
|
|||
ePercent = 0x0F, // 1111
|
||||
// Values below here won't matter, they'll be always stored in the 'misc'
|
||||
// struct.
|
||||
eCSSStyleRule = 0x10
|
||||
eCSSDeclaration = 0x10
|
||||
,eURL = 0x11
|
||||
,eImage = 0x12
|
||||
,eAtomArray = 0x13
|
||||
|
@ -120,7 +120,7 @@ public:
|
|||
nsAttrValue(const nsAttrValue& aOther);
|
||||
explicit nsAttrValue(const nsAString& aValue);
|
||||
explicit nsAttrValue(nsIAtom* aValue);
|
||||
nsAttrValue(mozilla::css::StyleRule* aValue, const nsAString* aSerialized);
|
||||
nsAttrValue(mozilla::css::Declaration* aValue, const nsAString* aSerialized);
|
||||
explicit nsAttrValue(const nsIntMargin& aValue);
|
||||
~nsAttrValue();
|
||||
|
||||
|
@ -145,7 +145,7 @@ public:
|
|||
void SetTo(int16_t aInt);
|
||||
void SetTo(int32_t aInt, const nsAString* aSerialized);
|
||||
void SetTo(double aValue, const nsAString* aSerialized);
|
||||
void SetTo(mozilla::css::StyleRule* aValue, const nsAString* aSerialized);
|
||||
void SetTo(mozilla::css::Declaration* aValue, const nsAString* aSerialized);
|
||||
void SetTo(mozilla::css::URLValue* aValue, const nsAString* aSerialized);
|
||||
void SetTo(const nsIntMargin& aValue);
|
||||
void SetTo(const nsSVGAngle& aValue, const nsAString* aSerialized);
|
||||
|
@ -196,7 +196,7 @@ public:
|
|||
inline int16_t GetEnumValue() const;
|
||||
inline float GetPercentValue() const;
|
||||
inline AtomArray* GetAtomArrayValue() const;
|
||||
inline mozilla::css::StyleRule* GetCSSStyleRuleValue() const;
|
||||
inline mozilla::css::Declaration* GetCSSDeclarationValue() const;
|
||||
inline mozilla::css::URLValue* GetURLValue() const;
|
||||
inline mozilla::css::ImageValue* GetImageValue() const;
|
||||
inline double GetDoubleValue() const;
|
||||
|
|
|
@ -20,7 +20,7 @@ struct MiscContainer final
|
|||
|
||||
ValueType mType;
|
||||
// mStringBits points to either nsIAtom* or nsStringBuffer* and is used when
|
||||
// mType isn't mCSSStyleRule.
|
||||
// mType isn't eCSSDeclaration.
|
||||
// Note eStringBase and eAtomBase is used also to handle the type of
|
||||
// mStringBits.
|
||||
uintptr_t mStringBits;
|
||||
|
@ -31,7 +31,7 @@ struct MiscContainer final
|
|||
nscolor mColor;
|
||||
uint32_t mEnumValue;
|
||||
int32_t mPercent;
|
||||
mozilla::css::StyleRule* mCSSStyleRule;
|
||||
mozilla::css::Declaration* mCSSDeclaration;
|
||||
mozilla::css::URLValue* mURL;
|
||||
mozilla::css::ImageValue* mImage;
|
||||
nsAttrValue::AtomArray* mAtomArray;
|
||||
|
@ -86,7 +86,7 @@ public:
|
|||
// Nothing stops us from refcounting (and sharing) other types of
|
||||
// MiscContainer (except eDoubleValue types) but there's no compelling
|
||||
// reason to
|
||||
return mType == nsAttrValue::eCSSStyleRule;
|
||||
return mType == nsAttrValue::eCSSDeclaration;
|
||||
}
|
||||
|
||||
inline int32_t AddRef() {
|
||||
|
@ -146,11 +146,11 @@ nsAttrValue::GetAtomArrayValue() const
|
|||
return GetMiscContainer()->mValue.mAtomArray;
|
||||
}
|
||||
|
||||
inline mozilla::css::StyleRule*
|
||||
nsAttrValue::GetCSSStyleRuleValue() const
|
||||
inline mozilla::css::Declaration*
|
||||
nsAttrValue::GetCSSDeclarationValue() const
|
||||
{
|
||||
NS_PRECONDITION(Type() == eCSSStyleRule, "wrong type");
|
||||
return GetMiscContainer()->mValue.mCSSStyleRule;
|
||||
NS_PRECONDITION(Type() == eCSSDeclaration, "wrong type");
|
||||
return GetMiscContainer()->mValue.mCSSDeclaration;
|
||||
}
|
||||
|
||||
inline mozilla::css::URLValue*
|
||||
|
@ -198,7 +198,7 @@ nsAttrValue::StoresOwnData() const
|
|||
return true;
|
||||
}
|
||||
ValueType t = Type();
|
||||
return t != eCSSStyleRule && !IsSVGType(t);
|
||||
return t != eCSSDeclaration && !IsSVGType(t);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
|
|
@ -127,6 +127,7 @@ class ContentPermissionRequestParent : public PContentPermissionRequestParent
|
|||
private:
|
||||
virtual bool Recvprompt();
|
||||
virtual bool RecvNotifyVisibility(const bool& aIsVisible);
|
||||
virtual bool RecvDestroy();
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
};
|
||||
|
||||
|
@ -167,6 +168,13 @@ ContentPermissionRequestParent::RecvNotifyVisibility(const bool& aIsVisible)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentPermissionRequestParent::RecvDestroy()
|
||||
{
|
||||
Unused << PContentPermissionRequestParent::Send__delete__(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ContentPermissionRequestParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
|
@ -301,6 +309,14 @@ ContentPermissionRequestParentMap()
|
|||
return sPermissionRequestParentMap;
|
||||
}
|
||||
|
||||
static std::map<PContentPermissionRequestChild*, TabId>&
|
||||
ContentPermissionRequestChildMap()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
static std::map<PContentPermissionRequestChild*, TabId> sPermissionRequestChildMap;
|
||||
return sPermissionRequestChildMap;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsContentPermissionUtils::CreatePermissionArray(const nsACString& aType,
|
||||
const nsACString& aAccess,
|
||||
|
@ -364,6 +380,7 @@ nsContentPermissionUtils::AskPermission(nsIContentPermissionRequest* aRequest, n
|
|||
permArray,
|
||||
IPC::Principal(principal),
|
||||
child->GetTabId());
|
||||
ContentPermissionRequestChildMap()[req.get()] = child->GetTabId();
|
||||
|
||||
req->Sendprompt();
|
||||
return NS_OK;
|
||||
|
@ -403,6 +420,29 @@ nsContentPermissionUtils::NotifyRemoveContentPermissionRequestParent(
|
|||
ContentPermissionRequestParentMap().erase(it);
|
||||
}
|
||||
|
||||
/* static */ nsTArray<PContentPermissionRequestChild*>
|
||||
nsContentPermissionUtils::GetContentPermissionRequestChildById(const TabId& aTabId)
|
||||
{
|
||||
nsTArray<PContentPermissionRequestChild*> childArray;
|
||||
for (auto& it : ContentPermissionRequestChildMap()) {
|
||||
if (it.second == aTabId) {
|
||||
childArray.AppendElement(it.first);
|
||||
}
|
||||
}
|
||||
|
||||
return Move(childArray);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentPermissionUtils::NotifyRemoveContentPermissionRequestChild(
|
||||
PContentPermissionRequestChild* aChild)
|
||||
{
|
||||
auto it = ContentPermissionRequestChildMap().find(aChild);
|
||||
MOZ_ASSERT(it != ContentPermissionRequestChildMap().end());
|
||||
|
||||
ContentPermissionRequestChildMap().erase(it);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsContentPermissionRequester, nsIContentPermissionRequester)
|
||||
|
||||
nsContentPermissionRequester::nsContentPermissionRequester(nsPIDOMWindow* aWindow)
|
||||
|
@ -609,7 +649,7 @@ nsContentPermissionRequestProxy::Cancel()
|
|||
|
||||
nsTArray<PermissionChoice> emptyChoices;
|
||||
|
||||
Unused << ContentPermissionRequestParent::Send__delete__(mParent, false, emptyChoices);
|
||||
Unused << mParent->SendNotifyResult(false, emptyChoices);
|
||||
mParent = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -678,7 +718,7 @@ nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
Unused << ContentPermissionRequestParent::Send__delete__(mParent, true, choices);
|
||||
Unused << mParent->SendNotifyResult(true, choices);
|
||||
mParent = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -711,6 +751,7 @@ RemotePermissionRequest::RemotePermissionRequest(
|
|||
: mRequest(aRequest)
|
||||
, mWindow(aWindow)
|
||||
, mIPCOpen(false)
|
||||
, mDestroyed(false)
|
||||
{
|
||||
mListener = new VisibilityChangeListener(mWindow);
|
||||
mListener->SetCallback(this);
|
||||
|
@ -732,11 +773,10 @@ RemotePermissionRequest::DoAllow(JS::HandleValue aChoices)
|
|||
|
||||
// PContentPermissionRequestChild
|
||||
bool
|
||||
RemotePermissionRequest::Recv__delete__(const bool& aAllow,
|
||||
InfallibleTArray<PermissionChoice>&& aChoices)
|
||||
RemotePermissionRequest::RecvNotifyResult(const bool& aAllow,
|
||||
InfallibleTArray<PermissionChoice>&& aChoices)
|
||||
{
|
||||
mListener->RemoveListener();
|
||||
mListener = nullptr;
|
||||
Destroy();
|
||||
|
||||
if (aAllow && mWindow->IsCurrentInnerWindow()) {
|
||||
// Use 'undefined' if no choice is provided.
|
||||
|
@ -786,10 +826,22 @@ RemotePermissionRequest::RecvGetVisibility()
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
RemotePermissionRequest::Destroy()
|
||||
{
|
||||
if (!IPCOpen()) {
|
||||
return;
|
||||
}
|
||||
Unused << this->SendDestroy();
|
||||
mListener->RemoveListener();
|
||||
mListener = nullptr;
|
||||
mDestroyed = true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RemotePermissionRequest::NotifyVisibility(bool isVisible)
|
||||
{
|
||||
if (!mIPCOpen) {
|
||||
if (!IPCOpen()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,12 @@ public:
|
|||
|
||||
static void
|
||||
NotifyRemoveContentPermissionRequestParent(PContentPermissionRequestParent* aParent);
|
||||
|
||||
static nsTArray<PContentPermissionRequestChild*>
|
||||
GetContentPermissionRequestChildById(const TabId& aTabId);
|
||||
|
||||
static void
|
||||
NotifyRemoveContentPermissionRequestChild(PContentPermissionRequestChild* aChild);
|
||||
};
|
||||
|
||||
class nsContentPermissionRequester final : public nsIContentPermissionRequester
|
||||
|
@ -188,8 +194,8 @@ public:
|
|||
nsPIDOMWindow* aWindow);
|
||||
|
||||
// It will be called when prompt dismissed.
|
||||
virtual bool Recv__delete__(const bool &aAllow,
|
||||
InfallibleTArray<PermissionChoice>&& aChoices) override;
|
||||
virtual bool RecvNotifyResult(const bool &aAllow,
|
||||
InfallibleTArray<PermissionChoice>&& aChoices) override;
|
||||
|
||||
virtual bool RecvGetVisibility() override;
|
||||
|
||||
|
@ -205,6 +211,10 @@ public:
|
|||
Release();
|
||||
}
|
||||
|
||||
void Destroy();
|
||||
|
||||
bool IPCOpen() const { return mIPCOpen && !mDestroyed; }
|
||||
|
||||
private:
|
||||
virtual ~RemotePermissionRequest()
|
||||
{
|
||||
|
@ -217,6 +227,7 @@ private:
|
|||
nsCOMPtr<nsIContentPermissionRequest> mRequest;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
bool mIPCOpen;
|
||||
bool mDestroyed;
|
||||
RefPtr<VisibilityChangeListener> mListener;
|
||||
};
|
||||
|
||||
|
|
|
@ -1513,7 +1513,7 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
|
|||
NS_ASSERTION(dom_obj, "nsDOMConstructor::HasInstance couldn't get object");
|
||||
|
||||
// This might not be the right object, if there are wrappers. Unwrap if we can.
|
||||
JSObject *wrapped_obj = js::CheckedUnwrap(dom_obj, /* stopAtOuter = */ false);
|
||||
JSObject *wrapped_obj = js::CheckedUnwrap(dom_obj, /* stopAtWindowProxy = */ false);
|
||||
if (wrapped_obj)
|
||||
dom_obj = wrapped_obj;
|
||||
|
||||
|
@ -2042,7 +2042,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
|||
// way the callee can decide whether to allow access based on the caller
|
||||
// or the window being touched.
|
||||
JS::Rooted<JSObject*> global(cx,
|
||||
js::CheckedUnwrap(obj, /* stopAtOuter = */ false));
|
||||
js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false));
|
||||
if (!global) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
|
|
@ -335,57 +335,6 @@ nsIdentifierMapEntry::RemoveContentChangeCallback(nsIDocument::IDTargetObserver
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
static PLDHashOperator
|
||||
CustomDefinitionsTraverse(CustomElementHashKey* aKey,
|
||||
CustomElementDefinition* aDefinition,
|
||||
void* aArg)
|
||||
{
|
||||
nsCycleCollectionTraversalCallback* cb =
|
||||
static_cast<nsCycleCollectionTraversalCallback*>(aArg);
|
||||
|
||||
nsAutoPtr<LifecycleCallbacks>& callbacks = aDefinition->mCallbacks;
|
||||
|
||||
if (callbacks->mAttributeChangedCallback.WasPassed()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
|
||||
"mCustomDefinitions->mCallbacks->mAttributeChangedCallback");
|
||||
cb->NoteXPCOMChild(aDefinition->mCallbacks->mAttributeChangedCallback.Value());
|
||||
}
|
||||
|
||||
if (callbacks->mCreatedCallback.WasPassed()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
|
||||
"mCustomDefinitions->mCallbacks->mCreatedCallback");
|
||||
cb->NoteXPCOMChild(aDefinition->mCallbacks->mCreatedCallback.Value());
|
||||
}
|
||||
|
||||
if (callbacks->mAttachedCallback.WasPassed()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
|
||||
"mCustomDefinitions->mCallbacks->mAttachedCallback");
|
||||
cb->NoteXPCOMChild(aDefinition->mCallbacks->mAttachedCallback.Value());
|
||||
}
|
||||
|
||||
if (callbacks->mDetachedCallback.WasPassed()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
|
||||
"mCustomDefinitions->mCallbacks->mDetachedCallback");
|
||||
cb->NoteXPCOMChild(aDefinition->mCallbacks->mDetachedCallback.Value());
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
CandidatesTraverse(CustomElementHashKey* aKey,
|
||||
nsTArray<RefPtr<Element>>* aData,
|
||||
void* aArg)
|
||||
{
|
||||
nsCycleCollectionTraversalCallback *cb =
|
||||
static_cast<nsCycleCollectionTraversalCallback*>(aArg);
|
||||
for (size_t i = 0; i < aData->Length(); ++i) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mCandidatesMap->Element");
|
||||
cb->NoteXPCOMChild(aData->ElementAt(i));
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Registry)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Registry)
|
||||
|
@ -397,8 +346,40 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Registry)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Registry)
|
||||
tmp->mCustomDefinitions.EnumerateRead(CustomDefinitionsTraverse, &cb);
|
||||
tmp->mCandidatesMap.EnumerateRead(CandidatesTraverse, &cb);
|
||||
for (auto iter = tmp->mCustomDefinitions.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsAutoPtr<LifecycleCallbacks>& callbacks = iter.UserData()->mCallbacks;
|
||||
|
||||
if (callbacks->mAttributeChangedCallback.WasPassed()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
|
||||
"mCustomDefinitions->mCallbacks->mAttributeChangedCallback");
|
||||
cb.NoteXPCOMChild(callbacks->mAttributeChangedCallback.Value());
|
||||
}
|
||||
|
||||
if (callbacks->mCreatedCallback.WasPassed()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
|
||||
"mCustomDefinitions->mCallbacks->mCreatedCallback");
|
||||
cb.NoteXPCOMChild(callbacks->mCreatedCallback.Value());
|
||||
}
|
||||
|
||||
if (callbacks->mAttachedCallback.WasPassed()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
|
||||
"mCustomDefinitions->mCallbacks->mAttachedCallback");
|
||||
cb.NoteXPCOMChild(callbacks->mAttachedCallback.Value());
|
||||
}
|
||||
|
||||
if (callbacks->mDetachedCallback.WasPassed()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
|
||||
"mCustomDefinitions->mCallbacks->mDetachedCallback");
|
||||
cb.NoteXPCOMChild(callbacks->mDetachedCallback.Value());
|
||||
}
|
||||
}
|
||||
for (auto iter = tmp->mCandidatesMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsTArray<RefPtr<Element>>* elems = iter.UserData();
|
||||
for (size_t i = 0; i < elems->Length(); ++i) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCandidatesMap->Element");
|
||||
cb.NoteXPCOMChild(elems->ElementAt(i));
|
||||
}
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
@ -962,38 +943,26 @@ nsExternalResourceMap::Traverse(nsCycleCollectionTraversalCallback* aCallback) c
|
|||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
ExternalResourceHider(nsIURI* aKey,
|
||||
nsExternalResourceMap::ExternalResource* aData,
|
||||
void* aClosure)
|
||||
{
|
||||
if (aData->mViewer) {
|
||||
aData->mViewer->Hide();
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsExternalResourceMap::HideViewers()
|
||||
{
|
||||
mMap.EnumerateRead(ExternalResourceHider, nullptr);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
ExternalResourceShower(nsIURI* aKey,
|
||||
nsExternalResourceMap::ExternalResource* aData,
|
||||
void* aClosure)
|
||||
{
|
||||
if (aData->mViewer) {
|
||||
aData->mViewer->Show();
|
||||
for (auto iter = mMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCOMPtr<nsIContentViewer> viewer = iter.UserData()->mViewer;
|
||||
if (viewer) {
|
||||
viewer->Hide();
|
||||
}
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsExternalResourceMap::ShowViewers()
|
||||
{
|
||||
mMap.EnumerateRead(ExternalResourceShower, nullptr);
|
||||
for (auto iter = mMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCOMPtr<nsIContentViewer> viewer = iter.UserData()->mViewer;
|
||||
if (viewer) {
|
||||
viewer->Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -729,8 +729,6 @@ const js::Class OuterWindowProxyClass =
|
|||
"Proxy",
|
||||
0, /* additional class flags */
|
||||
PROXY_MAKE_EXT(
|
||||
nullptr, /* outerObject */
|
||||
js::proxy_innerObject,
|
||||
false, /* isWrappedNative */
|
||||
nsOuterWindowProxy::ObjectMoved
|
||||
));
|
||||
|
@ -1102,8 +1100,7 @@ NewOuterWindowProxy(JSContext *cx, JS::Handle<JSObject*> global, bool isChrome)
|
|||
isChrome ? &nsChromeOuterWindowProxy::singleton
|
||||
: &nsOuterWindowProxy::singleton,
|
||||
options);
|
||||
|
||||
NS_ASSERTION(js::GetObjectClass(obj)->ext.innerObject, "bad class");
|
||||
MOZ_ASSERT_IF(obj, js::IsWindowProxy(obj));
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -2036,40 +2033,6 @@ nsGlobalWindow::TraceGlobalJSObject(JSTracer* aTrc)
|
|||
TraceWrapper(aTrc, "active window global");
|
||||
}
|
||||
|
||||
/* static */
|
||||
JSObject*
|
||||
nsGlobalWindow::OuterObject(JSContext* aCx, JS::Handle<JSObject*> aObj)
|
||||
{
|
||||
nsGlobalWindow* origWin = UnwrapDOMObject<nsGlobalWindow>(aObj);
|
||||
nsGlobalWindow* win = origWin->GetOuterWindowInternal();
|
||||
|
||||
if (!win) {
|
||||
// If we no longer have an outer window. No code should ever be
|
||||
// running on a window w/o an outer, which means this hook should
|
||||
// never be called when we have no outer. But just in case, return
|
||||
// null to prevent leaking an inner window to code in a different
|
||||
// window.
|
||||
NS_WARNING("nsGlobalWindow::OuterObject shouldn't fail!");
|
||||
Throw(aCx, NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> winObj(aCx, win->FastGetGlobalJSObject());
|
||||
MOZ_ASSERT(winObj);
|
||||
|
||||
// Note that while |wrapper| is same-compartment with cx, the outer window
|
||||
// might not be. If we're running script in an inactive scope and evalute
|
||||
// |this|, the outer window is actually a cross-compartment wrapper. So we
|
||||
// need to wrap here.
|
||||
if (!JS_WrapObject(aCx, &winObj)) {
|
||||
NS_WARNING("nsGlobalWindow::OuterObject shouldn't fail!");
|
||||
Throw(aCx, NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return winObj;
|
||||
}
|
||||
|
||||
bool
|
||||
nsGlobalWindow::WouldReuseInnerWindow(nsIDocument* aNewDocument)
|
||||
{
|
||||
|
@ -2659,6 +2622,11 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
// Enter the new global's compartment.
|
||||
JSAutoCompartment ac(cx, GetWrapperPreserveColor());
|
||||
|
||||
{
|
||||
JS::Rooted<JSObject*> outer(cx, GetWrapperPreserveColor());
|
||||
js::SetWindowProxy(cx, newInnerGlobal, outer);
|
||||
}
|
||||
|
||||
// Set scriptability based on the state of the docshell.
|
||||
bool allow = GetDocShell()->GetCanExecuteScripts();
|
||||
xpc::Scriptability::Get(GetWrapperPreserveColor()).SetDocShellAllowsScript(allow);
|
||||
|
@ -4506,7 +4474,7 @@ nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
|||
nsPIDOMWindow* win = nullptr;
|
||||
if (aOpener.isObject()) {
|
||||
JSObject* unwrapped = js::CheckedUnwrap(&aOpener.toObject(),
|
||||
/* stopAtOuter = */ false);
|
||||
/* stopAtWindowProxy = */ false);
|
||||
if (!unwrapped) {
|
||||
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
|
@ -7818,7 +7786,7 @@ nsGlobalWindow::CallerInnerWindow()
|
|||
bool ok = JS_GetPrototype(cx, scope, &scopeProto);
|
||||
NS_ENSURE_TRUE(ok, nullptr);
|
||||
if (scopeProto && xpc::IsSandboxPrototypeProxy(scopeProto) &&
|
||||
(scopeProto = js::CheckedUnwrap(scopeProto, /* stopAtOuter = */ false)))
|
||||
(scopeProto = js::CheckedUnwrap(scopeProto, /* stopAtWindowProxy = */ false)))
|
||||
{
|
||||
global = xpc::NativeGlobal(scopeProto);
|
||||
NS_ENSURE_TRUE(global, nullptr);
|
||||
|
|
|
@ -359,8 +359,6 @@ public:
|
|||
|
||||
virtual bool IsBlackForCC(bool aTracingNeeded = true) override;
|
||||
|
||||
static JSObject* OuterObject(JSContext* aCx, JS::Handle<JSObject*> aObj);
|
||||
|
||||
// nsIScriptObjectPrincipal
|
||||
virtual nsIPrincipal* GetPrincipal() override;
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "nsDOMCSSAttrDeclaration.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "mozilla/css/StyleRule.h"
|
||||
#include "mozilla/css/Declaration.h"
|
||||
#include "nsCSSParser.h"
|
||||
#include "mozilla/css/Loader.h"
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
|
@ -45,9 +45,9 @@ nsStyledElementNotElementCSSInlineStyle::ParseAttribute(int32_t aNamespaceID,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsStyledElementNotElementCSSInlineStyle::SetInlineStyleRule(css::StyleRule* aStyleRule,
|
||||
const nsAString* aSerialized,
|
||||
bool aNotify)
|
||||
nsStyledElementNotElementCSSInlineStyle::SetInlineStyleDeclaration(css::Declaration* aDeclaration,
|
||||
const nsAString* aSerialized,
|
||||
bool aNotify)
|
||||
{
|
||||
SetMayHaveStyle();
|
||||
bool modification = false;
|
||||
|
@ -77,7 +77,7 @@ nsStyledElementNotElementCSSInlineStyle::SetInlineStyleRule(css::StyleRule* aSty
|
|||
modification = !!mAttrsAndChildren.GetAttr(nsGkAtoms::style);
|
||||
}
|
||||
|
||||
nsAttrValue attrValue(aStyleRule, aSerialized);
|
||||
nsAttrValue attrValue(aDeclaration, aSerialized);
|
||||
|
||||
// XXXbz do we ever end up with ADDITION here? I doubt it.
|
||||
uint8_t modType = modification ?
|
||||
|
@ -89,16 +89,16 @@ nsStyledElementNotElementCSSInlineStyle::SetInlineStyleRule(css::StyleRule* aSty
|
|||
aNotify, kDontCallAfterSetAttr);
|
||||
}
|
||||
|
||||
css::StyleRule*
|
||||
nsStyledElementNotElementCSSInlineStyle::GetInlineStyleRule()
|
||||
css::Declaration*
|
||||
nsStyledElementNotElementCSSInlineStyle::GetInlineStyleDeclaration()
|
||||
{
|
||||
if (!MayHaveStyle()) {
|
||||
return nullptr;
|
||||
}
|
||||
const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
|
||||
|
||||
if (attrVal && attrVal->Type() == nsAttrValue::eCSSStyleRule) {
|
||||
return attrVal->GetCSSStyleRuleValue();
|
||||
if (attrVal && attrVal->Type() == nsAttrValue::eCSSDeclaration) {
|
||||
return attrVal->GetCSSDeclarationValue();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -131,13 +131,13 @@ nsStyledElementNotElementCSSInlineStyle::ReparseStyleAttribute(bool aForceInData
|
|||
}
|
||||
const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
|
||||
|
||||
if (oldVal && oldVal->Type() != nsAttrValue::eCSSStyleRule) {
|
||||
if (oldVal && oldVal->Type() != nsAttrValue::eCSSDeclaration) {
|
||||
nsAttrValue attrValue;
|
||||
nsAutoString stringValue;
|
||||
oldVal->ToString(stringValue);
|
||||
ParseStyleAttribute(stringValue, attrValue, aForceInDataDoc);
|
||||
// Don't bother going through SetInlineStyleRule, we don't want to fire off
|
||||
// mutation events or document notifications anyway
|
||||
// Don't bother going through SetInlineStyleDeclaration; we don't
|
||||
// want to fire off mutation events or document notifications anyway
|
||||
nsresult rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
class StyleRule;
|
||||
class Declaration;
|
||||
} // namespace css
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -35,11 +35,11 @@ protected:
|
|||
{}
|
||||
|
||||
public:
|
||||
// nsIContent interface methods
|
||||
virtual mozilla::css::StyleRule* GetInlineStyleRule() override;
|
||||
virtual nsresult SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule,
|
||||
const nsAString* aSerialized,
|
||||
bool aNotify) override;
|
||||
// Element interface methods
|
||||
virtual mozilla::css::Declaration* GetInlineStyleDeclaration() override;
|
||||
virtual nsresult SetInlineStyleDeclaration(mozilla::css::Declaration* aDeclaration,
|
||||
const nsAString* aSerialized,
|
||||
bool aNotify) override;
|
||||
|
||||
nsICSSDeclaration* Style();
|
||||
|
||||
|
|
|
@ -1066,17 +1066,12 @@ nsTreeSanitizer::MustPrune(int32_t aNamespace,
|
|||
}
|
||||
|
||||
bool
|
||||
nsTreeSanitizer::SanitizeStyleRule(mozilla::css::StyleRule *aRule,
|
||||
nsAutoString &aRuleText)
|
||||
nsTreeSanitizer::SanitizeStyleDeclaration(mozilla::css::Declaration* aDeclaration,
|
||||
nsAutoString& aRuleText)
|
||||
{
|
||||
bool didSanitize = false;
|
||||
aRuleText.Truncate();
|
||||
mozilla::css::Declaration* style = aRule->GetDeclaration();
|
||||
if (style) {
|
||||
didSanitize = style->HasProperty(eCSSProperty_binding);
|
||||
style->RemoveProperty(eCSSProperty_binding);
|
||||
style->ToString(aRuleText);
|
||||
}
|
||||
bool didSanitize = aDeclaration->HasProperty(eCSSProperty_binding);
|
||||
aDeclaration->RemoveProperty(eCSSProperty_binding);
|
||||
aDeclaration->ToString(aRuleText);
|
||||
return didSanitize;
|
||||
}
|
||||
|
||||
|
@ -1135,7 +1130,8 @@ nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
|
|||
RefPtr<mozilla::css::StyleRule> styleRule = do_QueryObject(rule);
|
||||
NS_ASSERTION(styleRule, "Must be a style rule");
|
||||
nsAutoString decl;
|
||||
bool sanitized = SanitizeStyleRule(styleRule, decl);
|
||||
bool sanitized =
|
||||
SanitizeStyleDeclaration(styleRule->GetDeclaration(), decl);
|
||||
didSanitize = sanitized || didSanitize;
|
||||
if (!sanitized) {
|
||||
styleRule->GetCssText(decl);
|
||||
|
@ -1157,10 +1153,7 @@ nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
|
|||
{
|
||||
uint32_t ac = aElement->GetAttrCount();
|
||||
|
||||
nsresult rv;
|
||||
|
||||
for (int32_t i = ac - 1; i >= 0; --i) {
|
||||
rv = NS_OK;
|
||||
const nsAttrName* attrName = aElement->GetAttrNameAt(i);
|
||||
int32_t attrNs = attrName->NamespaceID();
|
||||
nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
|
||||
|
@ -1172,17 +1165,14 @@ nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
|
|||
// Pass the CSS Loader object to the parser, to allow parser error
|
||||
// reports to include the outer window ID.
|
||||
nsCSSParser parser(document->CSSLoader());
|
||||
RefPtr<mozilla::css::StyleRule> rule;
|
||||
nsAutoString value;
|
||||
aElement->GetAttr(attrNs, attrLocal, value);
|
||||
rv = parser.ParseStyleAttribute(value,
|
||||
document->GetDocumentURI(),
|
||||
baseURI,
|
||||
document->NodePrincipal(),
|
||||
getter_AddRefs(rule));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
RefPtr<mozilla::css::Declaration> decl =
|
||||
parser.ParseStyleAttribute(value, document->GetDocumentURI(),
|
||||
baseURI, document->NodePrincipal());
|
||||
if (decl) {
|
||||
nsAutoString cleanValue;
|
||||
if (SanitizeStyleRule(rule, cleanValue)) {
|
||||
if (SanitizeStyleDeclaration(decl, cleanValue)) {
|
||||
aElement->SetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::style,
|
||||
cleanValue,
|
||||
|
|
|
@ -154,12 +154,12 @@ class MOZ_STACK_CLASS nsTreeSanitizer {
|
|||
* removes that property from the rule and reserializes in case the
|
||||
* property was found.
|
||||
*
|
||||
* @param aRule The style rule to check
|
||||
* @param aDeclaration The style declaration to check
|
||||
* @param aRuleText the serialized mutated rule if the method returns true
|
||||
* @return true if the rule was modified and false otherwise
|
||||
*/
|
||||
bool SanitizeStyleRule(mozilla::css::StyleRule* aRule,
|
||||
nsAutoString &aRuleText);
|
||||
bool SanitizeStyleDeclaration(mozilla::css::Declaration* aDeclaration,
|
||||
nsAutoString& aRuleText);
|
||||
|
||||
/**
|
||||
* Parses a style sheet and reserializes it with the 'binding' property
|
||||
|
|
|
@ -31,24 +31,26 @@ function test() {
|
|||
gTestBrowser = gBrowser.selectedBrowser;
|
||||
newTab.linkedBrowser.stop()
|
||||
|
||||
gTestBrowser.addEventListener("load", MixedTest1A, true);
|
||||
BrowserTestUtils.browserLoaded(gTestBrowser, true /*includeSubFrames*/).then(MixedTest1A);
|
||||
var url = gHttpTestRoot + "file_bug902350.html";
|
||||
gTestBrowser.contentWindow.location = url;
|
||||
gTestBrowser.loadURI(url);
|
||||
}
|
||||
|
||||
// Need to capture 2 loads, one for the main page and one for the iframe
|
||||
function MixedTest1A() {
|
||||
gTestBrowser.removeEventListener("load", MixedTest1A, true);
|
||||
gTestBrowser.addEventListener("load", MixedTest1B, true);
|
||||
dump("XYZ\n");
|
||||
BrowserTestUtils.browserLoaded(gTestBrowser, true /*includeSubFrames*/).then(MixedTest1B);
|
||||
}
|
||||
|
||||
// Find the iframe and click the link in it
|
||||
function MixedTest1B() {
|
||||
gTestBrowser.removeEventListener("load", MixedTest1B, true);
|
||||
gTestBrowser.addEventListener("load", MixedTest1C, true);
|
||||
var frame = content.document.getElementById("testing_frame");
|
||||
var topTarget = frame.contentWindow.document.getElementById("topTarget");
|
||||
topTarget.click();
|
||||
BrowserTestUtils.browserLoaded(gTestBrowser).then(MixedTest1C);
|
||||
|
||||
ContentTask.spawn(gTestBrowser, null, function() {
|
||||
var frame = content.document.getElementById("testing_frame");
|
||||
var topTarget = frame.contentWindow.document.getElementById("topTarget");
|
||||
topTarget.click();
|
||||
});
|
||||
|
||||
// The link click should have caused a load and should not invoke the Mixed Content Blocker
|
||||
let {gIdentityHandler} = gTestBrowser.ownerGlobal;
|
||||
|
@ -57,9 +59,12 @@ function MixedTest1B() {
|
|||
}
|
||||
|
||||
function MixedTest1C() {
|
||||
gTestBrowser.removeEventListener("load", MixedTest1C, true);
|
||||
ok(gTestBrowser.contentWindow.location == "http://example.com/", "Navigating to insecure domain through target='_top' failed.")
|
||||
MixedTestsCompleted();
|
||||
ContentTask.spawn(gTestBrowser, null, function() {
|
||||
return content.location.href;
|
||||
}).then(url => {
|
||||
ok(gTestBrowser.contentWindow.location == "http://example.com/", "Navigating to insecure domain through target='_top' failed.")
|
||||
MixedTestsCompleted();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -997,7 +997,7 @@ QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
|
|||
// unwrap.
|
||||
JS::Rooted<JSObject*> origObj(cx, &thisv.toObject());
|
||||
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrap(origObj,
|
||||
/* stopAtOuter = */ false));
|
||||
/* stopAtWindowProxy = */ false));
|
||||
if (!obj) {
|
||||
JS_ReportError(cx, "Permission denied to access object");
|
||||
return false;
|
||||
|
@ -2007,7 +2007,7 @@ GlobalObject::GlobalObject(JSContext* aCx, JSObject* aObject)
|
|||
MOZ_ASSERT(mCx);
|
||||
JS::Rooted<JSObject*> obj(aCx, aObject);
|
||||
if (js::IsWrapper(obj)) {
|
||||
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
|
||||
obj = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
|
||||
if (!obj) {
|
||||
// We should never end up here on a worker thread, since there shouldn't
|
||||
// be any security wrappers to worry about.
|
||||
|
@ -2078,7 +2078,8 @@ InterfaceHasInstance(JSContext* cx, JS::Handle<JSObject*> obj,
|
|||
const DOMIfaceAndProtoJSClass* clasp =
|
||||
DOMIfaceAndProtoJSClass::FromJSClass(js::GetObjectClass(obj));
|
||||
|
||||
const DOMJSClass* domClass = GetDOMClass(js::UncheckedUnwrap(instance, /* stopAtOuter = */ false));
|
||||
const DOMJSClass* domClass =
|
||||
GetDOMClass(js::UncheckedUnwrap(instance, /* stopAtWindowProxy = */ false));
|
||||
|
||||
MOZ_ASSERT(!domClass || clasp->mPrototypeID != prototypes::id::_ID_Count,
|
||||
"Why do we have a hasInstance hook if we don't have a prototype "
|
||||
|
@ -2909,7 +2910,7 @@ GetMaplikeSetlikeBackingObject(JSContext* aCx, JS::Handle<JSObject*> aObj,
|
|||
{
|
||||
JS::Rooted<JSObject*> reflector(aCx);
|
||||
reflector = IsDOMObject(aObj) ? aObj : js::UncheckedUnwrap(aObj,
|
||||
/* stopAtOuter = */ false);
|
||||
/* stopAtWindowProxy = */ false);
|
||||
|
||||
// Retrieve the backing object from the reserved slot on the maplike/setlike
|
||||
// object. If it doesn't exist yet, create it.
|
||||
|
@ -3121,13 +3122,5 @@ DeprecationWarning(JSContext* aCx, JSObject* aObject,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectToOuterObjectValue(JSContext* cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JS::Value> vp)
|
||||
{
|
||||
JSObject* outer = JS_ObjectToOuterObject(cx, obj);
|
||||
vp.setObject(*outer);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -222,7 +222,7 @@ UnwrapObject(JSObject* obj, U& value, prototypes::ID protoID,
|
|||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
}
|
||||
|
||||
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
|
||||
obj = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
|
||||
if (!obj) {
|
||||
return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
|
||||
}
|
||||
|
@ -776,22 +776,15 @@ CouldBeDOMBinding(nsWrapperCache* aCache)
|
|||
inline bool
|
||||
TryToOuterize(JSContext* cx, JS::MutableHandle<JS::Value> rval)
|
||||
{
|
||||
if (js::IsInnerObject(&rval.toObject())) {
|
||||
JS::Rooted<JSObject*> obj(cx, &rval.toObject());
|
||||
obj = JS_ObjectToOuterObject(cx, obj);
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (js::IsWindow(&rval.toObject())) {
|
||||
JSObject* obj = js::ToWindowProxyIfWindow(&rval.toObject());
|
||||
MOZ_ASSERT(obj);
|
||||
rval.set(JS::ObjectValue(*obj));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ObjectToOuterObjectValue(JSContext* cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JS::Value> vp);
|
||||
|
||||
// Make sure to wrap the given string value into the right compartment, as
|
||||
// needed.
|
||||
MOZ_ALWAYS_INLINE
|
||||
|
@ -1093,7 +1086,7 @@ WrapNewBindingNonWrapperCachedObject(JSContext* cx,
|
|||
JS::Rooted<JSObject*> scope(cx, scopeArg);
|
||||
JS::Rooted<JSObject*> proto(cx, givenProto);
|
||||
if (js::IsWrapper(scope)) {
|
||||
scope = js::CheckedUnwrap(scope, /* stopAtOuter = */ false);
|
||||
scope = js::CheckedUnwrap(scope, /* stopAtWindowProxy = */ false);
|
||||
if (!scope)
|
||||
return false;
|
||||
ac.emplace(cx, scope);
|
||||
|
@ -1144,7 +1137,7 @@ WrapNewBindingNonWrapperCachedObject(JSContext* cx,
|
|||
JS::Rooted<JSObject*> scope(cx, scopeArg);
|
||||
JS::Rooted<JSObject*> proto(cx, givenProto);
|
||||
if (js::IsWrapper(scope)) {
|
||||
scope = js::CheckedUnwrap(scope, /* stopAtOuter = */ false);
|
||||
scope = js::CheckedUnwrap(scope, /* stopAtWindowProxy = */ false);
|
||||
if (!scope)
|
||||
return false;
|
||||
ac.emplace(cx, scope);
|
||||
|
|
|
@ -237,7 +237,7 @@ CallbackObject::CallSetup::ShouldRethrowException(JS::Handle<JS::Value> aExcepti
|
|||
}
|
||||
|
||||
JS::Rooted<JSObject*> obj(mCx, &aException.toObject());
|
||||
obj = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
|
||||
obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
|
||||
return js::GetObjectCompartment(obj) == mCompartment;
|
||||
}
|
||||
|
||||
|
|
|
@ -418,8 +418,6 @@ class CGDOMJSClass(CGThing):
|
|||
classExtensionAndObjectOps = fill(
|
||||
"""
|
||||
{
|
||||
nullptr, /* outerObject */
|
||||
nullptr, /* innerObject */
|
||||
false, /* isWrappedNative */
|
||||
nullptr, /* weakmapKeyDelegateOp */
|
||||
${objectMoved} /* objectMovedOp */
|
||||
|
@ -435,8 +433,6 @@ class CGDOMJSClass(CGThing):
|
|||
classExtensionAndObjectOps = fill(
|
||||
"""
|
||||
{
|
||||
nsGlobalWindow::OuterObject, /* outerObject */
|
||||
nullptr, /* innerObject */
|
||||
false, /* isWrappedNative */
|
||||
nullptr, /* weakmapKeyDelegateOp */
|
||||
${objectMoved} /* objectMovedOp */
|
||||
|
@ -453,7 +449,6 @@ class CGDOMJSClass(CGThing):
|
|||
nullptr, /* unwatch */
|
||||
nullptr, /* getElements */
|
||||
nullptr, /* enumerate */
|
||||
mozilla::dom::ObjectToOuterObjectValue, /* thisValue */
|
||||
nullptr, /* funToString */
|
||||
}
|
||||
""",
|
||||
|
@ -541,9 +536,7 @@ class CGDOMProxyJSClass(CGThing):
|
|||
static const DOMJSClass Class = {
|
||||
PROXY_CLASS_WITH_EXT("${name}",
|
||||
${flags},
|
||||
PROXY_MAKE_EXT(nullptr, /* outerObject */
|
||||
nullptr, /* innerObject */
|
||||
false, /* isWrappedNative */
|
||||
PROXY_MAKE_EXT(false, /* isWrappedNative */
|
||||
${objectMoved})),
|
||||
$*{descriptor}
|
||||
};
|
||||
|
@ -743,7 +736,6 @@ class CGInterfaceObjectJSClass(CGThing):
|
|||
nullptr, /* unwatch */
|
||||
nullptr, /* getElements */
|
||||
nullptr, /* enumerate */
|
||||
nullptr, /* thisValue */
|
||||
InterfaceObjectToString, /* funToString */
|
||||
}
|
||||
},
|
||||
|
@ -1861,7 +1853,7 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod):
|
|||
// FIXME Limit this to chrome by checking xpc::AccessCheck::isChrome(obj).
|
||||
nsISupports* native =
|
||||
nsContentUtils::XPConnect()->GetNativeOfWrapper(cx,
|
||||
js::UncheckedUnwrap(instance, /* stopAtOuter = */ false));
|
||||
js::UncheckedUnwrap(instance, /* stopAtWindowProxy = */ false));
|
||||
nsCOMPtr<nsIDOM${name}> qiResult = do_QueryInterface(native);
|
||||
*bp = !!qiResult;
|
||||
return true;
|
||||
|
@ -1871,7 +1863,7 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod):
|
|||
|
||||
hasInstanceCode = dedent("""
|
||||
|
||||
const DOMJSClass* domClass = GetDOMClass(js::UncheckedUnwrap(instance, /* stopAtOuter = */ false));
|
||||
const DOMJSClass* domClass = GetDOMClass(js::UncheckedUnwrap(instance, /* stopAtWindowProxy = */ false));
|
||||
*bp = false;
|
||||
if (!domClass) {
|
||||
// Not a DOM object, so certainly not an instance of this interface
|
||||
|
@ -1879,7 +1871,7 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod):
|
|||
}
|
||||
""")
|
||||
if self.descriptor.interface.identifier.name == "ChromeWindow":
|
||||
setBp = "*bp = UnwrapDOMObject<nsGlobalWindow>(js::UncheckedUnwrap(instance, /* stopAtOuter = */ false))->IsChromeWindow()"
|
||||
setBp = "*bp = UnwrapDOMObject<nsGlobalWindow>(js::UncheckedUnwrap(instance, /* stopAtWindowProxy = */ false))->IsChromeWindow()"
|
||||
else:
|
||||
setBp = "*bp = true"
|
||||
# Sort interaces implementing self by name so we get stable output.
|
||||
|
@ -8384,7 +8376,7 @@ class CGSpecializedGetter(CGAbstractStaticMethod):
|
|||
// Safe to do an unchecked unwrap, since we've gotten this far.
|
||||
// Also make sure to unwrap outer windows, since we want the
|
||||
// real DOM object.
|
||||
reflector = IsDOMObject(obj) ? obj : js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
|
||||
reflector = IsDOMObject(obj) ? obj : js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
|
||||
{
|
||||
// Scope for cachedVal
|
||||
JS::Value cachedVal = js::GetReservedSlot(reflector, ${slot});
|
||||
|
@ -15395,7 +15387,7 @@ class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
|
|||
// This is a reflector, but due to trying to name things
|
||||
// similarly across method generators, it's called obj here.
|
||||
JS::Rooted<JSObject*> obj(cx);
|
||||
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtOuter = */ false);
|
||||
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
|
||||
JSAutoCompartment reflectorCompartment(cx, obj);
|
||||
""" % self.getDefaultRetval())
|
||||
|
||||
|
|
|
@ -27,6 +27,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "ManifestObtainer",
|
|||
|
||||
var kLongestReturnedString = 128;
|
||||
|
||||
const Timer = Components.Constructor("@mozilla.org/timer;1",
|
||||
"nsITimer",
|
||||
"initWithCallback");
|
||||
|
||||
function debug(msg) {
|
||||
//dump("BrowserElementChildPreload - " + msg + "\n");
|
||||
}
|
||||
|
@ -65,7 +69,8 @@ const OBSERVED_EVENTS = [
|
|||
'xpcom-shutdown',
|
||||
'audio-playback',
|
||||
'activity-done',
|
||||
'invalid-widget'
|
||||
'invalid-widget',
|
||||
'will-launch-app'
|
||||
];
|
||||
|
||||
const COMMAND_MAP = {
|
||||
|
@ -332,11 +337,14 @@ BrowserElementChild.prototype = {
|
|||
this.forwarder.init();
|
||||
},
|
||||
|
||||
_paintFrozenTimer: null,
|
||||
observe: function(subject, topic, data) {
|
||||
// Ignore notifications not about our document. (Note that |content| /can/
|
||||
// be null; see bug 874900.)
|
||||
|
||||
if (topic !== 'activity-done' && topic !== 'audio-playback' &&
|
||||
if (topic !== 'activity-done' &&
|
||||
topic !== 'audio-playback' &&
|
||||
topic !== 'will-launch-app' &&
|
||||
(!content || subject !== content.document)) {
|
||||
return;
|
||||
}
|
||||
|
@ -357,9 +365,26 @@ BrowserElementChild.prototype = {
|
|||
case 'invalid-widget':
|
||||
sendAsyncMsg('error', { type: 'invalid-widget' });
|
||||
break;
|
||||
case 'will-launch-app':
|
||||
// If the launcher is not visible, let's ignore the message.
|
||||
if (!docShell.isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
docShell.contentViewer.pausePainting();
|
||||
|
||||
this._paintFrozenTimer && this._paintFrozenTimer.cancel();
|
||||
this._paintFrozenTimer = new Timer(this, 3000, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
notify: function(timer) {
|
||||
docShell.contentViewer.resumePainting();
|
||||
this._paintFrozenTimer.cancel();
|
||||
this._paintFrozenTimer = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when our TabChildGlobal starts to die. This is not called when the
|
||||
* page inside |content| unloads.
|
||||
|
@ -1378,6 +1403,11 @@ BrowserElementChild.prototype = {
|
|||
if (docShell && docShell.isActive !== visible) {
|
||||
docShell.isActive = visible;
|
||||
sendAsyncMsg('visibilitychange', {visible: visible});
|
||||
|
||||
// Ensure painting is not frozen if the app goes visible.
|
||||
if (visible && this._paintFrozenTimer) {
|
||||
this.notify();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -2138,11 +2138,8 @@ CanvasRenderingContext2D::SetShadowColor(const nsAString& shadowColor)
|
|||
static already_AddRefed<Declaration>
|
||||
CreateDeclaration(nsINode* aNode,
|
||||
const nsCSSProperty aProp1, const nsAString& aValue1, bool* aChanged1,
|
||||
const nsCSSProperty aProp2, const nsAString& aValue2, bool* aChanged2,
|
||||
ErrorResult& error)
|
||||
const nsCSSProperty aProp2, const nsAString& aValue2, bool* aChanged2)
|
||||
{
|
||||
RefPtr<StyleRule> rule;
|
||||
|
||||
nsIPrincipal* principal = aNode->NodePrincipal();
|
||||
nsIDocument* document = aNode->OwnerDoc();
|
||||
|
||||
|
@ -2153,23 +2150,19 @@ CreateDeclaration(nsINode* aNode,
|
|||
// to include the outer window ID.
|
||||
nsCSSParser parser(document->CSSLoader());
|
||||
|
||||
error = parser.ParseStyleAttribute(EmptyString(), docURL, baseURL,
|
||||
principal, getter_AddRefs(rule));
|
||||
if (error.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<Declaration> declaration =
|
||||
parser.ParseStyleAttribute(EmptyString(), docURL, baseURL, principal);
|
||||
|
||||
if (aProp1 != eCSSProperty_UNKNOWN) {
|
||||
parser.ParseProperty(aProp1, aValue1, docURL, baseURL, principal,
|
||||
rule->GetDeclaration(), aChanged1, false);
|
||||
declaration, aChanged1, false);
|
||||
}
|
||||
|
||||
if (aProp2 != eCSSProperty_UNKNOWN) {
|
||||
parser.ParseProperty(aProp2, aValue2, docURL, baseURL, principal,
|
||||
rule->GetDeclaration(), aChanged2, false);
|
||||
declaration, aChanged2, false);
|
||||
}
|
||||
|
||||
RefPtr<Declaration> declaration = rule->GetDeclaration();
|
||||
declaration->SetImmutable();
|
||||
return declaration.forget();
|
||||
}
|
||||
|
@ -2177,14 +2170,12 @@ CreateDeclaration(nsINode* aNode,
|
|||
static already_AddRefed<Declaration>
|
||||
CreateFontDeclaration(const nsAString& aFont,
|
||||
nsINode* aNode,
|
||||
bool* aOutFontChanged,
|
||||
ErrorResult& error)
|
||||
bool* aOutFontChanged)
|
||||
{
|
||||
bool lineHeightChanged;
|
||||
return CreateDeclaration(aNode,
|
||||
eCSSProperty_font, aFont, aOutFontChanged,
|
||||
eCSSProperty_line_height, NS_LITERAL_STRING("normal"), &lineHeightChanged,
|
||||
error);
|
||||
eCSSProperty_line_height, NS_LITERAL_STRING("normal"), &lineHeightChanged);
|
||||
}
|
||||
|
||||
static already_AddRefed<nsStyleContext>
|
||||
|
@ -2207,11 +2198,7 @@ GetFontParentStyleContext(Element* aElement, nsIPresShell* presShell,
|
|||
bool changed;
|
||||
RefPtr<css::Declaration> parentRule =
|
||||
CreateFontDeclaration(NS_LITERAL_STRING("10px sans-serif"),
|
||||
presShell->GetDocument(), &changed, error);
|
||||
|
||||
if (error.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
presShell->GetDocument(), &changed);
|
||||
|
||||
nsTArray<nsCOMPtr<nsIStyleRule>> parentRules;
|
||||
parentRules.AppendElement(parentRule);
|
||||
|
@ -2246,11 +2233,7 @@ GetFontStyleContext(Element* aElement, const nsAString& aFont,
|
|||
bool fontParsedSuccessfully = false;
|
||||
RefPtr<css::Declaration> decl =
|
||||
CreateFontDeclaration(aFont, presShell->GetDocument(),
|
||||
&fontParsedSuccessfully, error);
|
||||
|
||||
if (error.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
&fontParsedSuccessfully);
|
||||
|
||||
if (!fontParsedSuccessfully) {
|
||||
// We got a syntax error. The spec says this value must be ignored.
|
||||
|
@ -2302,14 +2285,12 @@ GetFontStyleContext(Element* aElement, const nsAString& aFont,
|
|||
static already_AddRefed<Declaration>
|
||||
CreateFilterDeclaration(const nsAString& aFilter,
|
||||
nsINode* aNode,
|
||||
bool* aOutFilterChanged,
|
||||
ErrorResult& error)
|
||||
bool* aOutFilterChanged)
|
||||
{
|
||||
bool dummy;
|
||||
return CreateDeclaration(aNode,
|
||||
eCSSProperty_filter, aFilter, aOutFilterChanged,
|
||||
eCSSProperty_UNKNOWN, EmptyString(), &dummy,
|
||||
error);
|
||||
eCSSProperty_UNKNOWN, EmptyString(), &dummy);
|
||||
}
|
||||
|
||||
static already_AddRefed<nsStyleContext>
|
||||
|
@ -2321,11 +2302,7 @@ ResolveStyleForFilter(const nsAString& aFilterString,
|
|||
nsIDocument* document = aPresShell->GetDocument();
|
||||
bool filterChanged = false;
|
||||
RefPtr<css::Declaration> decl =
|
||||
CreateFilterDeclaration(aFilterString, document, &filterChanged, error);
|
||||
|
||||
if (error.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
CreateFilterDeclaration(aFilterString, document, &filterChanged);
|
||||
|
||||
if (!filterChanged) {
|
||||
// Refuse to accept the filter, but do not throw an error.
|
||||
|
@ -4425,6 +4402,7 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
|
|||
|
||||
#ifdef USE_SKIA_GPU
|
||||
if (mRenderingMode == RenderingMode::OpenGLBackendMode &&
|
||||
mIsSkiaGL &&
|
||||
!srcSurf &&
|
||||
image.IsHTMLVideoElement() &&
|
||||
gfxPlatform::GetPlatform()->GetSkiaGLGlue()) {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "nsQueryObject.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "mozilla/css/StyleRule.h"
|
||||
#include "mozilla/css/Declaration.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
|
@ -35,7 +35,6 @@
|
|||
#include "nsHTMLStyleSheet.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIStyleRule.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsIFrameInlines.h"
|
||||
|
@ -226,15 +225,14 @@ nsGenericHTMLElement::CopyInnerTo(Element* aDst)
|
|||
value->ToString(valStr);
|
||||
|
||||
if (name->Equals(nsGkAtoms::style, kNameSpaceID_None) &&
|
||||
value->Type() == nsAttrValue::eCSSStyleRule) {
|
||||
value->Type() == nsAttrValue::eCSSDeclaration) {
|
||||
// We can't just set this as a string, because that will fail
|
||||
// to reparse the string into style data until the node is
|
||||
// inserted into the document. Clone the Rule instead.
|
||||
RefPtr<mozilla::css::Rule> ruleClone = value->GetCSSStyleRuleValue()->Clone();
|
||||
RefPtr<mozilla::css::StyleRule> styleRule = do_QueryObject(ruleClone);
|
||||
NS_ENSURE_TRUE(styleRule, NS_ERROR_UNEXPECTED);
|
||||
RefPtr<css::Declaration> declClone =
|
||||
new css::Declaration(*value->GetCSSDeclarationValue());
|
||||
|
||||
rv = aDst->SetInlineStyleRule(styleRule, &valStr, false);
|
||||
rv = aDst->SetInlineStyleDeclaration(declClone, &valStr, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
continue;
|
||||
|
|
|
@ -398,7 +398,7 @@ public:
|
|||
MOZ_ASSERT(aId);
|
||||
|
||||
SelfType closure(aId, aName);
|
||||
aEnumerable.EnumerateRead(Enumerate, &closure);
|
||||
MatchHelper(aEnumerable, &closure);
|
||||
|
||||
return closure.mMetadata;
|
||||
}
|
||||
|
@ -411,7 +411,7 @@ public:
|
|||
MOZ_ASSERT(aId);
|
||||
|
||||
SelfType closure(aId);
|
||||
aEnumerable.EnumerateRead(Enumerate, &closure);
|
||||
MatchHelper(aEnumerable, &closure);
|
||||
|
||||
return closure.mMetadata;
|
||||
}
|
||||
|
@ -436,25 +436,29 @@ private:
|
|||
MOZ_ASSERT(aId);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
Enumerate(const uint64_t& aKey, MetadataType* aValue, void* aClosure)
|
||||
template <class Enumerable>
|
||||
static void
|
||||
MatchHelper(const Enumerable& aEnumerable, SelfType* aClosure)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aKey);
|
||||
MOZ_ASSERT(aValue);
|
||||
MOZ_ASSERT(aClosure);
|
||||
|
||||
auto* closure = static_cast<SelfType*>(aClosure);
|
||||
for (auto iter = aEnumerable.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
#ifdef DEBUG
|
||||
const uint64_t key = iter.Key();
|
||||
#endif
|
||||
MetadataType* value = iter.UserData();
|
||||
MOZ_ASSERT(key != 0);
|
||||
MOZ_ASSERT(value);
|
||||
|
||||
if (!aValue->mDeleted &&
|
||||
(closure->mId == aValue->mCommonMetadata.id() ||
|
||||
(closure->mCheckName &&
|
||||
closure->mName == aValue->mCommonMetadata.name()))) {
|
||||
closure->mMetadata = aValue;
|
||||
return PL_DHASH_STOP;
|
||||
if (!value->mDeleted &&
|
||||
(aClosure->mId == value->mCommonMetadata.id() ||
|
||||
(aClosure->mCheckName &&
|
||||
aClosure->mName == value->mCommonMetadata.name()))) {
|
||||
aClosure->mMetadata = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -15159,56 +15163,6 @@ VersionChangeTransaction::RecvDeleteObjectStore(const int64_t& aObjectStoreId)
|
|||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
class MOZ_STACK_CLASS Helper final
|
||||
{
|
||||
const int64_t mObjectStoreId;
|
||||
bool mIsLastObjectStore;
|
||||
DebugOnly<bool> mFoundTargetId;
|
||||
|
||||
public:
|
||||
static bool
|
||||
IsLastObjectStore(const FullDatabaseMetadata* aDatabaseMetadata,
|
||||
const int64_t aObjectStoreId)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aDatabaseMetadata);
|
||||
MOZ_ASSERT(aObjectStoreId);
|
||||
|
||||
Helper helper(aObjectStoreId);
|
||||
aDatabaseMetadata->mObjectStores.EnumerateRead(&Enumerate, &helper);
|
||||
|
||||
MOZ_ASSERT_IF(helper.mIsLastObjectStore, helper.mFoundTargetId);
|
||||
|
||||
return helper.mIsLastObjectStore;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit
|
||||
Helper(const int64_t aObjectStoreId)
|
||||
: mObjectStoreId(aObjectStoreId)
|
||||
, mIsLastObjectStore(true)
|
||||
, mFoundTargetId(false)
|
||||
{ }
|
||||
|
||||
static PLDHashOperator
|
||||
Enumerate(const uint64_t& aKey,
|
||||
FullObjectStoreMetadata* aValue,
|
||||
void* aClosure)
|
||||
{
|
||||
auto* helper = static_cast<Helper*>(aClosure);
|
||||
MOZ_ASSERT(helper);
|
||||
|
||||
if (uint64_t(helper->mObjectStoreId) == aKey) {
|
||||
helper->mFoundTargetId = true;
|
||||
} else if(!aValue->mDeleted) {
|
||||
helper->mIsLastObjectStore = false;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
|
||||
if (NS_WARN_IF(!aObjectStoreId)) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return false;
|
||||
|
@ -15238,11 +15192,22 @@ VersionChangeTransaction::RecvDeleteObjectStore(const int64_t& aObjectStoreId)
|
|||
|
||||
foundMetadata->mDeleted = true;
|
||||
|
||||
bool isLastObjectStore = true;
|
||||
DebugOnly<bool> foundTargetId = false;
|
||||
for (auto iter = dbMetadata->mObjectStores.Iter();
|
||||
!iter.Done();
|
||||
iter.Next()) {
|
||||
if (uint64_t(aObjectStoreId) == iter.Key()) {
|
||||
foundTargetId = true;
|
||||
} else if (!iter.UserData()->mDeleted) {
|
||||
isLastObjectStore = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT_IF(isLastObjectStore, foundTargetId);
|
||||
|
||||
RefPtr<DeleteObjectStoreOp> op =
|
||||
new DeleteObjectStoreOp(this,
|
||||
foundMetadata,
|
||||
Helper::IsLastObjectStore(dbMetadata,
|
||||
aObjectStoreId));
|
||||
new DeleteObjectStoreOp(this, foundMetadata, isLastObjectStore);
|
||||
|
||||
if (NS_WARN_IF(!op->Init(this))) {
|
||||
op->Cleanup();
|
||||
|
@ -15330,54 +15295,6 @@ VersionChangeTransaction::RecvDeleteIndex(const int64_t& aObjectStoreId,
|
|||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
class MOZ_STACK_CLASS Helper final
|
||||
{
|
||||
const int64_t mIndexId;
|
||||
bool mIsLastIndex;
|
||||
DebugOnly<bool> mFoundTargetId;
|
||||
|
||||
public:
|
||||
static bool
|
||||
IsLastIndex(const FullObjectStoreMetadata* aObjectStoreMetadata,
|
||||
const int64_t aIndexId)
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(aObjectStoreMetadata);
|
||||
MOZ_ASSERT(aIndexId);
|
||||
|
||||
Helper helper(aIndexId);
|
||||
aObjectStoreMetadata->mIndexes.EnumerateRead(&Enumerate, &helper);
|
||||
|
||||
MOZ_ASSERT_IF(helper.mIsLastIndex, helper.mFoundTargetId);
|
||||
|
||||
return helper.mIsLastIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit
|
||||
Helper(const int64_t aIndexId)
|
||||
: mIndexId(aIndexId)
|
||||
, mIsLastIndex(true)
|
||||
, mFoundTargetId(false)
|
||||
{ }
|
||||
|
||||
static PLDHashOperator
|
||||
Enumerate(const uint64_t& aKey, FullIndexMetadata* aValue, void* aClosure)
|
||||
{
|
||||
auto* helper = static_cast<Helper*>(aClosure);
|
||||
MOZ_ASSERT(helper);
|
||||
|
||||
if (uint64_t(helper->mIndexId) == aKey) {
|
||||
helper->mFoundTargetId = true;
|
||||
} else if (!aValue->mDeleted) {
|
||||
helper->mIsLastIndex = false;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
|
||||
if (NS_WARN_IF(!aObjectStoreId)) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return false;
|
||||
|
@ -15426,12 +15343,26 @@ VersionChangeTransaction::RecvDeleteIndex(const int64_t& aObjectStoreId,
|
|||
|
||||
foundIndexMetadata->mDeleted = true;
|
||||
|
||||
bool isLastIndex = true;
|
||||
DebugOnly<bool> foundTargetId = false;
|
||||
for (auto iter = foundObjectStoreMetadata->mIndexes.ConstIter();
|
||||
!iter.Done();
|
||||
iter.Next()) {
|
||||
if (uint64_t(aIndexId) == iter.Key()) {
|
||||
foundTargetId = true;
|
||||
} else if (!iter.UserData()->mDeleted) {
|
||||
isLastIndex = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT_IF(isLastIndex, foundTargetId);
|
||||
|
||||
RefPtr<DeleteIndexOp> op =
|
||||
new DeleteIndexOp(this,
|
||||
aObjectStoreId,
|
||||
aIndexId,
|
||||
foundIndexMetadata->mCommonMetadata.unique(),
|
||||
Helper::IsLastIndex(foundObjectStoreMetadata, aIndexId));
|
||||
isLastIndex);
|
||||
|
||||
if (NS_WARN_IF(!op->Init(this))) {
|
||||
op->Cleanup();
|
||||
|
@ -18609,51 +18540,7 @@ DatabaseOperationBase::GetUniqueIndexTableForObjectStore(
|
|||
MOZ_ASSERT(aObjectStoreId);
|
||||
MOZ_ASSERT(aMaybeUniqueIndexTable.isNothing());
|
||||
|
||||
class MOZ_STACK_CLASS Helper final
|
||||
{
|
||||
public:
|
||||
static nsresult
|
||||
CopyUniqueValues(const IndexTable& aIndexes,
|
||||
Maybe<UniqueIndexTable>& aMaybeUniqueIndexTable)
|
||||
{
|
||||
const uint32_t indexCount = aIndexes.Count();
|
||||
MOZ_ASSERT(indexCount);
|
||||
|
||||
aMaybeUniqueIndexTable.emplace();
|
||||
|
||||
aIndexes.EnumerateRead(Enumerate, aMaybeUniqueIndexTable.ptr());
|
||||
|
||||
if (NS_WARN_IF(aMaybeUniqueIndexTable.ref().Count() != indexCount)) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
aMaybeUniqueIndexTable.reset();
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
aMaybeUniqueIndexTable.ref().MarkImmutable();
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
static PLDHashOperator
|
||||
Enumerate(const uint64_t& aKey, FullIndexMetadata* aValue, void* aClosure)
|
||||
{
|
||||
auto* uniqueIndexTable = static_cast<UniqueIndexTable*>(aClosure);
|
||||
MOZ_ASSERT(uniqueIndexTable);
|
||||
MOZ_ASSERT(!uniqueIndexTable->Get(aValue->mCommonMetadata.id()));
|
||||
|
||||
if (NS_WARN_IF(!uniqueIndexTable->Put(aValue->mCommonMetadata.id(),
|
||||
aValue->mCommonMetadata.unique(),
|
||||
fallible))) {
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
|
||||
const RefPtr<FullObjectStoreMetadata> objectStoreMetadata =
|
||||
const RefPtr<FullObjectStoreMetadata> objectStoreMetadata =
|
||||
aTransaction->GetMetadataForObjectStoreId(aObjectStoreId);
|
||||
MOZ_ASSERT(objectStoreMetadata);
|
||||
|
||||
|
@ -18661,12 +18548,35 @@ DatabaseOperationBase::GetUniqueIndexTableForObjectStore(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = Helper::CopyUniqueValues(objectStoreMetadata->mIndexes,
|
||||
aMaybeUniqueIndexTable);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
const uint32_t indexCount = objectStoreMetadata->mIndexes.Count();
|
||||
MOZ_ASSERT(indexCount > 0);
|
||||
|
||||
aMaybeUniqueIndexTable.emplace();
|
||||
UniqueIndexTable* uniqueIndexTable = aMaybeUniqueIndexTable.ptr();
|
||||
MOZ_ASSERT(uniqueIndexTable);
|
||||
|
||||
for (auto iter = objectStoreMetadata->mIndexes.Iter(); !iter.Done(); iter.Next()) {
|
||||
FullIndexMetadata* value = iter.UserData();
|
||||
MOZ_ASSERT(!uniqueIndexTable->Get(value->mCommonMetadata.id()));
|
||||
|
||||
if (NS_WARN_IF(!uniqueIndexTable->Put(value->mCommonMetadata.id(),
|
||||
value->mCommonMetadata.unique(),
|
||||
fallible))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(aMaybeUniqueIndexTable.ref().Count() != indexCount)) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
aMaybeUniqueIndexTable.reset();
|
||||
NS_WARNING("out of memory");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
aMaybeUniqueIndexTable.ref().MarkImmutable();
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
|
||||
interface nsIChannel;
|
||||
interface nsIStreamListener;
|
||||
interface nsIURI;
|
||||
|
||||
/**
|
||||
* nsIContentSecurityManager
|
||||
* Describes an XPCOM component used to perform security checks
|
||||
* right before opnening a channel.
|
||||
* Describes an XPCOM component used to perform security checks.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(70eaa956-1077-41f6-bef8-d722cea31245)]
|
||||
[scriptable, uuid(ec955006-747d-4151-aeec-70bd0edc3341)]
|
||||
interface nsIContentSecurityManager : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -40,4 +40,15 @@ interface nsIContentSecurityManager : nsISupports
|
|||
*/
|
||||
nsIStreamListener performSecurityCheck(in nsIChannel aChannel,
|
||||
in nsIStreamListener aStreamListener);
|
||||
|
||||
/**
|
||||
* Implementation of
|
||||
* https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
|
||||
*
|
||||
* This method should only be used when the context of the URI isn't available
|
||||
* since isSecureContext is preffered as it handles parent contexts.
|
||||
*
|
||||
* This method returns false instead of throwing upon errors.
|
||||
*/
|
||||
boolean isURIPotentiallyTrustworthy(in nsIURI aURI);
|
||||
};
|
||||
|
|
|
@ -4447,7 +4447,8 @@ BlobParent::RecvGetFilePath(nsString* aFilePath)
|
|||
MOZ_ASSERT(mOwnsBlobImpl);
|
||||
|
||||
// In desktop e10s the file picker code sends this message.
|
||||
#ifdef MOZ_CHILD_PERMISSIONS
|
||||
|
||||
#if defined(MOZ_CHILD_PERMISSIONS) && !defined(MOZ_GRAPHENE)
|
||||
if (NS_WARN_IF(!IndexedDatabaseManager::InTestingMode())) {
|
||||
ASSERT_UNLESS_FUZZING();
|
||||
return false;
|
||||
|
|
|
@ -2969,6 +2969,7 @@ ContentChild::AllocPContentPermissionRequestChild(const InfallibleTArray<Permiss
|
|||
bool
|
||||
ContentChild::DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor)
|
||||
{
|
||||
nsContentPermissionUtils::NotifyRemoveContentPermissionRequestChild(actor);
|
||||
auto child = static_cast<RemotePermissionRequest*>(actor);
|
||||
child->IPDLRelease();
|
||||
return true;
|
||||
|
|
|
@ -2245,10 +2245,7 @@ ContentParent::NotifyTabDestroyed(const TabId& aTabId,
|
|||
|
||||
// Need to close undeleted ContentPermissionRequestParents before tab is closed.
|
||||
for (auto& permissionRequestParent : parentArray) {
|
||||
nsTArray<PermissionChoice> emptyChoices;
|
||||
Unused << PContentPermissionRequestParent::Send__delete__(permissionRequestParent,
|
||||
false,
|
||||
emptyChoices);
|
||||
Unused << PContentPermissionRequestParent::Send__delete__(permissionRequestParent);
|
||||
}
|
||||
|
||||
// There can be more than one PBrowser for a given app process
|
||||
|
|
|
@ -15,10 +15,12 @@ protocol PContentPermissionRequest
|
|||
parent:
|
||||
prompt();
|
||||
NotifyVisibility(bool visibility);
|
||||
Destroy();
|
||||
|
||||
child:
|
||||
GetVisibility();
|
||||
__delete__(bool allow, PermissionChoice[] choices);
|
||||
NotifyResult(bool allow, PermissionChoice[] choices);
|
||||
__delete__();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
#include "nsIOService.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsColorPickerProxy.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
#include "nsPresShell.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
@ -2116,7 +2117,6 @@ TabChild::DeallocPIndexedDBPermissionRequestChild(
|
|||
PIndexedDBPermissionRequestChild* aActor)
|
||||
{
|
||||
MOZ_ASSERT(aActor);
|
||||
|
||||
delete aActor;
|
||||
return true;
|
||||
}
|
||||
|
@ -2228,6 +2228,15 @@ TabChild::RecvDestroy()
|
|||
MOZ_ASSERT(mDestroyed == false);
|
||||
mDestroyed = true;
|
||||
|
||||
nsTArray<PContentPermissionRequestChild*> childArray =
|
||||
nsContentPermissionUtils::GetContentPermissionRequestChildById(GetTabId());
|
||||
|
||||
// Need to close undeleted ContentPermissionRequestChilds before tab is closed.
|
||||
for (auto& permissionRequestChild : childArray) {
|
||||
auto child = static_cast<RemotePermissionRequest*>(permissionRequestChild);
|
||||
child->Destroy();
|
||||
}
|
||||
|
||||
while (mActiveSuppressDisplayport > 0) {
|
||||
APZCCallbackHelper::SuppressDisplayport(false);
|
||||
mActiveSuppressDisplayport--;
|
||||
|
|
|
@ -1821,7 +1821,7 @@ MediaManager::GetUserMedia(nsPIDOMWindow* aWindow,
|
|||
bool isApp;
|
||||
docURI->SchemeIs("app", &isApp);
|
||||
// Same localhost check as ServiceWorkers uses
|
||||
// (see IsFromAuthenticatedOriginInternal())
|
||||
// (see IsURIPotentiallyTrustworthy())
|
||||
bool isLocalhost = NS_SUCCEEDED(rv) &&
|
||||
(host.LowerCaseEqualsLiteral("localhost") ||
|
||||
host.LowerCaseEqualsLiteral("127.0.0.1") ||
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
private:
|
||||
Image *CreateI420Image()
|
||||
{
|
||||
PlanarYCbCrImage *image = new PlanarYCbCrImage(new BufferRecycleBin());
|
||||
PlanarYCbCrImage *image = new RecyclingPlanarYCbCrImage(new BufferRecycleBin());
|
||||
PlanarYCbCrData data;
|
||||
data.mPicSize = mImageSize;
|
||||
|
||||
|
@ -93,7 +93,7 @@ private:
|
|||
|
||||
Image *CreateNV12Image()
|
||||
{
|
||||
PlanarYCbCrImage *image = new PlanarYCbCrImage(new BufferRecycleBin());
|
||||
PlanarYCbCrImage *image = new RecyclingPlanarYCbCrImage(new BufferRecycleBin());
|
||||
PlanarYCbCrData data;
|
||||
data.mPicSize = mImageSize;
|
||||
|
||||
|
@ -130,7 +130,7 @@ private:
|
|||
|
||||
Image *CreateNV21Image()
|
||||
{
|
||||
PlanarYCbCrImage *image = new PlanarYCbCrImage(new BufferRecycleBin());
|
||||
PlanarYCbCrImage *image = new RecyclingPlanarYCbCrImage(new BufferRecycleBin());
|
||||
PlanarYCbCrData data;
|
||||
data.mPicSize = mImageSize;
|
||||
|
||||
|
|
|
@ -75,16 +75,15 @@ GonkDecoderManager::ProcessQueuedSamples()
|
|||
status_t rv;
|
||||
while (mQueuedSamples.Length()) {
|
||||
RefPtr<MediaRawData> data = mQueuedSamples.ElementAt(0);
|
||||
{
|
||||
rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
|
||||
data->Size(),
|
||||
data->mTime,
|
||||
0,
|
||||
INPUT_TIMEOUT_US);
|
||||
}
|
||||
rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
|
||||
data->Size(),
|
||||
data->mTime,
|
||||
0,
|
||||
INPUT_TIMEOUT_US);
|
||||
if (rv == OK) {
|
||||
mQueuedSamples.RemoveElementAt(0);
|
||||
mWaitOutput.AppendElement(data->mOffset);
|
||||
mWaitOutput.AppendElement(WaitOutputInfo(data->mOffset, data->mTime,
|
||||
/* eos */ data->Data() == nullptr));
|
||||
} else if (rv == -EAGAIN || rv == -ETIMEDOUT) {
|
||||
// In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill
|
||||
// buffer on time.
|
||||
|
@ -171,7 +170,7 @@ GonkDecoderManager::ProcessInput(bool aEndOfStream)
|
|||
void
|
||||
GonkDecoderManager::ProcessFlush()
|
||||
{
|
||||
mLastTime = 0;
|
||||
mLastTime = INT64_MIN;
|
||||
MonitorAutoLock lock(mFlushMonitor);
|
||||
mWaitOutput.Clear();
|
||||
if (mDecoder->flush() != OK) {
|
||||
|
@ -182,6 +181,25 @@ GonkDecoderManager::ProcessFlush()
|
|||
lock.NotifyAll();
|
||||
}
|
||||
|
||||
// Use output timestamp to determine which output buffer is already returned
|
||||
// and remove corresponding info, except for EOS, from the waiting list.
|
||||
// This method handles the cases that audio decoder sends multiple output
|
||||
// buffers for one input.
|
||||
void
|
||||
GonkDecoderManager::UpdateWaitingList(int64_t aForgetUpTo)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < mWaitOutput.Length(); i++) {
|
||||
const auto& item = mWaitOutput.ElementAt(i);
|
||||
if (item.mEOS || item.mTimestamp > aForgetUpTo) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i > 0) {
|
||||
mWaitOutput.RemoveElementsAt(0, i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GonkDecoderManager::ProcessToDo(bool aEndOfStream)
|
||||
{
|
||||
|
@ -193,25 +211,22 @@ GonkDecoderManager::ProcessToDo(bool aEndOfStream)
|
|||
return;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
while (mWaitOutput.Length() > 0) {
|
||||
RefPtr<MediaData> output;
|
||||
int64_t offset = mWaitOutput.ElementAt(0);
|
||||
rv = Output(offset, output);
|
||||
WaitOutputInfo wait = mWaitOutput.ElementAt(0);
|
||||
nsresult rv = Output(wait.mOffset, output);
|
||||
if (rv == NS_OK) {
|
||||
mWaitOutput.RemoveElementAt(0);
|
||||
mDecodeCallback->Output(output);
|
||||
UpdateWaitingList(output->mTime);
|
||||
} else if (rv == NS_ERROR_ABORT) {
|
||||
// EOS
|
||||
MOZ_ASSERT(mQueuedSamples.IsEmpty());
|
||||
mWaitOutput.RemoveElementAt(0);
|
||||
// Sometimes the decoder attaches EOS flag to the final output buffer
|
||||
// instead of emits EOS by itself, hence the 2nd condition.
|
||||
MOZ_ASSERT(mWaitOutput.IsEmpty() ||
|
||||
(mWaitOutput.Length() == 1 && output.get()));
|
||||
if (output) {
|
||||
mDecodeCallback->Output(output);
|
||||
UpdateWaitingList(output->mTime);
|
||||
}
|
||||
MOZ_ASSERT(mWaitOutput.Length() == 1);
|
||||
mWaitOutput.RemoveElementAt(0);
|
||||
mDecodeCallback->DrainComplete();
|
||||
return;
|
||||
} else if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
protected:
|
||||
GonkDecoderManager()
|
||||
: mMutex("GonkDecoderManager")
|
||||
, mLastTime(0)
|
||||
, mLastTime(INT64_MIN)
|
||||
, mFlushMonitor("GonkDecoderManager::Flush")
|
||||
, mIsFlushing(false)
|
||||
, mDecodeCallback(nullptr)
|
||||
|
@ -116,10 +116,24 @@ protected:
|
|||
// forbidden by mDecoder.
|
||||
android::sp<android::AMessage> mToDo;
|
||||
|
||||
// Stores the offset of every output that needs to be read from mDecoder.
|
||||
nsTArray<int64_t> mWaitOutput;
|
||||
// Stores sample info for output buffer processing later.
|
||||
struct WaitOutputInfo {
|
||||
WaitOutputInfo(int64_t aOffset, int64_t aTimestamp, bool aEOS)
|
||||
: mOffset(aOffset)
|
||||
, mTimestamp(aTimestamp)
|
||||
, mEOS(aEOS)
|
||||
{}
|
||||
const int64_t mOffset;
|
||||
const int64_t mTimestamp;
|
||||
const bool mEOS;
|
||||
};
|
||||
|
||||
nsTArray<WaitOutputInfo> mWaitOutput;
|
||||
|
||||
MediaDataDecoderCallback* mDecodeCallback; // Reports decoder output or error.
|
||||
|
||||
private:
|
||||
void UpdateWaitingList(int64_t aForgetUpTo);
|
||||
};
|
||||
|
||||
class AutoReleaseMediaBuffer
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "MediaInfo.h"
|
||||
#include "prsystem.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -153,6 +154,8 @@ template<const GUID& aGuid>
|
|||
static bool
|
||||
CanCreateWMFDecoder()
|
||||
{
|
||||
static StaticMutex sMutex;
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
static Maybe<bool> result;
|
||||
if (result.isNothing()) {
|
||||
result.emplace(CanCreateMFTDecoder(aGuid));
|
||||
|
|
|
@ -553,6 +553,14 @@ CommandChain.prototype = {
|
|||
return this.commands.indexOf(functionOrName, start);
|
||||
},
|
||||
|
||||
mustHaveIndexOf: function(functionOrName, start) {
|
||||
var index = this.indexOf(functionOrName, start);
|
||||
if (index == -1) {
|
||||
throw new Error("Unknown test: " + functionOrName);
|
||||
}
|
||||
return index;
|
||||
},
|
||||
|
||||
/**
|
||||
* Inserts the new commands after the specified command.
|
||||
*/
|
||||
|
@ -575,7 +583,7 @@ CommandChain.prototype = {
|
|||
},
|
||||
|
||||
_insertHelper: function(functionOrName, commands, delta, all, start) {
|
||||
var index = this.indexOf(functionOrName);
|
||||
var index = this.mustHaveIndexOf(functionOrName);
|
||||
start = start || 0;
|
||||
for (; index !== -1; index = this.indexOf(functionOrName, index)) {
|
||||
if (!start) {
|
||||
|
@ -597,33 +605,21 @@ CommandChain.prototype = {
|
|||
* Removes the specified command, returns what was removed.
|
||||
*/
|
||||
remove: function(functionOrName) {
|
||||
var index = this.indexOf(functionOrName);
|
||||
if (index >= 0) {
|
||||
return this.commands.splice(index, 1);
|
||||
}
|
||||
return [];
|
||||
return this.commands.splice(this.mustHaveIndexOf(functionOrName), 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all commands after the specified one, returns what was removed.
|
||||
*/
|
||||
removeAfter: function(functionOrName, start) {
|
||||
var index = this.indexOf(functionOrName, start);
|
||||
if (index >= 0) {
|
||||
return this.commands.splice(index + 1);
|
||||
}
|
||||
return [];
|
||||
return this.commands.splice(this.mustHaveIndexOf(functionOrName, start) + 1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all commands before the specified one, returns what was removed.
|
||||
*/
|
||||
removeBefore: function(functionOrName) {
|
||||
var index = this.indexOf(functionOrName);
|
||||
if (index >= 0) {
|
||||
return this.commands.splice(0, index);
|
||||
}
|
||||
return [];
|
||||
return this.commands.splice(0, this.mustHaveIndexOf(functionOrName));
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -211,6 +211,7 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
|
|||
skip-if = toolkit == 'gonk' || (android_version == '18' && debug) # b2g (Bug 1059867), android(Bug 1189784, timeouts on 4.3 emulator)
|
||||
[test_peerConnection_remoteReofferRollback.html]
|
||||
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g (Bug 1059867)
|
||||
[test_selftest.html]
|
||||
|
||||
# Bug 950317: Hack for making a cleanup hook after finishing all WebRTC cases
|
||||
[test_zmedia_cleanup.html]
|
||||
|
|
|
@ -464,26 +464,30 @@ var commandsPeerConnectionOfferAnswer = [
|
|||
return checkAllTrackStats(test.pcRemote);
|
||||
},
|
||||
function PC_LOCAL_VERIFY_SDP_AFTER_END_OF_TRICKLE(test) {
|
||||
/* In case the endOfTrickleSdp promise is resolved already it will win the
|
||||
* race because it gets evaluated first. But if endOfTrickleSdp is still
|
||||
* pending the rejection will win the race. */
|
||||
return Promise.race([
|
||||
test.pcLocal.endOfTrickleSdp,
|
||||
Promise.reject("No SDP")
|
||||
])
|
||||
.then(sdp => sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcLocal.label),
|
||||
() => info("pcLocal: Gathering is not complete yet, skipping post-gathering SDP check"));
|
||||
if (test.pcLocal.endOfTrickleSdp) {
|
||||
/* In case the endOfTrickleSdp promise is resolved already it will win the
|
||||
* race because it gets evaluated first. But if endOfTrickleSdp is still
|
||||
* pending the rejection will win the race. */
|
||||
return Promise.race([
|
||||
test.pcLocal.endOfTrickleSdp,
|
||||
Promise.reject("No SDP")
|
||||
])
|
||||
.then(sdp => sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcLocal.label),
|
||||
() => info("pcLocal: Gathering is not complete yet, skipping post-gathering SDP check"));
|
||||
}
|
||||
},
|
||||
function PC_REMOTE_VERIFY_SDP_AFTER_END_OF_TRICKLE(test) {
|
||||
/* In case the endOfTrickleSdp promise is resolved already it will win the
|
||||
* race because it gets evaluated first. But if endOfTrickleSdp is still
|
||||
* pending the rejection will win the race. */
|
||||
return Promise.race([
|
||||
test.pcRemote.endOfTrickleSdp,
|
||||
Promise.reject("No SDP")
|
||||
])
|
||||
.then(sdp => sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcRemote.label),
|
||||
() => info("pcRemote: Gathering is not complete yet, skipping post-gathering SDP check"));
|
||||
if (test.pcRemote.endOfTrickelSdp) {
|
||||
/* In case the endOfTrickleSdp promise is resolved already it will win the
|
||||
* race because it gets evaluated first. But if endOfTrickleSdp is still
|
||||
* pending the rejection will win the race. */
|
||||
return Promise.race([
|
||||
test.pcRemote.endOfTrickleSdp,
|
||||
Promise.reject("No SDP")
|
||||
])
|
||||
.then(sdp => sdputils.checkSdpAfterEndOfTrickle(sdp, test.testOptions, test.pcRemote.label),
|
||||
() => info("pcRemote: Gathering is not complete yet, skipping post-gathering SDP check"));
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
<script type="application/javascript">
|
||||
createHTML({
|
||||
title: "getUserMedia Basic Screenshare Test",
|
||||
bug: "983504"
|
||||
bug: "1211656"
|
||||
});
|
||||
/**
|
||||
* Run a test to verify that we can complete a start and stop media playback
|
||||
* cycle for an screenshare LocalMediaStream on a video HTMLMediaElement.
|
||||
* cycle for a screenshare LocalMediaStream on a video HTMLMediaElement.
|
||||
*/
|
||||
runTest(function () {
|
||||
const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1;
|
||||
|
@ -21,6 +21,7 @@
|
|||
return;
|
||||
}
|
||||
var testVideo = createMediaElement('video', 'testVideo');
|
||||
|
||||
var constraints = {
|
||||
video: {
|
||||
mozMediaSource: "screen",
|
||||
|
@ -28,12 +29,49 @@
|
|||
},
|
||||
fake: false
|
||||
};
|
||||
|
||||
var videoConstraints = [
|
||||
{
|
||||
mediaSource: 'screen',
|
||||
width: {
|
||||
min: '10',
|
||||
max: '100'
|
||||
},
|
||||
height: {
|
||||
min: '10',
|
||||
max: '100'
|
||||
},
|
||||
frameRate: {
|
||||
min: '10',
|
||||
max: '15'
|
||||
}
|
||||
},
|
||||
{
|
||||
mediaSource: 'screen',
|
||||
width: 200,
|
||||
height: 200,
|
||||
frameRate: {
|
||||
min: '5',
|
||||
max: '10'
|
||||
}
|
||||
}
|
||||
];
|
||||
return getUserMedia(constraints).then(stream => {
|
||||
var playback = new LocalMediaStreamPlayback(testVideo, stream);
|
||||
return playback.playMediaWithDeprecatedStreamStop(false);
|
||||
});
|
||||
|
||||
return playback.playMediaWithDeprecatedStreamStop(false);
|
||||
})
|
||||
.then(() => getUserMedia({video: videoConstraints[0]}))
|
||||
.then(stream => {
|
||||
var playback = new LocalMediaStreamPlayback(testVideo, stream);
|
||||
playback.startMedia(false);
|
||||
return playback.verifyPlaying()
|
||||
.then(() => Promise.all([
|
||||
() => testVideo.srcObject.getVideoTracks()[0].applyConstraints(videoConstraints[1]),
|
||||
() => listenUntil(testVideo, "resize", () => true)
|
||||
]))
|
||||
.then(() => playback.verifyPlaying()) // still playing
|
||||
.then(() => playback.deprecatedStopStreamInMediaPlayback())
|
||||
.then(() => playback.stopMediaElement());
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
@ -29,7 +29,7 @@ runNetworkTest(function() {
|
|||
return Promise.resolve();
|
||||
}
|
||||
]);
|
||||
gumTest.chain.removeAfter("PC_REMOTE_CHECK_MEDIA_FLOW_PRESENT");
|
||||
gumTest.chain.removeAfter("PC_REMOTE_WAIT_FOR_MEDIA_FLOW");
|
||||
gumTest.chain.execute()
|
||||
.then(() => forwardingTest.chain.execute())
|
||||
.then(() => gumTest.close())
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
test = new PeerConnectionTest();
|
||||
test.audioCtx = new AudioContext();
|
||||
test.setMediaConstraints([{video: true, audio: true}], [{video: true}]);
|
||||
test.chain.removeAfter("PC_REMOTE_CHECK_MEDIA_FLOW_PRESENT");
|
||||
test.chain.removeAfter("PC_REMOTE_WAIT_FOR_MEDIA_FLOW");
|
||||
|
||||
// Test replaceTrack on pcRemote separately since it's video only.
|
||||
test.chain.append([
|
||||
|
|
|
@ -21,7 +21,9 @@ function PC_LOCAL_SET_LOCAL_DESCRIPTION_SYNC(test) {
|
|||
|
||||
function PC_REMOTE_SET_REMOTE_DESCRIPTION_SYNC(test) {
|
||||
test.pcRemote.onsignalingstatechange = function() {};
|
||||
test.pcRemote._pc.setRemoteDescription(test._local_offer);
|
||||
test.pcRemote._pc.setRemoteDescription(test._local_offer,
|
||||
test.pcRemote.releaseIceCandidates,
|
||||
generateErrorCallback("pcRemote._pc.setRemoteDescription() sync failed"));
|
||||
}
|
||||
function PC_REMOTE_SET_LOCAL_DESCRIPTION_SYNC(test) {
|
||||
test.pcRemote.onsignalingstatechange = function() {};
|
||||
|
@ -29,21 +31,18 @@ function PC_REMOTE_SET_LOCAL_DESCRIPTION_SYNC(test) {
|
|||
}
|
||||
function PC_LOCAL_SET_REMOTE_DESCRIPTION_SYNC(test) {
|
||||
test.pcLocal.onsignalingstatechange = function() {};
|
||||
test.pcLocal._pc.setRemoteDescription(test._remote_answer);
|
||||
test.pcLocal._pc.setRemoteDescription(test._remote_answer,
|
||||
test.pcLocal.releaseIceCandidates,
|
||||
generateErrorCallback("pcLocal._pc.setRemoteDescription() sync failed"));
|
||||
}
|
||||
|
||||
runNetworkTest(() => {
|
||||
var replace = (test, name, command) => {
|
||||
test.chain.insertAfter(name, command);
|
||||
test.chain.remove(name);
|
||||
}
|
||||
|
||||
var test = new PeerConnectionTest();
|
||||
test.setMediaConstraints([{video: true}], [{video: true}]);
|
||||
test.chain.replace(test, "PC_LOCAL_SET_LOCAL_DESCRIPTION", PC_LOCAL_SET_LOCAL_DESCRIPTION_SYNC);
|
||||
test.chain.replace(test, "PC_REMOTE_SET_REMOTE_DESCRIPTION", PC_REMOTE_SET_REMOTE_DESCRIPTION_SYNC);
|
||||
test.chain.replace(test, "PC_REMOTE_SET_LOCAL_DESCRIPTION", PC_REMOTE_SET_LOCAL_DESCRIPTION_SYNC);
|
||||
test.chain.replace(test, "PC_LOCAL_SET_REMOTE_DESCRIPTION", PC_LOCAL_SET_REMOTE_DESCRIPTION_SYNC);
|
||||
test.chain.replace("PC_LOCAL_SET_LOCAL_DESCRIPTION", PC_LOCAL_SET_LOCAL_DESCRIPTION_SYNC);
|
||||
test.chain.replace("PC_REMOTE_SET_REMOTE_DESCRIPTION", PC_REMOTE_SET_REMOTE_DESCRIPTION_SYNC);
|
||||
test.chain.replace("PC_REMOTE_SET_LOCAL_DESCRIPTION", PC_REMOTE_SET_LOCAL_DESCRIPTION_SYNC);
|
||||
test.chain.replace("PC_LOCAL_SET_REMOTE_DESCRIPTION", PC_LOCAL_SET_REMOTE_DESCRIPTION_SYNC);
|
||||
test.run();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<script type="application/javascript" src="pc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.8">
|
||||
createHTML({
|
||||
title: "Self-test of harness functions",
|
||||
visible: true
|
||||
});
|
||||
|
||||
function TEST(test) {}
|
||||
|
||||
var catcher = func => {
|
||||
try {
|
||||
func();
|
||||
return null;
|
||||
} catch (e) {
|
||||
return e.message;
|
||||
}
|
||||
};
|
||||
|
||||
runNetworkTest(() => {
|
||||
var test = new PeerConnectionTest();
|
||||
test.setMediaConstraints([{video: true}], [{video: true}]);
|
||||
is(catcher(() => test.chain.replace("PC_LOCAL_SET_LOCAL_DESCRIPTION", TEST)),
|
||||
null, "test.chain.replace works");
|
||||
is(catcher(() => test.chain.replace("FOO", TEST)),
|
||||
"Unknown test: FOO", "test.chain.replace catches typos");
|
||||
networkTestFinished();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -342,7 +342,9 @@ public:
|
|||
// - mDestination (probably)
|
||||
size_t amount = AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mSharedBuffers->SizeOfIncludingThis(aMallocSizeOf);
|
||||
amount += mInputBuffer->SizeOfIncludingThis(aMallocSizeOf);
|
||||
if (mInputBuffer) {
|
||||
amount += mInputBuffer->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
|
|
@ -181,3 +181,5 @@ skip-if = (toolkit == 'gonk' && !debug) || android_version == '10' || android_ve
|
|||
[test_waveShaperNoCurve.html]
|
||||
[test_waveShaperPassThrough.html]
|
||||
[test_waveShaperInvalidLengthCurve.html]
|
||||
[test_WebAudioMemoryReporting.html]
|
||||
skip-if = debug # assertion failures: bug 1222202
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Web Audio memory reporting</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var ac = new AudioContext();
|
||||
var sp = ac.createScriptProcessor(4096, 1, 1);
|
||||
sp.connect(ac.destination);
|
||||
|
||||
var nodeTypes = ["ScriptProcessorNode", "AudioDestinationNode"];
|
||||
var objectTypes = ["dom-nodes", "engine-objects", "stream-objects"];
|
||||
|
||||
var usages = {};
|
||||
|
||||
for (var i = 0; i < nodeTypes.length; ++i) {
|
||||
for (var j = 0; j < objectTypes.length; ++j) {
|
||||
usages["explicit/webaudio/audio-node/" +
|
||||
nodeTypes[i] + "/" + objectTypes[j]] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
var handleReport = function(aProcess, aPath, aKind, aUnits, aAmount, aDesc) {
|
||||
if (aPath in usages) {
|
||||
usages[aPath] += aAmount;
|
||||
}
|
||||
}
|
||||
|
||||
var finished = function () {
|
||||
ok(true, "Yay didn't crash!");
|
||||
for (var resource in usages) {
|
||||
ok(usages[resource] > 0, "Non-zero usage for " + resource);
|
||||
};
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SpecialPowers.Cc["@mozilla.org/memory-reporter-manager;1"].
|
||||
getService(SpecialPowers.Ci.nsIMemoryReporterManager).
|
||||
getReports(handleReport, null, finished, null, /* anonymized = */ false);
|
||||
|
||||
</script>
|
||||
</html>
|
|
@ -413,10 +413,10 @@ MediaEngineRemoteVideoSource::ChooseCapability(const MediaTrackConstraints &aCon
|
|||
case dom::MediaSourceEnum::Window:
|
||||
case dom::MediaSourceEnum::Application: {
|
||||
FlattenedConstraints c(aConstraints);
|
||||
mCapability.width = c.mWidth.Clamp(c.mWidth.mIdeal.WasPassed() ?
|
||||
c.mWidth.mIdeal.Value() : aPrefs.mWidth);
|
||||
mCapability.height = c.mHeight.Clamp(c.mHeight.mIdeal.WasPassed() ?
|
||||
c.mHeight.mIdeal.Value() : aPrefs.mHeight);
|
||||
mCapability.width = ((c.mWidth.mIdeal.WasPassed() ?
|
||||
c.mWidth.mIdeal.Value() : 0) & 0xffff) << 16 | (c.mWidth.mMax & 0xffff);
|
||||
mCapability.height = ((c.mHeight.mIdeal.WasPassed() ?
|
||||
c.mHeight.mIdeal.Value() : 0) & 0xffff) << 16 | (c.mHeight.mMax & 0xffff);
|
||||
mCapability.maxFPS = c.mFrameRate.Clamp(c.mFrameRate.mIdeal.WasPassed() ?
|
||||
c.mFrameRate.mIdeal.Value() : aPrefs.mFPS);
|
||||
return true;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче