mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-05 16:46:26 +00:00
Merge m-c to b2g-inbound a=merge
This commit is contained in:
commit
6736a62c9f
4
CLOBBER
4
CLOBBER
@ -22,4 +22,6 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Clobber to make sure any residual damage from bug 975011 is gone.
|
||||
Bug 800200: Removing the old JavaScript debugging API, js/jsd. I'm advised
|
||||
that our build system doesn't cope well with deletions, and that a spoonful
|
||||
of clobber helps the medicine go down (in a most delightful way).
|
||||
|
@ -24,14 +24,14 @@ add_task(function() {
|
||||
ok(CustomizableUI.inDefaultState, "Everything should be in its default state");
|
||||
|
||||
is(bookmarksToolbar.collapsed, true, "Test should start with bookmarks toolbar collapsed");
|
||||
is(bookmarksToolbar.getBoundingClientRect().height, 0, "bookmarksToolbar should have height=0");
|
||||
isnot(tabsToolbar.getBoundingClientRect().height, 0, "TabsToolbar should have non-zero height");
|
||||
ok(bookmarksToolbar.collapsed, "bookmarksToolbar should be collapsed");
|
||||
ok(!tabsToolbar.collapsed, "TabsToolbar should not be collapsed");
|
||||
is(navbar.collapsed, false, "The nav-bar should be shown by default");
|
||||
|
||||
setToolbarVisibility(bookmarksToolbar, true);
|
||||
setToolbarVisibility(navbar, false);
|
||||
isnot(bookmarksToolbar.getBoundingClientRect().height, 0, "bookmarksToolbar should be visible now");
|
||||
ok(navbar.getBoundingClientRect().height <= 1, "navbar should have height=0 or 1 (due to border)");
|
||||
ok(!bookmarksToolbar.collapsed, "bookmarksToolbar should be visible now");
|
||||
ok(navbar.collapsed, "navbar should be collapsed");
|
||||
is(CustomizableUI.inDefaultState, false, "Should no longer be in default state");
|
||||
|
||||
yield startCustomizing();
|
||||
@ -40,8 +40,8 @@ add_task(function() {
|
||||
yield endCustomizing();
|
||||
|
||||
is(bookmarksToolbar.collapsed, true, "Customization reset should restore collapsed-state to the bookmarks toolbar");
|
||||
isnot(tabsToolbar.getBoundingClientRect().height, 0, "TabsToolbar should have non-zero height");
|
||||
is(bookmarksToolbar.getBoundingClientRect().height, 0, "The bookmarksToolbar should have height=0 after reset");
|
||||
ok(!tabsToolbar.collapsed, "TabsToolbar should not be collapsed");
|
||||
ok(bookmarksToolbar.collapsed, "The bookmarksToolbar should be collapsed after reset");
|
||||
ok(CustomizableUI.inDefaultState, "Everything should be back to default state");
|
||||
});
|
||||
|
||||
@ -74,25 +74,25 @@ add_task(function() {
|
||||
// Customization reset should restore collapsed-state to default-collapsed toolbars.
|
||||
add_task(function() {
|
||||
ok(CustomizableUI.inDefaultState, "Everything should be in its default state");
|
||||
is(bookmarksToolbar.getBoundingClientRect().height, 0, "bookmarksToolbar should have height=0");
|
||||
isnot(tabsToolbar.getBoundingClientRect().height, 0, "TabsToolbar should have non-zero height");
|
||||
ok(bookmarksToolbar.collapsed, "bookmarksToolbar should be collapsed");
|
||||
ok(!tabsToolbar.collapsed, "TabsToolbar should not be collapsed");
|
||||
|
||||
setToolbarVisibility(bookmarksToolbar, true);
|
||||
isnot(bookmarksToolbar.getBoundingClientRect().height, 0, "bookmarksToolbar should be visible now");
|
||||
ok(!bookmarksToolbar.collapsed, "bookmarksToolbar should be visible now");
|
||||
is(CustomizableUI.inDefaultState, false, "Should no longer be in default state");
|
||||
|
||||
yield startCustomizing();
|
||||
|
||||
isnot(bookmarksToolbar.getBoundingClientRect().height, 0, "The bookmarksToolbar should be visible before reset");
|
||||
isnot(navbar.getBoundingClientRect().height, 0, "The navbar should be visible before reset");
|
||||
isnot(tabsToolbar.getBoundingClientRect().height, 0, "TabsToolbar should have non-zero height");
|
||||
ok(!bookmarksToolbar.collapsed, "The bookmarksToolbar should be visible before reset");
|
||||
ok(!navbar.collapsed, "The navbar should be visible before reset");
|
||||
ok(!tabsToolbar.collapsed, "TabsToolbar should not be collapsed");
|
||||
|
||||
gCustomizeMode.reset();
|
||||
yield waitForCondition(function() !gCustomizeMode.resetting);
|
||||
|
||||
is(bookmarksToolbar.getBoundingClientRect().height, 0, "The bookmarksToolbar should have height=0 after reset");
|
||||
isnot(tabsToolbar.getBoundingClientRect().height, 0, "TabsToolbar should have non-zero height");
|
||||
isnot(navbar.getBoundingClientRect().height, 0, "The navbar should still be visible after reset");
|
||||
ok(bookmarksToolbar.collapsed, "The bookmarksToolbar should be collapsed after reset");
|
||||
ok(!tabsToolbar.collapsed, "TabsToolbar should not be collapsed");
|
||||
ok(!navbar.collapsed, "The navbar should still be visible after reset");
|
||||
ok(CustomizableUI.inDefaultState, "Everything should be back to default state");
|
||||
yield endCustomizing();
|
||||
});
|
||||
|
@ -139,7 +139,6 @@ loop.shared.models = (function() {
|
||||
throw new Error("Can't start session as it's not ready");
|
||||
}
|
||||
this.session = this.sdk.initSession(this.get("sessionId"));
|
||||
this.listenTo(this.session, "sessionConnected", this._sessionConnected);
|
||||
this.listenTo(this.session, "streamCreated", this._streamCreated);
|
||||
this.listenTo(this.session, "connectionDestroyed",
|
||||
this._connectionDestroyed);
|
||||
@ -147,7 +146,8 @@ loop.shared.models = (function() {
|
||||
this._sessionDisconnected);
|
||||
this.listenTo(this.session, "networkDisconnected",
|
||||
this._networkDisconnected);
|
||||
this.session.connect(this.get("apiKey"), this.get("sessionToken"));
|
||||
this.session.connect(this.get("apiKey"), this.get("sessionToken"),
|
||||
this._onConnectCompletion.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -160,14 +160,22 @@ loop.shared.models = (function() {
|
||||
},
|
||||
|
||||
/**
|
||||
* Session is created.
|
||||
* Manages connection status
|
||||
* triggers apropriate event for connection error/success
|
||||
* http://tokbox.com/opentok/tutorials/connect-session/js/
|
||||
* http://tokbox.com/opentok/tutorials/hello-world/js/
|
||||
* http://tokbox.com/opentok/libraries/client/js/reference/SessionConnectEvent.html
|
||||
*
|
||||
* @param {SessionConnectEvent} event
|
||||
* @param {error|null} error
|
||||
*/
|
||||
_sessionConnected: function(event) {
|
||||
this.trigger("session:connected", event);
|
||||
this.set("ongoing", true);
|
||||
_onConnectCompletion: function(error) {
|
||||
if (error) {
|
||||
this.trigger("session:connection-error", error);
|
||||
this.endSession();
|
||||
} else {
|
||||
this.trigger("session:connected");
|
||||
this.set("ongoing", true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -103,10 +103,22 @@ loop.shared.router = (function(l10n) {
|
||||
this._onPeerHungup);
|
||||
this.listenTo(this._conversation, "session:network-disconnected",
|
||||
this._onNetworkDisconnected);
|
||||
this.listenTo(this._conversation, "session:connection-error",
|
||||
this._notifyError);
|
||||
|
||||
BaseRouter.apply(this, arguments);
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify the user that the connection was not possible
|
||||
* @param {{code: number, message: string}} error
|
||||
*/
|
||||
_notifyError: function(error) {
|
||||
console.log(error);
|
||||
this._notifier.errorL10n("connection_error_see_console_notification");
|
||||
this.endCall();
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts the call. This method should be overriden.
|
||||
*/
|
||||
|
@ -13,6 +13,7 @@ use_latest_firefox.innerHTML=To use Loop, please use the latest version of <a hr
|
||||
incompatible_device=Incompatible device
|
||||
sorry_device_unsupported=Sorry, Loop does not currently support your device.
|
||||
use_firefox_windows_mac_linux=Please open this page using the latest Firefox on Windows, Android, Mac or Linux.
|
||||
connection_error_see_console_notification=Call failed; see console for details.
|
||||
|
||||
[fr]
|
||||
call_has_ended=L'appel est terminé.
|
||||
|
@ -26,7 +26,9 @@ describe("loop.shared.models", function() {
|
||||
apiKey: "apiKey"
|
||||
};
|
||||
fakeSession = _.extend({
|
||||
connect: sandbox.spy(),
|
||||
connect: function () {},
|
||||
endSession: sandbox.stub(),
|
||||
set: sandbox.stub(),
|
||||
disconnect: sandbox.spy(),
|
||||
unpublish: sandbox.spy()
|
||||
}, Backbone.Events);
|
||||
@ -163,12 +165,72 @@ describe("loop.shared.models", function() {
|
||||
sinon.assert.calledOnce(fakeSDK.initSession);
|
||||
});
|
||||
|
||||
describe("Session events", function() {
|
||||
it("should trigger a session:connected event on sessionConnected",
|
||||
function(done) {
|
||||
model.once("session:connected", function(){ done(); });
|
||||
it("should call connect", function() {
|
||||
fakeSession.connect = sandbox.stub();
|
||||
|
||||
fakeSession.trigger("sessionConnected");
|
||||
model.startSession();
|
||||
|
||||
sinon.assert.calledOnce(fakeSession.connect);
|
||||
sinon.assert.calledWithExactly(fakeSession.connect,
|
||||
sinon.match.string, sinon.match.string,
|
||||
sinon.match.func);
|
||||
});
|
||||
|
||||
it("should set ongoing to true when no error is called back",
|
||||
function() {
|
||||
fakeSession.connect = function(key, token, cb) {
|
||||
cb(null);
|
||||
};
|
||||
sinon.stub(model, "set");
|
||||
|
||||
model.startSession();
|
||||
|
||||
sinon.assert.calledWith(model.set, "ongoing", true);
|
||||
});
|
||||
|
||||
it("should trigger session:connected when no error is called back",
|
||||
function() {
|
||||
fakeSession.connect = function(key, token, cb) {
|
||||
cb(null);
|
||||
};
|
||||
sandbox.stub(model, "trigger");
|
||||
|
||||
model.startSession();
|
||||
|
||||
sinon.assert.calledWithExactly(model.trigger, "session:connected");
|
||||
});
|
||||
|
||||
describe("Session events", function() {
|
||||
|
||||
it("should trigger a fail event when an error is called back",
|
||||
function() {
|
||||
fakeSession.connect = function(key, token, cb) {
|
||||
cb({
|
||||
error: true
|
||||
});
|
||||
};
|
||||
sinon.stub(model, "endSession");
|
||||
|
||||
model.startSession();
|
||||
|
||||
sinon.assert.calledOnce(model.endSession);
|
||||
sinon.assert.calledWithExactly(model.endSession);
|
||||
});
|
||||
|
||||
it("should trigger session:connection-error event when an error is" +
|
||||
" called back", function() {
|
||||
fakeSession.connect = function(key, token, cb) {
|
||||
cb({
|
||||
error: true
|
||||
});
|
||||
};
|
||||
sandbox.stub(model, "trigger");
|
||||
|
||||
model.startSession();
|
||||
|
||||
sinon.assert.calledOnce(model.trigger);
|
||||
sinon.assert.calledWithExactly(model.trigger,
|
||||
"session:connection-error", sinon.match.object);
|
||||
});
|
||||
|
||||
it("should trigger a session:ended event on sessionDisconnected",
|
||||
|
@ -125,6 +125,24 @@ describe("loop.shared.router", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("session:connection-error", function() {
|
||||
|
||||
it("should warn the user when .connect() call fails", function() {
|
||||
conversation.trigger("session:connection-error");
|
||||
|
||||
sinon.assert.calledOnce(notifier.errorL10n);
|
||||
sinon.assert.calledWithExactly(notifier.errorL10n, sinon.match.string);
|
||||
});
|
||||
|
||||
it("should invoke endCall()", function() {
|
||||
conversation.trigger("session:connection-error");
|
||||
|
||||
sinon.assert.calledOnce(router.endCall);
|
||||
sinon.assert.calledWithExactly(router.endCall);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("should call startCall() once the call session is ready", function() {
|
||||
conversation.trigger("session:ready");
|
||||
|
||||
|
@ -11,7 +11,7 @@ for platform in all_platforms:
|
||||
whitelist['nightly'][platform] = [
|
||||
'ac_add_options --enable-update-channel=nightly',
|
||||
'ac_add_options --enable-profiling',
|
||||
'mk_add_options CLIENT_PY_ARGS="--hg-options=\'--verbose --time\' --hgtool=../tools/buildfarm/utils/hgtool.py --skip-chatzilla --skip-comm --skip-inspector --skip-venkman --tinderbox-print"'
|
||||
'mk_add_options CLIENT_PY_ARGS="--hg-options=\'--verbose --time\' --hgtool=../tools/buildfarm/utils/hgtool.py --skip-chatzilla --skip-comm --skip-inspector --tinderbox-print"'
|
||||
]
|
||||
|
||||
for platform in ['linux32', 'linux64', 'macosx-universal']:
|
||||
|
@ -277,9 +277,10 @@ DevTools.prototype = {
|
||||
});
|
||||
|
||||
// If we were asked for a specific tool then we need to wait for the
|
||||
// tool to be ready, otherwise we can just wait for toolbox open
|
||||
// tool to be ready and selected, otherwise we can just wait for the
|
||||
// toolbox open promise.
|
||||
if (toolId != null) {
|
||||
toolbox.once(toolId + "-ready", (event, panel) => {
|
||||
toolbox.once(toolId + "-selected", (event, panel) => {
|
||||
this.emit("toolbox-ready", toolbox);
|
||||
deferred.resolve(toolbox);
|
||||
});
|
||||
|
@ -39,13 +39,7 @@ function runTests(aTab) {
|
||||
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
|
||||
gDevTools.showToolbox(target, toolId).then(function(toolbox) {
|
||||
// Wait for the test tool to be visible and selected.
|
||||
let { promise: testToolShown, resolve } = promise.defer();
|
||||
toolbox.once("test-tool-selected", resolve);
|
||||
|
||||
return testToolShown.then(() => toolbox);
|
||||
}).then(function (toolbox) {
|
||||
gDevTools.showToolbox(target, toolId).then(function (toolbox) {
|
||||
is(toolbox.target, target, "toolbox target is correct");
|
||||
is(toolbox._host.hostTab, gBrowser.selectedTab, "toolbox host is correct");
|
||||
continueTests(toolbox);
|
||||
|
@ -53,10 +53,8 @@ function testToggle() {
|
||||
target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target, "styleeditor").then(function(aToolbox) {
|
||||
toolbox = aToolbox;
|
||||
aToolbox.once("styleeditor-selected", () => {
|
||||
is(toolbox.currentToolId, "styleeditor", "The style editor is selected");
|
||||
finishUp();
|
||||
});
|
||||
is(toolbox.currentToolId, "styleeditor", "The style editor is selected");
|
||||
finishUp();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -24,7 +24,9 @@ function test() {
|
||||
}
|
||||
|
||||
function testShortcuts(aToolbox, aIndex) {
|
||||
if (aIndex == toolIDs.length) {
|
||||
if (aIndex === undefined) {
|
||||
aIndex = 1;
|
||||
} else if (aIndex == toolIDs.length) {
|
||||
aIndex = 0;
|
||||
if (secondTime) {
|
||||
secondTime = false;
|
||||
@ -55,20 +57,14 @@ function testShortcuts(aToolbox, aIndex) {
|
||||
|
||||
toolbox.once("select", onSelect);
|
||||
|
||||
if (aIndex != null) {
|
||||
// This if block is to allow the call of onSelect without shortcut press for
|
||||
// the first time. That happens because on opening of toolbox, one tool gets
|
||||
// selected atleast.
|
||||
|
||||
let key = (reverse ? prevKey: nextKey);
|
||||
let modifiers = {
|
||||
accelKey: true
|
||||
};
|
||||
idIndex = aIndex;
|
||||
info("Testing shortcut to switch to tool " + aIndex + ":" + toolIDs[aIndex] +
|
||||
" using key " + key);
|
||||
EventUtils.synthesizeKey(key, modifiers, toolbox.doc.defaultView);
|
||||
}
|
||||
let key = (reverse ? prevKey: nextKey);
|
||||
let modifiers = {
|
||||
accelKey: true
|
||||
};
|
||||
idIndex = aIndex;
|
||||
info("Testing shortcut to switch to tool " + aIndex + ":" + toolIDs[aIndex] +
|
||||
" using key " + key);
|
||||
EventUtils.synthesizeKey(key, modifiers, toolbox.doc.defaultView);
|
||||
}
|
||||
|
||||
function onSelect(event, id) {
|
||||
|
@ -41,7 +41,9 @@ function test() {
|
||||
}
|
||||
|
||||
function testShortcuts(aToolbox, aIndex) {
|
||||
if (aIndex == toolIDs.length) {
|
||||
if (aIndex === undefined) {
|
||||
aIndex = 1;
|
||||
} else if (aIndex == toolIDs.length) {
|
||||
tidyUp();
|
||||
return;
|
||||
}
|
||||
@ -51,23 +53,17 @@ function testShortcuts(aToolbox, aIndex) {
|
||||
|
||||
toolbox.once("select", selectCB);
|
||||
|
||||
if (aIndex != null) {
|
||||
// This if block is to allow the call of selectCB without shortcut press for
|
||||
// the first time. That happens because on opening of toolbox, one tool gets
|
||||
// selected atleast.
|
||||
|
||||
let key = gDevTools._tools.get(toolIDs[aIndex]).key;
|
||||
let toolModifiers = gDevTools._tools.get(toolIDs[aIndex]).modifiers;
|
||||
let modifiers = {
|
||||
accelKey: toolModifiers.contains("accel"),
|
||||
altKey: toolModifiers.contains("alt"),
|
||||
shiftKey: toolModifiers.contains("shift"),
|
||||
};
|
||||
idIndex = aIndex;
|
||||
info("Testing shortcut for tool " + aIndex + ":" + toolIDs[aIndex] +
|
||||
" using key " + key);
|
||||
EventUtils.synthesizeKey(key, modifiers, toolbox.doc.defaultView.parent);
|
||||
}
|
||||
let key = gDevTools._tools.get(toolIDs[aIndex]).key;
|
||||
let toolModifiers = gDevTools._tools.get(toolIDs[aIndex]).modifiers;
|
||||
let modifiers = {
|
||||
accelKey: toolModifiers.contains("accel"),
|
||||
altKey: toolModifiers.contains("alt"),
|
||||
shiftKey: toolModifiers.contains("shift"),
|
||||
};
|
||||
idIndex = aIndex;
|
||||
info("Testing shortcut for tool " + aIndex + ":" + toolIDs[aIndex] +
|
||||
" using key " + key);
|
||||
EventUtils.synthesizeKey(key, modifiers, toolbox.doc.defaultView.parent);
|
||||
}
|
||||
|
||||
function selectCB(event, id) {
|
||||
|
@ -187,6 +187,7 @@ InspectorPanel.prototype = {
|
||||
this.selection.setNodeFront(null);
|
||||
this._destroyMarkup();
|
||||
this.isDirty = false;
|
||||
this._pendingSelection = null;
|
||||
},
|
||||
|
||||
_getPageStyle: function() {
|
||||
@ -204,18 +205,35 @@ InspectorPanel.prototype = {
|
||||
}
|
||||
let walker = this.walker;
|
||||
let rootNode = null;
|
||||
let pendingSelection = this._pendingSelection;
|
||||
|
||||
// A helper to tell if the target has or is about to navigate.
|
||||
// this._pendingSelection changes on "will-navigate" and "new-root" events.
|
||||
let hasNavigated = () => pendingSelection !== this._pendingSelection;
|
||||
|
||||
// If available, set either the previously selected node or the body
|
||||
// as default selected, else set documentElement
|
||||
return walker.getRootNode().then(aRootNode => {
|
||||
if (hasNavigated()) {
|
||||
return promise.reject("navigated; resolution of _defaultNode aborted");
|
||||
}
|
||||
|
||||
rootNode = aRootNode;
|
||||
return walker.querySelector(rootNode, this.selectionCssSelector);
|
||||
}).then(front => {
|
||||
if (hasNavigated()) {
|
||||
return promise.reject("navigated; resolution of _defaultNode aborted");
|
||||
}
|
||||
|
||||
if (front) {
|
||||
return front;
|
||||
}
|
||||
return walker.querySelector(rootNode, "body");
|
||||
}).then(front => {
|
||||
if (hasNavigated()) {
|
||||
return promise.reject("navigated; resolution of _defaultNode aborted");
|
||||
}
|
||||
|
||||
if (front) {
|
||||
return front;
|
||||
}
|
||||
@ -339,7 +357,7 @@ InspectorPanel.prototype = {
|
||||
});
|
||||
};
|
||||
this._pendingSelection = onNodeSelected;
|
||||
this._getDefaultNodeForSelection().then(onNodeSelected);
|
||||
this._getDefaultNodeForSelection().then(onNodeSelected, console.error);
|
||||
},
|
||||
|
||||
_selectionCssSelector: null,
|
||||
|
@ -703,7 +703,9 @@ var ProjectEditor = Class({
|
||||
*/
|
||||
set menuEnabled(val) {
|
||||
this._menuEnabled = val;
|
||||
this._updateMenuItems();
|
||||
if (this._loaded) {
|
||||
this._updateMenuItems();
|
||||
}
|
||||
},
|
||||
|
||||
get menuEnabled() {
|
||||
|
@ -1953,8 +1953,10 @@ Widgets.JSObject.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
|
||||
*/
|
||||
_anchor: function(text, options = {})
|
||||
{
|
||||
if (!options.onClick && !options.href) {
|
||||
options.onClick = this._onClick;
|
||||
if (!options.onClick) {
|
||||
// If the anchor has an URL, open it in a new tab. If not, show the
|
||||
// current object actor.
|
||||
options.onClick = options.href ? this._onClickAnchor : this._onClick;
|
||||
}
|
||||
|
||||
let anchor = this.el("a", {
|
||||
@ -1963,7 +1965,7 @@ Widgets.JSObject.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
|
||||
href: options.href || "#",
|
||||
}, text);
|
||||
|
||||
this.message._addLinkCallback(anchor, !options.href ? options.onClick : null);
|
||||
this.message._addLinkCallback(anchor, options.onClick);
|
||||
|
||||
if (options.appendTo) {
|
||||
options.appendTo.appendChild(anchor);
|
||||
|
@ -492,8 +492,8 @@ WebConsole.prototype = {
|
||||
});
|
||||
return;
|
||||
}
|
||||
toolbox.selectTool("webconsole");
|
||||
this.viewSource(aSourceURL, aSourceLine);
|
||||
toolbox.selectTool("webconsole")
|
||||
.then(() => this.viewSource(aSourceURL, aSourceLine));
|
||||
}
|
||||
|
||||
// If the Debugger was already open, switch to it and try to show the
|
||||
|
@ -258,6 +258,7 @@ run-if = os == "mac"
|
||||
[browser_webconsole_netlogging.js]
|
||||
[browser_webconsole_network_panel.js]
|
||||
[browser_webconsole_notifications.js]
|
||||
[browser_webconsole_open-links-without-callback.js]
|
||||
[browser_webconsole_output_copy_newlines.js]
|
||||
[browser_webconsole_output_order.js]
|
||||
[browser_webconsole_property_provider.js]
|
||||
|
@ -0,0 +1,50 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that if a link without an onclick callback is clicked the link is
|
||||
// opened in a new tab and no exception occurs (bug 999236).
|
||||
|
||||
function test() {
|
||||
function* runner() {
|
||||
const TEST_EVAL_STRING = "document";
|
||||
const TEST_PAGE_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
|
||||
const {tab} = yield loadTab(TEST_PAGE_URI);
|
||||
const hud = yield openConsole(tab);
|
||||
|
||||
hud.jsterm.execute(TEST_EVAL_STRING);
|
||||
|
||||
const EXPECTED_OUTPUT = new RegExp("HTMLDocument \.+");
|
||||
|
||||
let messages = yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
name: "JS eval output",
|
||||
text: EXPECTED_OUTPUT,
|
||||
category: CATEGORY_OUTPUT,
|
||||
}],
|
||||
});
|
||||
|
||||
let messageNode = messages[0].matched.values().next().value;
|
||||
|
||||
// The correct anchor is second in the message node; the first anchor has
|
||||
// class .cm-variable. Ignore the first one by not matching anchors that
|
||||
// have the class .cm-variable.
|
||||
let urlNode = messageNode.querySelector("a:not(.cm-variable)");
|
||||
|
||||
let linkOpened = false;
|
||||
let oldOpenUILinkIn = window.openUILinkIn;
|
||||
window.openUILinkIn = function(aLink) {
|
||||
if (aLink == TEST_PAGE_URI) {
|
||||
linkOpened = true;
|
||||
}
|
||||
}
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(urlNode, {}, hud.iframeWindow);
|
||||
|
||||
ok(linkOpened, "Clicking the URL opens the desired page");
|
||||
window.openUILinkIn = oldOpenUILinkIn;
|
||||
}
|
||||
|
||||
Task.spawn(runner).then(finishTest);
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
const Cu = Components.utils;
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm");
|
||||
const {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
const {GetAvailableAddons} = require("devtools/webide/addons");
|
||||
const {GetAvailableAddons, ForgetAddonsList} = require("devtools/webide/addons");
|
||||
const Strings = Services.strings.createBundle("chrome://webide/content/webide.properties");
|
||||
|
||||
window.addEventListener("load", function onLoad() {
|
||||
@ -20,6 +20,11 @@ window.addEventListener("load", function onLoad() {
|
||||
});
|
||||
}, true);
|
||||
|
||||
window.addEventListener("unload", function onUnload() {
|
||||
window.removeEventListener("unload", onUnload);
|
||||
ForgetAddonsList();
|
||||
}, true);
|
||||
|
||||
function CloseUI() {
|
||||
window.parent.UI.openProject();
|
||||
}
|
||||
|
@ -27,9 +27,8 @@ const Strings = Services.strings.createBundle("chrome://webide/content/webide.pr
|
||||
const HTML = "http://www.w3.org/1999/xhtml";
|
||||
const HELP_URL = "https://developer.mozilla.org/Firefox_OS/Using_the_App_Manager#Troubleshooting";
|
||||
|
||||
// download some JSON early.
|
||||
// download template index early
|
||||
GetTemplatesJSON(true);
|
||||
GetAddonsJSON(true);
|
||||
|
||||
// See bug 989619
|
||||
console.log = console.log.bind(console);
|
||||
|
@ -66,7 +66,7 @@ let GetAvailableAddons = exports.GetAvailableAddons = function() {
|
||||
simulators: [],
|
||||
adb: null
|
||||
}
|
||||
GetAddonsJSON().then(json => {
|
||||
GetAddonsJSON(true).then(json => {
|
||||
for (let stability in json) {
|
||||
for (let version of json[stability]) {
|
||||
addons.simulators.push(new SimulatorAddon(stability, version));
|
||||
@ -82,6 +82,10 @@ let GetAvailableAddons = exports.GetAvailableAddons = function() {
|
||||
return GetAvailableAddons_promise;
|
||||
}
|
||||
|
||||
exports.ForgetAddonsList = function() {
|
||||
GetAvailableAddons_promise = null;
|
||||
}
|
||||
|
||||
function Addon() {}
|
||||
Addon.prototype = {
|
||||
_status: "unknown",
|
||||
|
@ -5,8 +5,7 @@
|
||||
body {
|
||||
margin: 0;
|
||||
background-color: white;
|
||||
font-family: Lucida Grande, Helvetica, Helvetica Neue, sans-serif;
|
||||
font-size: 12px;
|
||||
font: message-box;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
@ -30,6 +29,7 @@ h1, h3, p {
|
||||
border-style: solid;
|
||||
margin: 0;
|
||||
padding: 0 12px;
|
||||
font-family: inherit;
|
||||
font-weight: bold;
|
||||
height: 24px;
|
||||
}
|
||||
|
@ -34,7 +34,10 @@ window:not(.busy) #action-busy {
|
||||
/* Panel buttons */
|
||||
|
||||
.panel-button {
|
||||
-moz-appearance: none;
|
||||
-moz-box-align: center;
|
||||
border-width: 0;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.panel-button-anchor {
|
||||
@ -123,6 +126,7 @@ panel > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding: 3px 12px;
|
||||
margin: 0;
|
||||
-moz-appearance: none;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.panel-item-help {
|
||||
|
@ -84,10 +84,6 @@ ifneq (,$(filter WINNT Darwin Android,$(OS_TARGET)))
|
||||
DEFINES += -DMOZ_SHARED_MOZGLUE=1
|
||||
endif
|
||||
|
||||
ifdef MOZ_JSDEBUGGER
|
||||
DEFINES += -DMOZ_JSDEBUGGER
|
||||
endif
|
||||
|
||||
ifdef NECKO_WIFI
|
||||
DEFINES += -DNECKO_WIFI
|
||||
endif
|
||||
|
@ -247,9 +247,6 @@
|
||||
@BINPATH@/components/inspector.xpt
|
||||
@BINPATH@/components/intl.xpt
|
||||
@BINPATH@/components/jar.xpt
|
||||
#ifdef MOZ_JSDEBUGGER
|
||||
@BINPATH@/components/jsdservice.xpt
|
||||
#endif
|
||||
@BINPATH@/components/jsdebugger.xpt
|
||||
@BINPATH@/components/jsdownloads.xpt
|
||||
@BINPATH@/components/jsinspector.xpt
|
||||
|
@ -28,3 +28,5 @@ close_window=Close this window
|
||||
|
||||
cannot_start_call_session_not_ready=Can't start call, session is not ready.
|
||||
network_disconnected=The network connection terminated abruptly.
|
||||
|
||||
connection_error_see_console_notification=Call failed; see console for details.
|
||||
|
@ -31,11 +31,6 @@ leak:GI___strdup
|
||||
### Many leaks only affect some test suites. The suite annotations are not checked.
|
||||
###
|
||||
|
||||
# Bug 800200 - JSD1 is leaking, but it is about to be removed, so ignore it. m4
|
||||
leak:jsd_CreateLock
|
||||
leak:jsdScript::GetExecutableLines
|
||||
leak:jsdService::ActivateDebugger
|
||||
|
||||
# Bug 979928 - WebRTC is leaky. m2, m3
|
||||
leak:/media/mtransport/
|
||||
leak:/media/webrtc/signaling/
|
||||
|
18
configure.in
18
configure.in
@ -3849,7 +3849,6 @@ MOZ_BRANDING_DIRECTORY=
|
||||
MOZ_OFFICIAL_BRANDING=
|
||||
MOZ_FEEDS=1
|
||||
MOZ_WEBAPP_RUNTIME=
|
||||
MOZ_JSDEBUGGER=1
|
||||
MOZ_AUTH_EXTENSION=1
|
||||
MOZ_RAW=
|
||||
MOZ_VORBIS=
|
||||
@ -4944,15 +4943,6 @@ if test -n "$MOZ_ANDROID_BEAM"; then
|
||||
AC_DEFINE(MOZ_ANDROID_BEAM)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = JS Debugger XPCOM component (js/jsd)
|
||||
dnl ========================================================
|
||||
MOZ_ARG_DISABLE_BOOL(jsd,
|
||||
[ --disable-jsd Disable JavaScript debug library],
|
||||
MOZ_JSDEBUGGER=,
|
||||
MOZ_JSDEBUGGER=1)
|
||||
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable IPDL's "expensive" unit tests
|
||||
dnl ========================================================
|
||||
@ -6182,11 +6172,6 @@ if test `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
|
||||
fi
|
||||
AC_SUBST(MOZ_GIO_COMPONENT)
|
||||
|
||||
if test -z "$MOZ_JSDEBUGGER" -a `echo "$MOZ_EXTENSIONS" | grep -c venkman` -ne 0; then
|
||||
AC_MSG_WARN([Cannot build venkman without JavaScript debug library. Removing venkman from MOZ_EXTENSIONS.])
|
||||
MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|venkman||'`
|
||||
fi
|
||||
|
||||
dnl Remove dupes
|
||||
MOZ_EXTENSIONS=`${PERL} ${srcdir}/build/unix/uniq.pl ${MOZ_EXTENSIONS}`
|
||||
|
||||
@ -8195,7 +8180,7 @@ if test "$MOZ_XUL"; then
|
||||
AC_DEFINE(MOZ_XUL)
|
||||
else
|
||||
dnl remove extensions that require XUL
|
||||
MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's/inspector//' -e 's/venkman//' -e 's/irc//' -e 's/tasks//'`
|
||||
MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's/inspector//' -e 's/irc//' -e 's/tasks//'`
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_XUL)
|
||||
@ -8429,7 +8414,6 @@ AC_SUBST(MOZ_DEBUG_DISABLE_DEFS)
|
||||
AC_SUBST(MOZ_DEBUG_LDFLAGS)
|
||||
AC_SUBST(WARNINGS_AS_ERRORS)
|
||||
AC_SUBST(MOZ_EXTENSIONS)
|
||||
AC_SUBST(MOZ_JSDEBUGGER)
|
||||
AC_SUBST(MOZ_ENABLE_PROFILER_SPS)
|
||||
AC_SUBST(MOZ_JPROF)
|
||||
AC_SUBST(MOZ_SHARK)
|
||||
|
@ -125,7 +125,7 @@ SVGEllipseElement::BuildPath()
|
||||
|
||||
RefPtr<PathBuilder> pathBuilder = CreatePathBuilder();
|
||||
|
||||
ArcToBezier(pathBuilder.get(), Point(x, y), Size(rx, ry), 0, Float(2*M_PI), false);
|
||||
EllipseToBezier(pathBuilder.get(), Point(x, y), Size(rx, ry));
|
||||
|
||||
return pathBuilder->Finish();
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ LOCAL_INCLUDES += [
|
||||
'/js/xpconnect/wrappers',
|
||||
]
|
||||
|
||||
for var in ('MOZ_JSDEBUGGER', 'MOZ_B2G_RIL', 'MOZ_B2G_FM'):
|
||||
for var in ('MOZ_B2G_RIL', 'MOZ_B2G_FM'):
|
||||
if CONFIG[var]:
|
||||
DEFINES[var] = True
|
||||
|
||||
|
@ -230,10 +230,6 @@
|
||||
#include "mozilla/dom/SpeechSynthesis.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_JSDEBUGGER
|
||||
#include "jsdIDebuggerService.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
#include "nsPISocketTransportService.h"
|
||||
#endif
|
||||
@ -10881,7 +10877,6 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
||||
|
||||
// Prioritize the SlowScriptDebug interface over JSD1.
|
||||
nsCOMPtr<nsISlowScriptDebugCallback> debugCallback;
|
||||
bool oldDebugPossible = false;
|
||||
|
||||
if (hasFrame) {
|
||||
const char *debugCID = "@mozilla.org/dom/slow-script-debug;1";
|
||||
@ -10889,33 +10884,9 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
debugService->GetActivationHandler(getter_AddRefs(debugCallback));
|
||||
}
|
||||
|
||||
if (!debugCallback) {
|
||||
oldDebugPossible = js::CanCallContextDebugHandler(cx);
|
||||
#ifdef MOZ_JSDEBUGGER
|
||||
// Get the debugger service if necessary.
|
||||
if (oldDebugPossible) {
|
||||
bool jsds_IsOn = false;
|
||||
const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1";
|
||||
nsCOMPtr<jsdIExecutionHook> jsdHook;
|
||||
nsCOMPtr<jsdIDebuggerService> jsds = do_GetService(jsdServiceCtrID, &rv);
|
||||
|
||||
// Check if there's a user for the debugger service that's 'on' for us
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
jsds->GetDebuggerHook(getter_AddRefs(jsdHook));
|
||||
jsds->GetIsOn(&jsds_IsOn);
|
||||
}
|
||||
|
||||
// If there is a debug handler registered for this runtime AND
|
||||
// ((jsd is on AND has a hook) OR (jsd isn't on (something else debugs)))
|
||||
// then something useful will be done with our request to debug.
|
||||
oldDebugPossible = ((jsds_IsOn && (jsdHook != nullptr)) || !jsds_IsOn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool showDebugButton = debugCallback || oldDebugPossible;
|
||||
bool showDebugButton = !!debugCallback;
|
||||
|
||||
// Get localizable strings
|
||||
nsXPIDLString title, msg, stopButton, waitButton, debugButton, neverShowDlg;
|
||||
@ -11024,10 +10995,6 @@ nsGlobalWindow::ShowSlowScriptDialog()
|
||||
rv = debugCallback->HandleSlowScriptDebug(this);
|
||||
return NS_SUCCEEDED(rv) ? ContinueSlowScript : KillSlowScript;
|
||||
}
|
||||
|
||||
if (oldDebugPossible) {
|
||||
return js_CallContextDebugHandler(cx) ? ContinueSlowScript : KillSlowScript;
|
||||
}
|
||||
}
|
||||
JS_ClearPendingException(cx);
|
||||
return KillSlowScript;
|
||||
|
@ -70,9 +70,6 @@
|
||||
#endif
|
||||
#include "AccessCheck.h"
|
||||
|
||||
#ifdef MOZ_JSDEBUGGER
|
||||
#include "jsdIDebuggerService.h"
|
||||
#endif
|
||||
#ifdef MOZ_LOGGING
|
||||
// Force PR_LOGGING so we can get JS strict warnings even in release builds
|
||||
#define FORCE_PR_LOG 1
|
||||
|
@ -129,13 +129,9 @@ CameraPreferences::PreferenceChanged(const char* aPref, void* aClosure)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (NS_FAILED(rv)) {
|
||||
nsCString msg;
|
||||
msg.AppendPrintf("Failed to update pref '%s' (0x%x)\n", aPref, rv);
|
||||
NS_WARNING(msg.get());
|
||||
DOM_CAMERA_LOGE("Failed to get pref '%s' (0x%x)\n", aPref, rv);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -4,9 +4,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "EventListenerService.h"
|
||||
#ifdef MOZ_JSDEBUGGER
|
||||
#include "jsdIDebuggerService.h"
|
||||
#endif
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
@ -131,35 +128,6 @@ EventListenerInfo::ToSource(nsAString& aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EventListenerInfo::GetDebugObject(nsISupports** aRetVal)
|
||||
{
|
||||
*aRetVal = nullptr;
|
||||
|
||||
#ifdef MOZ_JSDEBUGGER
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<jsdIDebuggerService> jsd =
|
||||
do_GetService("@mozilla.org/js/jsd/debugger-service;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
bool isOn = false;
|
||||
jsd->GetIsOn(&isOn);
|
||||
NS_ENSURE_TRUE(isOn, NS_OK);
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
JS::Rooted<JS::Value> v(cx);
|
||||
if (GetJSVal(cx, ac, &v)) {
|
||||
nsCOMPtr<jsdIValue> jsdValue;
|
||||
rv = jsd->WrapValue(v, getter_AddRefs(jsdValue));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
jsdValue.forget(aRetVal);
|
||||
}
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EventListenerService::GetListenerInfoFor(nsIDOMEventTarget* aEventTarget,
|
||||
uint32_t* aCount,
|
||||
|
@ -144,6 +144,3 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/wifi',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_JSDEBUGGER']:
|
||||
DEFINES['MOZ_JSDEBUGGER'] = True
|
||||
|
@ -12,7 +12,7 @@ interface nsIDOMEventTarget;
|
||||
* An instance of this interface describes how an event listener
|
||||
* was added to an event target.
|
||||
*/
|
||||
[scriptable, uuid(c4776eb7-05bc-49ce-a0ca-6213a346d53a)]
|
||||
[scriptable, uuid(11ba5fd7-8db2-4b1a-9f67-342cfa11afad)]
|
||||
interface nsIEventListenerInfo : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -37,12 +37,6 @@ interface nsIEventListenerInfo : nsISupports
|
||||
* (for example with C++ listeners).
|
||||
*/
|
||||
AString toSource();
|
||||
|
||||
/**
|
||||
* If jsdIDebuggerService is active and the listener is implemented in JS,
|
||||
* this returns the listener as a jsdIValue. Otherwise null.
|
||||
*/
|
||||
nsISupports getDebugObject();
|
||||
};
|
||||
|
||||
[scriptable, uuid(f6964bfb-dabe-4cab-9733-be0ee2bf8171)]
|
||||
|
@ -22,12 +22,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=448602
|
||||
var els, root, l2, l3;
|
||||
|
||||
function runTests() {
|
||||
/*
|
||||
Disabled due to lack of present support for JSD in JM
|
||||
var jsdIDebuggerService = SpecialPowers.Ci.jsdIDebuggerService;
|
||||
var jsd = SpecialPowers.Components.classes['@mozilla.org/js/jsd/debugger-service;1']
|
||||
.getService(jsdIDebuggerService);
|
||||
*/
|
||||
els = SpecialPowers.Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(SpecialPowers.Ci.nsIEventListenerService);
|
||||
|
||||
@ -48,18 +42,6 @@ function runTests() {
|
||||
is(SpecialPowers.unwrap(infos[0].listenerObject), root.onclick,
|
||||
"Should have the right listener object (1)");
|
||||
|
||||
/*
|
||||
var jsdOn = jsd.isOn;
|
||||
if (!jsdOn) {
|
||||
is(infos[0].getDebugObject(), null,
|
||||
"If JSD isn't running, getDebugObject() should return null.")
|
||||
jsd.on();
|
||||
ok(jsd.isOn, "JSD should be running.");
|
||||
}
|
||||
var jsdvalue = infos[0].getDebugObject().QueryInterface(SpecialPowers.Ci.jsdIValue);
|
||||
is(jsdvalue.jsType, 3, "Event listener should be a function! (1)");
|
||||
*/
|
||||
|
||||
root.removeAttribute("onclick");
|
||||
root.setAttribute("onclick", "...invalid script...");
|
||||
SimpleTest.expectUncaughtException(true);
|
||||
@ -84,12 +66,6 @@ function runTests() {
|
||||
is(infos[0].allowsUntrusted, true, "Should allow untrusted events (2)");
|
||||
is(SpecialPowers.unwrap(infos[0].listenerObject), l,
|
||||
"Should have the right listener object (2)");
|
||||
/*
|
||||
jsdvalue = infos[0].getDebugObject().QueryInterface(SpecialPowers.Ci.jsdIValue);
|
||||
is(jsdvalue.jsType, 3, "Event listener should be a function!(2)");
|
||||
is(jsdvalue.getWrappedValue(), l, "Wrong JS value! (1)");
|
||||
*/
|
||||
|
||||
is(infos[1].toSource(), "(function (e) { alert(e); })",
|
||||
"Unexpected serialization (3)");
|
||||
is(infos[1].type, "foo", "Wrong type (3)");
|
||||
@ -98,11 +74,6 @@ function runTests() {
|
||||
is(SpecialPowers.unwrap(infos[1].listenerObject), l,
|
||||
"Should have the right listener object (3)");
|
||||
|
||||
/*
|
||||
jsdvalue2 = infos[1].getDebugObject().QueryInterface(SpecialPowers.Ci.jsdIValue);
|
||||
is(jsdvalue2.jsType, 3, "Event listener should be a function! (3)");
|
||||
is(jsdvalue2.getWrappedValue(), l, "Wrong JS value! (2)");
|
||||
*/
|
||||
root.removeEventListener("foo", l, true);
|
||||
root.removeEventListener("foo", l, false);
|
||||
infos = els.getListenerInfoFor(root, {});
|
||||
@ -142,12 +113,6 @@ function runTests() {
|
||||
|
||||
ok(hasDocumentInChain, "Should have document in event target chain!");
|
||||
ok(hasWindowInChain, "Should have window in event target chain!");
|
||||
/*
|
||||
if (!jsdOn) {
|
||||
jsd.off();
|
||||
ok(!jsd.isOn, "JSD shouldn't be running anymore.");
|
||||
}
|
||||
*/
|
||||
|
||||
try {
|
||||
els.getListenerInfoFor(null, {});
|
||||
|
@ -24,19 +24,31 @@
|
||||
}
|
||||
|
||||
function periodicCheck(type, checkFunc, successMessage, done) {
|
||||
var interval = setInterval(function periodic() {
|
||||
var num = 0;
|
||||
var timeout;
|
||||
function periodic() {
|
||||
if (checkFunc()) {
|
||||
ok(true, type + ' is ' + successMessage);
|
||||
clearInterval(interval);
|
||||
interval = null;
|
||||
done();
|
||||
} else {
|
||||
setupNext();
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
function setupNext() {
|
||||
// exponential backoff on the timer
|
||||
// on a very slow system (like the b2g emulator) a long timeout is
|
||||
// necessary, but we want to run fast if we can
|
||||
timeout = setTimeout(periodic, 200 << num);
|
||||
num++;
|
||||
}
|
||||
|
||||
setupNext();
|
||||
|
||||
return function cancel() {
|
||||
if (interval) {
|
||||
if (timeout) {
|
||||
ok(false, type + ' (' + successMessage + ')' +
|
||||
' failed after waiting full duration');
|
||||
clearInterval(interval);
|
||||
clearTimeout(timeout);
|
||||
done();
|
||||
}
|
||||
};
|
||||
@ -59,16 +71,22 @@
|
||||
var silent = check(constraintApplied, isSilence(view), 'be silence for audio');
|
||||
return sampleCount > 0 && silent;
|
||||
}
|
||||
function disconnect() {
|
||||
source.disconnect();
|
||||
analyser.disconnect();
|
||||
done();
|
||||
}
|
||||
return periodicCheck('audio', testAudio,
|
||||
(constraintApplied ? '' : 'not ') + 'silent', done);
|
||||
(constraintApplied ? '' : 'not ') + 'silent', disconnect);
|
||||
}
|
||||
|
||||
function mkElement(type) {
|
||||
var display = document.getElementById('display');
|
||||
// this makes an unattached element
|
||||
// it's not rendered to save the cycles that costs on b2g emulator
|
||||
// and it gets droped (and GC'd) when the test is done
|
||||
var e = document.createElement(type);
|
||||
e.width = 32;
|
||||
e.height = 24;
|
||||
display.appendChild(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -187,6 +187,50 @@ var commandsPeerConnection = [
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_CHECK_FOR_DUPLICATED_PORTS_IN_SDP',
|
||||
function (test) {
|
||||
var re = /a=candidate.* (UDP|TCP) [\d]+ ([\d\.]+) ([\d]+) typ host/g;
|
||||
|
||||
function _sdpCandidatesIntoArray(sdp) {
|
||||
var regexArray = [];
|
||||
var resultArray = [];
|
||||
while ((regexArray = re.exec(sdp)) !== null) {
|
||||
info("regexArray: " + regexArray);
|
||||
if ((regexArray[1] === "TCP") && (regexArray[3] === "9")) {
|
||||
// As both sides can advertise TCP active connection on port 9 lets
|
||||
// ignore them all together
|
||||
info("Ignoring TCP candidate on port 9");
|
||||
continue;
|
||||
}
|
||||
const triple = regexArray[1] + ":" + regexArray[2] + ":" + regexArray[3];
|
||||
info("triple: " + triple);
|
||||
if (resultArray.indexOf(triple) !== -1) {
|
||||
dump("SDP: " + sdp.replace(/[\r]/g, '') + "\n");
|
||||
ok(false, "This Transport:IP:Port " + triple + " appears twice in the SDP above!");
|
||||
}
|
||||
resultArray.push(triple);
|
||||
}
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
const offerTriples = _sdpCandidatesIntoArray(test._local_offer.sdp);
|
||||
info("Offer ICE host candidates: " + JSON.stringify(offerTriples));
|
||||
|
||||
const answerTriples = _sdpCandidatesIntoArray(test.pcRemote._last_answer.sdp);
|
||||
info("Answer ICE host candidates: " + JSON.stringify(answerTriples));
|
||||
|
||||
for (var i=0; i< offerTriples.length; i++) {
|
||||
if (answerTriples.indexOf(offerTriples[i]) !== -1) {
|
||||
dump("SDP offer: " + test._local_offer.sdp.replace(/[\r]/g, '') + "\n");
|
||||
dump("SDP answer: " + test.pcRemote._last_answer.sdp.replace(/[\r]/g, '') + "\n");
|
||||
ok(false, "This IP:Port " + offerTriples[i] + " appears in SDP offer and answer!");
|
||||
}
|
||||
}
|
||||
|
||||
test.next();
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_SET_LOCAL_DESCRIPTION',
|
||||
function (test) {
|
||||
|
@ -36,8 +36,8 @@ function theTest() {
|
||||
}
|
||||
var cancelAudioCheck = audioIsSilence(withConstraint, stream, checkDone);
|
||||
var cancelVideoCheck = videoIsBlack(withConstraint, stream, checkDone);
|
||||
setTimeout(cancelAudioCheck, 20000);
|
||||
setTimeout(cancelVideoCheck, 20000);
|
||||
setTimeout(cancelAudioCheck, 3*60*1000);
|
||||
setTimeout(cancelVideoCheck, 3*60*1000);
|
||||
}, function(e) {
|
||||
ok(false, 'gUM error: ' + e);
|
||||
});
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/dom/MessagePortBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
|
||||
#include "SharedWorker.h"
|
||||
@ -17,6 +18,7 @@ using mozilla::dom::EventHandlerNonNull;
|
||||
using mozilla::dom::MessagePortBase;
|
||||
using mozilla::dom::Optional;
|
||||
using mozilla::dom::Sequence;
|
||||
using mozilla::dom::AutoNoJSAPI;
|
||||
using namespace mozilla;
|
||||
|
||||
USING_WORKERS_NAMESPACE
|
||||
@ -42,6 +44,28 @@ public:
|
||||
mEvents.SwapElements(aEvents);
|
||||
}
|
||||
|
||||
bool PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
if (mBehavior == WorkerThreadModifyBusyCount) {
|
||||
return aWorkerPrivate->ModifyBusyCount(aCx, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult)
|
||||
{
|
||||
if (!aDispatchResult) {
|
||||
if (mBehavior == WorkerThreadModifyBusyCount) {
|
||||
aWorkerPrivate->ModifyBusyCount(aCx, false);
|
||||
}
|
||||
if (aCx) {
|
||||
JS_ReportPendingException(aCx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
|
||||
};
|
||||
@ -281,6 +305,8 @@ DelayedEventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
mMessagePort->AssertCorrectThread();
|
||||
MOZ_ASSERT(mEvents.Length());
|
||||
|
||||
AutoNoJSAPI nojsapi;
|
||||
|
||||
bool ignored;
|
||||
for (uint32_t i = 0; i < mEvents.Length(); i++) {
|
||||
mMessagePort->DispatchEvent(mEvents[i], &ignored);
|
||||
|
@ -11,20 +11,242 @@
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCxPusher.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "RuntimeService.h"
|
||||
#include "ServiceWorker.h"
|
||||
#include "WorkerInlines.h"
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
NS_IMPL_ISUPPORTS0(ServiceWorkerRegistration)
|
||||
|
||||
UpdatePromise::UpdatePromise()
|
||||
: mState(Pending)
|
||||
{
|
||||
MOZ_COUNT_CTOR(UpdatePromise);
|
||||
}
|
||||
|
||||
UpdatePromise::~UpdatePromise()
|
||||
{
|
||||
MOZ_COUNT_DTOR(UpdatePromise);
|
||||
}
|
||||
|
||||
void
|
||||
UpdatePromise::AddPromise(Promise* aPromise)
|
||||
{
|
||||
MOZ_ASSERT(mState == Pending);
|
||||
mPromises.AppendElement(aPromise);
|
||||
}
|
||||
|
||||
void
|
||||
UpdatePromise::ResolveAllPromises(const nsACString& aScriptSpec, const nsACString& aScope)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(mState == Pending);
|
||||
mState = Resolved;
|
||||
RuntimeService* rs = RuntimeService::GetOrCreateService();
|
||||
MOZ_ASSERT(rs);
|
||||
|
||||
nsTArray<nsTWeakRef<Promise>> array;
|
||||
array.SwapElements(mPromises);
|
||||
for (uint32_t i = 0; i < array.Length(); ++i) {
|
||||
nsTWeakRef<Promise>& pendingPromise = array.ElementAt(i);
|
||||
if (pendingPromise) {
|
||||
nsCOMPtr<nsIGlobalObject> go =
|
||||
do_QueryInterface(pendingPromise->GetParentObject());
|
||||
MOZ_ASSERT(go);
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
JS::Rooted<JSObject*> global(cx, go->GetGlobalJSObject());
|
||||
JSAutoCompartment ac(cx, global);
|
||||
|
||||
GlobalObject domGlobal(cx, global);
|
||||
|
||||
nsRefPtr<ServiceWorker> serviceWorker;
|
||||
nsresult rv = rs->CreateServiceWorker(domGlobal,
|
||||
NS_ConvertUTF8toUTF16(aScriptSpec),
|
||||
aScope,
|
||||
getter_AddRefs(serviceWorker));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
pendingPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||
continue;
|
||||
}
|
||||
|
||||
pendingPromise->MaybeResolve(serviceWorker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UpdatePromise::RejectAllPromises(nsresult aRv)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(mState == Pending);
|
||||
mState = Rejected;
|
||||
|
||||
nsTArray<nsTWeakRef<Promise>> array;
|
||||
array.SwapElements(mPromises);
|
||||
for (uint32_t i = 0; i < array.Length(); ++i) {
|
||||
nsTWeakRef<Promise>& pendingPromise = array.ElementAt(i);
|
||||
if (pendingPromise) {
|
||||
// Since ServiceWorkerContainer is only exposed to windows we can be
|
||||
// certain about this cast.
|
||||
nsCOMPtr<nsPIDOMWindow> window =
|
||||
do_QueryInterface(pendingPromise->GetParentObject());
|
||||
MOZ_ASSERT(window);
|
||||
nsRefPtr<DOMError> domError = new DOMError(window, aRv);
|
||||
pendingPromise->MaybeRejectBrokenly(domError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FinishFetchOnMainThreadRunnable : public nsRunnable
|
||||
{
|
||||
nsMainThreadPtrHandle<ServiceWorkerUpdateInstance> mUpdateInstance;
|
||||
public:
|
||||
FinishFetchOnMainThreadRunnable
|
||||
(const nsMainThreadPtrHandle<ServiceWorkerUpdateInstance>& aUpdateInstance)
|
||||
: mUpdateInstance(aUpdateInstance)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD
|
||||
Run() MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
class FinishSuccessfulFetchWorkerRunnable : public WorkerRunnable
|
||||
{
|
||||
nsMainThreadPtrHandle<ServiceWorkerUpdateInstance> mUpdateInstance;
|
||||
public:
|
||||
FinishSuccessfulFetchWorkerRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsMainThreadPtrHandle<ServiceWorkerUpdateInstance>& aUpdateInstance)
|
||||
: WorkerRunnable(aWorkerPrivate, WorkerThreadModifyBusyCount),
|
||||
mUpdateInstance(aUpdateInstance)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
if (!aWorkerPrivate->WorkerScriptExecutedSuccessfully()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsRefPtr<FinishFetchOnMainThreadRunnable> r =
|
||||
new FinishFetchOnMainThreadRunnable(mUpdateInstance);
|
||||
NS_DispatchToMainThread(r);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Allows newer calls to Update() to 'abort' older calls.
|
||||
// Each call to Update() creates the instance which handles creating the
|
||||
// worker and queues up a runnable to resolve the update promise once the
|
||||
// worker has successfully been parsed.
|
||||
class ServiceWorkerUpdateInstance MOZ_FINAL : public nsISupports
|
||||
{
|
||||
// Owner of this instance.
|
||||
ServiceWorkerRegistration* mRegistration;
|
||||
nsCString mScriptSpec;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
bool mAborted;
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
ServiceWorkerUpdateInstance(ServiceWorkerRegistration *aRegistration,
|
||||
nsPIDOMWindow* aWindow)
|
||||
: mRegistration(aRegistration),
|
||||
// Capture the current script spec in case register() gets called.
|
||||
mScriptSpec(aRegistration->mScriptSpec),
|
||||
mWindow(aWindow),
|
||||
mAborted(false)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
void
|
||||
Abort()
|
||||
{
|
||||
MOZ_ASSERT(!mAborted);
|
||||
mAborted = true;
|
||||
}
|
||||
|
||||
void
|
||||
Update()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
|
||||
nsRefPtr<ServiceWorker> serviceWorker;
|
||||
nsresult rv = swm->CreateServiceWorkerForWindow(mWindow,
|
||||
mScriptSpec,
|
||||
mRegistration->mScope,
|
||||
getter_AddRefs(serviceWorker));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
swm->RejectUpdatePromiseObservers(mRegistration, rv);
|
||||
return;
|
||||
}
|
||||
|
||||
nsMainThreadPtrHandle<ServiceWorkerUpdateInstance> handle =
|
||||
new nsMainThreadPtrHolder<ServiceWorkerUpdateInstance>(this);
|
||||
// FIXME(nsm): Deal with error case (worker failed to download, redirect,
|
||||
// parse) in error handler patch.
|
||||
nsRefPtr<FinishSuccessfulFetchWorkerRunnable> r =
|
||||
new FinishSuccessfulFetchWorkerRunnable(serviceWorker->GetWorkerPrivate(), handle);
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
if (!r->Dispatch(cx)) {
|
||||
swm->RejectUpdatePromiseObservers(mRegistration, NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FetchDone()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
if (mAborted) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
MOZ_ASSERT(swm);
|
||||
swm->FinishFetch(mRegistration, mWindow);
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS0(ServiceWorkerUpdateInstance)
|
||||
|
||||
NS_IMETHODIMP
|
||||
FinishFetchOnMainThreadRunnable::Run()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
mUpdateInstance->FetchDone();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ServiceWorkerRegistration::ServiceWorkerRegistration(const nsACString& aScope)
|
||||
: mScope(aScope),
|
||||
mPendingUninstall(false)
|
||||
{ }
|
||||
|
||||
ServiceWorkerRegistration::~ServiceWorkerRegistration()
|
||||
{ }
|
||||
|
||||
//////////////////////////
|
||||
// ServiceWorkerManager //
|
||||
//////////////////////////
|
||||
@ -89,13 +311,15 @@ public:
|
||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
ServiceWorkerManager::ServiceWorkerDomainInfo* domainInfo =
|
||||
swm->mDomainMap.Get(domain);
|
||||
// FIXME(nsm): Refactor this pattern.
|
||||
// XXXnsm: This pattern can be refactored if we end up using it
|
||||
// often enough.
|
||||
if (!swm->mDomainMap.Get(domain, &domainInfo)) {
|
||||
domainInfo = new ServiceWorkerManager::ServiceWorkerDomainInfo;
|
||||
swm->mDomainMap.Put(domain, domainInfo);
|
||||
}
|
||||
|
||||
nsRefPtr<ServiceWorkerRegistration> registration = domainInfo->GetRegistration(mScope);
|
||||
nsRefPtr<ServiceWorkerRegistration> registration =
|
||||
domainInfo->GetRegistration(mScope);
|
||||
|
||||
nsCString spec;
|
||||
rv = mScriptURI->GetSpec(spec);
|
||||
@ -107,9 +331,6 @@ public:
|
||||
if (registration) {
|
||||
registration->mPendingUninstall = false;
|
||||
if (spec.Equals(registration->mScriptSpec)) {
|
||||
// FIXME(nsm): Force update on Shift+Reload. Algorithm not specified for
|
||||
// that yet.
|
||||
|
||||
// There is an existing update in progress. Resolve with whatever it
|
||||
// results in.
|
||||
if (registration->HasUpdatePromise()) {
|
||||
@ -117,8 +338,8 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// There is no update in progress and since SW updating is upto the UA, we
|
||||
// will not update right now. Simply resolve with whatever worker we
|
||||
// There is no update in progress and since SW updating is upto the UA,
|
||||
// we will not update right now. Simply resolve with whatever worker we
|
||||
// have.
|
||||
ServiceWorkerInfo info = registration->Newest();
|
||||
if (info.IsValid()) {
|
||||
@ -143,10 +364,16 @@ public:
|
||||
|
||||
registration->mScriptSpec = spec;
|
||||
|
||||
// FIXME(nsm): Call Update. Same bug, different patch.
|
||||
// For now if the registration reaches this spot, the promise remains
|
||||
// unresolved.
|
||||
return NS_OK;
|
||||
rv = swm->Update(registration, mWindow);
|
||||
MOZ_ASSERT(registration->HasUpdatePromise());
|
||||
|
||||
// We append this register() call's promise after calling Update() because
|
||||
// we don't want this one to be aborted when the others (existing updates
|
||||
// for the same registration) are aborted. Update() sets a new
|
||||
// UpdatePromise on the registration.
|
||||
registration->mUpdatePromise->AddPromise(mPromise);
|
||||
|
||||
return rv;
|
||||
}
|
||||
};
|
||||
|
||||
@ -154,7 +381,8 @@ public:
|
||||
// automatically reject the Promise.
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::Register(nsIDOMWindow* aWindow, const nsAString& aScope,
|
||||
const nsAString& aScriptURL, nsISupports** aPromise)
|
||||
const nsAString& aScriptURL,
|
||||
nsISupports** aPromise)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aWindow);
|
||||
@ -206,10 +434,9 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow, const nsAString& aScope,
|
||||
return rv;
|
||||
}
|
||||
|
||||
// https://github.com/slightlyoff/ServiceWorker/issues/262
|
||||
// allowIfInheritsPrincipal: allow data: URLs for now.
|
||||
// Data URLs are not allowed.
|
||||
rv = documentPrincipal->CheckMayLoad(scriptURI, true /* report */,
|
||||
true /* allowIfInheritsPrincipal */);
|
||||
false /* allowIfInheritsPrincipal */);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
@ -238,11 +465,51 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow, const nsAString& aScope,
|
||||
return NS_DispatchToCurrentThread(registerRunnable);
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::RejectUpdatePromiseObservers(ServiceWorkerRegistration* aRegistration,
|
||||
nsresult aRv)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aRegistration->HasUpdatePromise());
|
||||
aRegistration->mUpdatePromise->RejectAllPromises(aRv);
|
||||
aRegistration->mUpdatePromise = nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update() does not return the Promise that the spec says it should. Callers
|
||||
* may access the registration's (new) Promise after calling this method.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::Update(ServiceWorkerRegistration* aRegistration,
|
||||
nsPIDOMWindow* aWindow)
|
||||
{
|
||||
// FIXME(nsm): Same bug, different patch.
|
||||
if (aRegistration->HasUpdatePromise()) {
|
||||
NS_WARNING("Already had a UpdatePromise. Aborting that one!");
|
||||
RejectUpdatePromiseObservers(aRegistration, NS_ERROR_DOM_ABORT_ERR);
|
||||
MOZ_ASSERT(aRegistration->mUpdateInstance);
|
||||
aRegistration->mUpdateInstance->Abort();
|
||||
aRegistration->mUpdateInstance = nullptr;
|
||||
}
|
||||
|
||||
if (aRegistration->mInstallingWorker.IsValid()) {
|
||||
// FIXME(nsm): Terminate the worker. We still haven't figured out worker
|
||||
// instance ownership when not associated with a window, so let's wait on
|
||||
// this.
|
||||
// FIXME(nsm): We should be setting the state on the actual worker
|
||||
// instance.
|
||||
// FIXME(nsm): Fire "statechange" on installing worker instance.
|
||||
aRegistration->mInstallingWorker.Invalidate();
|
||||
}
|
||||
|
||||
aRegistration->mUpdatePromise = new UpdatePromise();
|
||||
// FIXME(nsm): Bug 931249. If we don't need to fetch & install, resolve
|
||||
// promise and skip this.
|
||||
// FIXME(nsm): Bug 931249. Force cache update if > 1 day.
|
||||
|
||||
aRegistration->mUpdateInstance =
|
||||
new ServiceWorkerUpdateInstance(aRegistration, aWindow);
|
||||
aRegistration->mUpdateInstance->Update();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -266,11 +533,69 @@ ServiceWorkerManager::Unregister(nsIDOMWindow* aWindow, const nsAString& aScope,
|
||||
already_AddRefed<ServiceWorkerManager>
|
||||
ServiceWorkerManager::GetInstance()
|
||||
{
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm = do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
|
||||
nsCOMPtr<nsIServiceWorkerManager> swm =
|
||||
do_GetService(SERVICEWORKERMANAGER_CONTRACTID);
|
||||
nsRefPtr<ServiceWorkerManager> concrete = do_QueryObject(swm);
|
||||
return concrete.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::ResolveRegisterPromises(ServiceWorkerRegistration* aRegistration,
|
||||
const nsACString& aWorkerScriptSpec)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aRegistration->HasUpdatePromise());
|
||||
if (aRegistration->mUpdatePromise->IsRejected()) {
|
||||
aRegistration->mUpdatePromise = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
aRegistration->mUpdatePromise->ResolveAllPromises(aWorkerScriptSpec,
|
||||
aRegistration->mScope);
|
||||
aRegistration->mUpdatePromise = nullptr;
|
||||
}
|
||||
|
||||
// Must NS_Free() aString
|
||||
void
|
||||
ServiceWorkerManager::FinishFetch(ServiceWorkerRegistration* aRegistration,
|
||||
nsPIDOMWindow* aWindow)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
MOZ_ASSERT(aRegistration->HasUpdatePromise());
|
||||
MOZ_ASSERT(aRegistration->mUpdateInstance);
|
||||
aRegistration->mUpdateInstance = nullptr;
|
||||
if (aRegistration->mUpdatePromise->IsRejected()) {
|
||||
aRegistration->mUpdatePromise = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
// We have skipped Steps 3-8.3 of the Update algorithm here!
|
||||
|
||||
nsRefPtr<ServiceWorker> worker;
|
||||
nsresult rv = CreateServiceWorkerForWindow(aWindow,
|
||||
aRegistration->mScriptSpec,
|
||||
aRegistration->mScope,
|
||||
getter_AddRefs(worker));
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
RejectUpdatePromiseObservers(aRegistration, rv);
|
||||
return;
|
||||
}
|
||||
|
||||
ResolveRegisterPromises(aRegistration, aRegistration->mScriptSpec);
|
||||
|
||||
ServiceWorkerInfo info(aRegistration->mScriptSpec);
|
||||
Install(aRegistration, info);
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerManager::Install(ServiceWorkerRegistration* aRegistration,
|
||||
ServiceWorkerInfo aServiceWorkerInfo)
|
||||
{
|
||||
// FIXME(nsm): Same bug, different patch.
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ServiceWorkerManager::CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
|
||||
const nsACString& aScriptSpec,
|
||||
|
@ -23,6 +23,44 @@ namespace dom {
|
||||
namespace workers {
|
||||
|
||||
class ServiceWorker;
|
||||
class ServiceWorkerUpdateInstance;
|
||||
|
||||
/**
|
||||
* UpdatePromise is a utility class that sort of imitates Promise, but not
|
||||
* completely. Using DOM Promise from C++ is a pain when we know the precise types
|
||||
* we're dealing with since it involves dealing with JSAPI. In this case we
|
||||
* also don't (yet) need the 'thenables added after resolution should trigger
|
||||
* immediately' support and other things like that. All we want is something
|
||||
* that works reasonably Promise like and can resolve real DOM Promises added
|
||||
* pre-emptively.
|
||||
*/
|
||||
class UpdatePromise MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
UpdatePromise();
|
||||
~UpdatePromise();
|
||||
|
||||
void AddPromise(Promise* aPromise);
|
||||
void ResolveAllPromises(const nsACString& aScriptSpec, const nsACString& aScope);
|
||||
void RejectAllPromises(nsresult aRv);
|
||||
|
||||
bool
|
||||
IsRejected() const
|
||||
{
|
||||
return mState == Rejected;
|
||||
}
|
||||
|
||||
private:
|
||||
enum {
|
||||
Pending,
|
||||
Resolved,
|
||||
Rejected
|
||||
} mState;
|
||||
|
||||
// XXXnsm: Right now we don't need to support AddPromise() after
|
||||
// already being resolved (i.e. true Promise-like behaviour).
|
||||
nsTArray<nsTWeakRef<Promise>> mPromises;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wherever the spec treats a worker instance and a description of said worker
|
||||
@ -32,7 +70,7 @@ class ServiceWorker;
|
||||
*/
|
||||
class ServiceWorkerInfo
|
||||
{
|
||||
const nsCString mScriptSpec;
|
||||
nsCString mScriptSpec;
|
||||
public:
|
||||
|
||||
bool
|
||||
@ -41,6 +79,12 @@ public:
|
||||
return !mScriptSpec.IsVoid();
|
||||
}
|
||||
|
||||
void
|
||||
Invalidate()
|
||||
{
|
||||
mScriptSpec.SetIsVoid(true);
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
GetScriptSpec() const
|
||||
{
|
||||
@ -49,19 +93,23 @@ public:
|
||||
}
|
||||
|
||||
ServiceWorkerInfo()
|
||||
{ }
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
explicit ServiceWorkerInfo(const nsACString& aScriptSpec)
|
||||
: mScriptSpec(aScriptSpec)
|
||||
{ }
|
||||
};
|
||||
|
||||
class ServiceWorkerRegistration
|
||||
// Needs to inherit from nsISupports because NS_ProxyRelease() does not support
|
||||
// non-ISupports classes.
|
||||
class ServiceWorkerRegistration MOZ_FINAL : public nsISupports
|
||||
{
|
||||
private:
|
||||
~ServiceWorkerRegistration() {}
|
||||
virtual ~ServiceWorkerRegistration();
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(ServiceWorkerRegistration)
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsCString mScope;
|
||||
// The scriptURL for the registration. This may be completely different from
|
||||
@ -72,18 +120,20 @@ public:
|
||||
ServiceWorkerInfo mWaitingWorker;
|
||||
ServiceWorkerInfo mInstallingWorker;
|
||||
|
||||
bool mHasUpdatePromise;
|
||||
nsAutoPtr<UpdatePromise> mUpdatePromise;
|
||||
nsRefPtr<ServiceWorkerUpdateInstance> mUpdateInstance;
|
||||
|
||||
void
|
||||
AddUpdatePromiseObserver(Promise* aPromise)
|
||||
{
|
||||
// FIXME(nsm): Same bug, different patch.
|
||||
MOZ_ASSERT(HasUpdatePromise());
|
||||
mUpdatePromise->AddPromise(aPromise);
|
||||
}
|
||||
|
||||
bool
|
||||
HasUpdatePromise()
|
||||
{
|
||||
return mHasUpdatePromise;
|
||||
return mUpdatePromise;
|
||||
}
|
||||
|
||||
// When unregister() is called on a registration, it is not immediately
|
||||
@ -91,11 +141,7 @@ public:
|
||||
// pendingUninstall and when all controlling documents go away, removed.
|
||||
bool mPendingUninstall;
|
||||
|
||||
explicit ServiceWorkerRegistration(const nsACString& aScope)
|
||||
: mScope(aScope),
|
||||
mHasUpdatePromise(false),
|
||||
mPendingUninstall(false)
|
||||
{ }
|
||||
explicit ServiceWorkerRegistration(const nsACString& aScope);
|
||||
|
||||
ServiceWorkerInfo
|
||||
Newest() const
|
||||
@ -126,6 +172,8 @@ public:
|
||||
class ServiceWorkerManager MOZ_FINAL : public nsIServiceWorkerManager
|
||||
{
|
||||
friend class RegisterRunnable;
|
||||
friend class CallInstallRunnable;
|
||||
friend class ServiceWorkerUpdateInstance;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -174,12 +222,17 @@ public:
|
||||
|
||||
nsClassHashtable<nsCStringHashKey, ServiceWorkerDomainInfo> mDomainMap;
|
||||
|
||||
// FIXME(nsm): What do we do if a page calls for register("/foo_worker.js", { scope: "/*"
|
||||
// }) and then another page calls register("/bar_worker.js", { scope: "/*" })
|
||||
// while the install is in progress. The async install steps for register
|
||||
// bar_worker.js could finish before foo_worker.js, but bar_worker still has
|
||||
// to be the winning controller.
|
||||
// FIXME(nsm): Move this into per domain?
|
||||
void
|
||||
ResolveRegisterPromises(ServiceWorkerRegistration* aRegistration,
|
||||
const nsACString& aWorkerScriptSpec);
|
||||
|
||||
void
|
||||
RejectUpdatePromiseObservers(ServiceWorkerRegistration* aRegistration,
|
||||
nsresult aResult);
|
||||
|
||||
void
|
||||
FinishFetch(ServiceWorkerRegistration* aRegistration,
|
||||
nsPIDOMWindow* aWindow);
|
||||
|
||||
static already_AddRefed<ServiceWorkerManager>
|
||||
GetInstance();
|
||||
@ -191,6 +244,10 @@ private:
|
||||
NS_IMETHOD
|
||||
Update(ServiceWorkerRegistration* aRegistration, nsPIDOMWindow* aWindow);
|
||||
|
||||
void
|
||||
Install(ServiceWorkerRegistration* aRegistration,
|
||||
ServiceWorkerInfo aServiceWorkerInfo);
|
||||
|
||||
NS_IMETHODIMP
|
||||
CreateServiceWorkerForWindow(nsPIDOMWindow* aWindow,
|
||||
const nsACString& aScriptSpec,
|
||||
|
@ -40,6 +40,7 @@ SharedWorker::SharedWorker(nsPIDOMWindow* aWindow,
|
||||
SharedWorker::~SharedWorker()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
Close();
|
||||
MOZ_ASSERT(!mWorkerPrivate);
|
||||
}
|
||||
|
||||
|
6
dom/workers/test/bug998474_worker.js
Normal file
6
dom/workers/test/bug998474_worker.js
Normal file
@ -0,0 +1,6 @@
|
||||
self.addEventListener("connect", function(e) {
|
||||
var port = e.ports[0];
|
||||
port.onmessage = function(e) {
|
||||
port.postMessage(eval(e.data));
|
||||
};
|
||||
});
|
@ -7,6 +7,7 @@ support-files =
|
||||
bug1014466_worker.js
|
||||
bug1020226_worker.js
|
||||
bug1020226_frame.html
|
||||
bug998474_worker.js
|
||||
clearTimeouts_worker.js
|
||||
closeOnGC_server.sjs
|
||||
closeOnGC_worker.js
|
||||
@ -81,10 +82,12 @@ support-files =
|
||||
[test_atob.html]
|
||||
[test_blobConstructor.html]
|
||||
[test_blobWorkers.html]
|
||||
[test_bug1002702.html]
|
||||
[test_bug949946.html]
|
||||
[test_bug1010784.html]
|
||||
[test_bug1014466.html]
|
||||
[test_bug1020226.html]
|
||||
[test_bug998474.html]
|
||||
[test_chromeWorker.html]
|
||||
[test_clearTimeouts.html]
|
||||
[test_close.html]
|
||||
@ -121,6 +124,7 @@ skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_onLine.html]
|
||||
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_promise.html]
|
||||
[test_promise_resolved_with_string.html]
|
||||
[test_recursion.html]
|
||||
[test_recursiveOnerror.html]
|
||||
[test_relativeLoad.html]
|
||||
|
@ -1,2 +1,8 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
worker.js
|
||||
worker2.js
|
||||
worker3.js
|
||||
|
||||
[test_installation_simple.html]
|
||||
[test_navigator.html]
|
||||
|
@ -16,7 +16,7 @@
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function simpleRegister() {
|
||||
var p = navigator.serviceWorker.register("/fake_worker.js");
|
||||
var p = navigator.serviceWorker.register("worker.js");
|
||||
ok(p instanceof Promise, "register() should return a Promise");
|
||||
return Promise.resolve();
|
||||
}
|
||||
@ -50,14 +50,60 @@
|
||||
ok(false, "non-HTTPS pages cannot register ServiceWorkers");
|
||||
}, function(e) {
|
||||
ok(e.name === "SecurityError", "Should fail with a SecurityError");
|
||||
}).then(function() {
|
||||
return new Promise((resolve) => SpecialPowers.popPrefEnv(resolve));
|
||||
});
|
||||
}
|
||||
|
||||
function realWorker() {
|
||||
var p = navigator.serviceWorker.register("worker.js");
|
||||
return p.then(function(w) {
|
||||
ok(w instanceof ServiceWorker, "Register a ServiceWorker");
|
||||
info(w.scope);
|
||||
ok(w.scope == (new URL("/*", document.baseURI)).href, "Scope should match");
|
||||
ok(w.url == (new URL("worker.js", document.baseURI)).href, "URL should be of the worker");
|
||||
}, function(e) {
|
||||
info(e.name);
|
||||
ok(false, "Registration should have succeeded!");
|
||||
});
|
||||
}
|
||||
|
||||
function abortPrevious() {
|
||||
var p = navigator.serviceWorker.register("worker2.js", { scope: "foo/*" });
|
||||
var q = navigator.serviceWorker.register("worker3.js", { scope: "foo/*" });
|
||||
|
||||
return Promise.all([
|
||||
p.then(function(w) {
|
||||
ok(false, "First registration should fail with AbortError");
|
||||
}, function(e) {
|
||||
ok(e.name === "AbortError", "First registration should fail with AbortError");
|
||||
}),
|
||||
|
||||
q.then(function(w) {
|
||||
ok(w instanceof ServiceWorker, "Second registration should succeed");
|
||||
}, function(e) {
|
||||
ok(false, "Second registration should succeed");
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
function networkError404() {
|
||||
return navigator.serviceWorker.register("404.js").then(function(w) {
|
||||
todo(false, "Should fail with NetworkError");
|
||||
}, function(e) {
|
||||
todo(e.name === "NetworkError", "Should fail with NetworkError");
|
||||
});
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
simpleRegister()
|
||||
.then(sameOriginWorker)
|
||||
.then(sameOriginScope)
|
||||
.then(httpsOnly)
|
||||
.then(realWorker)
|
||||
.then(abortPrevious)
|
||||
// FIXME(nsm): Uncomment once we have the error trapping patch from Bug 984048.
|
||||
// .then(networkError404)
|
||||
// put more tests here.
|
||||
.then(function() {
|
||||
SimpleTest.finish();
|
||||
|
1
dom/workers/test/serviceworkers/worker.js
Normal file
1
dom/workers/test/serviceworkers/worker.js
Normal file
@ -0,0 +1 @@
|
||||
// empty worker, always succeed!
|
1
dom/workers/test/serviceworkers/worker2.js
Normal file
1
dom/workers/test/serviceworkers/worker2.js
Normal file
@ -0,0 +1 @@
|
||||
// worker2.js
|
1
dom/workers/test/serviceworkers/worker3.js
Normal file
1
dom/workers/test/serviceworkers/worker3.js
Normal file
@ -0,0 +1 @@
|
||||
// worker3.js
|
27
dom/workers/test/test_bug1002702.html
Normal file
27
dom/workers/test/test_bug1002702.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for bug 1002702</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var port = new SharedWorker('data:application/javascript,1').port;
|
||||
port.close();
|
||||
SpecialPowers.forceGC();
|
||||
ok(true, "No crash \\o/");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
39
dom/workers/test/test_bug998474.html
Normal file
39
dom/workers/test/test_bug998474.html
Normal file
@ -0,0 +1,39 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for bug 998474</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="boom();">
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function boom()
|
||||
{
|
||||
var worker = new SharedWorker("bug998474_worker.js");
|
||||
|
||||
setTimeout(function() {
|
||||
port = worker.port;
|
||||
port.postMessage("");
|
||||
|
||||
setTimeout(function() {
|
||||
port.start();
|
||||
ok(true, "Still alive!");
|
||||
SimpleTest.finish();
|
||||
}, 150);
|
||||
}, 150);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
41
dom/workers/test/test_promise_resolved_with_string.html
Normal file
41
dom/workers/test/test_promise_resolved_with_string.html
Normal file
@ -0,0 +1,41 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1027221
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1027221</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1027221 **/
|
||||
// Set up a permanent atom
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var x = "x";
|
||||
// Trigger some incremental gc
|
||||
SpecialPowers.Cu.getJSTestingFunctions().gcslice(0);
|
||||
|
||||
// Kick off a worker that uses this same atom
|
||||
var w = new Worker("data:text/plain,Promise.resolve('x').then(function() { postMessage(1); });");
|
||||
// Maybe trigger some more incremental gc
|
||||
SpecialPowers.Cu.getJSTestingFunctions().gcslice(0);
|
||||
|
||||
w.onmessage = function() {
|
||||
ok(true, "Got here");
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1027221">Mozilla Bug 1027221</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -620,6 +620,8 @@ public:
|
||||
DrawTarget() : mTransformDirty(false), mPermitSubpixelAA(false) {}
|
||||
virtual ~DrawTarget() {}
|
||||
|
||||
virtual DrawTargetType GetType() const = 0;
|
||||
|
||||
virtual BackendType GetBackendType() const = 0;
|
||||
/**
|
||||
* Returns a SourceSurface which is a snapshot of the current contents of the DrawTarget.
|
||||
|
@ -155,6 +155,13 @@ DrawTargetCG::~DrawTargetCG()
|
||||
CGContextRelease(mCg);
|
||||
}
|
||||
|
||||
DrawTargetType
|
||||
DrawTargetCG::GetType() const
|
||||
{
|
||||
return GetBackendType() == BackendType::COREGRAPHICS_ACCELERATED ?
|
||||
DrawTargetType::HARDWARE_RASTER : DrawTargetType::SOFTWARE_RASTER;
|
||||
}
|
||||
|
||||
BackendType
|
||||
DrawTargetCG::GetBackendType() const
|
||||
{
|
||||
|
@ -100,6 +100,7 @@ public:
|
||||
DrawTargetCG();
|
||||
virtual ~DrawTargetCG();
|
||||
|
||||
virtual DrawTargetType GetType() const MOZ_OVERRIDE;
|
||||
virtual BackendType GetBackendType() const;
|
||||
virtual TemporaryRef<SourceSurface> Snapshot();
|
||||
|
||||
|
@ -372,6 +372,56 @@ DrawTargetCairo::~DrawTargetCairo()
|
||||
MOZ_ASSERT(!mLockedBits);
|
||||
}
|
||||
|
||||
DrawTargetType
|
||||
DrawTargetCairo::GetType() const
|
||||
{
|
||||
if (mContext) {
|
||||
cairo_surface_type_t type = cairo_surface_get_type(mSurface);
|
||||
if (type == CAIRO_SURFACE_TYPE_TEE) {
|
||||
type = cairo_surface_get_type(cairo_tee_surface_index(mSurface, 0));
|
||||
MOZ_ASSERT(type != CAIRO_SURFACE_TYPE_TEE, "C'mon!");
|
||||
MOZ_ASSERT(type == cairo_surface_get_type(cairo_tee_surface_index(mSurface, 1)),
|
||||
"What should we do here?");
|
||||
}
|
||||
switch (type) {
|
||||
case CAIRO_SURFACE_TYPE_PDF:
|
||||
case CAIRO_SURFACE_TYPE_PS:
|
||||
case CAIRO_SURFACE_TYPE_SVG:
|
||||
case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
|
||||
case CAIRO_SURFACE_TYPE_XML:
|
||||
return DrawTargetType::VECTOR;
|
||||
|
||||
case CAIRO_SURFACE_TYPE_VG:
|
||||
case CAIRO_SURFACE_TYPE_GL:
|
||||
case CAIRO_SURFACE_TYPE_GLITZ:
|
||||
case CAIRO_SURFACE_TYPE_QUARTZ:
|
||||
case CAIRO_SURFACE_TYPE_DIRECTFB:
|
||||
return DrawTargetType::HARDWARE_RASTER;
|
||||
|
||||
case CAIRO_SURFACE_TYPE_SKIA:
|
||||
case CAIRO_SURFACE_TYPE_QT:
|
||||
MOZ_ASSERT(false, "Can't determine actual DrawTargetType for DrawTargetCairo - assuming SOFTWARE_RASTER");
|
||||
// fallthrough
|
||||
case CAIRO_SURFACE_TYPE_IMAGE:
|
||||
case CAIRO_SURFACE_TYPE_XLIB:
|
||||
case CAIRO_SURFACE_TYPE_XCB:
|
||||
case CAIRO_SURFACE_TYPE_WIN32:
|
||||
case CAIRO_SURFACE_TYPE_BEOS:
|
||||
case CAIRO_SURFACE_TYPE_OS2:
|
||||
case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE:
|
||||
case CAIRO_SURFACE_TYPE_SCRIPT:
|
||||
case CAIRO_SURFACE_TYPE_RECORDING:
|
||||
case CAIRO_SURFACE_TYPE_DRM:
|
||||
case CAIRO_SURFACE_TYPE_SUBSURFACE:
|
||||
case CAIRO_SURFACE_TYPE_D2D:
|
||||
case CAIRO_SURFACE_TYPE_TEE: // included to silence warning about unhandled enum value
|
||||
return DrawTargetType::SOFTWARE_RASTER;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(false, "Could not determine DrawTargetType for DrawTargetCairo");
|
||||
return DrawTargetType::SOFTWARE_RASTER;
|
||||
}
|
||||
|
||||
IntSize
|
||||
DrawTargetCairo::GetSize()
|
||||
{
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
DrawTargetCairo();
|
||||
virtual ~DrawTargetCairo();
|
||||
|
||||
virtual DrawTargetType GetType() const MOZ_OVERRIDE;
|
||||
virtual BackendType GetBackendType() const { return BackendType::CAIRO; }
|
||||
virtual TemporaryRef<SourceSurface> Snapshot();
|
||||
virtual IntSize GetSize();
|
||||
|
@ -47,6 +47,7 @@ public:
|
||||
DrawTargetD2D();
|
||||
virtual ~DrawTargetD2D();
|
||||
|
||||
virtual DrawTargetType GetType() const MOZ_OVERRIDE { return DrawTargetType::HARDWARE_RASTER; }
|
||||
virtual BackendType GetBackendType() const { return BackendType::DIRECT2D; }
|
||||
virtual TemporaryRef<SourceSurface> Snapshot();
|
||||
virtual IntSize GetSize() { return mSize; }
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
DrawTargetD2D1();
|
||||
virtual ~DrawTargetD2D1();
|
||||
|
||||
virtual DrawTargetType GetType() const MOZ_OVERRIDE { return DrawTargetType::HARDWARE_RASTER; }
|
||||
virtual BackendType GetBackendType() const { return BackendType::DIRECT2D1_1; }
|
||||
virtual TemporaryRef<SourceSurface> Snapshot();
|
||||
virtual IntSize GetSize() { return mSize; }
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
mFormat = aA->GetFormat();
|
||||
}
|
||||
|
||||
virtual DrawTargetType GetType() const MOZ_OVERRIDE { return mA->GetType(); }
|
||||
virtual BackendType GetBackendType() const { return mA->GetBackendType(); }
|
||||
virtual TemporaryRef<SourceSurface> Snapshot() { return new SourceSurfaceDual(mA, mB); }
|
||||
virtual IntSize GetSize() { return mA->GetSize(); }
|
||||
|
@ -19,6 +19,7 @@ public:
|
||||
DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData = false);
|
||||
~DrawTargetRecording();
|
||||
|
||||
virtual DrawTargetType GetType() const MOZ_OVERRIDE { return mFinalDT->GetType(); }
|
||||
virtual BackendType GetBackendType() const { return mFinalDT->GetBackendType(); }
|
||||
|
||||
virtual TemporaryRef<SourceSurface> Snapshot();
|
||||
|
@ -277,12 +277,12 @@ struct AutoPaintSetup {
|
||||
mPaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
|
||||
SkPaint temp;
|
||||
temp.setXfermodeMode(GfxOpToSkiaOp(aOptions.mCompositionOp));
|
||||
temp.setAlpha(U8CPU(aOptions.mAlpha*255+0.5));
|
||||
temp.setAlpha(ColorFloatToByte(aOptions.mAlpha));
|
||||
//TODO: Get a rect here
|
||||
mCanvas->saveLayer(nullptr, &temp);
|
||||
mNeedsRestore = true;
|
||||
} else {
|
||||
mPaint.setAlpha(U8CPU(aOptions.mAlpha*255.0+0.5));
|
||||
mPaint.setAlpha(ColorFloatToByte(aOptions.mAlpha));
|
||||
mAlpha = aOptions.mAlpha;
|
||||
}
|
||||
mPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
|
||||
@ -339,6 +339,17 @@ DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
|
||||
mCanvas->drawBitmapRectToRect(bitmap.mBitmap, &sourceRect, destRect, &paint.mPaint);
|
||||
}
|
||||
|
||||
DrawTargetType
|
||||
DrawTargetSkia::GetType() const
|
||||
{
|
||||
#ifdef USE_SKIA_GPU
|
||||
if (mGrContext) {
|
||||
return DrawTargetType::HARDWARE_RASTER;
|
||||
}
|
||||
#endif
|
||||
return DrawTargetType::SOFTWARE_RASTER;
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetSkia::DrawFilter(FilterNode *aNode,
|
||||
const Rect &aSourceRect,
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
DrawTargetSkia();
|
||||
virtual ~DrawTargetSkia();
|
||||
|
||||
virtual DrawTargetType GetType() const MOZ_OVERRIDE;
|
||||
virtual BackendType GetBackendType() const { return BackendType::SKIA; }
|
||||
virtual TemporaryRef<SourceSurface> Snapshot();
|
||||
virtual IntSize GetSize() { return mSize; }
|
||||
|
@ -21,6 +21,7 @@ public:
|
||||
|
||||
bool Init(const TileSet& mTiles);
|
||||
|
||||
virtual DrawTargetType GetType() const MOZ_OVERRIDE { return mTiles[0].mDrawTarget->GetType(); }
|
||||
virtual BackendType GetBackendType() const { return mTiles[0].mDrawTarget->GetBackendType(); }
|
||||
virtual TemporaryRef<SourceSurface> Snapshot();
|
||||
virtual IntSize GetSize() { return IntSize(mRect.XMost(), mRect.YMost()); }
|
||||
|
@ -235,11 +235,20 @@ GfxOpToSkiaOp(CompositionOp op)
|
||||
}
|
||||
}
|
||||
|
||||
static inline SkColor ColorToSkColor(const Color &color, Float aAlpha)
|
||||
/* There's quite a bit of inconsistency about
|
||||
* whether float colors should be rounded with .5f.
|
||||
* We choose to do it to match cairo which also
|
||||
* happens to match the Direct3D specs */
|
||||
static inline U8CPU ColorFloatToByte(Float color)
|
||||
{
|
||||
//XXX: do a better job converting to int
|
||||
return SkColorSetARGB(U8CPU(color.a*aAlpha*255.0), U8CPU(color.r*255.0),
|
||||
U8CPU(color.g*255.0), U8CPU(color.b*255.0));
|
||||
return U8CPU(color*255.f + .5f);
|
||||
};
|
||||
|
||||
static inline SkColor ColorToSkColor(const Color &color, Float aAlpha)
|
||||
{
|
||||
return SkColorSetARGB(ColorFloatToByte(color.a*aAlpha), ColorFloatToByte(color.r),
|
||||
ColorFloatToByte(color.g), ColorFloatToByte(color.b));
|
||||
}
|
||||
|
||||
static inline SkRect
|
||||
|
@ -83,6 +83,51 @@ void ArcToBezier(T* aSink, const Point &aOrigin, const Size &aRadius,
|
||||
}
|
||||
}
|
||||
|
||||
/* This is basically the ArcToBezier with the parameters for drawing a circle
|
||||
* inlined which vastly simplifies it and avoids a bunch of transcedental function
|
||||
* calls which should make it faster. */
|
||||
template <typename T>
|
||||
void EllipseToBezier(T* aSink, const Point &aOrigin, const Size &aRadius)
|
||||
{
|
||||
Point startPoint(aOrigin.x + aRadius.width,
|
||||
aOrigin.y);
|
||||
|
||||
aSink->LineTo(startPoint);
|
||||
|
||||
// Calculate kappa constant for partial curve. The sign of angle in the
|
||||
// tangent will actually ensure this is negative for a counter clockwise
|
||||
// sweep, so changing signs later isn't needed.
|
||||
Float kappaFactor = (4.0f / 3.0f) * tan((M_PI/2.0f) / 4.0f);
|
||||
Float kappaX = kappaFactor * aRadius.width;
|
||||
Float kappaY = kappaFactor * aRadius.height;
|
||||
Float cosStartAngle = 1;
|
||||
Float sinStartAngle = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// We guarantee here the current point is the start point of the next
|
||||
// curve segment.
|
||||
Point currentStartPoint(aOrigin.x + cosStartAngle * aRadius.width,
|
||||
aOrigin.y + sinStartAngle * aRadius.height);
|
||||
Point currentEndPoint(aOrigin.x + -sinStartAngle * aRadius.width,
|
||||
aOrigin.y + cosStartAngle * aRadius.height);
|
||||
|
||||
Point tangentStart(-sinStartAngle, cosStartAngle);
|
||||
Point cp1 = currentStartPoint;
|
||||
cp1 += Point(tangentStart.x * kappaX, tangentStart.y * kappaY);
|
||||
|
||||
Point revTangentEnd(cosStartAngle, sinStartAngle);
|
||||
Point cp2 = currentEndPoint;
|
||||
cp2 += Point(revTangentEnd.x * kappaX, revTangentEnd.y * kappaY);
|
||||
|
||||
aSink->BezierTo(cp1, cp2, currentEndPoint);
|
||||
|
||||
// cos(x+pi/2) == -sin(x)
|
||||
// sin(x+pi/2) == cos(x)
|
||||
Float tmp = cosStartAngle;
|
||||
cosStartAngle = -sinStartAngle;
|
||||
sinStartAngle = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a path represending a rounded rectangle to the path being built by
|
||||
* aPathBuilder.
|
||||
|
@ -72,6 +72,12 @@ MOZ_BEGIN_ENUM_CLASS(FilterType, int8_t)
|
||||
UNPREMULTIPLY
|
||||
MOZ_END_ENUM_CLASS(FilterType)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(DrawTargetType, int8_t)
|
||||
SOFTWARE_RASTER = 0,
|
||||
HARDWARE_RASTER,
|
||||
VECTOR
|
||||
MOZ_END_ENUM_CLASS(DrawTargetType)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(BackendType, int8_t)
|
||||
NONE = 0,
|
||||
DIRECT2D,
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "LayerSorter.h" // for SortLayersBy3DZOrder
|
||||
#include "LayersLogging.h" // for AppendToString
|
||||
#include "ReadbackLayer.h" // for ReadbackLayer
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
#include "gfxUtils.h" // for gfxUtils, etc
|
||||
#include "gfx2DGlue.h"
|
||||
@ -1232,18 +1231,13 @@ void WriteSnapshotLinkToDumpFile(T* aObj, std::stringstream& aStream)
|
||||
template <typename T>
|
||||
void WriteSnapshotToDumpFile_internal(T* aObj, DataSourceSurface* aSurf)
|
||||
{
|
||||
nsRefPtr<gfxImageSurface> deprecatedSurf =
|
||||
new gfxImageSurface(aSurf->GetData(),
|
||||
ThebesIntSize(aSurf->GetSize()),
|
||||
aSurf->Stride(),
|
||||
SurfaceFormatToImageFormat(aSurf->GetFormat()));
|
||||
nsCString string(aObj->Name());
|
||||
string.Append('-');
|
||||
string.AppendInt((uint64_t)aObj);
|
||||
if (gfxUtils::sDumpPaintFile) {
|
||||
fprintf_stderr(gfxUtils::sDumpPaintFile, "array[\"%s\"]=\"", string.BeginReading());
|
||||
}
|
||||
deprecatedSurf->DumpAsDataURL(gfxUtils::sDumpPaintFile);
|
||||
gfxUtils::DumpAsDataURI(aSurf, gfxUtils::sDumpPaintFile);
|
||||
if (gfxUtils::sDumpPaintFile) {
|
||||
fprintf_stderr(gfxUtils::sDumpPaintFile, "\";");
|
||||
}
|
||||
|
@ -55,6 +55,17 @@ public:
|
||||
uint64_t mAsyncID;
|
||||
};
|
||||
|
||||
void
|
||||
RemoveTextureFromCompositableTracker::ReleaseTextureClient()
|
||||
{
|
||||
if (mTextureClient) {
|
||||
TextureClientReleaseTask* task = new TextureClientReleaseTask(mTextureClient);
|
||||
RefPtr<ISurfaceAllocator> allocator = mTextureClient->GetAllocator();
|
||||
mTextureClient = nullptr;
|
||||
allocator->GetMessageLoop()->PostTask(FROM_HERE, task);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
CompositableClient::TransactionCompleteted(PCompositableChild* aActor, uint64_t aTransactionId)
|
||||
{
|
||||
|
@ -42,22 +42,22 @@ public:
|
||||
~RemoveTextureFromCompositableTracker()
|
||||
{
|
||||
MOZ_COUNT_DTOR(RemoveTextureFromCompositableTracker);
|
||||
ReleaseTextureClient();
|
||||
}
|
||||
|
||||
virtual void Complete() MOZ_OVERRIDE
|
||||
{
|
||||
// The TextureClient's recycling is postponed until the transaction
|
||||
// complete.
|
||||
mTextureClient = nullptr;
|
||||
ReleaseTextureClient();
|
||||
}
|
||||
|
||||
virtual void Cancel() MOZ_OVERRIDE
|
||||
{
|
||||
mTextureClient = nullptr;
|
||||
ReleaseTextureClient();
|
||||
}
|
||||
|
||||
virtual void SetTextureClient(TextureClient* aTextureClient) MOZ_OVERRIDE
|
||||
{
|
||||
ReleaseTextureClient();
|
||||
mTextureClient = aTextureClient;
|
||||
}
|
||||
|
||||
@ -68,6 +68,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void ReleaseTextureClient();
|
||||
|
||||
private:
|
||||
RefPtr<TextureClient> mTextureClient;
|
||||
};
|
||||
|
@ -203,6 +203,7 @@ TextureClient::InitIPDLActor(CompositableForwarder* aForwarder)
|
||||
MOZ_ASSERT(mActor);
|
||||
mActor->mForwarder = aForwarder;
|
||||
mActor->mTextureClient = this;
|
||||
mAllocator = aForwarder;
|
||||
mShared = true;
|
||||
return mActor->IPCOpen();
|
||||
}
|
||||
|
@ -364,7 +364,13 @@ protected:
|
||||
mFlags |= aFlags;
|
||||
}
|
||||
|
||||
ISurfaceAllocator* GetAllocator()
|
||||
{
|
||||
return mAllocator;
|
||||
}
|
||||
|
||||
RefPtr<TextureChild> mActor;
|
||||
RefPtr<ISurfaceAllocator> mAllocator;
|
||||
TextureFlags mFlags;
|
||||
bool mShared;
|
||||
bool mValid;
|
||||
@ -372,10 +378,30 @@ protected:
|
||||
FenceHandle mAcquireFenceHandle;
|
||||
|
||||
friend class TextureChild;
|
||||
friend class RemoveTextureFromCompositableTracker;
|
||||
friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
|
||||
friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Task that releases TextureClient pointer on a specified thread.
|
||||
*/
|
||||
class TextureClientReleaseTask : public Task
|
||||
{
|
||||
public:
|
||||
TextureClientReleaseTask(TextureClient* aClient)
|
||||
: mTextureClient(aClient) {
|
||||
}
|
||||
|
||||
virtual void Run() MOZ_OVERRIDE
|
||||
{
|
||||
mTextureClient = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
mozilla::RefPtr<TextureClient> mTextureClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* TextureClient that wraps a random access buffer such as a Shmem or raw memory.
|
||||
* This class must be inherited to implement the memory allocation and access bits.
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <utility> // for pair
|
||||
#include "ContentHost.h" // for ContentHostDoubleBuffered, etc
|
||||
#include "Effects.h" // for EffectMask, Effect, etc
|
||||
#include "gfxUtils.h"
|
||||
#include "ImageHost.h" // for ImageHostBuffered, etc
|
||||
#include "TiledContentHost.h" // for TiledContentHost
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
||||
@ -227,12 +228,8 @@ CompositableHost::DumpTextureHost(std::stringstream& aStream, TextureHost* aText
|
||||
dSurf->GetSize(),
|
||||
dSurf->Stride(),
|
||||
dSurf->GetFormat());
|
||||
nsRefPtr<gfxASurface> surf = platform->GetThebesSurfaceForDrawTarget(dt);
|
||||
if (!surf) {
|
||||
return;
|
||||
}
|
||||
// TODO stream surface
|
||||
surf->DumpAsDataURL(stderr);
|
||||
gfxUtils::DumpAsDataURI(dt, stderr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -85,7 +85,9 @@ class ISurfaceAllocator : public AtomicRefCountedWithFinalize<ISurfaceAllocator>
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(ISurfaceAllocator)
|
||||
ISurfaceAllocator() {}
|
||||
ISurfaceAllocator()
|
||||
: mDefaultMessageLoop(MessageLoop::current())
|
||||
{}
|
||||
|
||||
void Finalize();
|
||||
|
||||
@ -163,6 +165,11 @@ public:
|
||||
virtual bool IPCOpen() const { return true; }
|
||||
virtual bool IsSameProcess() const = 0;
|
||||
|
||||
virtual MessageLoop * GetMessageLoop() const
|
||||
{
|
||||
return mDefaultMessageLoop;
|
||||
}
|
||||
|
||||
// Returns true if aSurface wraps a Shmem.
|
||||
static bool IsShmem(SurfaceDescriptor* aSurface);
|
||||
|
||||
@ -177,6 +184,8 @@ protected:
|
||||
// This is used to implement an extremely simple & naive heap allocator.
|
||||
std::vector<mozilla::ipc::Shmem> mUsedShmems;
|
||||
|
||||
MessageLoop* mDefaultMessageLoop;
|
||||
|
||||
friend class AtomicRefCountedWithFinalize<ISurfaceAllocator>;
|
||||
};
|
||||
|
||||
|
@ -170,7 +170,7 @@ public:
|
||||
*
|
||||
* Can be called from any thread.
|
||||
*/
|
||||
MessageLoop * GetMessageLoop() const;
|
||||
virtual MessageLoop * GetMessageLoop() const MOZ_OVERRIDE;
|
||||
|
||||
PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo, uint64_t* aID) MOZ_OVERRIDE;
|
||||
bool DeallocPCompositableChild(PCompositableChild* aActor) MOZ_OVERRIDE;
|
||||
|
@ -261,7 +261,7 @@ ImageBridgeParent::RecvChildAsyncMessages(const InfallibleTArray<AsyncChildMessa
|
||||
return true;
|
||||
}
|
||||
|
||||
MessageLoop * ImageBridgeParent::GetMessageLoop() {
|
||||
MessageLoop * ImageBridgeParent::GetMessageLoop() const {
|
||||
return mMessageLoop;
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ public:
|
||||
// Shutdown step 2
|
||||
virtual bool RecvStop() MOZ_OVERRIDE;
|
||||
|
||||
MessageLoop * GetMessageLoop();
|
||||
virtual MessageLoop* GetMessageLoop() const MOZ_OVERRIDE;
|
||||
|
||||
|
||||
// ISurfaceAllocator
|
||||
|
@ -28,14 +28,14 @@ class nsIAtom;
|
||||
class nsIWidget;
|
||||
|
||||
// IID for the nsITheme interface
|
||||
// {b0f3efe9-0bd4-4f6b-8daa-0ec7f6006822}
|
||||
// {7a3474d9-3bd6-407c-8657-c5c7633639f0}
|
||||
#define NS_ITHEME_IID \
|
||||
{ 0x4440b5c7, 0xd8bd, 0x4d9c, \
|
||||
{ 0x9c, 0x3e, 0xa5, 0xe6, 0x26, 0x81, 0x10, 0xa0 } }
|
||||
// {D930E29B-6909-44e5-AB4B-AF10D6923705}
|
||||
{ 0x7a3474d9, 0x3bd6, 0x407c, \
|
||||
{ 0x86, 0x57, 0xc5, 0xc7, 0x63, 0x36, 0x39, 0xf0 } }
|
||||
// {0ae05515-cf7a-45a8-9e02-6556de7685b1}
|
||||
#define NS_THEMERENDERER_CID \
|
||||
{ 0x9020805b, 0x14a3, 0x4125, \
|
||||
{ 0xa5, 0x63, 0x4a, 0x8c, 0x5d, 0xe0, 0xa9, 0xa3 } }
|
||||
{ 0x0ae05515, 0xcf7a, 0x45a8, \
|
||||
{ 0x9e, 0x02, 0x65, 0x56, 0xde, 0x76, 0x85, 0xb1 } }
|
||||
|
||||
/**
|
||||
* nsITheme is a service that provides platform-specific native
|
||||
@ -113,7 +113,7 @@ public:
|
||||
* minimum size; if false, this size is the only valid size for the
|
||||
* widget.
|
||||
*/
|
||||
NS_IMETHOD GetMinimumWidgetSize(nsRenderingContext* aContext,
|
||||
NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
uint8_t aWidgetType,
|
||||
nsIntSize* aResult,
|
||||
|
@ -20,8 +20,6 @@
|
||||
#include "nsRect.h" // for nsRect, nsIntRect
|
||||
#include "nsRegion.h" // for nsIntRegionRectIterator, etc
|
||||
|
||||
class gfxASurface;
|
||||
|
||||
// XXXTodo: rename FORM_TWIPS to FROM_APPUNITS
|
||||
#define FROM_TWIPS(_x) ((gfxFloat)((_x)/(mP2A)))
|
||||
#define FROM_TWIPS_INT(_x) (NSToIntRound((gfxFloat)((_x)/(mP2A))))
|
||||
@ -65,13 +63,6 @@ static int32_t FindSafeLength(const char *aString, uint32_t aLength,
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//// nsRenderingContext
|
||||
|
||||
void
|
||||
nsRenderingContext::Init(nsDeviceContext* aContext,
|
||||
gfxASurface *aThebesSurface)
|
||||
{
|
||||
Init(aContext, new gfxContext(aThebesSurface));
|
||||
}
|
||||
|
||||
void
|
||||
nsRenderingContext::Init(nsDeviceContext* aContext,
|
||||
gfxContext *aThebesContext)
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "nsString.h" // for nsString
|
||||
#include "nscore.h" // for char16_t
|
||||
|
||||
class gfxASurface;
|
||||
class nsIntRegion;
|
||||
struct nsPoint;
|
||||
struct nsRect;
|
||||
@ -45,7 +44,6 @@ public:
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(nsRenderingContext)
|
||||
|
||||
void Init(nsDeviceContext* aContext, gfxASurface* aThebesSurface);
|
||||
void Init(nsDeviceContext* aContext, gfxContext* aThebesContext);
|
||||
void Init(nsDeviceContext* aContext, DrawTarget* aDrawTarget);
|
||||
|
||||
|
@ -683,179 +683,6 @@ gfxASurface::BytesPerPixel(gfxImageFormat aImageFormat)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxASurface::WriteAsPNG(const char* aFile)
|
||||
{
|
||||
FILE *file = fopen(aFile, "wb");
|
||||
if (file) {
|
||||
WriteAsPNG_internal(file, true);
|
||||
fclose(file);
|
||||
} else {
|
||||
NS_WARNING("Failed to create file!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxASurface::DumpAsDataURL(FILE* aOutput)
|
||||
{
|
||||
WriteAsPNG_internal(aOutput, false);
|
||||
}
|
||||
|
||||
void
|
||||
gfxASurface::CopyAsDataURL()
|
||||
{
|
||||
WriteAsPNG_internal(nullptr, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to a PNG file. If aBinary is true, then it is written
|
||||
* as binary, otherwise as a data URL. If no file is specified then
|
||||
* data is copied to the clipboard (must not be binary!).
|
||||
*/
|
||||
void
|
||||
gfxASurface::WriteAsPNG_internal(FILE* aFile, bool aBinary)
|
||||
{
|
||||
nsRefPtr<gfxImageSurface> imgsurf = GetAsImageSurface();
|
||||
nsIntSize size;
|
||||
|
||||
// FIXME/bug 831898: hack r5g6b5 for now.
|
||||
if (!imgsurf || imgsurf->Format() == gfxImageFormat::RGB16_565) {
|
||||
size = GetSize();
|
||||
if (size.width == -1 && size.height == -1) {
|
||||
printf("Could not determine surface size\n");
|
||||
return;
|
||||
}
|
||||
|
||||
imgsurf =
|
||||
new gfxImageSurface(nsIntSize(size.width, size.height),
|
||||
gfxImageFormat::ARGB32);
|
||||
|
||||
if (!imgsurf || imgsurf->CairoStatus()) {
|
||||
printf("Could not allocate image surface\n");
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(imgsurf);
|
||||
if (!ctx || ctx->HasError()) {
|
||||
printf("Could not allocate image context\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(this, gfxPoint(0, 0));
|
||||
ctx->Paint();
|
||||
}
|
||||
size = imgsurf->GetSize();
|
||||
|
||||
nsCOMPtr<imgIEncoder> encoder =
|
||||
do_CreateInstance("@mozilla.org/image/encoder;2?type=image/png");
|
||||
if (!encoder) {
|
||||
int32_t w = std::min(size.width, 8);
|
||||
int32_t h = std::min(size.height, 8);
|
||||
printf("Could not create encoder. Printing %dx%d pixels.\n", w, h);
|
||||
for (int32_t y = 0; y < h; ++y) {
|
||||
for (int32_t x = 0; x < w; ++x) {
|
||||
printf("%x ", reinterpret_cast<uint32_t*>(imgsurf->Data())[y*imgsurf->Stride()+ x]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = encoder->InitFromData(imgsurf->Data(),
|
||||
size.width * size.height * 4,
|
||||
size.width,
|
||||
size.height,
|
||||
imgsurf->Stride(),
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB,
|
||||
NS_LITERAL_STRING(""));
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIInputStream> imgStream;
|
||||
CallQueryInterface(encoder.get(), getter_AddRefs(imgStream));
|
||||
if (!imgStream)
|
||||
return;
|
||||
|
||||
uint64_t bufSize64;
|
||||
rv = imgStream->Available(&bufSize64);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
if (bufSize64 > UINT32_MAX - 16)
|
||||
return;
|
||||
|
||||
uint32_t bufSize = (uint32_t)bufSize64;
|
||||
|
||||
// ...leave a little extra room so we can call read again and make sure we
|
||||
// got everything. 16 bytes for better padding (maybe)
|
||||
bufSize += 16;
|
||||
uint32_t imgSize = 0;
|
||||
char* imgData = (char*)moz_malloc(bufSize);
|
||||
if (!imgData)
|
||||
return;
|
||||
uint32_t numReadThisTime = 0;
|
||||
while ((rv = imgStream->Read(&imgData[imgSize],
|
||||
bufSize - imgSize,
|
||||
&numReadThisTime)) == NS_OK && numReadThisTime > 0)
|
||||
{
|
||||
imgSize += numReadThisTime;
|
||||
if (imgSize == bufSize) {
|
||||
// need a bigger buffer, just double
|
||||
bufSize *= 2;
|
||||
char* newImgData = (char*)moz_realloc(imgData, bufSize);
|
||||
if (!newImgData) {
|
||||
moz_free(imgData);
|
||||
return;
|
||||
}
|
||||
imgData = newImgData;
|
||||
}
|
||||
}
|
||||
|
||||
if (aBinary) {
|
||||
if (aFile) {
|
||||
fwrite(imgData, 1, imgSize, aFile);
|
||||
} else {
|
||||
NS_WARNING("Can't write binary image data without a file!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// base 64, result will be null-terminated
|
||||
nsCString encodedImg;
|
||||
rv = Base64Encode(Substring(imgData, imgSize), encodedImg);
|
||||
moz_free(imgData);
|
||||
if (NS_FAILED(rv)) // not sure why this would fail
|
||||
return;
|
||||
|
||||
nsCString string("data:image/png;base64,");
|
||||
string.Append(encodedImg);
|
||||
|
||||
if (aFile) {
|
||||
#ifdef ANDROID
|
||||
if (aFile == stdout || aFile == stderr) {
|
||||
// ADB logcat cuts off long strings so we will break it down
|
||||
const char* cStr = string.BeginReading();
|
||||
size_t len = strlen(cStr);
|
||||
while (true) {
|
||||
printf_stderr("IMG: %.140s\n", cStr);
|
||||
if (len <= 140)
|
||||
break;
|
||||
len -= 140;
|
||||
cStr += 140;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fprintf_stderr(aFile, "%s", string.BeginReading());
|
||||
} else {
|
||||
nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
|
||||
if (clipboard) {
|
||||
clipboard->CopyString(NS_ConvertASCIItoUTF16(string), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
gfxASurface::SetOpaqueRect(const gfxRect& aRect)
|
||||
{
|
||||
|
@ -175,27 +175,6 @@ public:
|
||||
|
||||
virtual const nsIntSize GetSize() const;
|
||||
|
||||
/**
|
||||
* Debug functions to encode the current image as a PNG and export it.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Writes a binary PNG file.
|
||||
*/
|
||||
void WriteAsPNG(const char* aFile);
|
||||
|
||||
/**
|
||||
* Write as a PNG encoded Data URL to a file.
|
||||
*/
|
||||
void DumpAsDataURL(FILE* aOutput = stdout);
|
||||
|
||||
/**
|
||||
* Copy a PNG encoded Data URL to the clipboard.
|
||||
*/
|
||||
void CopyAsDataURL();
|
||||
|
||||
void WriteAsPNG_internal(FILE* aFile, bool aBinary);
|
||||
|
||||
void SetOpaqueRect(const gfxRect& aRect);
|
||||
|
||||
const gfxRect& GetOpaqueRect() {
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "gfxColor.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxPattern.h"
|
||||
#include "gfxPlatform.h"
|
||||
@ -1957,34 +1958,31 @@ gfxContext::RoundedRectangle(const gfxRect& rect,
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
void
|
||||
gfxContext::WriteAsPNG(const char* aFile)
|
||||
{
|
||||
nsRefPtr<gfxASurface> surf = CurrentSurface();
|
||||
if (surf) {
|
||||
surf->WriteAsPNG(aFile);
|
||||
{
|
||||
if (mDT) {
|
||||
gfxUtils::WriteAsPNG(mDT, aFile);
|
||||
} else {
|
||||
NS_WARNING("No surface found!");
|
||||
NS_WARNING("No DrawTarget found!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxContext::DumpAsDataURL()
|
||||
{
|
||||
nsRefPtr<gfxASurface> surf = CurrentSurface();
|
||||
if (surf) {
|
||||
surf->DumpAsDataURL();
|
||||
gfxContext::DumpAsDataURI()
|
||||
{
|
||||
if (mDT) {
|
||||
gfxUtils::DumpAsDataURI(mDT);
|
||||
} else {
|
||||
NS_WARNING("No surface found!");
|
||||
NS_WARNING("No DrawTarget found!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxContext::CopyAsDataURL()
|
||||
{
|
||||
nsRefPtr<gfxASurface> surf = CurrentSurface();
|
||||
if (surf) {
|
||||
surf->CopyAsDataURL();
|
||||
gfxContext::CopyAsDataURI()
|
||||
{
|
||||
if (mDT) {
|
||||
gfxUtils::CopyAsDataURI(mDT);
|
||||
} else {
|
||||
NS_WARNING("No surface found!");
|
||||
NS_WARNING("No DrawTarget found!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -707,12 +707,12 @@ public:
|
||||
/**
|
||||
* Write as a PNG encoded Data URL to stdout.
|
||||
*/
|
||||
void DumpAsDataURL();
|
||||
void DumpAsDataURI();
|
||||
|
||||
/**
|
||||
* Copy a PNG encoded Data URL to the clipboard.
|
||||
*/
|
||||
void CopyAsDataURL();
|
||||
void CopyAsDataURI();
|
||||
#endif
|
||||
|
||||
static mozilla::gfx::UserDataKey sDontUseAsSourceKey;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "gfxAndroidPlatform.h"
|
||||
#include "mozilla/Omnijar.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsNetUtil.h"
|
||||
#define gfxToolkitPlatform gfxAndroidPlatform
|
||||
@ -1084,7 +1085,8 @@ gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive,
|
||||
uint32_t bufSize = item->RealSize();
|
||||
// We use fallible allocation here; if there's not enough RAM, we'll simply
|
||||
// ignore the bundled fonts and fall back to the device's installed fonts.
|
||||
nsAutoPtr<uint8_t> buf(static_cast<uint8_t*>(moz_malloc(bufSize)));
|
||||
static const fallible_t fallible = fallible_t();
|
||||
nsAutoArrayPtr<uint8_t> buf(new (fallible) uint8_t[bufSize]);
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
@ -876,16 +876,32 @@ gfxUserFontSet::UserFontCache::Flusher::Observe(nsISupports* aSubject,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
IgnorePrincipal(nsIURI *aURI)
|
||||
{
|
||||
nsresult rv;
|
||||
bool inherits = false;
|
||||
rv = NS_URIChainHasFlags(aURI,
|
||||
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
|
||||
&inherits);
|
||||
return NS_SUCCEEDED(rv) && inherits;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxUserFontSet::UserFontCache::Entry::KeyEquals(const KeyTypePointer aKey) const
|
||||
{
|
||||
bool equal;
|
||||
if (NS_FAILED(mURI->Equals(aKey->mURI, &equal)) || !equal) {
|
||||
bool result;
|
||||
if (NS_FAILED(mURI->Equals(aKey->mURI, &result)) || !result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_FAILED(mPrincipal->Equals(aKey->mPrincipal, &equal)) || !equal) {
|
||||
return false;
|
||||
// For data: URIs, we don't care about the principal; otherwise, check it.
|
||||
if (!IgnorePrincipal(mURI)) {
|
||||
NS_ASSERTION(mPrincipal && aKey->mPrincipal,
|
||||
"only data: URIs are allowed to omit the principal");
|
||||
if (NS_FAILED(mPrincipal->Equals(aKey->mPrincipal, &result)) || !result) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mPrivate != aKey->mPrivate) {
|
||||
@ -925,7 +941,16 @@ gfxUserFontSet::UserFontCache::CacheFont(gfxFontEntry *aFontEntry)
|
||||
}
|
||||
|
||||
gfxUserFontData *data = aFontEntry->mUserFontData;
|
||||
sUserFonts->PutEntry(Key(data->mURI, data->mPrincipal, aFontEntry,
|
||||
// For data: URIs, the principal is ignored; anyone who has the same
|
||||
// data: URI is able to load it and get an equivalent font.
|
||||
// Otherwise, the principal is used as part of the cache key.
|
||||
nsIPrincipal *principal;
|
||||
if (IgnorePrincipal(data->mURI)) {
|
||||
principal = nullptr;
|
||||
} else {
|
||||
principal = data->mPrincipal;
|
||||
}
|
||||
sUserFonts->PutEntry(Key(data->mURI, principal, aFontEntry,
|
||||
data->mPrivate));
|
||||
|
||||
#ifdef DEBUG_USERFONT_CACHE
|
||||
@ -965,7 +990,15 @@ gfxUserFontSet::UserFontCache::GetFont(nsIURI *aSrcURI,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Entry* entry = sUserFonts->GetEntry(Key(aSrcURI, aPrincipal, aProxy,
|
||||
// Ignore principal when looking up a data: URI.
|
||||
nsIPrincipal *principal;
|
||||
if (IgnorePrincipal(aSrcURI)) {
|
||||
principal = nullptr;
|
||||
} else {
|
||||
principal = aPrincipal;
|
||||
}
|
||||
|
||||
Entry* entry = sUserFonts->GetEntry(Key(aSrcURI, principal, aProxy,
|
||||
aPrivate));
|
||||
if (entry) {
|
||||
return entry->GetFontEntry();
|
||||
@ -990,20 +1023,21 @@ gfxUserFontSet::UserFontCache::Entry::DumpEntry(Entry* aEntry, void* aUserData)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString principalURISpec;
|
||||
|
||||
nsCOMPtr<nsIURI> principalURI;
|
||||
rv = aEntry->mPrincipal->GetURI(getter_AddRefs(principalURI));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
principalURI->GetSpec(principalURISpec);
|
||||
}
|
||||
|
||||
nsAutoCString principalURISpec("(null)");
|
||||
bool setDomain = false;
|
||||
nsCOMPtr<nsIURI> domainURI;
|
||||
|
||||
aEntry->mPrincipal->GetDomain(getter_AddRefs(domainURI));
|
||||
if (domainURI) {
|
||||
setDomain = true;
|
||||
if (aEntry->mPrincipal) {
|
||||
nsCOMPtr<nsIURI> principalURI;
|
||||
rv = aEntry->mPrincipal->GetURI(getter_AddRefs(principalURI));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
principalURI->GetSpec(principalURISpec);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> domainURI;
|
||||
aEntry->mPrincipal->GetDomain(getter_AddRefs(domainURI));
|
||||
if (domainURI) {
|
||||
setDomain = true;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(aEntry->mURI, "null URI in userfont cache entry");
|
||||
|
@ -294,7 +294,7 @@ public:
|
||||
// entry and the corresponding "real" font entry.
|
||||
struct Key {
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal; // use nullptr with data: URLs
|
||||
gfxFontEntry *mFontEntry;
|
||||
bool mPrivate;
|
||||
|
||||
@ -333,8 +333,10 @@ public:
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
||||
|
||||
static PLDHashNumber HashKey(const KeyTypePointer aKey) {
|
||||
uint32_t principalHash;
|
||||
aKey->mPrincipal->GetHashValue(&principalHash);
|
||||
uint32_t principalHash = 0;
|
||||
if (aKey->mPrincipal) {
|
||||
aKey->mPrincipal->GetHashValue(&principalHash);
|
||||
}
|
||||
return mozilla::HashGeneric(principalHash + int(aKey->mPrivate),
|
||||
nsURIHashKey::HashKey(aKey->mURI),
|
||||
HashFeatures(aKey->mFontEntry->mFeatureSettings),
|
||||
@ -365,7 +367,7 @@ public:
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal; // or nullptr for data: URLs
|
||||
|
||||
// The "real" font entry corresponding to this downloaded font.
|
||||
// The font entry MUST notify the cache when it is destroyed
|
||||
|
@ -10,9 +10,19 @@
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxDrawable.h"
|
||||
#include "imgIEncoder.h"
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIClipboardHelper.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsRegion.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "yuv_convert.h"
|
||||
#include "ycbcr_to_rgb565.h"
|
||||
#include "GeckoProfiler.h"
|
||||
@ -1105,83 +1115,258 @@ gfxUtils::GetColorForFrameNumber(uint64_t aFrameNumber)
|
||||
return colors[aFrameNumber % sNumFrameColors];
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
/* static */ nsresult
|
||||
gfxUtils::EncodeSourceSurface(SourceSurface* aSurface,
|
||||
const nsACString& aMimeType,
|
||||
const nsAString& aOutputOptions,
|
||||
BinaryOrData aBinaryOrData,
|
||||
FILE* aFile)
|
||||
{
|
||||
MOZ_ASSERT(aBinaryOrData == eDataURIEncode || aFile,
|
||||
"Copying binary encoding to clipboard not currently supported");
|
||||
|
||||
const IntSize size = aSurface->GetSize();
|
||||
if (size.IsEmpty()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
const Size floatSize(size.width, size.height);
|
||||
|
||||
RefPtr<DataSourceSurface> dataSurface;
|
||||
if (aSurface->GetFormat() != SurfaceFormat::B8G8R8A8) {
|
||||
// FIXME bug 995807 (B8G8R8X8), bug 831898 (R5G6B5)
|
||||
dataSurface =
|
||||
CopySurfaceToDataSourceSurfaceWithFormat(aSurface,
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
} else {
|
||||
dataSurface = aSurface->GetDataSurface();
|
||||
}
|
||||
if (!dataSurface) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoCString encoderCID(
|
||||
NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type=") + aMimeType);
|
||||
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(encoderCID.get());
|
||||
if (!encoder) {
|
||||
#ifdef DEBUG
|
||||
int32_t w = std::min(size.width, 8);
|
||||
int32_t h = std::min(size.height, 8);
|
||||
printf("Could not create encoder. Top-left %dx%d pixels contain:\n", w, h);
|
||||
for (int32_t y = 0; y < h; ++y) {
|
||||
for (int32_t x = 0; x < w; ++x) {
|
||||
printf("%x ", reinterpret_cast<uint32_t*>(map.mData)[y*map.mStride+x]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
dataSurface->Unmap();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = encoder->InitFromData(map.mData,
|
||||
BufferSizeFromStrideAndHeight(map.mStride, size.height),
|
||||
size.width,
|
||||
size.height,
|
||||
map.mStride,
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB,
|
||||
aOutputOptions);
|
||||
dataSurface->Unmap();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIInputStream> imgStream;
|
||||
CallQueryInterface(encoder.get(), getter_AddRefs(imgStream));
|
||||
if (!imgStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint64_t bufSize64;
|
||||
rv = imgStream->Available(&bufSize64);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ENSURE_TRUE(bufSize64 < UINT32_MAX - 16, NS_ERROR_FAILURE);
|
||||
|
||||
uint32_t bufSize = (uint32_t)bufSize64;
|
||||
|
||||
// ...leave a little extra room so we can call read again and make sure we
|
||||
// got everything. 16 bytes for better padding (maybe)
|
||||
bufSize += 16;
|
||||
uint32_t imgSize = 0;
|
||||
Vector<char> imgData;
|
||||
if (!imgData.initCapacity(bufSize)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
uint32_t numReadThisTime = 0;
|
||||
while ((rv = imgStream->Read(imgData.begin() + imgSize,
|
||||
bufSize - imgSize,
|
||||
&numReadThisTime)) == NS_OK && numReadThisTime > 0)
|
||||
{
|
||||
imgSize += numReadThisTime;
|
||||
if (imgSize == bufSize) {
|
||||
// need a bigger buffer, just double
|
||||
bufSize *= 2;
|
||||
if (!imgData.resizeUninitialized(bufSize)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aBinaryOrData == eBinaryEncode) {
|
||||
if (aFile) {
|
||||
fwrite(imgData.begin(), 1, imgSize, aFile);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// base 64, result will be null-terminated
|
||||
nsCString encodedImg;
|
||||
rv = Base64Encode(Substring(imgData.begin(), imgSize), encodedImg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString string("data:");
|
||||
string.Append(aMimeType);
|
||||
string.Append(";base64,");
|
||||
string.Append(encodedImg);
|
||||
|
||||
if (aFile) {
|
||||
#ifdef ANDROID
|
||||
if (aFile == stdout || aFile == stderr) {
|
||||
// ADB logcat cuts off long strings so we will break it down
|
||||
const char* cStr = string.BeginReading();
|
||||
size_t len = strlen(cStr);
|
||||
while (true) {
|
||||
printf_stderr("IMG: %.140s\n", cStr);
|
||||
if (len <= 140)
|
||||
break;
|
||||
len -= 140;
|
||||
cStr += 140;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fprintf(aFile, "%s", string.BeginReading());
|
||||
} else {
|
||||
nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
|
||||
if (clipboard) {
|
||||
clipboard->CopyString(NS_ConvertASCIItoUTF16(string), nullptr);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::WriteAsPNG(SourceSurface* aSurface, const nsAString& aFile)
|
||||
{
|
||||
WriteAsPNG(aSurface, NS_ConvertUTF16toUTF8(aFile).get());
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::WriteAsPNG(SourceSurface* aSurface, const char* aFile)
|
||||
{
|
||||
FILE* file = fopen(aFile, "wb");
|
||||
|
||||
if (!file) {
|
||||
// Maybe the directory doesn't exist; try creating it, then fopen again.
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIFile> comFile = do_CreateInstance("@mozilla.org/file/local;1");
|
||||
if (comFile) {
|
||||
NS_ConvertUTF8toUTF16 utf16path((nsDependentCString(aFile)));
|
||||
rv = comFile->InitWithPath(utf16path);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIFile> dirPath;
|
||||
comFile->GetParent(getter_AddRefs(dirPath));
|
||||
if (dirPath) {
|
||||
rv = dirPath->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
||||
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
file = fopen(aFile, "wb");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!file) {
|
||||
NS_WARNING("Failed to open file to create PNG!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
|
||||
EmptyString(), eBinaryEncode, file);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::WriteAsPNG(DrawTarget* aDT, const nsAString& aFile)
|
||||
{
|
||||
WriteAsPNG(aDT, NS_ConvertUTF16toUTF8(aFile).get());
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::WriteAsPNG(DrawTarget* aDT, const char* aFile)
|
||||
{
|
||||
aDT->Flush();
|
||||
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(aDT);
|
||||
if (surf) {
|
||||
surf->WriteAsPNG(aFile);
|
||||
RefPtr<SourceSurface> surface = aDT->Snapshot();
|
||||
if (surface) {
|
||||
WriteAsPNG(surface, aFile);
|
||||
} else {
|
||||
NS_WARNING("Failed to get Thebes surface!");
|
||||
NS_WARNING("Failed to get surface!");
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::DumpAsDataURL(DrawTarget* aDT)
|
||||
gfxUtils::WriteAsPNG(nsIPresShell* aShell, const char* aFile)
|
||||
{
|
||||
aDT->Flush();
|
||||
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(aDT);
|
||||
if (surf) {
|
||||
surf->DumpAsDataURL();
|
||||
int32_t width = 1000, height = 1000;
|
||||
nsRect r(0, 0, aShell->GetPresContext()->DevPixelsToAppUnits(width),
|
||||
aShell->GetPresContext()->DevPixelsToAppUnits(height));
|
||||
|
||||
RefPtr<mozilla::gfx::DrawTarget> dt = gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenContentDrawTarget(IntSize(width, height),
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
NS_ENSURE_TRUE(dt, /*void*/);
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(dt);
|
||||
aShell->RenderDocument(r, 0, NS_RGB(255, 255, 0), context);
|
||||
WriteAsPNG(dt.get(), aFile);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::DumpAsDataURI(SourceSurface* aSurface, FILE* aFile)
|
||||
{
|
||||
EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
|
||||
EmptyString(), eDataURIEncode, aFile);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::DumpAsDataURI(DrawTarget* aDT, FILE* aFile)
|
||||
{
|
||||
RefPtr<SourceSurface> surface = aDT->Snapshot();
|
||||
if (surface) {
|
||||
DumpAsDataURI(surface, aFile);
|
||||
} else {
|
||||
NS_WARNING("Failed to get Thebes surface!");
|
||||
NS_WARNING("Failed to get surface!");
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::CopyAsDataURL(DrawTarget* aDT)
|
||||
gfxUtils::CopyAsDataURI(SourceSurface* aSurface)
|
||||
{
|
||||
aDT->Flush();
|
||||
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(aDT);
|
||||
if (surf) {
|
||||
surf->CopyAsDataURL();
|
||||
EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
|
||||
EmptyString(), eDataURIEncode, nullptr);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::CopyAsDataURI(DrawTarget* aDT)
|
||||
{
|
||||
RefPtr<SourceSurface> surface = aDT->Snapshot();
|
||||
if (surface) {
|
||||
CopyAsDataURI(surface);
|
||||
} else {
|
||||
NS_WARNING("Failed to get Thebes surface!");
|
||||
NS_WARNING("Failed to get surface!");
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::WriteAsPNG(gfx::SourceSurface* aSourceSurface, const char* aFile)
|
||||
{
|
||||
RefPtr<gfx::DataSourceSurface> dataSurface = aSourceSurface->GetDataSurface();
|
||||
RefPtr<gfx::DrawTarget> dt
|
||||
= gfxPlatform::GetPlatform()
|
||||
->CreateDrawTargetForData(dataSurface->GetData(),
|
||||
dataSurface->GetSize(),
|
||||
dataSurface->Stride(),
|
||||
aSourceSurface->GetFormat());
|
||||
gfxUtils::WriteAsPNG(dt.get(), aFile);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::DumpAsDataURL(gfx::SourceSurface* aSourceSurface)
|
||||
{
|
||||
RefPtr<gfx::DataSourceSurface> dataSurface = aSourceSurface->GetDataSurface();
|
||||
RefPtr<gfx::DrawTarget> dt
|
||||
= gfxPlatform::GetPlatform()
|
||||
->CreateDrawTargetForData(dataSurface->GetData(),
|
||||
dataSurface->GetSize(),
|
||||
dataSurface->Stride(),
|
||||
aSourceSurface->GetFormat());
|
||||
gfxUtils::DumpAsDataURL(dt.get());
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::CopyAsDataURL(gfx::SourceSurface* aSourceSurface)
|
||||
{
|
||||
RefPtr<gfx::DataSourceSurface> dataSurface = aSourceSurface->GetDataSurface();
|
||||
RefPtr<gfx::DrawTarget> dt
|
||||
= gfxPlatform::GetPlatform()
|
||||
->CreateDrawTargetForData(dataSurface->GetData(),
|
||||
dataSurface->GetSize(),
|
||||
dataSurface->Stride(),
|
||||
aSourceSurface->GetFormat());
|
||||
|
||||
gfxUtils::CopyAsDataURL(dt.get());
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
static bool sDumpPaintList = getenv("MOZ_DUMP_PAINT_LIST") != 0;
|
||||
|
||||
/* static */ bool
|
||||
|
@ -16,6 +16,8 @@
|
||||
class gfxASurface;
|
||||
class gfxDrawable;
|
||||
class nsIntRegion;
|
||||
class nsIPresShell;
|
||||
|
||||
struct nsIntRect;
|
||||
|
||||
namespace mozilla {
|
||||
@ -27,6 +29,7 @@ struct PlanarYCbCrData;
|
||||
class gfxUtils {
|
||||
public:
|
||||
typedef mozilla::gfx::DataSourceSurface DataSourceSurface;
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
typedef mozilla::gfx::IntPoint IntPoint;
|
||||
typedef mozilla::gfx::Matrix Matrix;
|
||||
typedef mozilla::gfx::SourceSurface SourceSurface;
|
||||
@ -228,45 +231,78 @@ public:
|
||||
static const mozilla::gfx::Color& GetColorForFrameNumber(uint64_t aFrameNumber);
|
||||
static const uint32_t sNumFrameColors;
|
||||
|
||||
|
||||
enum BinaryOrData {
|
||||
eBinaryEncode,
|
||||
eDataURIEncode
|
||||
};
|
||||
|
||||
/**
|
||||
* Encodes the given surface to PNG/JPEG/BMP/etc. using imgIEncoder.
|
||||
*
|
||||
* @param aMimeType The MIME-type of the image type that the surface is to
|
||||
* be encoded to. Used to create an appropriate imgIEncoder instance to
|
||||
* do the encoding.
|
||||
*
|
||||
* @param aOutputOptions Passed directly to imgIEncoder::InitFromData as
|
||||
* the value of the |outputOptions| parameter. Callers are responsible
|
||||
* for making sure that this is a sane value for the passed MIME-type
|
||||
* (i.e. for the type of encoder that will be created).
|
||||
*
|
||||
* @aBinaryOrData Flag used to determine if the surface is simply encoded
|
||||
* to the requested binary image format, or if the binary image is
|
||||
* further converted to base-64 and written out as a 'data:' URI.
|
||||
*
|
||||
* @aFile If specified, the encoded data is written out to aFile, otherwise
|
||||
* it is copied to the clipboard.
|
||||
*
|
||||
* TODO: Copying to the clipboard as a binary file is not currently
|
||||
* supported.
|
||||
*/
|
||||
static nsresult
|
||||
EncodeSourceSurface(SourceSurface* aSurface,
|
||||
const nsACString& aMimeType,
|
||||
const nsAString& aOutputOptions,
|
||||
BinaryOrData aBinaryOrData,
|
||||
FILE* aFile);
|
||||
|
||||
/**
|
||||
* Write as a PNG file to the path aFile.
|
||||
*/
|
||||
static void WriteAsPNG(SourceSurface* aSurface, const nsAString& aFile);
|
||||
static void WriteAsPNG(SourceSurface* aSurface, const char* aFile);
|
||||
static void WriteAsPNG(DrawTarget* aDT, const nsAString& aFile);
|
||||
static void WriteAsPNG(DrawTarget* aDT, const char* aFile);
|
||||
static void WriteAsPNG(nsIPresShell* aShell, const char* aFile);
|
||||
|
||||
/**
|
||||
* Dump as a PNG encoded Data URL to a FILE stream (using stdout by
|
||||
* default).
|
||||
*
|
||||
* Rather than giving aFile a default argument we have separate functions
|
||||
* to make them easier to use from a debugger.
|
||||
*/
|
||||
static void DumpAsDataURI(SourceSurface* aSourceSurface, FILE* aFile);
|
||||
static inline void DumpAsDataURI(SourceSurface* aSourceSurface) {
|
||||
DumpAsDataURI(aSourceSurface, stdout);
|
||||
}
|
||||
static void DumpAsDataURI(DrawTarget* aDT, FILE* aFile);
|
||||
static inline void DumpAsDataURI(DrawTarget* aDT) {
|
||||
DumpAsDataURI(aDT, stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy to the clipboard as a PNG encoded Data URL.
|
||||
*/
|
||||
static void CopyAsDataURI(SourceSurface* aSourceSurface);
|
||||
static void CopyAsDataURI(DrawTarget* aDT);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
/**
|
||||
* Writes a binary PNG file.
|
||||
*/
|
||||
static void WriteAsPNG(mozilla::gfx::DrawTarget* aDT, const char* aFile);
|
||||
|
||||
/**
|
||||
* Write as a PNG encoded Data URL to stdout.
|
||||
*/
|
||||
static void DumpAsDataURL(mozilla::gfx::DrawTarget* aDT);
|
||||
|
||||
/**
|
||||
* Copy a PNG encoded Data URL to the clipboard.
|
||||
*/
|
||||
static void CopyAsDataURL(mozilla::gfx::DrawTarget* aDT);
|
||||
|
||||
static bool DumpPaintList();
|
||||
|
||||
static bool sDumpPainting;
|
||||
static bool sDumpPaintingToFile;
|
||||
static FILE* sDumpPaintFile;
|
||||
|
||||
/**
|
||||
* Writes a binary PNG file.
|
||||
* Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads
|
||||
*/
|
||||
static void WriteAsPNG(mozilla::gfx::SourceSurface* aSourceSurface, const char* aFile);
|
||||
|
||||
/**
|
||||
* Write as a PNG encoded Data URL to stdout.
|
||||
* Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads
|
||||
*/
|
||||
static void DumpAsDataURL(mozilla::gfx::SourceSurface* aSourceSurface);
|
||||
|
||||
/**
|
||||
* Copy a PNG encoded Data URL to the clipboard.
|
||||
* Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads
|
||||
*/
|
||||
static void CopyAsDataURL(mozilla::gfx::SourceSurface* aSourceSurface);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1,6 +0,0 @@
|
||||
js/jsd contains code for debugging support for the C-based JavaScript engine
|
||||
in js/src. jsd_xpc.cpp provides an XPCOM binding for the library.
|
||||
|
||||
js/jsd/jsdb is a console debugger using only native code (see README in that
|
||||
directory.) This debugger is no longer being actively developed, though it
|
||||
should work.
|
File diff suppressed because it is too large
Load Diff
@ -1,12 +0,0 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'jsdIDebuggerService.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'jsdservice'
|
||||
|
1054
js/jsd/jsd.h
1054
js/jsd/jsd.h
File diff suppressed because it is too large
Load Diff
@ -1,77 +0,0 @@
|
||||
; -*- Mode: Fundamental; tab-width: 4; indent-tabs-mode: nil -*-
|
||||
;
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
|
||||
LIBRARY JSD1640.DLL
|
||||
EXETYPE WINDOWS
|
||||
PROTMODE
|
||||
|
||||
DESCRIPTION 'Netscape 16-bit JavaScript Debugger Library'
|
||||
|
||||
CODE LOADONCALL MOVEABLE DISCARDABLE
|
||||
DATA PRELOAD MOVEABLE SINGLE
|
||||
|
||||
HEAPSIZE 8192
|
||||
|
||||
EXPORTS
|
||||
WEP @1 RESIDENTNAME NONAME
|
||||
_JSD_AppendSourceText
|
||||
_JSD_ClearAllExecutionHooks
|
||||
_JSD_ClearAllExecutionHooksForScript
|
||||
_JSD_ClearDebugBreakHook
|
||||
_JSD_ClearExecutionHook
|
||||
_JSD_ClearInterruptHook
|
||||
_JSD_ClearSourceText
|
||||
_JSD_DebuggerOff
|
||||
_JSD_DebuggerOn
|
||||
_JSD_EvaluateScriptInStackFrame
|
||||
_JSD_FindSourceForURL
|
||||
_JSD_GetCallingStackFrame
|
||||
_JSD_GetClosestLine
|
||||
_JSD_GetClosestPC
|
||||
_JSD_GetCountOfStackFrames
|
||||
_JSD_GetMajorVersion
|
||||
_JSD_GetMinorVersion
|
||||
_JSD_GetPCForStackFrame
|
||||
_JSD_GetScriptBaseLineNumber
|
||||
_JSD_GetScriptFilename
|
||||
_JSD_GetScriptForStackFrame
|
||||
_JSD_GetScriptFunctionId
|
||||
_JSD_GetScriptHook
|
||||
_JSD_GetScriptLineExtent
|
||||
_JSD_GetSourceAlterCount
|
||||
_JSD_GetSourceStatus
|
||||
_JSD_GetSourceText
|
||||
_JSD_GetSourceURL
|
||||
_JSD_GetStackFrame
|
||||
_JSD_IncrementSourceAlterCount
|
||||
_JSD_IsSourceDirty
|
||||
_JSD_IterateScripts
|
||||
_JSD_IterateSources
|
||||
_JSD_LockScriptSubsystem
|
||||
_JSD_LockSourceTextSubsystem
|
||||
_JSD_NewSourceText
|
||||
_JSD_SetDebugBreakHook
|
||||
_JSD_SetErrorReporter
|
||||
_JSD_SetExecutionHook
|
||||
_JSD_SetInterruptHook
|
||||
_JSD_SetScriptHook
|
||||
_JSD_SetSourceDirty
|
||||
_JSD_SetUserCallbacks
|
||||
_JSD_UnlockScriptSubsystem
|
||||
_JSD_UnlockSourceTextSubsystem
|
||||
_Java_netscape_jsdebug_DebugController__0005fsetController_stub
|
||||
_Java_netscape_jsdebug_DebugController_executeScriptInStackFrame_stub
|
||||
_Java_netscape_jsdebug_DebugController_sendInterrupt_stub
|
||||
_Java_netscape_jsdebug_DebugController_setInstructionHook0_stub
|
||||
_Java_netscape_jsdebug_JSPC_getSourceLocation_stub
|
||||
_Java_netscape_jsdebug_JSSourceTextProvider_loadSourceTextItem_stub
|
||||
_Java_netscape_jsdebug_JSSourceTextProvider_refreshSourceTextVector_stub
|
||||
_Java_netscape_jsdebug_JSStackFrameInfo_getCaller0_stub
|
||||
_Java_netscape_jsdebug_JSStackFrameInfo_getPC_stub
|
||||
_Java_netscape_jsdebug_JSThreadState_countStackFrames_stub
|
||||
_Java_netscape_jsdebug_JSThreadState_getCurrentFrame_stub
|
||||
_Java_netscape_jsdebug_Script_getClosestPC_stub
|
@ -1,67 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Version stamp for this .DLL
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <ver.h>
|
||||
|
||||
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
|
||||
FILEVERSION 4 // major, minor, release (alpha 1), build #
|
||||
|
||||
PRODUCTVERSION 4
|
||||
|
||||
FILEFLAGSMASK 0
|
||||
|
||||
FILEFLAGS 0 // final version
|
||||
|
||||
FILEOS VOS_DOS_WINDOWS16
|
||||
|
||||
FILETYPE VFT_DLL
|
||||
|
||||
FILESUBTYPE 0 // not used
|
||||
|
||||
BEGIN
|
||||
|
||||
BLOCK "StringFileInfo"
|
||||
|
||||
BEGIN
|
||||
|
||||
BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual
|
||||
|
||||
BEGIN
|
||||
|
||||
VALUE "CompanyName", "Netscape Communications Corporation\0"
|
||||
|
||||
VALUE "FileDescription", "Netscape 16-bit JavaScript Debugger Module\0"
|
||||
|
||||
VALUE "FileVersion", "4.0\0"
|
||||
|
||||
VALUE "InternalName", "JSD1640\0"
|
||||
|
||||
VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
|
||||
|
||||
VALUE "LegalTrademarks", "Netscape, Mozilla\0"
|
||||
|
||||
VALUE "OriginalFilename","JSD1640.DLL\0"
|
||||
|
||||
VALUE "ProductName", "NETSCAPE\0"
|
||||
|
||||
VALUE "ProductVersion", "4.0\0"
|
||||
|
||||
END
|
||||
|
||||
END
|
||||
|
||||
END
|
||||
|
@ -1,86 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winver.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,0,0,0
|
||||
PRODUCTVERSION 4,0,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x10004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Netscape Communications Corporation\0"
|
||||
VALUE "FileDescription", "Netscape 32-bit JavaScript Debugger Module\0"
|
||||
VALUE "FileVersion", "4.0\0"
|
||||
VALUE "InternalName", "JSD3240\0"
|
||||
VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
|
||||
VALUE "LegalTrademarks", "Netscape, Mozilla\0"
|
||||
VALUE "OriginalFilename", "jsd3240.dll\0"
|
||||
VALUE "ProductName", "NETSCAPE\0"
|
||||
VALUE "ProductVersion", "4.0\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1252
|
||||
END
|
||||
END
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""winver.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
@ -1,147 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* JavaScript Debugging support - Atom support
|
||||
*/
|
||||
|
||||
#include "jsd.h"
|
||||
|
||||
/* #define TEST_ATOMS 1 */
|
||||
|
||||
#ifdef TEST_ATOMS
|
||||
static void
|
||||
_testAtoms(JSDContext*jsdc)
|
||||
{
|
||||
JSDAtom* atom0 = jsd_AddAtom(jsdc, "foo");
|
||||
JSDAtom* atom1 = jsd_AddAtom(jsdc, "foo");
|
||||
JSDAtom* atom2 = jsd_AddAtom(jsdc, "bar");
|
||||
JSDAtom* atom3 = jsd_CloneAtom(jsdc, atom1);
|
||||
JSDAtom* atom4 = jsd_CloneAtom(jsdc, atom2);
|
||||
|
||||
const char* c0 = JSD_ATOM_TO_STRING(atom0);
|
||||
const char* c1 = JSD_ATOM_TO_STRING(atom1);
|
||||
const char* c2 = JSD_ATOM_TO_STRING(atom2);
|
||||
const char* c3 = JSD_ATOM_TO_STRING(atom3);
|
||||
const char* c4 = JSD_ATOM_TO_STRING(atom4);
|
||||
|
||||
jsd_DropAtom(jsdc, atom0);
|
||||
jsd_DropAtom(jsdc, atom1);
|
||||
jsd_DropAtom(jsdc, atom2);
|
||||
jsd_DropAtom(jsdc, atom3);
|
||||
jsd_DropAtom(jsdc, atom4);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
_atom_smasher(JSHashEntry *he, int i, void *arg)
|
||||
{
|
||||
MOZ_ASSERT(he);
|
||||
MOZ_ASSERT(he->value);
|
||||
MOZ_ASSERT(((JSDAtom*)(he->value))->str);
|
||||
|
||||
free(((JSDAtom*)(he->value))->str);
|
||||
free(he->value);
|
||||
he->value = nullptr;
|
||||
he->key = nullptr;
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
static int
|
||||
_compareAtomKeys(const void *v1, const void *v2)
|
||||
{
|
||||
return 0 == strcmp((const char*)v1, (const char*)v2);
|
||||
}
|
||||
|
||||
static int
|
||||
_compareAtoms(const void *v1, const void *v2)
|
||||
{
|
||||
return 0 == strcmp(((JSDAtom*)v1)->str, ((JSDAtom*)v2)->str);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
jsd_CreateAtomTable(JSDContext* jsdc)
|
||||
{
|
||||
jsdc->atoms = JS_NewHashTable(256, JS_HashString,
|
||||
_compareAtomKeys, _compareAtoms,
|
||||
nullptr, nullptr);
|
||||
#ifdef TEST_ATOMS
|
||||
_testAtoms(jsdc);
|
||||
#endif
|
||||
return !!jsdc->atoms;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_DestroyAtomTable(JSDContext* jsdc)
|
||||
{
|
||||
if( jsdc->atoms )
|
||||
{
|
||||
JS_HashTableEnumerateEntries(jsdc->atoms, _atom_smasher, nullptr);
|
||||
JS_HashTableDestroy(jsdc->atoms);
|
||||
jsdc->atoms = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
JSDAtom*
|
||||
jsd_AddAtom(JSDContext* jsdc, const char* str)
|
||||
{
|
||||
JSDAtom* atom;
|
||||
|
||||
if(!str)
|
||||
{
|
||||
MOZ_ASSERT(0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSD_LOCK_ATOMS(jsdc);
|
||||
|
||||
atom = (JSDAtom*) JS_HashTableLookup(jsdc->atoms, str);
|
||||
|
||||
if( atom )
|
||||
atom->refcount++;
|
||||
else
|
||||
{
|
||||
atom = (JSDAtom*) malloc(sizeof(JSDAtom));
|
||||
if( atom )
|
||||
{
|
||||
atom->str = strdup(str);
|
||||
atom->refcount = 1;
|
||||
if(!JS_HashTableAdd(jsdc->atoms, atom->str, atom))
|
||||
{
|
||||
free(atom->str);
|
||||
free(atom);
|
||||
atom = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSD_UNLOCK_ATOMS(jsdc);
|
||||
return atom;
|
||||
}
|
||||
|
||||
JSDAtom*
|
||||
jsd_CloneAtom(JSDContext* jsdc, JSDAtom* atom)
|
||||
{
|
||||
JSD_LOCK_ATOMS(jsdc);
|
||||
atom->refcount++;
|
||||
JSD_UNLOCK_ATOMS(jsdc);
|
||||
return atom;
|
||||
}
|
||||
|
||||
void
|
||||
jsd_DropAtom(JSDContext* jsdc, JSDAtom* atom)
|
||||
{
|
||||
JSD_LOCK_ATOMS(jsdc);
|
||||
if(! --atom->refcount)
|
||||
{
|
||||
JS_HashTableRemove(jsdc->atoms, atom->str);
|
||||
free(atom->str);
|
||||
free(atom);
|
||||
}
|
||||
JSD_UNLOCK_ATOMS(jsdc);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user