Merge mozilla-central to b2g-inbound
@ -976,6 +976,9 @@ pref("browser.autofocus", false);
|
||||
// Enable wakelock
|
||||
pref("dom.wakelock.enabled", true);
|
||||
|
||||
// Disable touch caret by default
|
||||
pref("touchcaret.enabled", false);
|
||||
|
||||
// Enable sync and mozId with Firefox Accounts.
|
||||
#ifdef MOZ_SERVICES_FXACCOUNTS
|
||||
pref("services.sync.fxaccounts.enabled", true);
|
||||
|
@ -671,6 +671,9 @@
|
||||
@BINPATH@/res/table-remove-row-active.gif
|
||||
@BINPATH@/res/table-remove-row-hover.gif
|
||||
@BINPATH@/res/table-remove-row.gif
|
||||
@BINPATH@/res/text_selection_handle.png
|
||||
@BINPATH@/res/text_selection_handle@1.5.png
|
||||
@BINPATH@/res/text_selection_handle@2.png
|
||||
@BINPATH@/res/grabber.gif
|
||||
#ifdef XP_MACOSX
|
||||
@BINPATH@/res/cursors/*
|
||||
|
@ -1517,6 +1517,9 @@ pref("security.csp.speccompliant", true);
|
||||
// Block insecure active content on https pages
|
||||
pref("security.mixed_content.block_active_content", true);
|
||||
|
||||
// 1 = allow MITM for certificate pinning checks.
|
||||
pref("security.cert_pinning.enforcement_level", 1);
|
||||
|
||||
// Override the Gecko-default value of false for Firefox.
|
||||
pref("plain_text.wrap_long_lines", true);
|
||||
|
||||
|
@ -2,10 +2,15 @@
|
||||
skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
doc_layoutview_iframe1.html
|
||||
doc_layoutview_iframe2.html
|
||||
head.js
|
||||
|
||||
[browser_layoutview.js]
|
||||
[browser_layoutview_rotate-labels-on-sides.js]
|
||||
[browser_layoutview_update-after-navigation.js]
|
||||
[browser_layoutview_update-after-reload.js]
|
||||
[browser_layoutview_update-in-iframes.js]
|
||||
[browser_editablemodel.js]
|
||||
[browser_editablemodel_allproperties.js]
|
||||
[browser_editablemodel_border.js]
|
||||
|
@ -0,0 +1,99 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the layout-view continues to work after a page navigation and that
|
||||
// it also works after going back
|
||||
|
||||
let test = asyncTest(function*() {
|
||||
yield addTab(TEST_URL_ROOT + "doc_layoutview_iframe1.html");
|
||||
let {toolbox, inspector, view} = yield openLayoutView();
|
||||
yield runTests(inspector, view);
|
||||
yield destroyToolbox(inspector);
|
||||
});
|
||||
|
||||
addTest("Test that the layout-view works on the first page",
|
||||
function*(inspector, view) {
|
||||
info("Selecting the test node");
|
||||
yield selectNode("p", inspector);
|
||||
|
||||
info("Checking that the layout-view shows the right value");
|
||||
let paddingElt = view.doc.querySelector(".padding.top > span");
|
||||
is(paddingElt.textContent, "50");
|
||||
|
||||
info("Listening for layout-view changes and modifying the padding");
|
||||
let onUpdated = waitForUpdate(inspector);
|
||||
getNode("p").style.padding = "20px";
|
||||
yield onUpdated;
|
||||
ok(true, "Layout-view got updated");
|
||||
|
||||
info("Checking that the layout-view shows the right value after update");
|
||||
is(paddingElt.textContent, "20");
|
||||
});
|
||||
|
||||
addTest("Navigate to the second page",
|
||||
function*(inspector, view) {
|
||||
yield navigateTo(TEST_URL_ROOT + "doc_layoutview_iframe2.html");
|
||||
yield inspector.once("markuploaded");
|
||||
});
|
||||
|
||||
addTest("Test that the layout-view works on the second page",
|
||||
function*(inspector, view) {
|
||||
info("Selecting the test node");
|
||||
yield selectNode("p", inspector);
|
||||
|
||||
info("Checking that the layout-view shows the right value");
|
||||
let sizeElt = view.doc.querySelector(".size > span");
|
||||
is(sizeElt.textContent, "100x100");
|
||||
|
||||
info("Listening for layout-view changes and modifying the size");
|
||||
let onUpdated = waitForUpdate(inspector);
|
||||
getNode("p").style.width = "200px";
|
||||
yield onUpdated;
|
||||
ok(true, "Layout-view got updated");
|
||||
|
||||
info("Checking that the layout-view shows the right value after update");
|
||||
is(sizeElt.textContent, "200x100");
|
||||
});
|
||||
|
||||
addTest("Go back to the first page",
|
||||
function*(inspector, view) {
|
||||
content.history.back();
|
||||
yield inspector.once("markuploaded");
|
||||
});
|
||||
|
||||
addTest("Test that the layout-view works on the first page after going back",
|
||||
function*(inspector, view) {
|
||||
info("Selecting the test node");
|
||||
yield selectNode("p", inspector);
|
||||
|
||||
info("Checking that the layout-view shows the right value, which is the" +
|
||||
"modified value from step one because of the bfcache");
|
||||
let paddingElt = view.doc.querySelector(".padding.top > span");
|
||||
is(paddingElt.textContent, "20");
|
||||
|
||||
info("Listening for layout-view changes and modifying the padding");
|
||||
let onUpdated = waitForUpdate(inspector);
|
||||
getNode("p").style.padding = "100px";
|
||||
yield onUpdated;
|
||||
ok(true, "Layout-view got updated");
|
||||
|
||||
info("Checking that the layout-view shows the right value after update");
|
||||
is(paddingElt.textContent, "100");
|
||||
});
|
||||
|
||||
function navigateTo(url) {
|
||||
info("Navigating to " + url);
|
||||
|
||||
let def = promise.defer();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
info("URL " + url + " loading complete");
|
||||
waitForFocus(def.resolve, content);
|
||||
}, true);
|
||||
content.location = url;
|
||||
|
||||
return def.promise;
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the layout-view continues to work after the page is reloaded
|
||||
|
||||
let test = asyncTest(function*() {
|
||||
yield addTab(TEST_URL_ROOT + "doc_layoutview_iframe1.html");
|
||||
let {toolbox, inspector, view} = yield openLayoutView();
|
||||
|
||||
info("Test that the layout-view works on the first page");
|
||||
yield assertLayoutView(inspector, view);
|
||||
|
||||
info("Reload the page");
|
||||
content.location.reload();
|
||||
yield inspector.once("markuploaded");
|
||||
|
||||
info("Test that the layout-view works on the reloaded page");
|
||||
yield assertLayoutView(inspector, view);
|
||||
|
||||
yield destroyToolbox(inspector);
|
||||
});
|
||||
|
||||
function* assertLayoutView(inspector, view) {
|
||||
info("Selecting the test node");
|
||||
yield selectNode("p", inspector);
|
||||
|
||||
info("Checking that the layout-view shows the right value");
|
||||
let paddingElt = view.doc.querySelector(".padding.top > span");
|
||||
is(paddingElt.textContent, "50");
|
||||
|
||||
info("Listening for layout-view changes and modifying the padding");
|
||||
let onUpdated = waitForUpdate(inspector);
|
||||
getNode("p").style.padding = "20px";
|
||||
yield onUpdated;
|
||||
ok(true, "Layout-view got updated");
|
||||
|
||||
info("Checking that the layout-view shows the right value after update");
|
||||
is(paddingElt.textContent, "20");
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the layout-view for elements within iframes also updates when they
|
||||
// change
|
||||
|
||||
let test = asyncTest(function*() {
|
||||
yield addTab(TEST_URL_ROOT + "doc_layoutview_iframe1.html");
|
||||
let iframe2 = getNode("iframe").contentDocument.querySelector("iframe");
|
||||
|
||||
let {toolbox, inspector, view} = yield openLayoutView();
|
||||
yield runTests(inspector, view, iframe2);
|
||||
yield destroyToolbox(inspector);
|
||||
});
|
||||
|
||||
addTest("Test that resizing an element in an iframe updates its box model",
|
||||
function*(inspector, view, iframe2) {
|
||||
info("Selecting the nested test node");
|
||||
let node = iframe2.contentDocument.querySelector("div");
|
||||
yield selectNode(node, inspector);
|
||||
|
||||
info("Checking that the layout-view shows the right value");
|
||||
let sizeElt = view.doc.querySelector(".size > span");
|
||||
is(sizeElt.textContent, "400x200");
|
||||
|
||||
info("Listening for layout-view changes and modifying its size");
|
||||
let onUpdated = waitForUpdate(inspector);
|
||||
node.style.width = "200px";
|
||||
yield onUpdated;
|
||||
ok(true, "Layout-view got updated");
|
||||
|
||||
info("Checking that the layout-view shows the right value after update");
|
||||
is(sizeElt.textContent, "200x200");
|
||||
});
|
||||
|
||||
addTest("Test reflows are still sent to the layout-view after deleting an iframe",
|
||||
function*(inspector, view, iframe2) {
|
||||
info("Deleting the iframe2");
|
||||
iframe2.remove();
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
info("Selecting the test node in iframe1");
|
||||
let node = getNode("iframe").contentDocument.querySelector("p");
|
||||
yield selectNode(node, inspector);
|
||||
|
||||
info("Checking that the layout-view shows the right value");
|
||||
let sizeElt = view.doc.querySelector(".size > span");
|
||||
is(sizeElt.textContent, "100x100");
|
||||
|
||||
info("Listening for layout-view changes and modifying its size");
|
||||
let onUpdated = waitForUpdate(inspector);
|
||||
node.style.width = "200px";
|
||||
yield onUpdated;
|
||||
ok(true, "Layout-view got updated");
|
||||
|
||||
info("Checking that the layout-view shows the right value after update");
|
||||
is(sizeElt.textContent, "200x100");
|
||||
});
|
@ -0,0 +1,3 @@
|
||||
<!DOCTYPE html>
|
||||
<p style="padding:50px;color:#f06;">Root page</p>
|
||||
<iframe src="doc_layoutview_iframe2.html"></iframe>
|
@ -0,0 +1,3 @@
|
||||
<!DOCTYPE html>
|
||||
<p style="width:100px;height:100px;background:red;">iframe 1</p>
|
||||
<iframe src="data:text/html,<div style='width:400px;height:200px;background:yellow;'>iframe 2</div>"></iframe>
|
@ -23,6 +23,7 @@ support-files = head.js
|
||||
[browser_scratchpad_falsy.js]
|
||||
[browser_scratchpad_edit_ui_updates.js]
|
||||
[browser_scratchpad_revert_to_saved.js]
|
||||
[browser_scratchpad_run_error_goto_line.js]
|
||||
[browser_scratchpad_contexts.js]
|
||||
[browser_scratchpad_execute_print.js]
|
||||
[browser_scratchpad_files.js]
|
||||
@ -34,6 +35,7 @@ support-files = head.js
|
||||
[browser_scratchpad_throw_output.js]
|
||||
[browser_scratchpad_pprint-02.js]
|
||||
[browser_scratchpad_pprint.js]
|
||||
[browser_scratchpad_pprint_error_goto_line.js]
|
||||
[browser_scratchpad_restore.js]
|
||||
[browser_scratchpad_tab_switch.js]
|
||||
[browser_scratchpad_ui.js]
|
||||
|
@ -0,0 +1,66 @@
|
||||
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
openScratchpad(runTests);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html;charset=utf8,test Scratchpad pretty print error goto line.";
|
||||
}
|
||||
|
||||
function testJumpToPrettyPrintError(sp, error, remark) {
|
||||
info("will test jumpToLine after prettyPrint error" + remark);
|
||||
// CodeMirror lines and columns are 0-based, Scratchpad UI and error
|
||||
// stack are 1-based.
|
||||
is(/Invalid regexp flag \(3:10\)/.test(error), true, "prettyPrint expects error in editor text:\n" + error);
|
||||
const errorLine = 3, errorColumn = 10;
|
||||
const editorDoc = sp.editor.container.contentDocument;
|
||||
sp.editor.jumpToLine();
|
||||
const lineInput = editorDoc.querySelector("input");
|
||||
const errorLocation = lineInput.value;
|
||||
const [ inputLine, inputColumn ] = errorLocation.split(":");
|
||||
is(inputLine, errorLine, "jumpToLine input field is set from editor selection (line)");
|
||||
is(inputColumn, errorColumn, "jumpToLine input field is set from editor selection (column)");
|
||||
EventUtils.synthesizeKey("VK_RETURN", { }, editorDoc.defaultView);
|
||||
// CodeMirror lines and columns are 0-based, Scratchpad UI and error
|
||||
// stack are 1-based.
|
||||
const cursor = sp.editor.getCursor();
|
||||
is(inputLine, cursor.line + 1, "jumpToLine goto error location (line)");
|
||||
is(inputColumn, cursor.ch + 1, "jumpToLine goto error location (column)");
|
||||
}
|
||||
|
||||
function runTests(sw, sp)
|
||||
{
|
||||
sp.setText([
|
||||
"// line 1",
|
||||
"// line 2",
|
||||
"var re = /a bad /regexp/; // line 3 is an obvious syntax error!",
|
||||
"// line 4",
|
||||
"// line 5",
|
||||
""
|
||||
].join("\n"));
|
||||
sp.prettyPrint().then(aFulfill => {
|
||||
ok(false, "Expecting Invalid regexp flag (3:10)");
|
||||
finish();
|
||||
}, error => {
|
||||
testJumpToPrettyPrintError(sp, error, " (Bug 1005471, first time)");
|
||||
});
|
||||
sp.prettyPrint().then(aFulfill => {
|
||||
ok(false, "Expecting Invalid regexp flag (3:10)");
|
||||
finish();
|
||||
}, error => {
|
||||
// Second time verifies bug in earlier implementation fixed.
|
||||
testJumpToPrettyPrintError(sp, error, " (second time)");
|
||||
finish();
|
||||
});
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
openScratchpad(runTests);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html;charset=utf8,test Scratchpad pretty print.";
|
||||
}
|
||||
|
||||
function runTests(sw)
|
||||
{
|
||||
const sp = sw.Scratchpad;
|
||||
sp.setText([
|
||||
"// line 1",
|
||||
"// line 2",
|
||||
"var re = /a bad /regexp/; // line 3 is an obvious syntax error!",
|
||||
"// line 4",
|
||||
"// line 5",
|
||||
""
|
||||
].join("\n"));
|
||||
sp.run().then(() => {
|
||||
// CodeMirror lines and columns are 0-based, Scratchpad UI and error
|
||||
// stack are 1-based.
|
||||
let errorLine = 3;
|
||||
let editorDoc = sp.editor.container.contentDocument;
|
||||
sp.editor.jumpToLine();
|
||||
let lineInput = editorDoc.querySelector("input");
|
||||
let inputLine = lineInput.value;
|
||||
is(inputLine, errorLine, "jumpToLine input field is set from editor selection");
|
||||
EventUtils.synthesizeKey("VK_RETURN", { }, editorDoc.defaultView);
|
||||
// CodeMirror lines and columns are 0-based, Scratchpad UI and error
|
||||
// stack are 1-based.
|
||||
let cursor = sp.editor.getCursor();
|
||||
is(cursor.line + 1, inputLine, "jumpToLine goto error location (line)");
|
||||
is(cursor.ch + 1, 1, "jumpToLine goto error location (column)");
|
||||
finish();
|
||||
});
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et tw=80:
|
||||
* 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
|
||||
@ -20,6 +21,11 @@ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.x
|
||||
// while shifting to a line which was initially out of view.
|
||||
const MAX_VERTICAL_OFFSET = 3;
|
||||
|
||||
// Match @Scratchpad/N:LINE[:COLUMN] or (LINE[:COLUMN]) anywhere at an end of
|
||||
// line in text selection.
|
||||
const RE_SCRATCHPAD_ERROR = /(?:@Scratchpad\/\d+:|\()(\d+):?(\d+)?(?:\)|\n)/;
|
||||
const RE_JUMP_TO_LINE = /^(\d+):?(\d+)?/;
|
||||
|
||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
const events = require("devtools/toolkit/event-emitter");
|
||||
|
||||
@ -752,7 +758,28 @@ Editor.prototype = {
|
||||
div.appendChild(txt);
|
||||
div.appendChild(inp);
|
||||
|
||||
this.openDialog(div, (line) => this.setCursor({ line: line - 1, ch: 0 }));
|
||||
if (!this.hasMultipleSelections()) {
|
||||
let cm = editors.get(this);
|
||||
let sel = cm.getSelection();
|
||||
// Scratchpad inserts and selects a comment after an error happens:
|
||||
// "@Scratchpad/1:10:2". Parse this to get the line and column.
|
||||
// In the string above this is line 10, column 2.
|
||||
let match = sel.match(RE_SCRATCHPAD_ERROR);
|
||||
if (match) {
|
||||
let [ , line, column ] = match;
|
||||
inp.value = column ? line + ":" + column : line;
|
||||
inp.selectionStart = inp.selectionEnd = inp.value.length;
|
||||
}
|
||||
}
|
||||
|
||||
this.openDialog(div, (line) => {
|
||||
// Handle LINE:COLUMN as well as LINE
|
||||
let match = line.toString().match(RE_JUMP_TO_LINE);
|
||||
if (match) {
|
||||
let [ , line, column ] = match;
|
||||
this.setCursor({line: line - 1, ch: column ? column - 1 : 0 });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -22,6 +22,7 @@ support-files =
|
||||
|
||||
[browser_editor_basic.js]
|
||||
[browser_editor_cursor.js]
|
||||
[browser_editor_goto_line.js]
|
||||
[browser_editor_history.js]
|
||||
[browser_editor_markers.js]
|
||||
[browser_editor_movelines.js]
|
||||
|
130
browser/devtools/sourceeditor/test/browser_editor_goto_line.js
Normal file
@ -0,0 +1,130 @@
|
||||
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2; fill-column: 80 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function testJumpToLine (ed, inputLine, expectCursor) {
|
||||
ed.jumpToLine();
|
||||
let editorDoc = ed.container.contentDocument;
|
||||
let lineInput = editorDoc.querySelector("input");
|
||||
lineInput.value = inputLine;
|
||||
EventUtils.synthesizeKey("VK_RETURN", { }, editorDoc.defaultView);
|
||||
// CodeMirror lines and columns are 0-based, Scratchpad UI is 1-based.
|
||||
ch(ed.getCursor(), expectCursor, "jumpToLine " + inputLine + " expects cursor " + expectCursor.toSource());
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
setup((ed, win) => {
|
||||
let textLines = [
|
||||
"// line 1",
|
||||
"// line 2",
|
||||
"// line 3",
|
||||
"// line 4",
|
||||
"// line 5",
|
||||
""];
|
||||
ed.setText(textLines.join("\n"));
|
||||
waitForFocus(function () {
|
||||
let testVectors = [
|
||||
// Various useless inputs go to line 0, column 0 or do nothing.
|
||||
["",
|
||||
{line:0, ch:0}],
|
||||
[":",
|
||||
{line:0, ch:0}],
|
||||
[" ",
|
||||
{line:0, ch:0}],
|
||||
[" : ",
|
||||
{line:0, ch:0}],
|
||||
["a:b",
|
||||
{line:0, ch:0}],
|
||||
["LINE:COLUMN",
|
||||
{line:0, ch:0}],
|
||||
["-1",
|
||||
{line:0, ch:0}],
|
||||
[":-1",
|
||||
{line:0, ch:0}],
|
||||
["-1:-1",
|
||||
{line:0, ch:0}],
|
||||
["0",
|
||||
{line:0, ch:0}],
|
||||
[":0",
|
||||
{line:0, ch:0}],
|
||||
["0:0",
|
||||
{line:0, ch:0}],
|
||||
// Starting here expect data needs to get updated for length changes to
|
||||
// "textLines" above.
|
||||
// Just jump to line
|
||||
["1",
|
||||
{line:0, ch:0}],
|
||||
// Jump to second character in line
|
||||
["1:2",
|
||||
{line:0, ch:1}],
|
||||
// Jump to last character on line
|
||||
["1:9",
|
||||
{line:0, ch:8}],
|
||||
// Jump just after last character on line (end of line)
|
||||
["1:10",
|
||||
{line:0, ch:9}],
|
||||
// Jump one character past end of line (gets clamped to end of line)
|
||||
["1:11",
|
||||
{line:0, ch:9}],
|
||||
["2",
|
||||
{line:1, ch:0}],
|
||||
["2:2",
|
||||
{line:1, ch:1}],
|
||||
["2:10",
|
||||
{line:1, ch:9}],
|
||||
["2:11",
|
||||
{line:1, ch:10}],
|
||||
["2:12",
|
||||
{line:1, ch:10}],
|
||||
["3",
|
||||
{line:2, ch:0}],
|
||||
["3:2",
|
||||
{line:2, ch:1}],
|
||||
["3:11",
|
||||
{line:2, ch:10}],
|
||||
["3:12",
|
||||
{line:2, ch:11}],
|
||||
["3:13",
|
||||
{line:2, ch:11}],
|
||||
["4",
|
||||
{line:3, ch:0}],
|
||||
["4:2",
|
||||
{line:3, ch:1}],
|
||||
["4:12",
|
||||
{line:3, ch:11}],
|
||||
["4:13",
|
||||
{line:3, ch:12}],
|
||||
["4:14",
|
||||
{line:3, ch:12}],
|
||||
["5",
|
||||
{line:4, ch:0}],
|
||||
["5:2",
|
||||
{line:4, ch:1}],
|
||||
["5:13",
|
||||
{line:4, ch:12}],
|
||||
["5:14",
|
||||
{line:4, ch:13}],
|
||||
["5:15",
|
||||
{line:4, ch:13}],
|
||||
// One line beyond last newline in editor text:
|
||||
["6",
|
||||
{line:5, ch:0}],
|
||||
["6:2",
|
||||
{line:5, ch:0}],
|
||||
// Two line beyond last newline in editor text (gets clamped):
|
||||
["7",
|
||||
{line:5, ch:0}],
|
||||
["7:2",
|
||||
{line:5, ch:0}]
|
||||
];
|
||||
testVectors.forEach(function (vector) {
|
||||
testJumpToLine(ed, vector[0], vector[1]);
|
||||
});
|
||||
teardown(ed, win);
|
||||
});
|
||||
});
|
||||
}
|
@ -5,53 +5,47 @@
|
||||
// This test makes sure that the style editor does not store any
|
||||
// content CSS files in the permanent cache when opened from PB mode.
|
||||
|
||||
let gUI;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
let windowsToClose = [];
|
||||
let gUI;
|
||||
let testURI = 'http://' + TEST_HOST + '/browser/browser/devtools/styleeditor/test/test_private.html';
|
||||
|
||||
function checkCache() {
|
||||
checkDiskCacheFor(TEST_HOST, function() {
|
||||
gUI = null;
|
||||
finish();
|
||||
});
|
||||
}
|
||||
info("Opening a new private window");
|
||||
let win = OpenBrowserWindow({private: true});
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
executeSoon(startTest);
|
||||
}, false);
|
||||
|
||||
function doTest(aWindow) {
|
||||
aWindow.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
aWindow.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
function startTest() {
|
||||
win.gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
win.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
|
||||
info("Clearing the browser cache");
|
||||
cache.clear();
|
||||
openStyleEditorInWindow(aWindow, function(panel) {
|
||||
|
||||
info("Opening the style editor in the private window");
|
||||
openStyleEditorInWindow(win, function(panel) {
|
||||
gUI = panel.UI;
|
||||
gUI.on("editor-added", onEditorAdded);
|
||||
});
|
||||
}, true);
|
||||
|
||||
aWindow.gBrowser.selectedBrowser.loadURI(testURI);
|
||||
info("Loading the test URL in the new private window");
|
||||
win.content.location = testURI;
|
||||
}
|
||||
|
||||
function onEditorAdded(aEvent, aEditor) {
|
||||
info("The style editor is ready")
|
||||
aEditor.getSourceEditor().then(checkCache);
|
||||
}
|
||||
|
||||
function testOnWindow(options, callback) {
|
||||
let win = OpenBrowserWindow(options);
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
windowsToClose.push(win);
|
||||
executeSoon(function() callback(win));
|
||||
}, false);
|
||||
};
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
windowsToClose.forEach(function(win) {
|
||||
function checkCache() {
|
||||
checkDiskCacheFor(TEST_HOST, function() {
|
||||
win.close();
|
||||
});
|
||||
});
|
||||
|
||||
testOnWindow({private: true}, function(win) {
|
||||
doTest(win);
|
||||
win = null;
|
||||
gUI = null;
|
||||
finish();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -272,10 +272,18 @@ browser.jar:
|
||||
skin/classic/browser/devtools/debugger-toggleBreakpoints@2x.png (../shared/devtools/images/debugger-toggleBreakpoints@2x.png)
|
||||
skin/classic/browser/devtools/tracer-icon.png (../shared/devtools/images/tracer-icon.png)
|
||||
skin/classic/browser/devtools/tracer-icon@2x.png (../shared/devtools/images/tracer-icon@2x.png)
|
||||
skin/classic/browser/devtools/responsive-se-resizer.png (../shared/devtools/images/responsive-se-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-vertical-resizer.png (../shared/devtools/images/responsive-vertical-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-horizontal-resizer.png (../shared/devtools/images/responsive-horizontal-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-background.png (../shared/devtools/images/responsive-background.png)
|
||||
skin/classic/browser/devtools/responsive-se-resizer.png (../shared/devtools/images/responsivemode/responsive-se-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-se-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-se-resizer@2x.png)
|
||||
skin/classic/browser/devtools/responsive-vertical-resizer.png (../shared/devtools/images/responsivemode/responsive-vertical-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-vertical-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-vertical-resizer@2x.png)
|
||||
skin/classic/browser/devtools/responsive-horizontal-resizer.png (../shared/devtools/images/responsivemode/responsive-horizontal-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-horizontal-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-horizontal-resizer@2x.png)
|
||||
skin/classic/browser/devtools/responsiveui-rotate.png (../shared/devtools/images/responsivemode/responsiveui-rotate.png)
|
||||
skin/classic/browser/devtools/responsiveui-rotate@2x.png (../shared/devtools/images/responsivemode/responsiveui-rotate@2x.png)
|
||||
skin/classic/browser/devtools/responsiveui-touch.png (../shared/devtools/images/responsivemode/responsiveui-touch.png)
|
||||
skin/classic/browser/devtools/responsiveui-touch@2x.png (../shared/devtools/images/responsivemode/responsiveui-touch@2x.png)
|
||||
skin/classic/browser/devtools/responsiveui-screenshot.png (../shared/devtools/images/responsivemode/responsiveui-screenshot.png)
|
||||
skin/classic/browser/devtools/responsiveui-screenshot@2x.png (../shared/devtools/images/responsivemode/responsiveui-screenshot@2x.png)
|
||||
skin/classic/browser/devtools/toggle-tools.png (../shared/devtools/images/toggle-tools.png)
|
||||
skin/classic/browser/devtools/dock-bottom@2x.png (../shared/devtools/images/dock-bottom@2x.png)
|
||||
skin/classic/browser/devtools/dock-side@2x.png (../shared/devtools/images/dock-side@2x.png)
|
||||
@ -309,9 +317,6 @@ browser.jar:
|
||||
skin/classic/browser/devtools/font-inspector.css (../shared/devtools/font-inspector.css)
|
||||
skin/classic/browser/devtools/computedview.css (../shared/devtools/computedview.css)
|
||||
skin/classic/browser/devtools/arrow-e.png (../shared/devtools/images/arrow-e.png)
|
||||
skin/classic/browser/devtools/responsiveui-rotate.png (../shared/devtools/responsiveui-rotate.png)
|
||||
skin/classic/browser/devtools/responsiveui-touch.png (../shared/devtools/responsiveui-touch.png)
|
||||
skin/classic/browser/devtools/responsiveui-screenshot.png (../shared/devtools/responsiveui-screenshot.png)
|
||||
skin/classic/browser/devtools/projecteditor/projecteditor.css (../shared/devtools/projecteditor/projecteditor.css)
|
||||
skin/classic/browser/devtools/projecteditor/file-icons-sheet@2x.png (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
|
||||
skin/classic/browser/devtools/app-manager/connection-footer.css (../shared/devtools/app-manager/connection-footer.css)
|
||||
|
@ -4,6 +4,14 @@
|
||||
|
||||
%include ../../../shared/incontentprefs/preferences.css
|
||||
|
||||
tab[selected] {
|
||||
/* Override styles for tab[selected] from
|
||||
toolkit/themes/linux/global/tabbox.css */
|
||||
margin-bottom: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
button > .button-box,
|
||||
menulist > .menulist-label-box {
|
||||
-moz-appearance: none;
|
||||
|
@ -392,10 +392,18 @@ browser.jar:
|
||||
skin/classic/browser/devtools/tracer-icon@2x.png (../shared/devtools/images/tracer-icon@2x.png)
|
||||
skin/classic/browser/devtools/floating-scrollbars.css (devtools/floating-scrollbars.css)
|
||||
skin/classic/browser/devtools/floating-scrollbars-light.css (devtools/floating-scrollbars-light.css)
|
||||
skin/classic/browser/devtools/responsive-se-resizer.png (../shared/devtools/images/responsive-se-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-vertical-resizer.png (../shared/devtools/images/responsive-vertical-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-horizontal-resizer.png (../shared/devtools/images/responsive-horizontal-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-background.png (../shared/devtools/images/responsive-background.png)
|
||||
skin/classic/browser/devtools/responsive-se-resizer.png (../shared/devtools/images/responsivemode/responsive-se-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-se-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-se-resizer@2x.png)
|
||||
skin/classic/browser/devtools/responsive-vertical-resizer.png (../shared/devtools/images/responsivemode/responsive-vertical-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-vertical-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-vertical-resizer@2x.png)
|
||||
skin/classic/browser/devtools/responsive-horizontal-resizer.png (../shared/devtools/images/responsivemode/responsive-horizontal-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-horizontal-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-horizontal-resizer@2x.png)
|
||||
skin/classic/browser/devtools/responsiveui-rotate.png (../shared/devtools/images/responsivemode/responsiveui-rotate.png)
|
||||
skin/classic/browser/devtools/responsiveui-rotate@2x.png (../shared/devtools/images/responsivemode/responsiveui-rotate@2x.png)
|
||||
skin/classic/browser/devtools/responsiveui-touch.png (../shared/devtools/images/responsivemode/responsiveui-touch.png)
|
||||
skin/classic/browser/devtools/responsiveui-touch@2x.png (../shared/devtools/images/responsivemode/responsiveui-touch@2x.png)
|
||||
skin/classic/browser/devtools/responsiveui-screenshot.png (../shared/devtools/images/responsivemode/responsiveui-screenshot.png)
|
||||
skin/classic/browser/devtools/responsiveui-screenshot@2x.png (../shared/devtools/images/responsivemode/responsiveui-screenshot@2x.png)
|
||||
skin/classic/browser/devtools/toggle-tools.png (../shared/devtools/images/toggle-tools.png)
|
||||
skin/classic/browser/devtools/dock-bottom@2x.png (../shared/devtools/images/dock-bottom@2x.png)
|
||||
skin/classic/browser/devtools/dock-side@2x.png (../shared/devtools/images/dock-side@2x.png)
|
||||
@ -427,9 +435,6 @@ browser.jar:
|
||||
skin/classic/browser/devtools/font-inspector.css (../shared/devtools/font-inspector.css)
|
||||
skin/classic/browser/devtools/computedview.css (../shared/devtools/computedview.css)
|
||||
skin/classic/browser/devtools/arrow-e.png (../shared/devtools/images/arrow-e.png)
|
||||
skin/classic/browser/devtools/responsiveui-rotate.png (../shared/devtools/responsiveui-rotate.png)
|
||||
skin/classic/browser/devtools/responsiveui-touch.png (../shared/devtools/responsiveui-touch.png)
|
||||
skin/classic/browser/devtools/responsiveui-screenshot.png (../shared/devtools/responsiveui-screenshot.png)
|
||||
skin/classic/browser/devtools/projecteditor/projecteditor.css (../shared/devtools/projecteditor/projecteditor.css)
|
||||
skin/classic/browser/devtools/projecteditor/file-icons-sheet@2x.png (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
|
||||
skin/classic/browser/devtools/app-manager/connection-footer.css (../shared/devtools/app-manager/connection-footer.css)
|
||||
|
@ -4,6 +4,20 @@
|
||||
|
||||
%include ../../../shared/incontentprefs/preferences.css
|
||||
|
||||
prefpane .groupbox-title {
|
||||
background: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
tabs {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
tab[selected] {
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
menulist:not([editable="true"]) > menupopup > menuitem[checked="true"]::before,
|
||||
menulist:not([editable="true"]) > menupopup > menuitem[selected="true"]::before {
|
||||
display: none;
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 256 B |
Before Width: | Height: | Size: 339 B |
Before Width: | Height: | Size: 237 B |
After Width: | Height: | Size: 102 B |
After Width: | Height: | Size: 129 B |
After Width: | Height: | Size: 129 B |
After Width: | Height: | Size: 205 B |
After Width: | Height: | Size: 105 B |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 245 B |
After Width: | Height: | Size: 438 B |
After Width: | Height: | Size: 303 B |
After Width: | Height: | Size: 531 B |
After Width: | Height: | Size: 470 B |
After Width: | Height: | Size: 927 B |
@ -7,7 +7,7 @@
|
||||
/* Responsive Mode */
|
||||
|
||||
.browserContainer[responsivemode] {
|
||||
background: #222 url("chrome://browser/skin/devtools/responsive-background.png");
|
||||
background-color: #222;
|
||||
padding: 0 20px 20px 20px;
|
||||
}
|
||||
|
||||
@ -43,6 +43,11 @@
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.devtools-responsiveui-toolbarbutton > .toolbarbutton-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.devtools-responsiveui-toolbarbutton > .toolbarbutton-menubutton-button {
|
||||
-moz-box-orient: horizontal;
|
||||
}
|
||||
@ -135,6 +140,16 @@
|
||||
list-style-image: url("chrome://browser/skin/devtools/responsiveui-rotate.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
.devtools-responsiveui-close {
|
||||
list-style-image: url("chrome://browser/skin/devtools/close@2x.png");
|
||||
}
|
||||
|
||||
.devtools-responsiveui-rotate {
|
||||
list-style-image: url("chrome://browser/skin/devtools/responsiveui-rotate@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
.devtools-responsiveui-touch {
|
||||
list-style-image: url("chrome://browser/skin/devtools/responsiveui-touch.png");
|
||||
-moz-image-region: rect(0px,16px,16px,0px);
|
||||
@ -144,15 +159,33 @@
|
||||
-moz-image-region: rect(0px,32px,16px,16px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
.devtools-responsiveui-touch {
|
||||
list-style-image: url("chrome://browser/skin/devtools/responsiveui-touch@2x.png");
|
||||
-moz-image-region: rect(0px,32px,32px,0px);
|
||||
}
|
||||
|
||||
.devtools-responsiveui-touch[checked] {
|
||||
-moz-image-region: rect(0px,64px,32px,32px);
|
||||
}
|
||||
}
|
||||
|
||||
.devtools-responsiveui-screenshot {
|
||||
list-style-image: url("chrome://browser/skin/devtools/responsiveui-screenshot.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
.devtools-responsiveui-screenshot {
|
||||
list-style-image: url("chrome://browser/skin/devtools/responsiveui-screenshot@2x.png");
|
||||
}
|
||||
}
|
||||
|
||||
.devtools-responsiveui-resizebarV {
|
||||
width: 7px;
|
||||
height: 24px;
|
||||
cursor: ew-resize;
|
||||
transform: translate(12px, -12px);
|
||||
background-size: cover;
|
||||
background-image: url("chrome://browser/skin/devtools/responsive-vertical-resizer.png");
|
||||
}
|
||||
|
||||
@ -161,6 +194,7 @@
|
||||
height: 7px;
|
||||
cursor: ns-resize;
|
||||
transform: translate(-12px, 12px);
|
||||
background-size: cover;
|
||||
background-image: url("chrome://browser/skin/devtools/responsive-horizontal-resizer.png");
|
||||
}
|
||||
|
||||
@ -169,5 +203,20 @@
|
||||
height: 16px;
|
||||
cursor: se-resize;
|
||||
transform: translate(12px, 12px);
|
||||
background-size: cover;
|
||||
background-image: url("chrome://browser/skin/devtools/responsive-se-resizer.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
.devtools-responsiveui-resizebarV {
|
||||
background-image: url("chrome://browser/skin/devtools/responsive-vertical-resizer@2x.png");
|
||||
}
|
||||
|
||||
.devtools-responsiveui-resizebarH {
|
||||
background-image: url("chrome://browser/skin/devtools/responsive-horizontal-resizer@2x.png");
|
||||
}
|
||||
|
||||
.devtools-responsiveui-resizehandle {
|
||||
background-image: url("chrome://browser/skin/devtools/responsive-se-resizer@2x.png");
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 498 B |
Before Width: | Height: | Size: 528 B |
Before Width: | Height: | Size: 834 B |
@ -12,7 +12,7 @@
|
||||
|
||||
page {
|
||||
-moz-appearance: none;
|
||||
background-image: linear-gradient(#FFFFFF, #EDEDED 100px);
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
* {
|
||||
@ -84,10 +84,9 @@ tabpanels {
|
||||
tabs {
|
||||
-moz-margin-start: 60px;
|
||||
margin-bottom: 15px;
|
||||
border-top: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
-moz-border-top-colors: #BBBBBB #F9F9F9;
|
||||
-moz-border-bottom-colors: #F9F9F9 #BBBBBB;
|
||||
border-top: 1px solid #c1c1c1;
|
||||
border-bottom: 1px solid #c1c1c1;
|
||||
background-color: #fbfbfb;
|
||||
}
|
||||
|
||||
.tabs-left,
|
||||
@ -98,38 +97,26 @@ tabs {
|
||||
tab {
|
||||
-moz-appearance: none;
|
||||
margin-top: 0;
|
||||
padding: 0;
|
||||
-moz-margin-end: 30px;
|
||||
min-height: 60px;
|
||||
background-color: transparent;
|
||||
padding: 0 20px;
|
||||
min-height: 44px;
|
||||
color: #424f5a;
|
||||
background-color: #fbfbfb;
|
||||
border-width: 0;
|
||||
border-bottom: 3px solid transparent;
|
||||
transition: background-color 50ms ease 0s;
|
||||
}
|
||||
|
||||
tab:hover {
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
|
||||
tab[selected] {
|
||||
border-bottom-color: #FF9500;
|
||||
background-color: #ebebeb;
|
||||
box-shadow: inset 0 -4px 0 0 #ff9500;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
font-size: 1.3rem;
|
||||
line-height: 22px;
|
||||
color: #333333;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
tab:not([selected]):hover > .tab-middle > .tab-text {
|
||||
background-color: rgba(255,255,255,0.5);
|
||||
border-color: #FFFFFF;
|
||||
}
|
||||
|
||||
tab:not([selected]):hover:active > .tab-middle > .tab-text {
|
||||
background-color: rgba(0,0,0,0.03);
|
||||
}
|
||||
|
||||
tab[selected] > .tab-middle > .tab-text {
|
||||
font-weight: bold;
|
||||
color: #424E5A;
|
||||
}
|
||||
|
||||
/* buttons and menulists */
|
||||
|
@ -310,10 +310,18 @@ browser.jar:
|
||||
skin/classic/browser/devtools/debugger-toggleBreakpoints@2x.png (../shared/devtools/images/debugger-toggleBreakpoints@2x.png)
|
||||
skin/classic/browser/devtools/tracer-icon.png (../shared/devtools/images/tracer-icon.png)
|
||||
skin/classic/browser/devtools/tracer-icon@2x.png (../shared/devtools/images/tracer-icon@2x.png)
|
||||
skin/classic/browser/devtools/responsive-se-resizer.png (../shared/devtools/images/responsive-se-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-vertical-resizer.png (../shared/devtools/images/responsive-vertical-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-horizontal-resizer.png (../shared/devtools/images/responsive-horizontal-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-background.png (../shared/devtools/images/responsive-background.png)
|
||||
skin/classic/browser/devtools/responsive-se-resizer.png (../shared/devtools/images/responsivemode/responsive-se-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-se-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-se-resizer@2x.png)
|
||||
skin/classic/browser/devtools/responsive-vertical-resizer.png (../shared/devtools/images/responsivemode/responsive-vertical-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-vertical-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-vertical-resizer@2x.png)
|
||||
skin/classic/browser/devtools/responsive-horizontal-resizer.png (../shared/devtools/images/responsivemode/responsive-horizontal-resizer.png)
|
||||
skin/classic/browser/devtools/responsive-horizontal-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-horizontal-resizer@2x.png)
|
||||
skin/classic/browser/devtools/responsiveui-rotate.png (../shared/devtools/images/responsivemode/responsiveui-rotate.png)
|
||||
skin/classic/browser/devtools/responsiveui-rotate@2x.png (../shared/devtools/images/responsivemode/responsiveui-rotate@2x.png)
|
||||
skin/classic/browser/devtools/responsiveui-touch.png (../shared/devtools/images/responsivemode/responsiveui-touch.png)
|
||||
skin/classic/browser/devtools/responsiveui-touch@2x.png (../shared/devtools/images/responsivemode/responsiveui-touch@2x.png)
|
||||
skin/classic/browser/devtools/responsiveui-screenshot.png (../shared/devtools/images/responsivemode/responsiveui-screenshot.png)
|
||||
skin/classic/browser/devtools/responsiveui-screenshot@2x.png (../shared/devtools/images/responsivemode/responsiveui-screenshot@2x.png)
|
||||
skin/classic/browser/devtools/toggle-tools.png (../shared/devtools/images/toggle-tools.png)
|
||||
skin/classic/browser/devtools/dock-bottom@2x.png (../shared/devtools/images/dock-bottom@2x.png)
|
||||
skin/classic/browser/devtools/dock-side@2x.png (../shared/devtools/images/dock-side@2x.png)
|
||||
@ -346,9 +354,6 @@ browser.jar:
|
||||
skin/classic/browser/devtools/font-inspector.css (../shared/devtools/font-inspector.css)
|
||||
skin/classic/browser/devtools/computedview.css (../shared/devtools/computedview.css)
|
||||
skin/classic/browser/devtools/arrow-e.png (../shared/devtools/images/arrow-e.png)
|
||||
skin/classic/browser/devtools/responsiveui-rotate.png (../shared/devtools/responsiveui-rotate.png)
|
||||
skin/classic/browser/devtools/responsiveui-touch.png (../shared/devtools/responsiveui-touch.png)
|
||||
skin/classic/browser/devtools/responsiveui-screenshot.png (../shared/devtools/responsiveui-screenshot.png)
|
||||
skin/classic/browser/devtools/projecteditor/projecteditor.css (../shared/devtools/projecteditor/projecteditor.css)
|
||||
skin/classic/browser/devtools/projecteditor/file-icons-sheet@2x.png (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
|
||||
skin/classic/browser/devtools/app-manager/connection-footer.css (../shared/devtools/app-manager/connection-footer.css)
|
||||
@ -705,10 +710,18 @@ browser.jar:
|
||||
skin/classic/aero/browser/devtools/debugger-toggleBreakpoints@2x.png (../shared/devtools/images/debugger-toggleBreakpoints@2x.png)
|
||||
skin/classic/aero/browser/devtools/tracer-icon.png (../shared/devtools/images/tracer-icon.png)
|
||||
skin/classic/aero/browser/devtools/tracer-icon@2x.png (../shared/devtools/images/tracer-icon@2x.png)
|
||||
skin/classic/aero/browser/devtools/responsive-se-resizer.png (../shared/devtools/images/responsive-se-resizer.png)
|
||||
skin/classic/aero/browser/devtools/responsive-vertical-resizer.png (../shared/devtools/images/responsive-vertical-resizer.png)
|
||||
skin/classic/aero/browser/devtools/responsive-horizontal-resizer.png (../shared/devtools/images/responsive-horizontal-resizer.png)
|
||||
skin/classic/aero/browser/devtools/responsive-background.png (../shared/devtools/images/responsive-background.png)
|
||||
skin/classic/aero/browser/devtools/responsive-se-resizer.png (../shared/devtools/images/responsivemode/responsive-se-resizer.png)
|
||||
skin/classic/aero/browser/devtools/responsive-se-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-se-resizer@2x.png)
|
||||
skin/classic/aero/browser/devtools/responsive-vertical-resizer.png (../shared/devtools/images/responsivemode/responsive-vertical-resizer.png)
|
||||
skin/classic/aero/browser/devtools/responsive-vertical-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-vertical-resizer@2x.png)
|
||||
skin/classic/aero/browser/devtools/responsive-horizontal-resizer.png (../shared/devtools/images/responsivemode/responsive-horizontal-resizer.png)
|
||||
skin/classic/aero/browser/devtools/responsive-horizontal-resizer@2x.png (../shared/devtools/images/responsivemode/responsive-horizontal-resizer@2x.png)
|
||||
skin/classic/aero/browser/devtools/responsiveui-rotate.png (../shared/devtools/images/responsivemode/responsiveui-rotate.png)
|
||||
skin/classic/aero/browser/devtools/responsiveui-rotate@2x.png (../shared/devtools/images/responsivemode/responsiveui-rotate@2x.png)
|
||||
skin/classic/aero/browser/devtools/responsiveui-touch.png (../shared/devtools/images/responsivemode/responsiveui-touch.png)
|
||||
skin/classic/aero/browser/devtools/responsiveui-touch@2x.png (../shared/devtools/images/responsivemode/responsiveui-touch@2x.png)
|
||||
skin/classic/aero/browser/devtools/responsiveui-screenshot.png (../shared/devtools/images/responsivemode/responsiveui-screenshot.png)
|
||||
skin/classic/aero/browser/devtools/responsiveui-screenshot@2x.png (../shared/devtools/images/responsivemode/responsiveui-screenshot@2x.png)
|
||||
skin/classic/aero/browser/devtools/toggle-tools.png (../shared/devtools/images/toggle-tools.png)
|
||||
skin/classic/aero/browser/devtools/dock-bottom@2x.png (../shared/devtools/images/dock-bottom@2x.png)
|
||||
skin/classic/aero/browser/devtools/dock-side@2x.png (../shared/devtools/images/dock-side@2x.png)
|
||||
@ -741,9 +754,6 @@ browser.jar:
|
||||
skin/classic/aero/browser/devtools/font-inspector.css (../shared/devtools/font-inspector.css)
|
||||
skin/classic/aero/browser/devtools/computedview.css (../shared/devtools/computedview.css)
|
||||
skin/classic/aero/browser/devtools/arrow-e.png (../shared/devtools/images/arrow-e.png)
|
||||
skin/classic/aero/browser/devtools/responsiveui-rotate.png (../shared/devtools/responsiveui-rotate.png)
|
||||
skin/classic/aero/browser/devtools/responsiveui-touch.png (../shared/devtools/responsiveui-touch.png)
|
||||
skin/classic/aero/browser/devtools/responsiveui-screenshot.png (../shared/devtools/responsiveui-screenshot.png)
|
||||
skin/classic/aero/browser/devtools/projecteditor/projecteditor.css (../shared/devtools/projecteditor/projecteditor.css)
|
||||
skin/classic/aero/browser/devtools/projecteditor/file-icons-sheet@2x.png (../shared/devtools/projecteditor/file-icons-sheet@2x.png)
|
||||
skin/classic/aero/browser/devtools/app-manager/connection-footer.css (../shared/devtools/app-manager/connection-footer.css)
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
%include ../../../shared/incontentprefs/preferences.css
|
||||
|
||||
caption {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
menulist:not([editable="true"]) > .menulist-dropmarker {
|
||||
margin-top: 1px;
|
||||
margin-bottom: 1px;
|
||||
|
@ -1039,7 +1039,7 @@ nsScriptSecurityManager::CanCreateWrapper(JSContext *cx,
|
||||
}
|
||||
|
||||
// We give remote-XUL whitelisted domains a free pass here. See bug 932906.
|
||||
if (!xpc::AllowXBLScope(js::GetContextCompartment(cx)))
|
||||
if (!xpc::AllowContentXBLScope(js::GetContextCompartment(cx)))
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ public:
|
||||
|
||||
static bool IsCallerChrome();
|
||||
static bool ThreadsafeIsCallerChrome();
|
||||
static bool IsCallerXBL();
|
||||
static bool IsCallerContentXBL();
|
||||
|
||||
static bool IsImageSrcSetDisabled();
|
||||
|
||||
|
@ -696,7 +696,8 @@ nsCSPParser::sourceList(nsTArray<nsCSPBaseSrc*>& outSrcs)
|
||||
}
|
||||
// Otherwise, we ignore 'none' and report a warning
|
||||
else {
|
||||
const char16_t* params[] = { NS_ConvertUTF8toUTF16(CSP_EnumToKeyword(CSP_NONE)).get() };
|
||||
NS_ConvertUTF8toUTF16 unicodeNone(CSP_EnumToKeyword(CSP_NONE));
|
||||
const char16_t* params[] = { unicodeNone.get() };
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag, "ignoringUnknownOption",
|
||||
params, ArrayLength(params));
|
||||
}
|
||||
@ -887,7 +888,8 @@ nsCSPParser::parseContentSecurityPolicy(const nsAString& aPolicyString,
|
||||
nsAutoCString prePath;
|
||||
nsresult rv = aSelfURI->GetPrePath(prePath);
|
||||
NS_ENSURE_SUCCESS(rv, policy);
|
||||
const char16_t* params[] = { NS_ConvertUTF8toUTF16(prePath).get() };
|
||||
NS_ConvertUTF8toUTF16 unicodePrePath(prePath);
|
||||
const char16_t* params[] = { unicodePrePath.get() };
|
||||
parser.logWarningErrorToConsole(nsIScriptError::warningFlag, "reportURInotInReportOnlyHeader",
|
||||
params, ArrayLength(params));
|
||||
}
|
||||
|
@ -367,7 +367,8 @@ CSPService::AsyncOnChannelRedirect(nsIChannel *oldChannel,
|
||||
// to enforce the load policy if it redirects again, so we stop it now.
|
||||
nsAutoCString newUriSpec;
|
||||
rv = newUri->GetSpec(newUriSpec);
|
||||
const char16_t *formatParams[] = { NS_ConvertUTF8toUTF16(newUriSpec).get() };
|
||||
NS_ConvertUTF8toUTF16 unicodeSpec(newUriSpec);
|
||||
const char16_t *formatParams[] = { unicodeSpec.get() };
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("Redirect Error"), nullptr,
|
||||
|
@ -1714,7 +1714,7 @@ nsContentUtils::ThreadsafeIsCallerChrome()
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::IsCallerXBL()
|
||||
nsContentUtils::IsCallerContentXBL()
|
||||
{
|
||||
JSContext *cx = GetCurrentJSContext();
|
||||
if (!cx)
|
||||
@ -1724,12 +1724,12 @@ nsContentUtils::IsCallerXBL()
|
||||
|
||||
// For remote XUL, we run XBL in the XUL scope. Given that we care about
|
||||
// compat and not security for remote XUL, just always claim to be XBL.
|
||||
if (!xpc::AllowXBLScope(c)) {
|
||||
if (!xpc::AllowContentXBLScope(c)) {
|
||||
MOZ_ASSERT(nsContentUtils::AllowXULXBLForPrincipal(xpc::GetCompartmentPrincipal(c)));
|
||||
return true;
|
||||
}
|
||||
|
||||
return xpc::IsXBLScope(c);
|
||||
return xpc::IsContentXBLScope(c);
|
||||
}
|
||||
|
||||
|
||||
@ -5585,7 +5585,7 @@ nsContentTypeParser::GetParameter(const char* aParameterName, nsAString& aResult
|
||||
bool
|
||||
nsContentUtils::CanAccessNativeAnon()
|
||||
{
|
||||
return IsCallerChrome() || IsCallerXBL();
|
||||
return IsCallerChrome() || IsCallerContentXBL();
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
|
@ -2660,7 +2660,7 @@ nsINode::WrapObject(JSContext *aCx)
|
||||
|
||||
JS::Rooted<JSObject*> obj(aCx, WrapNode(aCx));
|
||||
MOZ_ASSERT_IF(ChromeOnlyAccess(),
|
||||
xpc::IsInXBLScope(obj) || !xpc::UseXBLScope(js::GetObjectCompartment(obj)));
|
||||
xpc::IsInContentXBLScope(obj) || !xpc::UseContentXBLScope(js::GetObjectCompartment(obj)));
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -2650,7 +2650,7 @@ nsObjectLoadingContent::ScriptRequestPluginInstance(JSContext* aCx,
|
||||
MOZ_ASSERT_IF(nsContentUtils::GetCurrentJSContext(),
|
||||
aCx == nsContentUtils::GetCurrentJSContext());
|
||||
bool callerIsContentJS = (!nsContentUtils::IsCallerChrome() &&
|
||||
!nsContentUtils::IsCallerXBL() &&
|
||||
!nsContentUtils::IsCallerContentXBL() &&
|
||||
js::IsContextRunningJS(aCx));
|
||||
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
|
@ -83,18 +83,21 @@ WebGLMemoryPressureObserver::Observe(nsISupports* aSubject,
|
||||
|
||||
if (!mContext->mCanLoseContextInForeground &&
|
||||
ProcessPriorityManager::CurrentProcessIsForeground())
|
||||
{
|
||||
wantToLoseContext = false;
|
||||
else if (!nsCRT::strcmp(aSomeData,
|
||||
} else if (!nsCRT::strcmp(aSomeData,
|
||||
MOZ_UTF16("heap-minimize")))
|
||||
{
|
||||
wantToLoseContext = mContext->mLoseContextOnHeapMinimize;
|
||||
}
|
||||
|
||||
if (wantToLoseContext)
|
||||
if (wantToLoseContext) {
|
||||
mContext->ForceLoseContext();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
WebGLContextOptions::WebGLContextOptions()
|
||||
: alpha(true), depth(true), stencil(false),
|
||||
premultipliedAlpha(true), antialias(true),
|
||||
@ -168,12 +171,12 @@ WebGLContext::WebGLContext()
|
||||
|
||||
WebGLMemoryTracker::AddWebGLContext(this);
|
||||
|
||||
mAllowRestore = true;
|
||||
mAllowContextRestore = true;
|
||||
mLastLossWasSimulated = false;
|
||||
mContextLossTimerRunning = false;
|
||||
mDrawSinceContextLossTimerSet = false;
|
||||
mRunContextLossTimerAgain = false;
|
||||
mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
mContextStatus = ContextNotLost;
|
||||
mContextLostErrorSet = false;
|
||||
mLoseContextOnHeapMinimize = false;
|
||||
mCanLoseContextInForeground = true;
|
||||
|
||||
@ -571,11 +574,8 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
|
||||
mResetLayer = true;
|
||||
mOptionsFrozen = true;
|
||||
|
||||
mHasRobustness = gl->HasRobustness();
|
||||
|
||||
// increment the generation number
|
||||
++mGeneration;
|
||||
|
||||
#if 0
|
||||
if (mGeneration > 0) {
|
||||
// XXX dispatch context lost event
|
||||
@ -1115,6 +1115,96 @@ WebGLContext::DummyFramebufferOperation(const char *info)
|
||||
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckContextLost(GLContext* gl, bool* out_isGuilty)
|
||||
{
|
||||
MOZ_ASSERT(gl);
|
||||
MOZ_ASSERT(out_isGuilty);
|
||||
|
||||
bool isEGL = gl->GetContextType() == gl::GLContextType::EGL;
|
||||
|
||||
GLenum resetStatus = LOCAL_GL_NO_ERROR;
|
||||
if (gl->HasRobustness()) {
|
||||
gl->MakeCurrent();
|
||||
resetStatus = gl->fGetGraphicsResetStatus();
|
||||
} else if (isEGL) {
|
||||
// Simulate a ARB_robustness guilty context loss for when we
|
||||
// get an EGL_CONTEXT_LOST error. It may not actually be guilty,
|
||||
// but we can't make any distinction.
|
||||
if (!gl->MakeCurrent(true) && gl->IsContextLost()) {
|
||||
resetStatus = LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB;
|
||||
}
|
||||
}
|
||||
|
||||
if (resetStatus == LOCAL_GL_NO_ERROR) {
|
||||
*out_isGuilty = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assume guilty unless we find otherwise!
|
||||
bool isGuilty = true;
|
||||
switch (resetStatus) {
|
||||
case LOCAL_GL_INNOCENT_CONTEXT_RESET_ARB:
|
||||
// Either nothing wrong, or not our fault.
|
||||
isGuilty = false;
|
||||
break;
|
||||
case LOCAL_GL_GUILTY_CONTEXT_RESET_ARB:
|
||||
NS_WARNING("WebGL content on the page definitely caused the graphics"
|
||||
" card to reset.");
|
||||
break;
|
||||
case LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB:
|
||||
NS_WARNING("WebGL content on the page might have caused the graphics"
|
||||
" card to reset");
|
||||
// If we can't tell, assume guilty.
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unreachable.");
|
||||
// If we do get here, let's pretend to be guilty as an escape plan.
|
||||
break;
|
||||
}
|
||||
|
||||
if (isGuilty) {
|
||||
NS_WARNING("WebGL context on this page is considered guilty, and will"
|
||||
" not be restored.");
|
||||
}
|
||||
|
||||
*out_isGuilty = isGuilty;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::TryToRestoreContext()
|
||||
{
|
||||
if (NS_FAILED(SetDimensions(mWidth, mHeight)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class UpdateContextLossStatusTask : public nsRunnable
|
||||
{
|
||||
nsRefPtr<WebGLContext> mContext;
|
||||
|
||||
public:
|
||||
UpdateContextLossStatusTask(WebGLContext* context)
|
||||
: mContext(context)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
mContext->UpdateContextLossStatus();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
WebGLContext::EnqueueUpdateContextLossStatus()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> task = new UpdateContextLossStatusTask(this);
|
||||
NS_DispatchToCurrentThread(task);
|
||||
}
|
||||
|
||||
// We use this timer for many things. Here are the things that it is activated for:
|
||||
// 1) If a script is using the MOZ_WEBGL_lose_context extension.
|
||||
// 2) If we are using EGL and _NOT ANGLE_, we query periodically to see if the
|
||||
@ -1130,137 +1220,124 @@ WebGLContext::DummyFramebufferOperation(const char *info)
|
||||
// At a bare minimum, from context lost to context restores, it would take 3
|
||||
// full timer iterations: detection, webglcontextlost, webglcontextrestored.
|
||||
void
|
||||
WebGLContext::RobustnessTimerCallback(nsITimer* timer)
|
||||
WebGLContext::UpdateContextLossStatus()
|
||||
{
|
||||
TerminateContextLossTimer();
|
||||
|
||||
if (!mCanvasElement) {
|
||||
// the canvas is gone. That happens when the page was closed before we got
|
||||
// this timer event. In this case, there's nothing to do here, just don't crash.
|
||||
return;
|
||||
}
|
||||
if (mContextStatus == ContextNotLost) {
|
||||
// We don't know that we're lost, but we might be, so we need to
|
||||
// check. If we're guilty, don't allow restores, though.
|
||||
|
||||
bool isGuilty = true;
|
||||
MOZ_ASSERT(gl); // Shouldn't be missing gl if we're NotLost.
|
||||
bool isContextLost = CheckContextLost(gl, &isGuilty);
|
||||
|
||||
if (isContextLost) {
|
||||
if (isGuilty)
|
||||
mAllowContextRestore = false;
|
||||
|
||||
ForceLoseContext();
|
||||
}
|
||||
|
||||
// Fall through.
|
||||
}
|
||||
|
||||
// If the context has been lost and we're waiting for it to be restored, do
|
||||
// that now.
|
||||
if (mContextStatus == ContextLostAwaitingEvent) {
|
||||
bool defaultAction;
|
||||
// The context has been lost and we haven't yet triggered the
|
||||
// callback, so do that now.
|
||||
|
||||
bool useDefaultHandler;
|
||||
nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
|
||||
NS_LITERAL_STRING("webglcontextlost"),
|
||||
true,
|
||||
true,
|
||||
&defaultAction);
|
||||
|
||||
// If the script didn't handle the event, we don't allow restores.
|
||||
if (defaultAction)
|
||||
mAllowRestore = false;
|
||||
|
||||
// If the script handled the event and we are allowing restores, then
|
||||
// mark it to be restored. Otherwise, leave it as context lost
|
||||
// (unusable).
|
||||
if (!defaultAction && mAllowRestore) {
|
||||
ForceRestoreContext();
|
||||
// Restart the timer so that it will be restored on the next
|
||||
// callback.
|
||||
SetupContextLossTimer();
|
||||
} else {
|
||||
&useDefaultHandler);
|
||||
// We sent the callback, so we're just 'regular lost' now.
|
||||
mContextStatus = ContextLost;
|
||||
// If we're told to use the default handler, it means the script
|
||||
// didn't bother to handle the event. In this case, we shouldn't
|
||||
// auto-restore the context.
|
||||
if (useDefaultHandler)
|
||||
mAllowContextRestore = false;
|
||||
|
||||
// Fall through.
|
||||
}
|
||||
} else if (mContextStatus == ContextLostAwaitingRestore) {
|
||||
// Try to restore the context. If it fails, try again later.
|
||||
if (NS_FAILED(SetDimensions(mWidth, mHeight))) {
|
||||
SetupContextLossTimer();
|
||||
|
||||
if (mContextStatus == ContextLost) {
|
||||
// Context is lost, and we've already sent the callback. We
|
||||
// should try to restore the context if we're both allowed to,
|
||||
// and supposed to.
|
||||
|
||||
// Are we allowed to restore the context?
|
||||
if (!mAllowContextRestore)
|
||||
return;
|
||||
|
||||
// If we're only simulated-lost, we shouldn't auto-restore, and
|
||||
// instead we should wait for restoreContext() to be called.
|
||||
if (mLastLossWasSimulated)
|
||||
return;
|
||||
|
||||
ForceRestoreContext();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mContextStatus == ContextLostAwaitingRestore) {
|
||||
// Context is lost, but we should try to restore it.
|
||||
|
||||
if (!mAllowContextRestore) {
|
||||
// We might decide this after thinking we'd be OK restoring
|
||||
// the context, so downgrade.
|
||||
mContextStatus = ContextLost;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryToRestoreContext()) {
|
||||
// Failed to restore. Try again later.
|
||||
RunContextLossTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
// Revival!
|
||||
mContextStatus = ContextNotLost;
|
||||
nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
|
||||
NS_LITERAL_STRING("webglcontextrestored"),
|
||||
true,
|
||||
true);
|
||||
// Set all flags back to the state they were in before the context was
|
||||
// lost.
|
||||
mEmitContextLostErrorOnce = true;
|
||||
mAllowRestore = true;
|
||||
}
|
||||
|
||||
MaybeRestoreContext();
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::MaybeRestoreContext()
|
||||
{
|
||||
// Don't try to handle it if we already know it's busted.
|
||||
if (mContextStatus != ContextNotLost || gl == nullptr)
|
||||
return;
|
||||
|
||||
bool isEGL = gl->GetContextType() == gl::GLContextType::EGL,
|
||||
isANGLE = gl->IsANGLE();
|
||||
|
||||
GLContext::ContextResetARB resetStatus = GLContext::CONTEXT_NO_ERROR;
|
||||
if (mHasRobustness) {
|
||||
gl->MakeCurrent();
|
||||
resetStatus = (GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
|
||||
} else if (isEGL) {
|
||||
// Simulate a ARB_robustness guilty context loss for when we
|
||||
// get an EGL_CONTEXT_LOST error. It may not actually be guilty,
|
||||
// but we can't make any distinction, so we must assume the worst
|
||||
// case.
|
||||
if (!gl->MakeCurrent(true) && gl->IsContextLost()) {
|
||||
resetStatus = GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB;
|
||||
}
|
||||
}
|
||||
|
||||
if (resetStatus != GLContext::CONTEXT_NO_ERROR) {
|
||||
// It's already lost, but clean up after it and signal to JS that it is
|
||||
// lost.
|
||||
ForceLoseContext();
|
||||
}
|
||||
|
||||
switch (resetStatus) {
|
||||
case GLContext::CONTEXT_NO_ERROR:
|
||||
// If there has been activity since the timer was set, it's possible
|
||||
// that we did or are going to miss something, so clear this flag and
|
||||
// run it again some time later.
|
||||
if (mDrawSinceContextLossTimerSet)
|
||||
SetupContextLossTimer();
|
||||
break;
|
||||
case GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB:
|
||||
NS_WARNING("WebGL content on the page caused the graphics card to reset; not restoring the context");
|
||||
mAllowRestore = false;
|
||||
break;
|
||||
case GLContext::CONTEXT_INNOCENT_CONTEXT_RESET_ARB:
|
||||
break;
|
||||
case GLContext::CONTEXT_UNKNOWN_CONTEXT_RESET_ARB:
|
||||
NS_WARNING("WebGL content on the page might have caused the graphics card to reset");
|
||||
if (isEGL && isANGLE) {
|
||||
// If we're using ANGLE, we ONLY get back UNKNOWN context resets, including for guilty contexts.
|
||||
// This means that we can't restore it or risk restoring a guilty context. Should this ever change,
|
||||
// we can get rid of the whole IsANGLE() junk from GLContext.h since, as of writing, this is the
|
||||
// only use for it. See ANGLE issue 261.
|
||||
mAllowRestore = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::ForceLoseContext()
|
||||
{
|
||||
if (mContextStatus == ContextLostAwaitingEvent)
|
||||
return;
|
||||
|
||||
printf_stderr("WebGL(%p)::ForceLoseContext\n", this);
|
||||
MOZ_ASSERT(!IsContextLost());
|
||||
mContextStatus = ContextLostAwaitingEvent;
|
||||
// Queue up a task to restore the event.
|
||||
SetupContextLossTimer();
|
||||
mContextLostErrorSet = false;
|
||||
mLastLossWasSimulated = false;
|
||||
|
||||
// Burn it all!
|
||||
DestroyResourcesAndContext();
|
||||
|
||||
// Queue up a task, since we know the status changed.
|
||||
EnqueueUpdateContextLossStatus();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::ForceRestoreContext()
|
||||
{
|
||||
printf_stderr("WebGL(%p)::ForceRestoreContext\n", this);
|
||||
mContextStatus = ContextLostAwaitingRestore;
|
||||
mAllowContextRestore = true; // Hey, you did say 'force'.
|
||||
|
||||
// Queue up a task, since we know the status changed.
|
||||
EnqueueUpdateContextLossStatus();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -202,9 +202,6 @@ public:
|
||||
int32_t x, int32_t y, int32_t w, int32_t h)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
bool LoseContext();
|
||||
bool RestoreContext();
|
||||
|
||||
void SynthesizeGLError(GLenum err);
|
||||
void SynthesizeGLError(GLenum err, const char *fmt, ...);
|
||||
|
||||
@ -261,11 +258,14 @@ public:
|
||||
|
||||
bool MinCapabilityMode() const { return mMinCapability; }
|
||||
|
||||
void RobustnessTimerCallback(nsITimer* timer);
|
||||
static void RobustnessTimerCallbackStatic(nsITimer* timer, void *thisPointer);
|
||||
void SetupContextLossTimer();
|
||||
void UpdateContextLossStatus();
|
||||
void EnqueueUpdateContextLossStatus();
|
||||
static void ContextLossCallbackStatic(nsITimer* timer, void* thisPointer);
|
||||
void RunContextLossTimer();
|
||||
void TerminateContextLossTimer();
|
||||
|
||||
bool TryToRestoreContext();
|
||||
|
||||
void AssertCachedBindings();
|
||||
void AssertCachedState();
|
||||
|
||||
@ -666,8 +666,12 @@ public:
|
||||
bool ValidateSamplerUniformSetter(const char* info,
|
||||
WebGLUniformLocation *location,
|
||||
GLint value);
|
||||
|
||||
void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
// -----------------------------------------------------------------------------
|
||||
// WEBGL_lose_context
|
||||
public:
|
||||
void LoseContext();
|
||||
void RestoreContext();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Asynchronous Queries (WebGLContextAsyncQueries.cpp)
|
||||
@ -869,7 +873,6 @@ protected:
|
||||
bool mOptionsFrozen;
|
||||
bool mMinCapability;
|
||||
bool mDisableExtensions;
|
||||
bool mHasRobustness;
|
||||
bool mIsMesa;
|
||||
bool mLoseContextOnHeapMinimize;
|
||||
bool mCanLoseContextInForeground;
|
||||
@ -1116,7 +1119,6 @@ protected:
|
||||
GLenum type,
|
||||
const GLvoid *data);
|
||||
|
||||
void MaybeRestoreContext();
|
||||
void ForceLoseContext();
|
||||
void ForceRestoreContext();
|
||||
|
||||
@ -1192,9 +1194,10 @@ protected:
|
||||
bool mAlreadyWarnedAboutViewportLargerThanDest;
|
||||
|
||||
nsCOMPtr<nsITimer> mContextRestorer;
|
||||
bool mAllowRestore;
|
||||
bool mAllowContextRestore;
|
||||
bool mLastLossWasSimulated;
|
||||
bool mContextLossTimerRunning;
|
||||
bool mDrawSinceContextLossTimerSet;
|
||||
bool mRunContextLossTimerAgain;
|
||||
ContextStatus mContextStatus;
|
||||
bool mContextLostErrorSet;
|
||||
|
||||
|
@ -128,7 +128,7 @@ WebGLContext::DrawArrays(GLenum mode, GLint first, GLsizei count)
|
||||
if (!DrawArrays_check(first, count, 1, "drawArrays"))
|
||||
return;
|
||||
|
||||
SetupContextLossTimer();
|
||||
RunContextLossTimer();
|
||||
gl->fDrawArrays(mode, first, count);
|
||||
|
||||
Draw_cleanup();
|
||||
@ -149,7 +149,7 @@ WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsiz
|
||||
if (!DrawInstanced_check("drawArraysInstanced"))
|
||||
return;
|
||||
|
||||
SetupContextLossTimer();
|
||||
RunContextLossTimer();
|
||||
gl->fDrawArraysInstanced(mode, first, count, primcount);
|
||||
|
||||
Draw_cleanup();
|
||||
@ -296,7 +296,7 @@ WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
|
||||
return;
|
||||
}
|
||||
|
||||
SetupContextLossTimer();
|
||||
RunContextLossTimer();
|
||||
|
||||
if (gl->IsSupported(gl::GLFeature::draw_range_elements)) {
|
||||
gl->fDrawRangeElements(mode, 0, upperBound,
|
||||
@ -324,7 +324,7 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
|
||||
if (!DrawInstanced_check("drawElementsInstanced"))
|
||||
return;
|
||||
|
||||
SetupContextLossTimer();
|
||||
RunContextLossTimer();
|
||||
gl->fDrawElementsInstanced(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset), primcount);
|
||||
|
||||
Draw_cleanup();
|
||||
|
@ -3857,27 +3857,34 @@ WebGLContext::TexSubImage2D(GLenum target, GLint level,
|
||||
WebGLTexelFormat::RGBA8, false);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
WebGLContext::LoseContext()
|
||||
{
|
||||
if (IsContextLost())
|
||||
return false;
|
||||
return ErrorInvalidOperation("loseContext: Context is already lost.");
|
||||
|
||||
ForceLoseContext();
|
||||
|
||||
return true;
|
||||
mLastLossWasSimulated = true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
WebGLContext::RestoreContext()
|
||||
{
|
||||
if (!IsContextLost() || !mAllowRestore) {
|
||||
return false;
|
||||
if (!IsContextLost())
|
||||
return ErrorInvalidOperation("restoreContext: Context is not lost.");
|
||||
|
||||
if (!mLastLossWasSimulated) {
|
||||
return ErrorInvalidOperation("restoreContext: Context loss was not simulated."
|
||||
" Cannot simulate restore.");
|
||||
}
|
||||
// If we're currently lost, and the last loss was simulated, then
|
||||
// we're currently only simulated-lost, allowing us to call
|
||||
// restoreContext().
|
||||
|
||||
if (!mAllowContextRestore)
|
||||
return ErrorInvalidOperation("restoreContext: Context cannot be restored.");
|
||||
|
||||
ForceRestoreContext();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -8,33 +8,45 @@
|
||||
using namespace mozilla;
|
||||
|
||||
/* static */ void
|
||||
WebGLContext::RobustnessTimerCallbackStatic(nsITimer* timer, void *thisPointer) {
|
||||
static_cast<WebGLContext*>(thisPointer)->RobustnessTimerCallback(timer);
|
||||
WebGLContext::ContextLossCallbackStatic(nsITimer* timer, void* thisPointer)
|
||||
{
|
||||
(void)timer;
|
||||
WebGLContext* context = static_cast<WebGLContext*>(thisPointer);
|
||||
|
||||
context->TerminateContextLossTimer();
|
||||
|
||||
context->UpdateContextLossStatus();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::SetupContextLossTimer() {
|
||||
WebGLContext::RunContextLossTimer()
|
||||
{
|
||||
// If the timer was already running, don't restart it here. Instead,
|
||||
// wait until the previous call is done, then fire it one more time.
|
||||
// This is an optimization to prevent unnecessary cross-communication
|
||||
// between threads.
|
||||
// This is an optimization to prevent unnecessary
|
||||
// cross-communication between threads.
|
||||
if (mContextLossTimerRunning) {
|
||||
mDrawSinceContextLossTimerSet = true;
|
||||
mRunContextLossTimerAgain = true;
|
||||
return;
|
||||
}
|
||||
|
||||
mContextRestorer->InitWithFuncCallback(RobustnessTimerCallbackStatic,
|
||||
mContextRestorer->InitWithFuncCallback(ContextLossCallbackStatic,
|
||||
static_cast<void*>(this),
|
||||
1000,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
mContextLossTimerRunning = true;
|
||||
mDrawSinceContextLossTimerSet = false;
|
||||
mRunContextLossTimerAgain = false;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::TerminateContextLossTimer() {
|
||||
if (mContextLossTimerRunning) {
|
||||
WebGLContext::TerminateContextLossTimer()
|
||||
{
|
||||
if (!mContextLossTimerRunning)
|
||||
return;
|
||||
|
||||
mContextRestorer->Cancel();
|
||||
mContextLossTimerRunning = false;
|
||||
|
||||
if (mRunContextLossTimerAgain) {
|
||||
RunContextLossTimer();
|
||||
}
|
||||
}
|
||||
|
@ -21,15 +21,13 @@ WebGLExtensionLoseContext::~WebGLExtensionLoseContext()
|
||||
void
|
||||
WebGLExtensionLoseContext::LoseContext()
|
||||
{
|
||||
if (!mContext->LoseContext())
|
||||
mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
|
||||
mContext->LoseContext();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLExtensionLoseContext::RestoreContext()
|
||||
{
|
||||
if (!mContext->RestoreContext())
|
||||
mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
|
||||
mContext->RestoreContext();
|
||||
}
|
||||
|
||||
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionLoseContext)
|
||||
|
@ -3064,6 +3064,14 @@ void HTMLMediaElement::UpdateReadyStateForData(MediaDecoderOwner::NextFrameStatu
|
||||
return;
|
||||
}
|
||||
|
||||
// Section 2.4.3.1 of the Media Source Extensions spec requires
|
||||
// changing to HAVE_METADATA when seeking into an unbuffered
|
||||
// range.
|
||||
if (aNextFrame == MediaDecoderOwner::NEXT_FRAME_WAIT_FOR_MSE_DATA) {
|
||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mReadyState > nsIDOMHTMLMediaElement::HAVE_METADATA &&
|
||||
mDownloadSuspendedByCache &&
|
||||
mDecoder &&
|
||||
|
@ -119,6 +119,9 @@ public:
|
||||
NEXT_FRAME_UNAVAILABLE_BUFFERING,
|
||||
// The next frame of audio/video is unavailable for some other reasons
|
||||
NEXT_FRAME_UNAVAILABLE,
|
||||
// The next frame is unavailable due to waiting for more Media Source
|
||||
// Extensions data to become available.
|
||||
NEXT_FRAME_WAIT_FOR_MSE_DATA,
|
||||
// Sentinel value
|
||||
NEXT_FRAME_UNINITIALIZED
|
||||
};
|
||||
|
@ -152,7 +152,6 @@ TEST(WebMWriter, Cluster)
|
||||
EXPECT_TRUE(encodedBuf.Length() > 0);
|
||||
encodedBuf.Clear();
|
||||
|
||||
uint64_t timestamp = 0;
|
||||
// write the first I-Frame.
|
||||
writer.AppendDummyFrame(EncodedFrame::VP8_I_FRAME, FIXED_DURATION);
|
||||
// No data because the cluster is not closed.
|
||||
@ -191,7 +190,6 @@ TEST(WebMWriter, FLUSH_NEEDED)
|
||||
writer.SetVP8Metadata(width, height, displayWidth,
|
||||
displayHeight, aTrackRate);
|
||||
|
||||
uint64_t timestamp = 0;
|
||||
// write the first I-Frame.
|
||||
writer.AppendDummyFrame(EncodedFrame::VP8_I_FRAME, FIXED_DURATION);
|
||||
|
||||
|
@ -26,3 +26,5 @@ LOCAL_INCLUDES += [
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul-gtest'
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
@ -299,6 +299,7 @@ MediaSource::MediaSource(nsPIDOMWindow* aWindow)
|
||||
, mDuration(UnspecifiedNaN<double>())
|
||||
, mDecoder(nullptr)
|
||||
, mReadyState(MediaSourceReadyState::Closed)
|
||||
, mWaitForDataMonitor("MediaSource.WaitForData.Monitor")
|
||||
{
|
||||
mSourceBuffers = new SourceBufferList(this);
|
||||
mActiveSourceBuffers = new SourceBufferList(this);
|
||||
@ -395,6 +396,20 @@ MediaSource::NotifyEvicted(double aStart, double aEnd)
|
||||
mSourceBuffers->Evict(aStart, aEnd);
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::WaitForData()
|
||||
{
|
||||
MonitorAutoLock lock(mWaitForDataMonitor);
|
||||
lock.Wait();
|
||||
}
|
||||
|
||||
void
|
||||
MediaSource::NotifyGotData()
|
||||
{
|
||||
MonitorAutoLock lock(mWaitForDataMonitor);
|
||||
lock.NotifyAll();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaSource, DOMEventTargetHelper,
|
||||
mSourceBuffers, mActiveSourceBuffers)
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/MediaSourceBinding.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionNoteChild.h"
|
||||
@ -89,6 +90,12 @@ public:
|
||||
// that were evicted are provided.
|
||||
void NotifyEvicted(double aStart, double aEnd);
|
||||
|
||||
// Block thread waiting for data to be appended to a SourceBuffer.
|
||||
void WaitForData();
|
||||
|
||||
// Unblock threads waiting for data to be appended to a SourceBuffer.
|
||||
void NotifyGotData();
|
||||
|
||||
private:
|
||||
explicit MediaSource(nsPIDOMWindow* aWindow);
|
||||
|
||||
@ -106,6 +113,10 @@ private:
|
||||
nsRefPtr<MediaSourceDecoder> mDecoder;
|
||||
|
||||
MediaSourceReadyState mReadyState;
|
||||
|
||||
// Monitor for waiting for when new data is appended to
|
||||
// a Source Buffer.
|
||||
Monitor mWaitForDataMonitor;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(MediaSource, MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID)
|
||||
|
@ -130,6 +130,11 @@ public:
|
||||
|
||||
void InitializePendingDecoders();
|
||||
|
||||
bool IsShutdown() {
|
||||
ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
|
||||
return mDecoder->IsShutdown();
|
||||
}
|
||||
|
||||
private:
|
||||
bool MaybeSwitchVideoReaders(int64_t aTimeThreshold) {
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
@ -383,14 +388,50 @@ MediaSourceReader::CreateSubDecoder(const nsACString& aType, MediaSourceDecoder*
|
||||
return decoder.forget();
|
||||
}
|
||||
|
||||
namespace {
|
||||
class ChangeToHaveMetadata : public nsRunnable {
|
||||
public:
|
||||
ChangeToHaveMetadata(AbstractMediaDecoder* aDecoder) :
|
||||
mDecoder(aDecoder)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
|
||||
auto owner = mDecoder->GetOwner();
|
||||
if (owner) {
|
||||
owner->UpdateReadyStateForData(MediaDecoderOwner::NEXT_FRAME_WAIT_FOR_MSE_DATA);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<AbstractMediaDecoder> mDecoder;
|
||||
};
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
|
||||
int64_t aCurrentTime)
|
||||
{
|
||||
ResetDecode();
|
||||
if (!mMediaSource->ActiveSourceBuffers()->AllContainsTime (aTime / USECS_PER_S)) {
|
||||
NS_DispatchToMainThread(new ChangeToHaveMetadata(mDecoder));
|
||||
}
|
||||
|
||||
dom::SourceBufferList* sbl = mMediaSource->ActiveSourceBuffers();
|
||||
if (sbl->AllContainsTime (aTime / USECS_PER_S)) {
|
||||
// Loop until we have the requested time range in the source buffers.
|
||||
// This is a workaround for our lack of async functionality in the
|
||||
// MediaDecoderStateMachine. Bug 979104 implements what we need and
|
||||
// we'll remove this for an async approach based on that in bug XXXXXXX.
|
||||
while (!mMediaSource->ActiveSourceBuffers()->AllContainsTime (aTime / USECS_PER_S)
|
||||
&& !IsShutdown()) {
|
||||
mMediaSource->WaitForData();
|
||||
MaybeSwitchVideoReaders(aTime);
|
||||
}
|
||||
|
||||
if (IsShutdown()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ResetDecode();
|
||||
if (GetAudioReader()) {
|
||||
nsresult rv = GetAudioReader()->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -403,7 +444,6 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -493,6 +493,8 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
|
||||
// Schedule the state machine thread to ensure playback starts
|
||||
// if required when data is appended.
|
||||
mMediaSource->GetDecoder()->ScheduleStateMachineThread();
|
||||
|
||||
mMediaSource->NotifyGotData();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -14,6 +14,11 @@ WebMWriter::WebMWriter(uint32_t aTrackTypes) : ContainerWriter()
|
||||
mEbmlComposer = new EbmlComposer();
|
||||
}
|
||||
|
||||
WebMWriter::~WebMWriter()
|
||||
{
|
||||
// Out-of-line dtor so mEbmlComposer nsAutoPtr can delete a complete type.
|
||||
}
|
||||
|
||||
nsresult
|
||||
WebMWriter::WriteEncodedTrack(const EncodedFrameContainer& aData,
|
||||
uint32_t aFlags)
|
||||
|
@ -47,6 +47,8 @@ public:
|
||||
// aTrackTypes indicate this muxer should multiplex into Video only or A/V foramt.
|
||||
// Run in MediaRecorder thread
|
||||
WebMWriter(uint32_t aTrackTypes);
|
||||
virtual ~WebMWriter();
|
||||
|
||||
// WriteEncodedTrack inserts raw packets into WebM stream.
|
||||
nsresult WriteEncodedTrack(const EncodedFrameContainer &aData,
|
||||
uint32_t aFlags = 0) MOZ_OVERRIDE;
|
||||
|
@ -2166,8 +2166,12 @@ nsFocusManager::SetCaretVisible(nsIPresShell* aPresShell,
|
||||
nsISelection* domSelection = docFrameSelection->
|
||||
GetSelection(nsISelectionController::SELECTION_NORMAL);
|
||||
if (domSelection) {
|
||||
nsCOMPtr<nsISelectionController> selCon(do_QueryInterface(aPresShell));
|
||||
if (!selCon) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// First, hide the caret to prevent attempting to show it in SetCaretDOMSelection
|
||||
caret->SetCaretVisible(false);
|
||||
selCon->SetCaretEnabled(false);
|
||||
|
||||
// Caret must blink on non-editable elements
|
||||
caret->SetIgnoreUserModify(true);
|
||||
@ -2178,13 +2182,8 @@ nsFocusManager::SetCaretVisible(nsIPresShell* aPresShell,
|
||||
// fields, which have a different frame selection from the document.
|
||||
// They will take care of making the caret visible themselves.
|
||||
|
||||
nsCOMPtr<nsISelectionController> selCon(do_QueryInterface(aPresShell));
|
||||
if (!selCon)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
selCon->SetCaretReadOnly(false);
|
||||
selCon->SetCaretEnabled(aVisible);
|
||||
caret->SetCaretVisible(aVisible);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -570,7 +570,7 @@ nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
|
||||
mRunningTimeout(nullptr), mMutationBits(0), mIsDocumentLoaded(false),
|
||||
mIsHandlingResizeEvent(false), mIsInnerWindow(aOuterWindow != nullptr),
|
||||
mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
|
||||
mMayHaveMouseEnterLeaveEventListener(false),
|
||||
mMayHaveTouchCaret(false), mMayHaveMouseEnterLeaveEventListener(false),
|
||||
mMayHavePointerEnterLeaveEventListener(false),
|
||||
mIsModalContentWindow(false),
|
||||
mIsActive(false), mIsBackground(false),
|
||||
|
@ -60,8 +60,8 @@ enum UIStateChangeType
|
||||
};
|
||||
|
||||
#define NS_PIDOMWINDOW_IID \
|
||||
{ 0xf26953de, 0xa799, 0x4a92, \
|
||||
{ 0x87, 0x49, 0x7c, 0x37, 0xe5, 0x90, 0x3f, 0x37 } }
|
||||
{ 0x33403513, 0x6e4a, 0x4985, \
|
||||
{ 0x99, 0x8d, 0xfc, 0x02, 0x81, 0x6e, 0xb9, 0xf2 } }
|
||||
|
||||
class nsPIDOMWindow : public nsIDOMWindowInternal
|
||||
{
|
||||
@ -468,6 +468,21 @@ public:
|
||||
return mMayHaveTouchEventListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will be called when touch caret visibility has changed. mMayHaveTouchCaret
|
||||
* is set if that some node (this window, its document, or content in that
|
||||
* document) has a visible touch caret.
|
||||
*/
|
||||
void SetMayHaveTouchCaret(bool aSetValue)
|
||||
{
|
||||
mMayHaveTouchCaret = aSetValue;
|
||||
}
|
||||
|
||||
bool MayHaveTouchCaret()
|
||||
{
|
||||
return mMayHaveTouchCaret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the top-level window into fullscreen mode if aIsFullScreen is true,
|
||||
* otherwise exits fullscreen. If aRequireTrust is true, this method only
|
||||
@ -761,6 +776,7 @@ protected:
|
||||
bool mIsInnerWindow;
|
||||
bool mMayHavePaintEventListener;
|
||||
bool mMayHaveTouchEventListener;
|
||||
bool mMayHaveTouchCaret;
|
||||
bool mMayHaveMouseEnterLeaveEventListener;
|
||||
bool mMayHavePointerEnterLeaveEventListener;
|
||||
|
||||
|
@ -1405,7 +1405,7 @@ WrapNativeParent(JSContext* cx, T* p, nsWrapperCache* cache,
|
||||
|
||||
// If useXBLScope is true, it means that the canonical reflector for this
|
||||
// native object should live in the XBL scope.
|
||||
if (xpc::IsInXBLScope(parent)) {
|
||||
if (xpc::IsInContentXBLScope(parent)) {
|
||||
return parent;
|
||||
}
|
||||
JS::Rooted<JSObject*> rootedParent(cx, parent);
|
||||
|
@ -24,7 +24,7 @@ USING_BLUETOOTH_NAMESPACE
|
||||
* BluetoothRequestParent::ReplyRunnable
|
||||
******************************************************************************/
|
||||
|
||||
class BluetoothRequestParent::ReplyRunnable : public BluetoothReplyRunnable
|
||||
class BluetoothRequestParent::ReplyRunnable MOZ_FINAL : public BluetoothReplyRunnable
|
||||
{
|
||||
BluetoothRequestParent* mRequest;
|
||||
|
||||
@ -59,8 +59,7 @@ public:
|
||||
void
|
||||
Revoke()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mRequest = nullptr;
|
||||
ReleaseMembers();
|
||||
}
|
||||
|
||||
virtual bool
|
||||
@ -68,6 +67,14 @@ public:
|
||||
{
|
||||
MOZ_CRASH("This should never be called!");
|
||||
}
|
||||
|
||||
virtual void
|
||||
ReleaseMembers() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mRequest = nullptr;
|
||||
BluetoothReplyRunnable::ReleaseMembers();
|
||||
}
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -1,7 +1,6 @@
|
||||
# nsDOMIdentity.js
|
||||
component {210853d9-2c97-4669-9761-b1ab9cbf57ef} nsDOMIdentity.js
|
||||
contract @mozilla.org/dom/identity;1 {210853d9-2c97-4669-9761-b1ab9cbf57ef}
|
||||
category JavaScript-navigator-property mozId @mozilla.org/dom/identity;1
|
||||
contract @mozilla.org/identity/manager;1 {210853d9-2c97-4669-9761-b1ab9cbf57ef}
|
||||
|
||||
# nsIDService.js (initialization on startup)
|
||||
component {4e0a0e98-b1d3-4745-a1eb-f815199dd06b} nsIDService.js
|
||||
|
@ -48,29 +48,10 @@ const ERRORS = {
|
||||
"The request() method may only be invoked when handling user input",
|
||||
};
|
||||
|
||||
function nsDOMIdentity(aIdentityInternal) {
|
||||
this._identityInternal = aIdentityInternal;
|
||||
function nsDOMIdentity() {
|
||||
}
|
||||
|
||||
nsDOMIdentity.prototype = {
|
||||
__exposedProps__: {
|
||||
// Relying Party (RP)
|
||||
watch: 'r',
|
||||
request: 'r',
|
||||
logout: 'r',
|
||||
get: 'r',
|
||||
getVerifiedEmail: 'r',
|
||||
|
||||
// Provisioning
|
||||
beginProvisioning: 'r',
|
||||
genKeyPair: 'r',
|
||||
registerCertificate: 'r',
|
||||
raiseProvisioningFailure: 'r',
|
||||
|
||||
// Authentication
|
||||
beginAuthentication: 'r',
|
||||
completeAuthentication: 'r',
|
||||
raiseAuthenticationFailure: 'r'
|
||||
},
|
||||
|
||||
// require native events unless syntheticEventsOk is set
|
||||
get nativeEventsRequired() {
|
||||
@ -149,7 +130,7 @@ nsDOMIdentity.prototype = {
|
||||
// broken client to be able to call watch() any more. It's broken.
|
||||
return;
|
||||
}
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:RP:Watch", message);
|
||||
this._mm.sendAsyncMessage("Identity:RP:Watch", message);
|
||||
},
|
||||
|
||||
request: function nsDOMIdentity_request(aOptions = {}) {
|
||||
@ -219,7 +200,7 @@ nsDOMIdentity.prototype = {
|
||||
}
|
||||
|
||||
this._rpCalls++;
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:RP:Request", message);
|
||||
this._mm.sendAsyncMessage("Identity:RP:Request", message);
|
||||
},
|
||||
|
||||
logout: function nsDOMIdentity_logout() {
|
||||
@ -239,7 +220,7 @@ nsDOMIdentity.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:RP:Logout", message);
|
||||
this._mm.sendAsyncMessage("Identity:RP:Logout", message);
|
||||
},
|
||||
|
||||
/*
|
||||
@ -322,7 +303,7 @@ nsDOMIdentity.prototype = {
|
||||
}
|
||||
|
||||
this._beginProvisioningCallback = aCallback;
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:IDP:BeginProvisioning",
|
||||
this._mm.sendAsyncMessage("Identity:IDP:BeginProvisioning",
|
||||
this.DOMIdentityMessage());
|
||||
},
|
||||
|
||||
@ -339,7 +320,7 @@ nsDOMIdentity.prototype = {
|
||||
}
|
||||
|
||||
this._genKeyPairCallback = aCallback;
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:IDP:GenKeyPair",
|
||||
this._mm.sendAsyncMessage("Identity:IDP:GenKeyPair",
|
||||
this.DOMIdentityMessage());
|
||||
},
|
||||
|
||||
@ -355,7 +336,7 @@ nsDOMIdentity.prototype = {
|
||||
|
||||
let message = this.DOMIdentityMessage();
|
||||
message.cert = aCertificate;
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:IDP:RegisterCertificate", message);
|
||||
this._mm.sendAsyncMessage("Identity:IDP:RegisterCertificate", message);
|
||||
},
|
||||
|
||||
raiseProvisioningFailure: function nsDOMIdentity_raiseProvisioningFailure(aReason) {
|
||||
@ -370,7 +351,7 @@ nsDOMIdentity.prototype = {
|
||||
|
||||
let message = this.DOMIdentityMessage();
|
||||
message.reason = aReason;
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:IDP:ProvisioningFailure", message);
|
||||
this._mm.sendAsyncMessage("Identity:IDP:ProvisioningFailure", message);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -390,7 +371,7 @@ nsDOMIdentity.prototype = {
|
||||
}
|
||||
|
||||
this._beginAuthenticationCallback = aCallback;
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:IDP:BeginAuthentication",
|
||||
this._mm.sendAsyncMessage("Identity:IDP:BeginAuthentication",
|
||||
this.DOMIdentityMessage());
|
||||
},
|
||||
|
||||
@ -403,7 +384,7 @@ nsDOMIdentity.prototype = {
|
||||
}
|
||||
this._authenticationEnded = true;
|
||||
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:IDP:CompleteAuthentication",
|
||||
this._mm.sendAsyncMessage("Identity:IDP:CompleteAuthentication",
|
||||
this.DOMIdentityMessage());
|
||||
},
|
||||
|
||||
@ -417,27 +398,7 @@ nsDOMIdentity.prototype = {
|
||||
|
||||
let message = this.DOMIdentityMessage();
|
||||
message.reason = aReason;
|
||||
this._identityInternal._mm.sendAsyncMessage("Identity:IDP:AuthenticationFailure", message);
|
||||
},
|
||||
|
||||
// Private.
|
||||
_init: function nsDOMIdentity__init(aWindow) {
|
||||
|
||||
this._initializeState();
|
||||
|
||||
// Store window and origin URI.
|
||||
this._window = aWindow;
|
||||
this._origin = aWindow.document.nodePrincipal.origin;
|
||||
this._appStatus = aWindow.document.nodePrincipal.appStatus;
|
||||
this._appId = aWindow.document.nodePrincipal.appId;
|
||||
|
||||
// Setup identifiers for current window.
|
||||
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
// We need to inherit the id from the internalIdentity service.
|
||||
// See comments below in that service's init.
|
||||
this._id = this._identityInternal._id;
|
||||
this._mm.sendAsyncMessage("Identity:IDP:AuthenticationFailure", message);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -457,12 +418,18 @@ nsDOMIdentity.prototype = {
|
||||
this._beginAuthenticationCallback = null;
|
||||
},
|
||||
|
||||
_receiveMessage: function nsDOMIdentity_receiveMessage(aMessage) {
|
||||
// nsIMessageListener
|
||||
receiveMessage: function nsDOMIdentity_receiveMessage(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
|
||||
// Is this message intended for this window?
|
||||
if (msg.id != this._id) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aMessage.name) {
|
||||
case "Identity:ResetState":
|
||||
if (!this._identityInternal._debug) {
|
||||
if (!this._debug) {
|
||||
return;
|
||||
}
|
||||
this._initializeState();
|
||||
@ -538,10 +505,6 @@ nsDOMIdentity.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_log: function nsDOMIdentity__log(msg) {
|
||||
this._identityInternal._log(msg);
|
||||
},
|
||||
|
||||
_callGenKeyPairCallback: function nsDOMIdentity__callGenKeyPairCallback(message) {
|
||||
// create a pubkey object that works
|
||||
let chrome_pubkey = JSON.parse(message.publicKey);
|
||||
@ -642,32 +605,10 @@ nsDOMIdentity.prototype = {
|
||||
return message;
|
||||
},
|
||||
|
||||
uninit: function DOMIdentity_uninit() {
|
||||
this._log("nsDOMIdentity uninit() " + this._id);
|
||||
this._identityInternal._mm.sendAsyncMessage(
|
||||
"Identity:RP:Unwatch",
|
||||
{ id: this._id }
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal functions that shouldn't be exposed to content.
|
||||
/*
|
||||
* Internal methods that are not exposed to content.
|
||||
* See dom/webidl/Identity.webidl for the public interface.
|
||||
*/
|
||||
function nsDOMIdentityInternal() {
|
||||
}
|
||||
nsDOMIdentityInternal.prototype = {
|
||||
|
||||
// nsIMessageListener
|
||||
receiveMessage: function nsDOMIdentityInternal_receiveMessage(aMessage) {
|
||||
let msg = aMessage.json;
|
||||
// Is this message intended for this window?
|
||||
if (msg.id != this._id) {
|
||||
return;
|
||||
}
|
||||
this._identity._receiveMessage(aMessage);
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe: function nsDOMIdentityInternal_observe(aSubject, aTopic, aData) {
|
||||
@ -676,11 +617,10 @@ nsDOMIdentityInternal.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
this._identity.uninit();
|
||||
this.uninit();
|
||||
|
||||
Services.obs.removeObserver(this, "inner-window-destroyed");
|
||||
this._identity._initializeState();
|
||||
this._identity = null;
|
||||
this._initializeState();
|
||||
|
||||
// TODO: Also send message to DOMIdentity notifiying window is no longer valid
|
||||
// ie. in the case that the user closes the auth. window and we need to know.
|
||||
@ -696,7 +636,8 @@ nsDOMIdentityInternal.prototype = {
|
||||
this._mm = null;
|
||||
},
|
||||
|
||||
// nsIDOMGlobalPropertyInitializer
|
||||
// Because we implement nsIDOMGlobalPropertyInitializer, our init() method
|
||||
// is invoked with content window as its single argument.
|
||||
init: function nsDOMIdentityInternal_init(aWindow) {
|
||||
if (Services.prefs.getPrefType(PREF_ENABLED) != Ci.nsIPrefBranch.PREF_BOOL
|
||||
|| !Services.prefs.getBoolPref(PREF_ENABLED)) {
|
||||
@ -720,8 +661,17 @@ nsDOMIdentityInternal.prototype = {
|
||||
|
||||
// nsDOMIdentity needs to know our _id, so this goes after
|
||||
// its creation.
|
||||
this._identity = new nsDOMIdentity(this);
|
||||
this._identity._init(aWindow);
|
||||
this._initializeState();
|
||||
|
||||
// Store window and origin URI.
|
||||
this._window = aWindow;
|
||||
this._origin = aWindow.document.nodePrincipal.origin;
|
||||
this._appStatus = aWindow.document.nodePrincipal.appStatus;
|
||||
this._appId = aWindow.document.nodePrincipal.appId;
|
||||
|
||||
// Setup identifiers for current window.
|
||||
let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
this._log("init was called from " + aWindow.document.location);
|
||||
|
||||
@ -745,8 +695,14 @@ nsDOMIdentityInternal.prototype = {
|
||||
|
||||
// Setup observers so we can remove message listeners.
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", false);
|
||||
},
|
||||
|
||||
return this._identity;
|
||||
uninit: function DOMIdentity_uninit() {
|
||||
this._log("nsDOMIdentity uninit() " + this._id);
|
||||
this._mm.sendAsyncMessage(
|
||||
"Identity:RP:Unwatch",
|
||||
{ id: this._id }
|
||||
);
|
||||
},
|
||||
|
||||
// Private.
|
||||
@ -760,9 +716,11 @@ nsDOMIdentityInternal.prototype = {
|
||||
// Component setup.
|
||||
classID: Components.ID("{210853d9-2c97-4669-9761-b1ab9cbf57ef}"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI(
|
||||
[Ci.nsIDOMGlobalPropertyInitializer, Ci.nsIMessageListener]
|
||||
),
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIMessageListener,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsIDOMGlobalPropertyInitializer
|
||||
]),
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({
|
||||
classID: Components.ID("{210853d9-2c97-4669-9761-b1ab9cbf57ef}"),
|
||||
@ -804,4 +762,4 @@ function assertCorrectCallbacks(aOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsDOMIdentityInternal]);
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsDOMIdentity]);
|
||||
|
@ -2009,7 +2009,8 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
|
||||
nsCOMPtr<nsPIDOMWindow> outerWindow = do_GetInterface(WebNavigation());
|
||||
nsCOMPtr<nsPIDOMWindow> innerWindow = outerWindow->GetCurrentInnerWindow();
|
||||
|
||||
if (!innerWindow || !innerWindow->HasTouchEventListeners()) {
|
||||
if (!innerWindow || (!innerWindow->HasTouchEventListeners() &&
|
||||
!innerWindow->MayHaveTouchCaret())) {
|
||||
SendContentReceivedTouch(aGuid, false);
|
||||
return true;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ const PC_SESSION_CONTRACT = "@mozilla.org/dom/rtcsessiondescription;1";
|
||||
const PC_MANAGER_CONTRACT = "@mozilla.org/dom/peerconnectionmanager;1";
|
||||
const PC_STATS_CONTRACT = "@mozilla.org/dom/rtcstatsreport;1";
|
||||
const PC_IDENTITY_CONTRACT = "@mozilla.org/dom/rtcidentityassertion;1";
|
||||
const PC_STATIC_CONTRACT = "@mozilla.org/dom/peerconnectionstatic;1";
|
||||
|
||||
const PC_CID = Components.ID("{00e0e20d-1494-4776-8e0e-0f0acbea3c79}");
|
||||
const PC_OBS_CID = Components.ID("{d1748d4c-7f6a-4dc5-add6-d55b7678537e}");
|
||||
@ -27,12 +28,14 @@ const PC_SESSION_CID = Components.ID("{1775081b-b62d-4954-8ffe-a067bbf508a7}");
|
||||
const PC_MANAGER_CID = Components.ID("{7293e901-2be3-4c02-b4bd-cbef6fc24f78}");
|
||||
const PC_STATS_CID = Components.ID("{7fe6e18b-0da3-4056-bf3b-440ef3809e06}");
|
||||
const PC_IDENTITY_CID = Components.ID("{1abc7499-3c54-43e0-bd60-686e2703f072}");
|
||||
const PC_STATIC_CID = Components.ID("{0fb47c47-a205-4583-a9fc-cbadf8c95880}");
|
||||
|
||||
// Global list of PeerConnection objects, so they can be cleaned up when
|
||||
// a page is torn down. (Maps inner window ID to an array of PC objects).
|
||||
function GlobalPCList() {
|
||||
this._list = {};
|
||||
this._networkdown = false; // XXX Need to query current state somehow
|
||||
this._lifecycleobservers = {};
|
||||
Services.obs.addObserver(this, "inner-window-destroyed", true);
|
||||
Services.obs.addObserver(this, "profile-change-net-teardown", true);
|
||||
Services.obs.addObserver(this, "network:offline-about-to-go-offline", true);
|
||||
@ -52,6 +55,12 @@ GlobalPCList.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
notifyLifecycleObservers: function(pc, type) {
|
||||
for (var key of Object.keys(this._lifecycleobservers)) {
|
||||
this._lifecycleobservers[key](pc, pc._winID, type);
|
||||
}
|
||||
},
|
||||
|
||||
addPC: function(pc) {
|
||||
let winID = pc._winID;
|
||||
if (this._list[winID]) {
|
||||
@ -97,7 +106,12 @@ GlobalPCList.prototype = {
|
||||
};
|
||||
|
||||
if (topic == "inner-window-destroyed") {
|
||||
cleanupWinId(this._list, subject.QueryInterface(Ci.nsISupportsPRUint64).data);
|
||||
let winID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
|
||||
cleanupWinId(this._list, winID);
|
||||
|
||||
if (this._lifecycleobservers.hasOwnProperty(winID)) {
|
||||
delete this._lifecycleobservers[winID];
|
||||
}
|
||||
} else if (topic == "profile-change-net-teardown" ||
|
||||
topic == "network:offline-about-to-go-offline") {
|
||||
// Delete all peerconnections on shutdown - mostly synchronously (we
|
||||
@ -121,6 +135,9 @@ GlobalPCList.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_registerPeerConnectionLifecycleCallback: function(winID, cb) {
|
||||
this._lifecycleobservers[winID] = cb;
|
||||
},
|
||||
};
|
||||
let _globalPCList = new GlobalPCList();
|
||||
|
||||
@ -335,6 +352,7 @@ RTCPeerConnection.prototype = {
|
||||
this._impl.initialize(this._observer, this._win, rtcConfig,
|
||||
Services.tm.currentThread);
|
||||
this._initIdp();
|
||||
_globalPCList.notifyLifecycleObservers(this, "initialized");
|
||||
},
|
||||
|
||||
get _impl() {
|
||||
@ -877,6 +895,7 @@ RTCPeerConnection.prototype = {
|
||||
},
|
||||
|
||||
get peerIdentity() { return this._peerIdentity; },
|
||||
get id() { return this._impl.id; },
|
||||
get iceGatheringState() { return this._iceGatheringState; },
|
||||
get iceConnectionState() { return this._iceConnectionState; },
|
||||
|
||||
@ -899,10 +918,12 @@ RTCPeerConnection.prototype = {
|
||||
|
||||
changeIceGatheringState: function(state) {
|
||||
this._iceGatheringState = state;
|
||||
_globalPCList.notifyLifecycleObservers(this, "icegatheringstatechange");
|
||||
},
|
||||
|
||||
changeIceConnectionState: function(state) {
|
||||
this._iceConnectionState = state;
|
||||
_globalPCList.notifyLifecycleObservers(this, "iceconnectionstatechange");
|
||||
this.dispatchEvent(new this._win.Event("iceconnectionstatechange"));
|
||||
},
|
||||
|
||||
@ -1284,11 +1305,32 @@ PeerConnectionObserver.prototype = {
|
||||
},
|
||||
};
|
||||
|
||||
function RTCPeerConnectionStatic() {
|
||||
}
|
||||
RTCPeerConnectionStatic.prototype = {
|
||||
classDescription: "mozRTCPeerConnectionStatic",
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
||||
Ci.nsIDOMGlobalPropertyInitializer]),
|
||||
|
||||
classID: PC_STATIC_CID,
|
||||
contractID: PC_STATIC_CONTRACT,
|
||||
|
||||
init: function(win) {
|
||||
this._winID = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID;
|
||||
},
|
||||
|
||||
registerPeerConnectionLifecycleCallback: function(cb) {
|
||||
_globalPCList._registerPeerConnectionLifecycleCallback(this._winID, cb);
|
||||
},
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
|
||||
[GlobalPCList,
|
||||
RTCIceCandidate,
|
||||
RTCSessionDescription,
|
||||
RTCPeerConnection,
|
||||
RTCPeerConnectionStatic,
|
||||
RTCStatsReport,
|
||||
RTCIdentityAssertion,
|
||||
PeerConnectionObserver]
|
||||
|
@ -5,6 +5,7 @@ component {1775081b-b62d-4954-8ffe-a067bbf508a7} PeerConnection.js
|
||||
component {7293e901-2be3-4c02-b4bd-cbef6fc24f78} PeerConnection.js
|
||||
component {7fe6e18b-0da3-4056-bf3b-440ef3809e06} PeerConnection.js
|
||||
component {1abc7499-3c54-43e0-bd60-686e2703f072} PeerConnection.js
|
||||
component {0fb47c47-a205-4583-a9fc-cbadf8c95880} PeerConnection.js
|
||||
|
||||
contract @mozilla.org/dom/peerconnection;1 {00e0e20d-1494-4776-8e0e-0f0acbea3c79}
|
||||
contract @mozilla.org/dom/peerconnectionobserver;1 {d1748d4c-7f6a-4dc5-add6-d55b7678537e}
|
||||
@ -13,3 +14,4 @@ contract @mozilla.org/dom/rtcsessiondescription;1 {1775081b-b62d-4954-8ffe-a067b
|
||||
contract @mozilla.org/dom/peerconnectionmanager;1 {7293e901-2be3-4c02-b4bd-cbef6fc24f78}
|
||||
contract @mozilla.org/dom/rtcstatsreport;1 {7fe6e18b-0da3-4056-bf3b-440ef3809e06}
|
||||
contract @mozilla.org/dom/rtcidentityassertion;1 {1abc7499-3c54-43e0-bd60-686e2703f072}
|
||||
contract @mozilla.org/dom/peerconnectionstatic;1 {0fb47c47-a205-4583-a9fc-cbadf8c95880}
|
||||
|
@ -19,6 +19,8 @@ skip-if = os == 'mac' || toolkit=='gonk' # b2g(Bug 960442, video support for Web
|
||||
skip-if = os == 'mac' || toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
|
||||
[test_dataChannel_basicDataOnly.html]
|
||||
[test_dataChannel_basicVideo.html]
|
||||
skip-if = toolkit=='gonk' # b2g emulator seems to bee too slow (Bug 1016498 and 1008080)
|
||||
[test_dataChannel_bug1013809.html]
|
||||
skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
|
||||
[test_dataChannel_noOffer.html]
|
||||
[test_getUserMedia_basicAudio.html]
|
||||
@ -60,6 +62,8 @@ skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled
|
||||
skip-if = toolkit=='gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) b2g-debug(Bug 960442, video support for WebRTC is disabled on b2g)
|
||||
[test_peerConnection_bug834153.html]
|
||||
[test_peerConnection_bug835370.html]
|
||||
skip-if = toolkit=='gonk' # b2g emulator seems to bee too slow (Bug 1016498 and 1008080)
|
||||
[test_peerConnection_bug1013809.html]
|
||||
[test_peerConnection_close.html]
|
||||
[test_peerConnection_errorCallbacks.html]
|
||||
[test_peerConnection_offerRequiresReceiveAudio.html]
|
||||
|
@ -481,8 +481,6 @@ function PeerConnectionTest(options) {
|
||||
else
|
||||
this.pcRemote = null;
|
||||
|
||||
this.connected = false;
|
||||
|
||||
// Create command chain instance and assign default commands
|
||||
this.chain = new CommandChain(this, options.commands);
|
||||
if (!options.is_local) {
|
||||
@ -510,7 +508,7 @@ function PeerConnectionTest(options) {
|
||||
* Callback to execute when the peer connection has been closed successfully
|
||||
*/
|
||||
PeerConnectionTest.prototype.close = function PCT_close(onSuccess) {
|
||||
info("Closing peer connections. Connection state=" + this.connected);
|
||||
info("Closing peer connections");
|
||||
|
||||
var self = this;
|
||||
var closeTimeout = null;
|
||||
@ -533,7 +531,6 @@ PeerConnectionTest.prototype.close = function PCT_close(onSuccess) {
|
||||
is(self.pcRemote.signalingState, "closed", "pcRemote is in 'closed' state");
|
||||
}
|
||||
clearTimeout(closeTimeout);
|
||||
self.connected = false;
|
||||
everythingClosed = true;
|
||||
onSuccess();
|
||||
}
|
||||
@ -566,11 +563,14 @@ PeerConnectionTest.prototype.close = function PCT_close(onSuccess) {
|
||||
self.waitingForRemote = true;
|
||||
self.pcRemote.close();
|
||||
}
|
||||
verifyClosed();
|
||||
// give the signals handlers time to fire
|
||||
setTimeout(verifyClosed, 1000);
|
||||
}
|
||||
|
||||
closeTimeout = setTimeout(function() {
|
||||
ok(false, "Closing PeerConnections timed out!");
|
||||
var closed = ((self.pcLocal && (self.pcLocal.signalingState === "closed")) &&
|
||||
(self.pcRemote && (self.pcRemote.signalingState === "closed")));
|
||||
ok(closed, "Closing PeerConnections timed out");
|
||||
// it is not a success, but the show must go on
|
||||
onSuccess();
|
||||
}, 60000);
|
||||
@ -794,53 +794,173 @@ DataChannelTest.prototype = Object.create(PeerConnectionTest.prototype, {
|
||||
* Close the open data channels, followed by the underlying peer connection
|
||||
*
|
||||
* @param {Function} onSuccess
|
||||
* Callback to execute when the connection has been closed
|
||||
* Callback to execute when all connections have been closed
|
||||
*/
|
||||
value : function DCT_close(onSuccess) {
|
||||
var self = this;
|
||||
var pendingDcClose = []
|
||||
var closeTimeout = null;
|
||||
|
||||
function _closeChannels() {
|
||||
var length = self.pcLocal.dataChannels.length;
|
||||
info("DataChannelTest.close() called");
|
||||
|
||||
if (length > 0) {
|
||||
self.closeDataChannel(length - 1, function () {
|
||||
_closeChannels();
|
||||
});
|
||||
}
|
||||
else {
|
||||
function _closePeerConnection() {
|
||||
info("DataChannelTest closing PeerConnection");
|
||||
PeerConnectionTest.prototype.close.call(self, onSuccess);
|
||||
}
|
||||
|
||||
function _closePeerConnectionCallback(index) {
|
||||
info("_closePeerConnection called with index " + index);
|
||||
var pos = pendingDcClose.indexOf(index);
|
||||
if (pos != -1) {
|
||||
pendingDcClose.splice(pos, 1);
|
||||
}
|
||||
else {
|
||||
info("_closePeerConnection index " + index + " is missing from pendingDcClose: " + pendingDcClose);
|
||||
}
|
||||
if (pendingDcClose.length === 0) {
|
||||
clearTimeout(closeTimeout);
|
||||
_closePeerConnection();
|
||||
}
|
||||
}
|
||||
|
||||
_closeChannels();
|
||||
var myDataChannels = null;
|
||||
if (self.pcLocal) {
|
||||
myDataChannels = self.pcLocal.dataChannels;
|
||||
}
|
||||
else if (self.pcRemote) {
|
||||
myDataChannels = self.pcRemote.dataChannels;
|
||||
}
|
||||
var length = myDataChannels.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
var dataChannel = myDataChannels[i];
|
||||
if (dataChannel.readyState !== "closed") {
|
||||
pendingDcClose.push(i);
|
||||
self.closeDataChannels(i, _closePeerConnectionCallback);
|
||||
}
|
||||
}
|
||||
if (pendingDcClose.length === 0) {
|
||||
_closePeerConnection();
|
||||
}
|
||||
else {
|
||||
closeTimeout = setTimeout(function() {
|
||||
ok(false, "Failed to properly close data channels: " +
|
||||
pendingDcClose);
|
||||
_closePeerConnection();
|
||||
}, 60000);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
closeDataChannel : {
|
||||
closeDataChannels : {
|
||||
/**
|
||||
* Close the specified data channel
|
||||
* Close the specified data channels
|
||||
*
|
||||
* @param {Number} index
|
||||
* Index of the data channel to close on both sides
|
||||
* Index of the data channels to close on both sides
|
||||
* @param {Function} onSuccess
|
||||
* Callback to execute when the data channel has been closed
|
||||
* Callback to execute when the data channels has been closed
|
||||
*/
|
||||
value : function DCT_closeDataChannel(index, onSuccess) {
|
||||
var localChannel = this.pcLocal.dataChannels[index];
|
||||
var remoteChannel = this.pcRemote.dataChannels[index];
|
||||
value : function DCT_closeDataChannels(index, onSuccess) {
|
||||
info("_closeDataChannels called with index: " + index);
|
||||
var localChannel = null;
|
||||
if (this.pcLocal) {
|
||||
localChannel = this.pcLocal.dataChannels[index];
|
||||
}
|
||||
var remoteChannel = null;
|
||||
if (this.pcRemote) {
|
||||
remoteChannel = this.pcRemote.dataChannels[index];
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var wait = false;
|
||||
var pollingMode = false;
|
||||
var everythingClosed = false;
|
||||
var verifyInterval = null;
|
||||
var remoteCloseTimer = null;
|
||||
|
||||
// Register handler for remote channel, cause we have to wait until
|
||||
// the current close operation has been finished.
|
||||
function _allChannelsAreClosed() {
|
||||
var ret = null;
|
||||
if (localChannel) {
|
||||
ret = (localChannel.readyState === "closed");
|
||||
}
|
||||
if (remoteChannel) {
|
||||
if (ret !== null) {
|
||||
ret = (ret && (remoteChannel.readyState === "closed"));
|
||||
}
|
||||
else {
|
||||
ret = (remoteChannel.readyState === "closed");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function verifyClosedChannels() {
|
||||
if (everythingClosed) {
|
||||
// safety protection against events firing late
|
||||
return;
|
||||
}
|
||||
if (_allChannelsAreClosed) {
|
||||
ok(true, "DataChannel(s) have reached 'closed' state for data channel " + index);
|
||||
if (remoteCloseTimer !== null) {
|
||||
clearTimeout(remoteCloseTimer);
|
||||
}
|
||||
if (verifyInterval !== null) {
|
||||
clearInterval(verifyInterval);
|
||||
}
|
||||
everythingClosed = true;
|
||||
onSuccess(index);
|
||||
}
|
||||
else {
|
||||
info("Still waiting for DataChannel closure");
|
||||
}
|
||||
}
|
||||
|
||||
if ((localChannel) && (localChannel.readyState !== "closed")) {
|
||||
// in case of steeplechase there is no far end, so we can only poll
|
||||
if (remoteChannel) {
|
||||
remoteChannel.onclose = function () {
|
||||
self.pcRemote.dataChannels.splice(index, 1);
|
||||
|
||||
onSuccess(remoteChannel);
|
||||
is(remoteChannel.readyState, "closed", "remoteChannel is in state 'closed'");
|
||||
verifyClosedChannels();
|
||||
};
|
||||
}
|
||||
else {
|
||||
pollingMode = true;
|
||||
verifyInterval = setInterval(verifyClosedChannels, 1000);
|
||||
}
|
||||
|
||||
localChannel.close();
|
||||
this.pcLocal.dataChannels.splice(index, 1);
|
||||
wait = true;
|
||||
}
|
||||
if ((remoteChannel) && (remoteChannel.readyState !== "closed")) {
|
||||
if (localChannel) {
|
||||
localChannel.onclose = function () {
|
||||
is(localChannel.readyState, "closed", "localChannel is in state 'closed'");
|
||||
verifyClosedChannels();
|
||||
};
|
||||
|
||||
// Apparently we are running a local test which has both ends of the
|
||||
// data channel locally available, so by default lets wait for the
|
||||
// remoteChannel.onclose handler from above to confirm closure on both
|
||||
// ends.
|
||||
remoteCloseTimer = setTimeout(function() {
|
||||
todo(false, "localChannel.close() did not resulted in close signal on remote side");
|
||||
remoteChannel.close();
|
||||
verifyClosedChannels();
|
||||
}, 30000);
|
||||
}
|
||||
else {
|
||||
pollingMode = true;
|
||||
verifyTimer = setInterval(verifyClosedChannels, 1000);
|
||||
|
||||
remoteChannel.close();
|
||||
}
|
||||
|
||||
wait = true;
|
||||
}
|
||||
|
||||
if (!wait) {
|
||||
onSuccess(index);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -860,7 +980,7 @@ DataChannelTest.prototype = Object.create(PeerConnectionTest.prototype, {
|
||||
|
||||
// Method to synchronize all asynchronous events.
|
||||
function check_next_test() {
|
||||
if (self.connected && localChannel && remoteChannel) {
|
||||
if (localChannel && remoteChannel) {
|
||||
onSuccess(localChannel, remoteChannel);
|
||||
}
|
||||
}
|
||||
@ -925,8 +1045,7 @@ DataChannelTest.prototype = Object.create(PeerConnectionTest.prototype, {
|
||||
setLocalDescription : {
|
||||
/**
|
||||
* Sets the local description for the specified peer connection instance
|
||||
* and automatically handles the failure case. In case for the final call
|
||||
* it will setup the requested datachannel.
|
||||
* and automatically handles the failure case.
|
||||
*
|
||||
* @param {PeerConnectionWrapper} peer
|
||||
The peer connection wrapper to run the command on
|
||||
@ -936,70 +1055,52 @@ DataChannelTest.prototype = Object.create(PeerConnectionTest.prototype, {
|
||||
* Callback to execute if the local description was set successfully
|
||||
*/
|
||||
value : function DCT_setLocalDescription(peer, desc, state, onSuccess) {
|
||||
// If the peer has a remote offer we are in the final call, and have
|
||||
// to wait for the datachannel connection to be open. It will also set
|
||||
// the local description internally.
|
||||
if (peer.signalingState === 'have-remote-offer') {
|
||||
this.waitForInitialDataChannel(peer, desc, state, onSuccess);
|
||||
}
|
||||
else {
|
||||
PeerConnectionTest.prototype.setLocalDescription.call(this, peer,
|
||||
desc, state, onSuccess);
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
waitForInitialDataChannel : {
|
||||
/**
|
||||
* Create an initial data channel before the peer connection has been connected
|
||||
* Wait for the initial data channel to get into the open state
|
||||
*
|
||||
* @param {PeerConnectionWrapper} peer
|
||||
The peer connection wrapper to run the command on
|
||||
* @param {mozRTCSessionDescription} desc
|
||||
* Session description for the local description request
|
||||
* The peer connection wrapper to run the command on
|
||||
* @param {Function} onSuccess
|
||||
* Callback when the creation was successful
|
||||
*/
|
||||
value : function DCT_waitForInitialDataChannel(peer, desc, state, onSuccess) {
|
||||
var self = this;
|
||||
value : function DCT_waitForInitialDataChannel(peer, onSuccess, onFailure) {
|
||||
var dcConnectionTimeout = null;
|
||||
|
||||
var targetPeer = peer;
|
||||
var targetChannel = null;
|
||||
function dataChannelConnected(channel) {
|
||||
clearTimeout(dcConnectionTimeout);
|
||||
is(channel.readyState, "open", peer + " dataChannels[0] is in state: 'open'");
|
||||
onSuccess();
|
||||
}
|
||||
|
||||
var sourcePeer = (peer == this.pcLocal) ? this.pcRemote : this.pcLocal;
|
||||
var sourceChannel = null;
|
||||
if ((peer.dataChannels.length >= 1) &&
|
||||
(peer.dataChannels[0].readyState === "open")) {
|
||||
is(peer.dataChannels[0].readyState, "open", peer + " dataChannels[0] is in state: 'open'");
|
||||
onSuccess();
|
||||
return;
|
||||
}
|
||||
|
||||
// Method to synchronize all asynchronous events which current happen
|
||||
// due to a non-predictable flow. With bug 875346 fixed we will be able
|
||||
// to simplify this code.
|
||||
function check_next_test() {
|
||||
if (self.connected && sourceChannel && targetChannel) {
|
||||
onSuccess(sourceChannel, targetChannel);
|
||||
// TODO: drno: convert dataChannels into an object and make
|
||||
// registerDataChannelOPenEvent a generic function
|
||||
if (peer == this.pcLocal) {
|
||||
peer.dataChannels[0].onopen = dataChannelConnected;
|
||||
} else {
|
||||
peer.registerDataChannelOpenEvents(dataChannelConnected);
|
||||
}
|
||||
|
||||
dcConnectionTimeout = setTimeout(function () {
|
||||
info(peer + " timed out while waiting for dataChannels[0] to connect");
|
||||
onFailure();
|
||||
}, 60000);
|
||||
}
|
||||
}
|
||||
|
||||
// Register 'onopen' handler for the first local data channel
|
||||
sourcePeer.dataChannels[0].onopen = function (channel) {
|
||||
sourceChannel = channel;
|
||||
check_next_test();
|
||||
};
|
||||
|
||||
// Register handlers for the target peer
|
||||
targetPeer.registerDataChannelOpenEvents(function (channel) {
|
||||
targetChannel = channel;
|
||||
check_next_test();
|
||||
});
|
||||
|
||||
PeerConnectionTest.prototype.setLocalDescription.call(this, targetPeer, desc,
|
||||
state,
|
||||
function () {
|
||||
self.connected = true;
|
||||
check_next_test();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@ -1966,10 +2067,7 @@ PeerConnectionWrapper.prototype = {
|
||||
info(this + ": Register callbacks for 'ondatachannel' and 'onopen'");
|
||||
|
||||
this.ondatachannel = function (targetChannel) {
|
||||
targetChannel.onopen = function (targetChannel) {
|
||||
onDataChannelOpened(targetChannel);
|
||||
};
|
||||
|
||||
targetChannel.onopen = onDataChannelOpened;
|
||||
this.dataChannels.push(targetChannel);
|
||||
};
|
||||
},
|
||||
|
@ -134,6 +134,16 @@ var commandsPeerConnection = [
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_SET_LOCAL_DESCRIPTION',
|
||||
function (test) {
|
||||
test.setLocalDescription(test.pcRemote, test.pcRemote._last_answer, STABLE, function () {
|
||||
is(test.pcRemote.signalingState, STABLE,
|
||||
"signalingState after remote setLocalDescription is 'stable'");
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_LOCAL_GET_ANSWER',
|
||||
function (test) {
|
||||
@ -161,16 +171,6 @@ var commandsPeerConnection = [
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_SET_LOCAL_DESCRIPTION',
|
||||
function (test) {
|
||||
test.setLocalDescription(test.pcRemote, test.pcRemote._last_answer, STABLE, function () {
|
||||
is(test.pcRemote.signalingState, STABLE,
|
||||
"signalingState after remote setLocalDescription is 'stable'");
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_LOCAL_WAIT_FOR_ICE_CONNECTED',
|
||||
function (test) {
|
||||
@ -374,6 +374,42 @@ var commandsDataChannel = [
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_LOCAL_SETUP_DATA_CHANNEL_CALLBACK',
|
||||
function (test) {
|
||||
test.waitForInitialDataChannel(test.pcLocal, function () {
|
||||
ok(true, test.pcLocal + " dataChannels[0] switched to 'open'");
|
||||
}, function () {
|
||||
ok(false, test.pcLocal + " initial dataChannels[0] failed to switch to 'open'");
|
||||
unexpectedEventAndFinish(this, 'timeout')
|
||||
});
|
||||
test.next();
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_SETUP_DATA_CHANNEL_CALLBACK',
|
||||
function (test) {
|
||||
test.waitForInitialDataChannel(test.pcRemote, function () {
|
||||
ok(true, test.pcRemote + " dataChannels[0] switched to 'open'");
|
||||
}, function () {
|
||||
ok(false, test.pcRemote + " initial dataChannels[0] failed to switch to 'open'");
|
||||
unexpectedEventAndFinish(this, 'timeout');
|
||||
});
|
||||
test.next();
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_SET_LOCAL_DESCRIPTION',
|
||||
function (test) {
|
||||
test.setLocalDescription(test.pcRemote, test.pcRemote._last_answer, STABLE,
|
||||
function () {
|
||||
is(test.pcRemote.signalingState, STABLE,
|
||||
"signalingState after remote setLocalDescription is 'stable'");
|
||||
test.next();
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_LOCAL_SET_REMOTE_DESCRIPTION',
|
||||
function (test) {
|
||||
@ -386,18 +422,25 @@ var commandsDataChannel = [
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_SET_LOCAL_DESCRIPTION',
|
||||
'PC_LOCAL_VERIFY_DATA_CHANNEL_STATE',
|
||||
function (test) {
|
||||
test.setLocalDescription(test.pcRemote, test.pcRemote._last_answer, STABLE,
|
||||
function (sourceChannel, targetChannel) {
|
||||
is(sourceChannel.readyState, "open", test.pcLocal + " is in state: 'open'");
|
||||
is(targetChannel.readyState, "open", test.pcRemote + " is in state: 'open'");
|
||||
|
||||
is(test.pcRemote.signalingState, STABLE,
|
||||
"signalingState after remote setLocalDescription is 'stable'");
|
||||
test.waitForInitialDataChannel(test.pcLocal, function() {
|
||||
test.next();
|
||||
}, function() {
|
||||
ok(false, test.pcLocal + " initial dataChannels[0] failed to switch to 'open'");
|
||||
unexpectedEventAndFinish(this, 'timeout')
|
||||
});
|
||||
}
|
||||
);
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_VERIFY_DATA_CHANNEL_STATE',
|
||||
function (test) {
|
||||
test.waitForInitialDataChannel(test.pcRemote, function() {
|
||||
test.next();
|
||||
}, function() {
|
||||
ok(false, test.pcRemote + " initial dataChannels[0] failed to switch to 'open'");
|
||||
unexpectedEventAndFinish(this, 'timeout');
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
@ -507,6 +550,23 @@ var commandsDataChannel = [
|
||||
}, options);
|
||||
}
|
||||
],
|
||||
[
|
||||
'SEND_MESSAGE_BACK_THROUGH_FIRST_CHANNEL',
|
||||
function (test) {
|
||||
var message = "Return a message also through 1st channel";
|
||||
var options = {
|
||||
sourceChannel: test.pcRemote.dataChannels[0],
|
||||
targetChannel: test.pcLocal.dataChannels[0]
|
||||
};
|
||||
|
||||
test.send(message, function (channel, data) {
|
||||
is(test.pcLocal.dataChannels.indexOf(channel), 0, "1st channel used");
|
||||
is(data, message, "Return message has the correct content.");
|
||||
|
||||
test.next();
|
||||
}, options);
|
||||
}
|
||||
],
|
||||
[
|
||||
'CREATE_NEGOTIATED_DATA_CHANNEL',
|
||||
function (test) {
|
||||
@ -521,7 +581,8 @@ var commandsDataChannel = [
|
||||
|
||||
if (options.id != undefined) {
|
||||
is(sourceChannel2.id, options.id, sourceChannel2 + " id is:" + sourceChannel2.id);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
options.id = sourceChannel2.id;
|
||||
}
|
||||
var reliable = !options.ordered ? false : (options.maxRetransmits || options.maxRetransmitTime);
|
||||
@ -562,30 +623,6 @@ var commandsDataChannel = [
|
||||
is(channels.indexOf(channel), channels.length - 1, "Last channel used");
|
||||
is(data, message, "Received message has the correct content.");
|
||||
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'CLOSE_LAST_OPENED_DATA_CHANNEL2',
|
||||
function (test) {
|
||||
var channels = test.pcRemote.dataChannels;
|
||||
|
||||
test.closeDataChannel(channels.length - 1, function (channel) {
|
||||
is(channel.readyState, "closed", "Channel is in state: 'closed'");
|
||||
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'CLOSE_LAST_OPENED_DATA_CHANNEL',
|
||||
function (test) {
|
||||
var channels = test.pcRemote.dataChannels;
|
||||
|
||||
test.closeDataChannel(channels.length - 1, function (channel) {
|
||||
is(channel.readyState, "closed", "Channel is in state: 'closed'");
|
||||
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
|
31
dom/media/tests/mochitest/test_dataChannel_bug1013809.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript" src="pc.js"></script>
|
||||
<script type="application/javascript" src="templates.js"></script>
|
||||
<script type="application/javascript" src="turnConfig.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
createHTML({
|
||||
bug: "796895",
|
||||
title: "Basic data channel audio connection"
|
||||
});
|
||||
|
||||
var test;
|
||||
runTest(function () {
|
||||
test = new DataChannelTest();
|
||||
var sld = test.chain.remove("PC_REMOTE_SET_LOCAL_DESCRIPTION");
|
||||
test.chain.insertAfter("PC_LOCAL_SET_REMOTE_DESCRIPTION", sld);
|
||||
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||
test.run();
|
||||
}, true);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,30 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="head.js"></script>
|
||||
<script type="application/javascript" src="pc.js"></script>
|
||||
<script type="application/javascript" src="templates.js"></script>
|
||||
<script type="application/javascript" src="turnConfig.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
createHTML({
|
||||
bug: "1013809",
|
||||
title: "Audio-only peer connection with swapped setLocal and setRemote steps"
|
||||
});
|
||||
|
||||
var test;
|
||||
runTest(function (options) {
|
||||
test = new PeerConnectionTest(options);
|
||||
var sld = test.chain.remove("PC_REMOTE_SET_LOCAL_DESCRIPTION");
|
||||
test.chain.insertAfter("PC_LOCAL_SET_REMOTE_DESCRIPTION", sld);
|
||||
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||
test.run();
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
70
dom/webidl/Identity.webidl
Normal file
@ -0,0 +1,70 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
callback IdentityOnReadyCallback = void();
|
||||
callback IdentityOnLoginCallback = void(DOMString identityAssertion);
|
||||
callback IdentityOnLogoutCallback = void();
|
||||
callback IdentityOnCancelCallback = void(DOMString? error);
|
||||
callback IdentityOnErrorCallback = void(DOMString error);
|
||||
|
||||
dictionary IdentityWatchOptions {
|
||||
// Required callback
|
||||
IdentityOnLoginCallback onlogin;
|
||||
|
||||
// Optional parameters
|
||||
DOMString wantIssuer;
|
||||
DOMString loggedInUser;
|
||||
|
||||
// Optional callbacks
|
||||
IdentityOnReadyCallback onready;
|
||||
IdentityOnLogoutCallback onlogout;
|
||||
IdentityOnErrorCallback onerror;
|
||||
|
||||
// Certified apps can specify this
|
||||
DOMString audience;
|
||||
};
|
||||
|
||||
dictionary IdentityRequestOptions {
|
||||
// Optional parameters
|
||||
long refreshAuthentication;
|
||||
DOMString termsOfService;
|
||||
DOMString privacyPolicy;
|
||||
DOMString backgroundColor;
|
||||
DOMString siteLogo;
|
||||
DOMString siteName;
|
||||
DOMString returnTo;
|
||||
|
||||
IdentityOnCancelCallback oncancel;
|
||||
|
||||
// Certified apps can specify this
|
||||
DOMString origin;
|
||||
};
|
||||
|
||||
dictionary IdentityGetOptions {
|
||||
DOMString privacyPolicy;
|
||||
DOMString termsOfService;
|
||||
DOMString privacyURL;
|
||||
DOMString tosURL;
|
||||
DOMString siteName;
|
||||
DOMString siteLogo;
|
||||
};
|
||||
|
||||
[JSImplementation="@mozilla.org/identity/manager;1",
|
||||
NoInterfaceObject,
|
||||
NavigatorProperty="mozId",
|
||||
Pref="dom.identity.enabled"]
|
||||
interface IdentityManager {
|
||||
void watch(optional IdentityWatchOptions options);
|
||||
void request(optional IdentityRequestOptions options);
|
||||
void logout();
|
||||
|
||||
[Pref="dom.identity.exposeLegacyGetAPI"]
|
||||
void get(IdentityOnLoginCallback callback, optional IdentityGetOptions options);
|
||||
|
||||
[Pref="dom.identity.exposeLegacyGetVerifiedEmailAPI"]
|
||||
void getVerifiedEmail(IdentityOnLoginCallback callback);
|
||||
};
|
||||
|
@ -70,6 +70,7 @@ interface PeerConnectionImpl {
|
||||
readonly attribute PCImplIceGatheringState iceGatheringState;
|
||||
readonly attribute PCImplSignalingState signalingState;
|
||||
readonly attribute PCImplSipccState sipccState;
|
||||
readonly attribute DOMString id;
|
||||
|
||||
attribute DOMString peerIdentity;
|
||||
readonly attribute boolean privacyRequested;
|
||||
|
@ -118,6 +118,9 @@ interface mozRTCPeerConnection : EventTarget {
|
||||
[Pref="media.peerconnection.identity.enabled"]
|
||||
readonly attribute RTCIdentityAssertion? peerIdentity;
|
||||
|
||||
[ChromeOnly]
|
||||
readonly attribute DOMString id;
|
||||
|
||||
sequence<MediaStream> getLocalStreams ();
|
||||
sequence<MediaStream> getRemoteStreams ();
|
||||
MediaStream? getStreamById (DOMString streamId);
|
||||
@ -148,3 +151,4 @@ interface mozRTCPeerConnection : EventTarget {
|
||||
[Pref="media.peerconnection.identity.enabled"]
|
||||
attribute EventHandler onidpvalidationerror;
|
||||
};
|
||||
|
||||
|
39
dom/webidl/RTCPeerConnectionStatic.webidl
Normal file
@ -0,0 +1,39 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/*
|
||||
Right now, it is not possible to add static functions to a JS implemented
|
||||
interface (see bug 863952), so we need to create a simple interface with a
|
||||
trivial constructor and no data to hold these functions that really ought to
|
||||
be static in mozRTCPeerConnection.
|
||||
TODO(bcampen@mozilla.com) Merge this code into RTCPeerConnection once this
|
||||
limitation is gone. (Bug 1017082)
|
||||
*/
|
||||
|
||||
enum RTCLifecycleEvent {
|
||||
"initialized",
|
||||
"icegatheringstatechange",
|
||||
"iceconnectionstatechange"
|
||||
};
|
||||
|
||||
callback PeerConnectionLifecycleCallback = void (mozRTCPeerConnection pc,
|
||||
unsigned long long windowId,
|
||||
RTCLifecycleEvent eventType);
|
||||
|
||||
[ChromeOnly,
|
||||
Pref="media.peerconnection.enabled",
|
||||
JSImplementation="@mozilla.org/dom/peerconnectionstatic;1",
|
||||
Constructor()]
|
||||
interface mozRTCPeerConnectionStatic {
|
||||
|
||||
/* One slot per window (the window in which the register call is made),
|
||||
automatically unregistered when window goes away.
|
||||
Fires when a PC is created, and whenever the ICE connection state or
|
||||
gathering state changes. */
|
||||
void registerPeerConnectionLifecycleCallback(
|
||||
PeerConnectionLifecycleCallback cb);
|
||||
};
|
||||
|
@ -15,7 +15,8 @@ callback WebrtcGlobalLoggingCallback = void (sequence<DOMString> logMessages);
|
||||
interface WebrtcGlobalInformation {
|
||||
|
||||
[Throws]
|
||||
static void getAllStats(WebrtcGlobalStatisticsCallback callback);
|
||||
static void getAllStats(WebrtcGlobalStatisticsCallback callback,
|
||||
optional DOMString pcIdFilter);
|
||||
|
||||
[Throws]
|
||||
static void getLogging(DOMString pattern,
|
||||
|
@ -212,6 +212,7 @@ WEBIDL_FILES = [
|
||||
'IDBRequest.webidl',
|
||||
'IDBTransaction.webidl',
|
||||
'IDBVersionChangeEvent.webidl',
|
||||
'Identity.webidl',
|
||||
'ImageData.webidl',
|
||||
'ImageDocument.webidl',
|
||||
'InputEvent.webidl',
|
||||
@ -298,6 +299,7 @@ WEBIDL_FILES = [
|
||||
'RTCIceCandidate.webidl',
|
||||
'RTCIdentityAssertion.webidl',
|
||||
'RTCPeerConnection.webidl',
|
||||
'RTCPeerConnectionStatic.webidl',
|
||||
'RTCSessionDescription.webidl',
|
||||
'RTCStatsReport.webidl',
|
||||
'Screen.webidl',
|
||||
|
@ -104,7 +104,7 @@ static const JSClass gPrototypeJSClass = {
|
||||
// Constructors/Destructors
|
||||
nsXBLBinding::nsXBLBinding(nsXBLPrototypeBinding* aBinding)
|
||||
: mMarkedForDeath(false)
|
||||
, mUsingXBLScope(false)
|
||||
, mUsingContentXBLScope(false)
|
||||
, mPrototypeBinding(aBinding)
|
||||
{
|
||||
NS_ASSERTION(mPrototypeBinding, "Must have a prototype binding!");
|
||||
@ -115,7 +115,7 @@ nsXBLBinding::nsXBLBinding(nsXBLPrototypeBinding* aBinding)
|
||||
// Constructor used by web components.
|
||||
nsXBLBinding::nsXBLBinding(ShadowRoot* aShadowRoot, nsXBLPrototypeBinding* aBinding)
|
||||
: mMarkedForDeath(false),
|
||||
mUsingXBLScope(false),
|
||||
mUsingContentXBLScope(false),
|
||||
mPrototypeBinding(aBinding),
|
||||
mContent(aShadowRoot)
|
||||
{
|
||||
@ -278,7 +278,7 @@ nsXBLBinding::SetBoundElement(nsIContent* aElement)
|
||||
// is not given in the handler declaration.
|
||||
nsCOMPtr<nsIGlobalObject> go = mBoundElement->OwnerDoc()->GetScopeObject();
|
||||
NS_ENSURE_TRUE_VOID(go && go->GetGlobalJSObject());
|
||||
mUsingXBLScope = xpc::UseXBLScope(js::GetObjectCompartment(go->GetGlobalJSObject()));
|
||||
mUsingContentXBLScope = xpc::UseContentXBLScope(js::GetObjectCompartment(go->GetGlobalJSObject()));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -512,7 +512,7 @@ nsXBLBinding::InstallEventHandlers()
|
||||
|
||||
bool hasAllowUntrustedAttr = curr->HasAllowUntrustedAttr();
|
||||
if ((hasAllowUntrustedAttr && curr->AllowUntrustedEvents()) ||
|
||||
(!hasAllowUntrustedAttr && !isChromeDoc && !mUsingXBLScope)) {
|
||||
(!hasAllowUntrustedAttr && !isChromeDoc && !mUsingContentXBLScope)) {
|
||||
flags.mAllowUntrustedEvents = true;
|
||||
}
|
||||
|
||||
@ -528,7 +528,7 @@ nsXBLBinding::InstallEventHandlers()
|
||||
for (i = 0; i < keyHandlers->Count(); ++i) {
|
||||
nsXBLKeyEventHandler* handler = keyHandlers->ObjectAt(i);
|
||||
handler->SetIsBoundToChrome(isChromeDoc);
|
||||
handler->SetUsingXBLScope(mUsingXBLScope);
|
||||
handler->SetUsingContentXBLScope(mUsingContentXBLScope);
|
||||
|
||||
nsAutoString type;
|
||||
handler->GetEventName(type);
|
||||
@ -920,7 +920,7 @@ GetOrCreateMapEntryForPrototype(JSContext *cx, JS::Handle<JSObject*> proto)
|
||||
// So we define two maps - one class objects that live in content (prototyped
|
||||
// to content prototypes), and the other for class objects that live in the
|
||||
// XBL scope (prototyped to cross-compartment-wrapped content prototypes).
|
||||
const char* name = xpc::IsInXBLScope(proto) ? "__ContentClassObjectMap__"
|
||||
const char* name = xpc::IsInContentXBLScope(proto) ? "__ContentClassObjectMap__"
|
||||
: "__XBLClassObjectMap__";
|
||||
|
||||
// Now, enter the XBL scope, since that's where we need to operate, and wrap
|
||||
@ -1116,7 +1116,7 @@ nsXBLBinding::LookupMember(JSContext* aCx, JS::Handle<jsid> aId,
|
||||
// We do a release-mode assertion here to be extra safe.
|
||||
JS::Rooted<JSObject*> boundScope(aCx,
|
||||
js::GetGlobalForObjectCrossCompartment(mBoundElement->GetWrapper()));
|
||||
MOZ_RELEASE_ASSERT(!xpc::IsInXBLScope(boundScope));
|
||||
MOZ_RELEASE_ASSERT(!xpc::IsInContentXBLScope(boundScope));
|
||||
JS::Rooted<JSObject*> xblScope(aCx, xpc::GetXBLScope(aCx, boundScope));
|
||||
NS_ENSURE_TRUE(xblScope, false);
|
||||
MOZ_ASSERT(boundScope != xblScope);
|
||||
|
@ -160,7 +160,7 @@ public:
|
||||
protected:
|
||||
|
||||
bool mMarkedForDeath;
|
||||
bool mUsingXBLScope;
|
||||
bool mUsingContentXBLScope;
|
||||
|
||||
nsXBLPrototypeBinding* mPrototypeBinding; // Weak, but we're holding a ref to the docinfo
|
||||
nsCOMPtr<nsIContent> mContent; // Strong. Our anonymous content stays around with us.
|
||||
|
@ -71,7 +71,7 @@ nsXBLKeyEventHandler::nsXBLKeyEventHandler(nsIAtom* aEventType, uint8_t aPhase,
|
||||
mPhase(aPhase),
|
||||
mType(aType),
|
||||
mIsBoundToChrome(false),
|
||||
mUsingXBLScope(false)
|
||||
mUsingContentXBLScope(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ nsXBLKeyEventHandler::ExecuteMatchedHandlers(nsIDOMKeyEvent* aKeyEvent,
|
||||
bool hasAllowUntrustedAttr = handler->HasAllowUntrustedAttr();
|
||||
if ((trustedEvent ||
|
||||
(hasAllowUntrustedAttr && handler->AllowUntrustedEvents()) ||
|
||||
(!hasAllowUntrustedAttr && !mIsBoundToChrome && !mUsingXBLScope)) &&
|
||||
(!hasAllowUntrustedAttr && !mIsBoundToChrome && !mUsingContentXBLScope)) &&
|
||||
handler->KeyEventMatched(aKeyEvent, aCharCode, aIgnoreShiftKey)) {
|
||||
handler->ExecuteHandler(target, aKeyEvent);
|
||||
executed = true;
|
||||
|
@ -86,9 +86,9 @@ public:
|
||||
mIsBoundToChrome = aIsBoundToChrome;
|
||||
}
|
||||
|
||||
void SetUsingXBLScope(bool aUsingXBLScope)
|
||||
void SetUsingContentXBLScope(bool aUsingContentXBLScope)
|
||||
{
|
||||
mUsingXBLScope = aUsingXBLScope;
|
||||
mUsingContentXBLScope = aUsingContentXBLScope;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -101,7 +101,7 @@ private:
|
||||
uint8_t mPhase;
|
||||
uint8_t mType;
|
||||
bool mIsBoundToChrome;
|
||||
bool mUsingXBLScope;
|
||||
bool mUsingContentXBLScope;
|
||||
};
|
||||
|
||||
nsresult
|
||||
|
@ -104,7 +104,7 @@ nsXBLProtoImplMethod::InstallMember(JSContext* aCx,
|
||||
MOZ_ASSERT(js::IsObjectInContextCompartment(aTargetClassObject, aCx));
|
||||
|
||||
JS::Rooted<JSObject*> globalObject(aCx, JS_GetGlobalForObject(aCx, aTargetClassObject));
|
||||
MOZ_ASSERT(xpc::IsInXBLScope(globalObject) ||
|
||||
MOZ_ASSERT(xpc::IsInContentXBLScope(globalObject) ||
|
||||
globalObject == xpc::GetXBLScope(aCx, globalObject));
|
||||
|
||||
JS::Rooted<JSObject*> jsMethodObject(aCx, GetCompiledMethod());
|
||||
|
@ -129,7 +129,7 @@ nsXBLProtoImplProperty::InstallMember(JSContext *aCx,
|
||||
MOZ_ASSERT(mGetter.IsCompiled() && mSetter.IsCompiled());
|
||||
MOZ_ASSERT(js::IsObjectInContextCompartment(aTargetClassObject, aCx));
|
||||
JS::Rooted<JSObject*> globalObject(aCx, JS_GetGlobalForObject(aCx, aTargetClassObject));
|
||||
MOZ_ASSERT(xpc::IsInXBLScope(globalObject) ||
|
||||
MOZ_ASSERT(xpc::IsInContentXBLScope(globalObject) ||
|
||||
globalObject == xpc::GetXBLScope(aCx, globalObject));
|
||||
|
||||
JS::Rooted<JSObject*> getter(aCx, mGetter.GetJSFunction());
|
||||
|
@ -39,4 +39,7 @@ RESOURCE_FILES += [
|
||||
'res/table-remove-row-active.gif',
|
||||
'res/table-remove-row-hover.gif',
|
||||
'res/table-remove-row.gif',
|
||||
'res/text_selection_handle.png',
|
||||
'res/text_selection_handle@1.5.png',
|
||||
'res/text_selection_handle@2.png',
|
||||
]
|
||||
|
BIN
editor/composer/src/res/text_selection_handle.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
editor/composer/src/res/text_selection_handle@1.5.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
editor/composer/src/res/text_selection_handle@2.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
@ -731,6 +731,10 @@ nsEditorEventListener::CleanupDragDropCaret()
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
if (presShell)
|
||||
{
|
||||
nsCOMPtr<nsISelectionController> selCon(do_QueryInterface(presShell));
|
||||
if (selCon) {
|
||||
selCon->SetCaretEnabled(false);
|
||||
}
|
||||
presShell->RestoreCaret();
|
||||
}
|
||||
|
||||
|
@ -2699,19 +2699,6 @@ public:
|
||||
|
||||
GLint GetMaxTextureImageSize() { return mMaxTextureImageSize; }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Context reset constants.
|
||||
* These are used to determine who is guilty when a context reset
|
||||
* happens.
|
||||
*/
|
||||
enum ContextResetARB {
|
||||
CONTEXT_NO_ERROR = 0,
|
||||
CONTEXT_GUILTY_CONTEXT_RESET_ARB = 0x8253,
|
||||
CONTEXT_INNOCENT_CONTEXT_RESET_ARB = 0x8254,
|
||||
CONTEXT_UNKNOWN_CONTEXT_RESET_ARB = 0x8255
|
||||
};
|
||||
|
||||
public:
|
||||
std::map<GLuint, SharedSurface_GL*> mFBOMapping;
|
||||
|
||||
|
@ -758,6 +758,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
WriteParam(aMsg, aParam.mZoom);
|
||||
WriteParam(aMsg, aParam.mDevPixelsPerCSSPixel);
|
||||
WriteParam(aMsg, aParam.mMayHaveTouchListeners);
|
||||
WriteParam(aMsg, aParam.mMayHaveTouchCaret);
|
||||
WriteParam(aMsg, aParam.mPresShellId);
|
||||
WriteParam(aMsg, aParam.mIsRoot);
|
||||
WriteParam(aMsg, aParam.mHasScrollgrab);
|
||||
@ -785,6 +786,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
ReadParam(aMsg, aIter, &aResult->mZoom) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDevPixelsPerCSSPixel) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mMayHaveTouchListeners) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mMayHaveTouchCaret) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mPresShellId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mIsRoot) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasScrollgrab) &&
|
||||
|