Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2015-11-09 15:00:54 +01:00
Родитель a261720fe8 4d6f05d2f8
Коммит 3d1c284b12
487 изменённых файлов: 20467 добавлений и 8772 удалений

Просмотреть файл

@ -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)))

Просмотреть файл

@ -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;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше