mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-04-02 20:42:49 +00:00
Merge inbound to mozilla-central. a=merge
This commit is contained in:
commit
59f801793b
@ -70,6 +70,7 @@
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
@ -758,10 +759,12 @@ Accessible::TakeFocus()
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(focusContent));
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm)
|
||||
if (fm) {
|
||||
AutoHandlingUserInputStatePusher inputStatePusher(true, nullptr, focusContent->OwnerDoc());
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(focusContent));
|
||||
fm->SetFocus(element, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "nsFocusManager.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "mozilla/HTMLEditor.h"
|
||||
#include "mozilla/TextEditor.h"
|
||||
@ -325,6 +326,7 @@ DocAccessible::TakeFocus()
|
||||
// Focus the document.
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
nsCOMPtr<nsIDOMElement> newFocus;
|
||||
AutoHandlingUserInputStatePusher inputStatePusher(true, nullptr, mDocumentNode);
|
||||
fm->MoveFocus(mDocumentNode->GetWindow(), nullptr,
|
||||
nsFocusManager::MOVEFOCUS_ROOT, 0, getter_AddRefs(newFocus));
|
||||
}
|
||||
|
@ -163,7 +163,10 @@
|
||||
atEnd: true
|
||||
},
|
||||
{ focused: "input[type=text]" }),
|
||||
new ExpectedTextSelectionChanged(0, 0)],
|
||||
new ExpectedTextSelectionChanged(0, 0,
|
||||
// Bug 1455749: Fix granularity control in text entries.
|
||||
{ android_todo: true }
|
||||
)],
|
||||
[ContentMessages.simpleMovePrevious,
|
||||
new ExpectedCursorChange(
|
||||
[ "So we don't get dessert?", {string: "label"} ]),
|
||||
|
@ -1273,11 +1273,7 @@ pref("browser.newtabpage.enabled", true);
|
||||
// Activity Stream prefs that control to which page to redirect
|
||||
pref("browser.newtabpage.activity-stream.prerender", true);
|
||||
#ifndef RELEASE_OR_BETA
|
||||
#ifdef MOZILLA_OFFICIAL
|
||||
pref("browser.newtabpage.activity-stream.debug", false);
|
||||
#else
|
||||
pref("browser.newtabpage.activity-stream.debug", true);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
pref("browser.library.activity-stream.enabled", true);
|
||||
|
@ -197,7 +197,7 @@ skip-if = os == 'mac' # Save as PDF not supported on Mac OS X
|
||||
[browser_ext_themes_validation.js]
|
||||
[browser_ext_url_overrides_newtab.js]
|
||||
[browser_ext_user_events.js]
|
||||
skip-if = debug
|
||||
skip-if = debug || os == "linux" #Bug 1381305
|
||||
[browser_ext_webRequest.js]
|
||||
[browser_ext_webNavigation_frameId0.js]
|
||||
[browser_ext_webNavigation_getFrames.js]
|
||||
|
@ -13,7 +13,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
|
||||
"nsIAboutNewTabService");
|
||||
|
||||
const IS_RELEASE_OR_BETA = AppConstants.RELEASE_OR_BETA;
|
||||
const MOZILLA_OFFICIAL = AppConstants.MOZILLA_OFFICIAL;
|
||||
|
||||
const ACTIVITY_STREAM_PRERENDER_URL = "resource://activity-stream/prerendered/en-US/activity-stream-prerendered.html";
|
||||
const ACTIVITY_STREAM_PRERENDER_DEBUG_URL = "resource://activity-stream/prerendered/static/activity-stream-prerendered-debug.html";
|
||||
@ -135,16 +134,6 @@ add_task(function test_locale() {
|
||||
"The locale for testing should be en-US");
|
||||
});
|
||||
|
||||
add_task(async function test_debug_mode() {
|
||||
if (!IS_RELEASE_OR_BETA && !MOZILLA_OFFICIAL) { // Check if local build
|
||||
Assert.equal(aboutNewTabService.activityStreamDebug, true,
|
||||
"Debug mode is set for builds that are not official");
|
||||
} else {
|
||||
Assert.equal(aboutNewTabService.activityStreamDebug, false,
|
||||
"Debug mode is not set for any other builds");
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests reponse to updates to prefs
|
||||
*/
|
||||
@ -206,9 +195,6 @@ function setBoolPrefAndWaitForChange(pref, value, testMessage) {
|
||||
|
||||
|
||||
function setupASPrerendered() {
|
||||
// Don't run in debug mode regardless of build type
|
||||
Services.prefs.setBoolPref(ACTIVITY_STREAM_DEBUG_PREF, false);
|
||||
|
||||
if (Services.prefs.getBoolPref(ACTIVITY_STREAM_PRERENDER_PREF)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
@ -175,6 +175,16 @@ https://trac.torproject.org/projects/tor/ticket/1517
|
||||
// and check if it is rounded
|
||||
for (let timeStampCode of timeStampCodesDOM) {
|
||||
let timeStamp = eval(timeStampCode);
|
||||
|
||||
// Audio Contexts increment in intervals of (minimum) 5.4ms, so we don't
|
||||
// clamp/jitter if the timer precision is les than that.
|
||||
// (Technically on MBPs they increment in intervals of 2.6 but this is
|
||||
// non-standard and will eventually be changed. We don't cover this situation
|
||||
// because we don't really support arbitrary Timer Precision, especially in
|
||||
// the 2.6 - 5.4ms interval.)
|
||||
if (timeStampCode.includes("audioContext") && expectedPrecision < 5.4)
|
||||
continue;
|
||||
|
||||
ok(isRounded(timeStamp, expectedPrecision),
|
||||
"pref: " + prefname + " - '" +
|
||||
"'" + timeStampCode +
|
||||
|
@ -670,7 +670,7 @@ function prompt(aBrowser, aRequest) {
|
||||
stream.getTracks().forEach(t => t.stop());
|
||||
return;
|
||||
}
|
||||
video.src = chromeWin.URL.createObjectURL(stream);
|
||||
video.srcObject = stream;
|
||||
video.stream = stream;
|
||||
doc.getElementById("webRTC-preview").hidden = false;
|
||||
video.onloadedmetadata = function(e) {
|
||||
|
@ -150,7 +150,7 @@ skip-if = (os == "win" && ccov) # Bug 1453549
|
||||
skip-if = ccov # Bug 1441545
|
||||
[browser_dbg-babel-stepping.js]
|
||||
[browser_dbg-babel-preview.js]
|
||||
skip-if = (os == "win" && ccov) # Bug 1448523
|
||||
skip-if = (os == "win" && ccov) || (os == "win" && !debug) # Bug 1448523, Bug 1448450
|
||||
[browser_dbg-breaking.js]
|
||||
[browser_dbg-breaking-from-console.js]
|
||||
[browser_dbg-breakpoints.js]
|
||||
|
@ -5,7 +5,7 @@ code, and optionally help with indentation.
|
||||
|
||||
# Upgrade
|
||||
|
||||
Currently used version is 5.36.0. To upgrade: download a new version of
|
||||
Currently used version is 5.37.0. To upgrade: download a new version of
|
||||
CodeMirror from the project's page [1] and replace all JavaScript and
|
||||
CSS files inside the codemirror directory [2].
|
||||
|
||||
|
@ -137,12 +137,14 @@
|
||||
CodeMirror.registerHelper("fold", "xml", function(cm, start) {
|
||||
var iter = new Iter(cm, start.line, 0);
|
||||
for (;;) {
|
||||
var openTag = toNextTag(iter), end;
|
||||
if (!openTag || !(end = toTagEnd(iter)) || iter.line != start.line) return;
|
||||
var openTag = toNextTag(iter)
|
||||
if (!openTag || iter.line != start.line) return
|
||||
var end = toTagEnd(iter)
|
||||
if (!end) return
|
||||
if (!openTag[1] && end != "selfClose") {
|
||||
var startPos = Pos(iter.line, iter.ch);
|
||||
var endPos = findMatchingClose(iter, openTag[2]);
|
||||
return endPos && {from: startPos, to: endPos.from};
|
||||
return endPos && cmp(endPos.from, startPos) > 0 ? {from: startPos, to: endPos.from} : null
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -90,7 +90,7 @@
|
||||
var state = cm.state.matchHighlighter;
|
||||
cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style));
|
||||
if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) {
|
||||
var searchFor = hasBoundary ? new RegExp("\\b" + query.replace(/[\\\[+*?(){|^$]/g, "\\$&") + "\\b") : query;
|
||||
var searchFor = hasBoundary ? new RegExp("\\b" + query.replace(/[\\\[.+*?(){|^$]/g, "\\$&") + "\\b") : query;
|
||||
state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false,
|
||||
{className: "CodeMirror-selection-highlight-scrollbar"});
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -307,6 +307,7 @@
|
||||
"Backspace": function(cm) { killRegion(cm, false) || killTo(cm, byChar, -1, false); },
|
||||
|
||||
"Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1),
|
||||
"Alt-Right": move(byWord, 1), "Alt-Left": move(byWord, -1),
|
||||
"Alt-D": function(cm) { killTo(cm, byWord, 1, "grow"); },
|
||||
"Alt-Backspace": function(cm) { killTo(cm, byWord, -1, "grow"); },
|
||||
|
||||
|
@ -93,6 +93,8 @@
|
||||
{ keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }},
|
||||
{ keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }},
|
||||
{ keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }},
|
||||
{ keys: '(', type: 'motion', motion: 'moveBySentence', motionArgs: { forward: false }},
|
||||
{ keys: ')', type: 'motion', motion: 'moveBySentence', motionArgs: { forward: true }},
|
||||
{ keys: '<C-f>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }},
|
||||
{ keys: '<C-b>', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }},
|
||||
{ keys: '<C-d>', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }},
|
||||
@ -423,6 +425,9 @@
|
||||
function isWhiteSpaceString(k) {
|
||||
return (/^\s*$/).test(k);
|
||||
}
|
||||
function isEndOfSentenceSymbol(k) {
|
||||
return '.?!'.indexOf(k) != -1;
|
||||
}
|
||||
function inArray(val, arr) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (arr[i] == val) {
|
||||
@ -866,7 +871,7 @@
|
||||
if (vim.insertMode) { command = handleKeyInsertMode(); }
|
||||
else { command = handleKeyNonInsertMode(); }
|
||||
if (command === false) {
|
||||
return undefined;
|
||||
return !vim.insertMode && key.length === 1 ? function() { return true; } : undefined;
|
||||
} else if (command === true) {
|
||||
// TODO: Look into using CodeMirror's multi-key handling.
|
||||
// Return no-op since we are caching the key. Counts as handled, but
|
||||
@ -1811,6 +1816,10 @@
|
||||
var dir = motionArgs.forward ? 1 : -1;
|
||||
return findParagraph(cm, head, motionArgs.repeat, dir);
|
||||
},
|
||||
moveBySentence: function(cm, head, motionArgs) {
|
||||
var dir = motionArgs.forward ? 1 : -1;
|
||||
return findSentence(cm, head, motionArgs.repeat, dir);
|
||||
},
|
||||
moveByScroll: function(cm, head, motionArgs, vim) {
|
||||
var scrollbox = cm.getScrollInfo();
|
||||
var curEnd = null;
|
||||
@ -3534,6 +3543,179 @@
|
||||
return { start: start, end: end };
|
||||
}
|
||||
|
||||
function findSentence(cm, cur, repeat, dir) {
|
||||
|
||||
/*
|
||||
Takes an index object
|
||||
{
|
||||
line: the line string,
|
||||
ln: line number,
|
||||
pos: index in line,
|
||||
dir: direction of traversal (-1 or 1)
|
||||
}
|
||||
and modifies the line, ln, and pos members to represent the
|
||||
next valid position or sets them to null if there are
|
||||
no more valid positions.
|
||||
*/
|
||||
function nextChar(cm, idx) {
|
||||
if (idx.pos + idx.dir < 0 || idx.pos + idx.dir >= idx.line.length) {
|
||||
idx.ln += idx.dir;
|
||||
if (!isLine(cm, idx.ln)) {
|
||||
idx.line = null;
|
||||
idx.ln = null;
|
||||
idx.pos = null;
|
||||
return;
|
||||
}
|
||||
idx.line = cm.getLine(idx.ln);
|
||||
idx.pos = (idx.dir > 0) ? 0 : idx.line.length - 1;
|
||||
}
|
||||
else {
|
||||
idx.pos += idx.dir;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Performs one iteration of traversal in forward direction
|
||||
Returns an index object of the new location
|
||||
*/
|
||||
function forward(cm, ln, pos, dir) {
|
||||
var line = cm.getLine(ln);
|
||||
var stop = (line === "");
|
||||
|
||||
var curr = {
|
||||
line: line,
|
||||
ln: ln,
|
||||
pos: pos,
|
||||
dir: dir,
|
||||
}
|
||||
|
||||
var last_valid = {
|
||||
ln: curr.ln,
|
||||
pos: curr.pos,
|
||||
}
|
||||
|
||||
var skip_empty_lines = (curr.line === "");
|
||||
|
||||
// Move one step to skip character we start on
|
||||
nextChar(cm, curr);
|
||||
|
||||
while (curr.line !== null) {
|
||||
last_valid.ln = curr.ln;
|
||||
last_valid.pos = curr.pos;
|
||||
|
||||
if (curr.line === "" && !skip_empty_lines) {
|
||||
return { ln: curr.ln, pos: curr.pos, };
|
||||
}
|
||||
else if (stop && curr.line !== "" && !isWhiteSpaceString(curr.line[curr.pos])) {
|
||||
return { ln: curr.ln, pos: curr.pos, };
|
||||
}
|
||||
else if (isEndOfSentenceSymbol(curr.line[curr.pos])
|
||||
&& !stop
|
||||
&& (curr.pos === curr.line.length - 1
|
||||
|| isWhiteSpaceString(curr.line[curr.pos + 1]))) {
|
||||
stop = true;
|
||||
}
|
||||
|
||||
nextChar(cm, curr);
|
||||
}
|
||||
|
||||
/*
|
||||
Set the position to the last non whitespace character on the last
|
||||
valid line in the case that we reach the end of the document.
|
||||
*/
|
||||
var line = cm.getLine(last_valid.ln);
|
||||
last_valid.pos = 0;
|
||||
for(var i = line.length - 1; i >= 0; --i) {
|
||||
if (!isWhiteSpaceString(line[i])) {
|
||||
last_valid.pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return last_valid;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Performs one iteration of traversal in reverse direction
|
||||
Returns an index object of the new location
|
||||
*/
|
||||
function reverse(cm, ln, pos, dir) {
|
||||
var line = cm.getLine(ln);
|
||||
|
||||
var curr = {
|
||||
line: line,
|
||||
ln: ln,
|
||||
pos: pos,
|
||||
dir: dir,
|
||||
}
|
||||
|
||||
var last_valid = {
|
||||
ln: curr.ln,
|
||||
pos: null,
|
||||
};
|
||||
|
||||
var skip_empty_lines = (curr.line === "");
|
||||
|
||||
// Move one step to skip character we start on
|
||||
nextChar(cm, curr);
|
||||
|
||||
while (curr.line !== null) {
|
||||
|
||||
if (curr.line === "" && !skip_empty_lines) {
|
||||
if (last_valid.pos !== null) {
|
||||
return last_valid;
|
||||
}
|
||||
else {
|
||||
return { ln: curr.ln, pos: curr.pos };
|
||||
}
|
||||
}
|
||||
else if (isEndOfSentenceSymbol(curr.line[curr.pos])
|
||||
&& last_valid.pos !== null
|
||||
&& !(curr.ln === last_valid.ln && curr.pos + 1 === last_valid.pos)) {
|
||||
return last_valid;
|
||||
}
|
||||
else if (curr.line !== "" && !isWhiteSpaceString(curr.line[curr.pos])) {
|
||||
skip_empty_lines = false;
|
||||
last_valid = { ln: curr.ln, pos: curr.pos }
|
||||
}
|
||||
|
||||
nextChar(cm, curr);
|
||||
}
|
||||
|
||||
/*
|
||||
Set the position to the first non whitespace character on the last
|
||||
valid line in the case that we reach the beginning of the document.
|
||||
*/
|
||||
var line = cm.getLine(last_valid.ln);
|
||||
last_valid.pos = 0;
|
||||
for(var i = 0; i < line.length; ++i) {
|
||||
if (!isWhiteSpaceString(line[i])) {
|
||||
last_valid.pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return last_valid;
|
||||
}
|
||||
|
||||
var curr_index = {
|
||||
ln: cur.line,
|
||||
pos: cur.ch,
|
||||
};
|
||||
|
||||
while (repeat > 0) {
|
||||
if (dir < 0) {
|
||||
curr_index = reverse(cm, curr_index.ln, curr_index.pos, dir);
|
||||
}
|
||||
else {
|
||||
curr_index = forward(cm, curr_index.ln, curr_index.pos, dir);
|
||||
}
|
||||
repeat--;
|
||||
}
|
||||
|
||||
return Pos(curr_index.ln, curr_index.pos);
|
||||
}
|
||||
|
||||
// TODO: perhaps this finagling of start and end positions belonds
|
||||
// in codemirror/replaceRange?
|
||||
function selectCompanionObject(cm, head, symb, inclusive) {
|
||||
@ -3552,8 +3734,8 @@
|
||||
// cursor is on a matching open bracket.
|
||||
var offset = curChar === openSym ? 1 : 0;
|
||||
|
||||
start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp});
|
||||
end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp});
|
||||
start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, undefined, {'bracketRegex': bracketRegexp});
|
||||
end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, undefined, {'bracketRegex': bracketRegexp});
|
||||
|
||||
if (!start || !end) {
|
||||
return { start: cur, end: cur };
|
||||
|
@ -9005,7 +9005,7 @@ ContentEditableInput.prototype.setUneditable = function (node) {
|
||||
};
|
||||
|
||||
ContentEditableInput.prototype.onKeyPress = function (e) {
|
||||
if (e.charCode == 0) { return }
|
||||
if (e.charCode == 0 || this.composing) { return }
|
||||
e.preventDefault()
|
||||
if (!this.cm.isReadOnly())
|
||||
{ operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0) }
|
||||
@ -9658,7 +9658,7 @@ CodeMirror.fromTextArea = fromTextArea
|
||||
|
||||
addLegacyProps(CodeMirror)
|
||||
|
||||
CodeMirror.version = "5.36.0"
|
||||
CodeMirror.version = "5.37.0"
|
||||
|
||||
return CodeMirror;
|
||||
|
||||
|
@ -624,6 +624,10 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
|
||||
defKeywords: words("class val var object interface fun"),
|
||||
atoms: words("true false null this"),
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
},
|
||||
'"': function(stream, state) {
|
||||
state.tokenize = tokenKotlinString(stream.match('""'));
|
||||
return state.tokenize(stream, state);
|
||||
|
@ -126,7 +126,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
var kw = keywords[word]
|
||||
return ret(kw.type, kw.style, word)
|
||||
}
|
||||
if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\(\w]/, false))
|
||||
if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false))
|
||||
return ret("async", "keyword", word)
|
||||
}
|
||||
return ret("variable", "variable", word)
|
||||
@ -356,6 +356,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
} else if (isTS && value == "namespace") {
|
||||
cx.marked = "keyword"
|
||||
return cont(pushlex("form"), expression, block, poplex)
|
||||
} else if (isTS && value == "abstract") {
|
||||
cx.marked = "keyword"
|
||||
return cont(statement)
|
||||
} else {
|
||||
return cont(pushlex("stat"), maybelabel);
|
||||
}
|
||||
@ -562,7 +565,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
function typeexpr(type, value) {
|
||||
if (value == "keyof" || value == "typeof") {
|
||||
cx.marked = "keyword"
|
||||
return cont(value == "keyof" ? typeexpr : expression)
|
||||
return cont(value == "keyof" ? typeexpr : expressionNoComma)
|
||||
}
|
||||
if (type == "variable" || value == "void") {
|
||||
cx.marked = "type"
|
||||
@ -572,6 +575,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
|
||||
if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
|
||||
if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType)
|
||||
if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
|
||||
}
|
||||
function maybeReturnType(type) {
|
||||
if (type == "=>") return cont(typeexpr)
|
||||
@ -588,9 +592,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||
return cont(expression, maybetype, expect("]"), typeprop)
|
||||
}
|
||||
}
|
||||
function typearg(type) {
|
||||
if (type == "variable") return cont(typearg)
|
||||
else if (type == ":") return cont(typeexpr)
|
||||
function typearg(type, value) {
|
||||
if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
|
||||
if (type == ":") return cont(typeexpr)
|
||||
return pass(typeexpr)
|
||||
}
|
||||
function afterType(type, value) {
|
||||
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
|
||||
|
@ -402,6 +402,15 @@
|
||||
" [def META],",
|
||||
"}")
|
||||
|
||||
TS("parenthesized type",
|
||||
"[keyword class] [def Foo] {",
|
||||
" [property x] [operator =] [keyword new] [variable A][operator <][type B], [type string][operator |](() [operator =>] [type void])[operator >]();",
|
||||
" [keyword private] [property bar]();",
|
||||
"}")
|
||||
|
||||
TS("abstract class",
|
||||
"[keyword export] [keyword abstract] [keyword class] [def Foo] {}")
|
||||
|
||||
var jsonld_mode = CodeMirror.getMode(
|
||||
{indentUnit: 2},
|
||||
{name: "javascript", jsonld: true}
|
||||
|
@ -509,6 +509,40 @@ testVim('{', function(cm, vim, helpers) {
|
||||
helpers.doKeys('6', '{');
|
||||
helpers.assertCursorAt(0, 0);
|
||||
}, { value: 'a\n\nb\nc\n\nd' });
|
||||
testVim('(', function(cm, vim, helpers) {
|
||||
cm.setCursor(6, 23);
|
||||
helpers.doKeys('(');
|
||||
helpers.assertCursorAt(6, 14);
|
||||
helpers.doKeys('2', '(');
|
||||
helpers.assertCursorAt(5, 0);
|
||||
helpers.doKeys('(');
|
||||
helpers.assertCursorAt(4, 0);
|
||||
helpers.doKeys('(');
|
||||
helpers.assertCursorAt(3, 0);
|
||||
helpers.doKeys('(');
|
||||
helpers.assertCursorAt(2, 0);
|
||||
helpers.doKeys('(');
|
||||
helpers.assertCursorAt(0, 0);
|
||||
helpers.doKeys('(');
|
||||
helpers.assertCursorAt(0, 0);
|
||||
}, { value: 'sentence1.\n\n\nsentence2\n\nsentence3. sentence4\n sentence5? sentence6!' });
|
||||
testVim(')', function(cm, vim, helpers) {
|
||||
cm.setCursor(0, 0);
|
||||
helpers.doKeys('2', ')');
|
||||
helpers.assertCursorAt(3, 0);
|
||||
helpers.doKeys(')');
|
||||
helpers.assertCursorAt(4, 0);
|
||||
helpers.doKeys(')');
|
||||
helpers.assertCursorAt(5, 0);
|
||||
helpers.doKeys(')');
|
||||
helpers.assertCursorAt(5, 11);
|
||||
helpers.doKeys(')');
|
||||
helpers.assertCursorAt(6, 14);
|
||||
helpers.doKeys(')');
|
||||
helpers.assertCursorAt(6, 23);
|
||||
helpers.doKeys(')');
|
||||
helpers.assertCursorAt(6, 23);
|
||||
}, { value: 'sentence1.\n\n\nsentence2\n\nsentence3. sentence4\n sentence5? sentence6!' });
|
||||
testVim('paragraph_motions', function(cm, vim, helpers) {
|
||||
cm.setCursor(10, 0);
|
||||
helpers.doKeys('{');
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
#include "HTMLLinkElement.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -162,8 +163,8 @@ Link::TryDNSPrefetchOrPreconnectOrPrefetchOrPreloadOrPrerender()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nsStyleLinkElement::CheckPreloadAttrs(asAttr, mimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
if (!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
policyType = nsIContentPolicy::TYPE_INVALID;
|
||||
}
|
||||
|
||||
@ -247,8 +248,8 @@ Link::UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
|
||||
}
|
||||
|
||||
nsContentPolicyType policyType = asPolicyType;
|
||||
if (!nsStyleLinkElement::CheckPreloadAttrs(asAttr, mimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
if (!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
policyType = nsIContentPolicy::TYPE_INVALID;
|
||||
}
|
||||
|
||||
@ -268,8 +269,8 @@ Link::UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
|
||||
if (aName == nsGkAtoms::as) {
|
||||
if (aOldValue) {
|
||||
oldPolicyType = AsValueToContentPolicy(*aOldValue);
|
||||
if (!nsStyleLinkElement::CheckPreloadAttrs(*aOldValue, mimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
if (!HTMLLinkElement::CheckPreloadAttrs(*aOldValue, mimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
oldPolicyType = nsIContentPolicy::TYPE_INVALID;
|
||||
}
|
||||
} else {
|
||||
@ -285,8 +286,8 @@ Link::UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
|
||||
}
|
||||
nsAutoString oldMimeType;
|
||||
nsContentUtils::SplitMimeType(oldType, oldMimeType, notUsed);
|
||||
if (nsStyleLinkElement::CheckPreloadAttrs(asAttr, oldMimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
if (HTMLLinkElement::CheckPreloadAttrs(asAttr, oldMimeType, media,
|
||||
mElement->OwnerDoc())) {
|
||||
oldPolicyType = asPolicyType;
|
||||
} else {
|
||||
oldPolicyType = nsIContentPolicy::TYPE_INVALID;
|
||||
@ -299,8 +300,8 @@ Link::UpdatePreload(nsAtom* aName, const nsAttrValue* aValue,
|
||||
} else {
|
||||
oldMedia = EmptyString();
|
||||
}
|
||||
if (nsStyleLinkElement::CheckPreloadAttrs(asAttr, mimeType, oldMedia,
|
||||
mElement->OwnerDoc())) {
|
||||
if (HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType, oldMedia,
|
||||
mElement->OwnerDoc())) {
|
||||
oldPolicyType = asPolicyType;
|
||||
} else {
|
||||
oldPolicyType = nsIContentPolicy::TYPE_INVALID;
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "nsParserConstants.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "Link.h"
|
||||
#include "HTMLLinkElement.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -886,8 +887,8 @@ nsContentSink::PrefetchPreloadHref(const nsAString &aHref,
|
||||
nsAutoString mimeType;
|
||||
nsAutoString notUsed;
|
||||
nsContentUtils::SplitMimeType(aType, mimeType, notUsed);
|
||||
if (!nsStyleLinkElement::CheckPreloadAttrs(asAttr, mimeType,
|
||||
aMedia,mDocument)) {
|
||||
if (!HTMLLinkElement::CheckPreloadAttrs(asAttr, mimeType,
|
||||
aMedia,mDocument)) {
|
||||
policyType = nsIContentPolicy::TYPE_INVALID;
|
||||
}
|
||||
|
||||
|
@ -434,7 +434,7 @@ public:
|
||||
|
||||
bool IsContainerNode() const
|
||||
{
|
||||
return IsElement() || !IsCharacterData();
|
||||
return IsElement() || IsDocument() || IsDocumentFragment();
|
||||
}
|
||||
|
||||
bool IsSlotable() const
|
||||
|
@ -31,14 +31,6 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsStyleUtil.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "imgLoader.h"
|
||||
#include "MediaContainerType.h"
|
||||
#include "DecoderDoctorDiagnostics.h"
|
||||
#include "DecoderTraits.h"
|
||||
#include "MediaList.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -184,120 +176,6 @@ uint32_t nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes)
|
||||
return linkMask;
|
||||
}
|
||||
|
||||
// We will use official mime-types from:
|
||||
// https://www.iana.org/assignments/media-types/media-types.xhtml#font
|
||||
// We do not support old deprecated mime-types for preload feature.
|
||||
// (We currectly do not support font/collection)
|
||||
static uint32_t StyleLinkElementFontMimeTypesNum = 5;
|
||||
static const char* StyleLinkElementFontMimeTypes[] = {
|
||||
"font/otf",
|
||||
"font/sfnt",
|
||||
"font/ttf",
|
||||
"font/woff",
|
||||
"font/woff2"
|
||||
};
|
||||
|
||||
bool
|
||||
IsFontMimeType(const nsAString& aType)
|
||||
{
|
||||
if (aType.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
for (uint32_t i = 0; i < StyleLinkElementFontMimeTypesNum; i++) {
|
||||
if (aType.EqualsASCII(StyleLinkElementFontMimeTypes[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsStyleLinkElement::CheckPreloadAttrs(const nsAttrValue& aAs,
|
||||
const nsAString& aType,
|
||||
const nsAString& aMedia,
|
||||
nsIDocument* aDocument)
|
||||
{
|
||||
nsContentPolicyType policyType = Link::AsValueToContentPolicy(aAs);
|
||||
if (policyType == nsIContentPolicy::TYPE_INVALID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if media attribute is valid.
|
||||
if (!aMedia.IsEmpty()) {
|
||||
RefPtr<MediaList> mediaList = MediaList::Create(aMedia);
|
||||
nsPresContext* presContext = aDocument->GetPresContext();
|
||||
if (!presContext) {
|
||||
return false;
|
||||
}
|
||||
if (!mediaList->Matches(presContext)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (aType.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsString type = nsString(aType);
|
||||
ToLowerCase(type);
|
||||
|
||||
if (policyType == nsIContentPolicy::TYPE_OTHER) {
|
||||
return true;
|
||||
|
||||
} else if (policyType == nsIContentPolicy::TYPE_MEDIA) {
|
||||
if (aAs.GetEnumValue() == DESTINATION_TRACK) {
|
||||
if (type.EqualsASCII("text/vtt")) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Maybe<MediaContainerType> mimeType = MakeMediaContainerType(aType);
|
||||
if (!mimeType) {
|
||||
return false;
|
||||
}
|
||||
DecoderDoctorDiagnostics diagnostics;
|
||||
CanPlayStatus status = DecoderTraits::CanHandleContainerType(*mimeType,
|
||||
&diagnostics);
|
||||
// Preload if this return CANPLAY_YES and CANPLAY_MAYBE.
|
||||
if (status == CANPLAY_NO) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
} else if (policyType == nsIContentPolicy::TYPE_FONT) {
|
||||
if (IsFontMimeType(type)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (policyType == nsIContentPolicy::TYPE_IMAGE) {
|
||||
if (imgLoader::SupportImageWithMimeType(NS_ConvertUTF16toUTF8(type).get(),
|
||||
AcceptedMimeTypes::IMAGES_AND_DOCUMENTS)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (policyType == nsIContentPolicy::TYPE_SCRIPT) {
|
||||
if (nsContentUtils::IsJavascriptMIMEType(type)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (policyType == nsIContentPolicy::TYPE_STYLESHEET) {
|
||||
if (type.EqualsASCII("text/css")) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsStyleLinkElement::UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
|
||||
bool* aWillNotify,
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIStyleSheetLinkingElement.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAttrValue.h"
|
||||
|
||||
class nsIDocument;
|
||||
class nsIURI;
|
||||
@ -71,9 +70,6 @@ public:
|
||||
// The return value is a bitwise or of 0 or more RelValues.
|
||||
static uint32_t ParseLinkTypes(const nsAString& aTypes);
|
||||
|
||||
static bool CheckPreloadAttrs(const nsAttrValue& aAs, const nsAString& aType,
|
||||
const nsAString& aMedia, nsIDocument* aDocument);
|
||||
|
||||
void UpdateStyleSheetInternal()
|
||||
{
|
||||
UpdateStyleSheetInternal(nullptr, nullptr);
|
||||
|
@ -66,6 +66,23 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline typename EnableIf<IsBaseOf<DictionaryBase, T>::value, void>::Type
|
||||
ImplCycleCollectionUnlink(T& aDictionary)
|
||||
{
|
||||
aDictionary.UnlinkForCC();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline typename EnableIf<IsBaseOf<DictionaryBase, T>::value, void>::Type
|
||||
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||
T& aDictionary,
|
||||
const char* aName,
|
||||
uint32_t aFlags = 0)
|
||||
{
|
||||
aDictionary.TraverseForCC(aCallback, aFlags);
|
||||
}
|
||||
|
||||
// Struct that serves as a base class for all typed arrays and array buffers and
|
||||
// array buffer views. Particularly useful so we can use IsBaseOf to detect
|
||||
// typed array/buffer/view template arguments.
|
||||
@ -382,6 +399,27 @@ private:
|
||||
const nsAString* mStr;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
ImplCycleCollectionUnlink(Optional<T>& aField)
|
||||
{
|
||||
if (aField.WasPassed()) {
|
||||
ImplCycleCollectionUnlink(aField.Value());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||
Optional<T>& aField,
|
||||
const char* aName,
|
||||
uint32_t aFlags = 0)
|
||||
{
|
||||
if (aField.WasPassed()) {
|
||||
ImplCycleCollectionTraverse(aCallback, aField.Value(), aName, aFlags);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
class NonNull
|
||||
{
|
||||
|
@ -73,6 +73,11 @@ def isTypeCopyConstructible(type):
|
||||
(type.isInterface() and type.isGeckoInterface()))
|
||||
|
||||
|
||||
class CycleCollectionUnsupported(TypeError):
|
||||
def __init__(self, message):
|
||||
TypeError.__init__(self, message)
|
||||
|
||||
|
||||
def idlTypeNeedsCycleCollection(type):
|
||||
type = type.unroll() # Takes care of sequences and nullables
|
||||
if ((type.isPrimitive() and type.tag() in builtinNames) or
|
||||
@ -88,14 +93,13 @@ def idlTypeNeedsCycleCollection(type):
|
||||
return any(idlTypeNeedsCycleCollection(t) for t in type.flatMemberTypes)
|
||||
elif type.isRecord():
|
||||
if idlTypeNeedsCycleCollection(type.inner):
|
||||
raise TypeError("Cycle collection for type %s is not supported" % type)
|
||||
raise CycleCollectionUnsupported("Cycle collection for type %s is not supported" %
|
||||
type)
|
||||
return False
|
||||
elif type.isDictionary():
|
||||
if any(idlTypeNeedsCycleCollection(m.type) for m in type.inner.members):
|
||||
raise TypeError("Cycle collection for type %s is not supported" % type)
|
||||
return False
|
||||
return CGDictionary.dictionaryNeedsCycleCollection(type.inner)
|
||||
else:
|
||||
raise TypeError("Don't know whether to cycle-collect type %s" % type)
|
||||
raise CycleCollectionUnsupported("Don't know whether to cycle-collect type %s" % type)
|
||||
|
||||
|
||||
def wantsAddProperty(desc):
|
||||
@ -12828,6 +12832,56 @@ class CGDictionary(CGThing):
|
||||
Argument("JSTracer*", "trc"),
|
||||
], body=body)
|
||||
|
||||
@staticmethod
|
||||
def dictionaryNeedsCycleCollection(dictionary):
|
||||
return (any(idlTypeNeedsCycleCollection(m.type) for m in dictionary.members) or
|
||||
(dictionary.parent and
|
||||
CGDictionary.dictionaryNeedsCycleCollection(dictionary.parent)))
|
||||
|
||||
def traverseForCCMethod(self):
|
||||
body = ""
|
||||
if (self.dictionary.parent and
|
||||
self.dictionaryNeedsCycleCollection(self.dictionary.parent)):
|
||||
cls = self.makeClassName(self.dictionary.parent)
|
||||
body += "%s::TraverseForCC(aCallback, aFlags);\n" % cls
|
||||
|
||||
for m, _ in self.memberInfo:
|
||||
if idlTypeNeedsCycleCollection(m.type):
|
||||
memberName = self.makeMemberName(m.identifier.name);
|
||||
body += ('ImplCycleCollectionTraverse(aCallback, %s, "%s", aFlags);\n' %
|
||||
(memberName, memberName))
|
||||
|
||||
return ClassMethod(
|
||||
"TraverseForCC", "void",
|
||||
[
|
||||
Argument("nsCycleCollectionTraversalCallback&", "aCallback"),
|
||||
Argument("uint32_t", "aFlags"),
|
||||
],
|
||||
body=body,
|
||||
# Inline so we don't pay a codesize hit unless someone actually uses
|
||||
# this traverse method.
|
||||
inline=True,
|
||||
bodyInHeader=True)
|
||||
|
||||
def unlinkForCCMethod(self):
|
||||
body = ""
|
||||
if (self.dictionary.parent and
|
||||
self.dictionaryNeedsCycleCollection(self.dictionary.parent)):
|
||||
cls = self.makeClassName(self.dictionary.parent)
|
||||
body += "%s::UnlinkForCC();\n" % cls
|
||||
|
||||
for m, _ in self.memberInfo:
|
||||
if idlTypeNeedsCycleCollection(m.type):
|
||||
memberName = self.makeMemberName(m.identifier.name);
|
||||
body += ('ImplCycleCollectionUnlink(%s);\n' % memberName)
|
||||
|
||||
return ClassMethod(
|
||||
"UnlinkForCC", "void", [], body=body,
|
||||
# Inline so we don't pay a codesize hit unless someone actually uses
|
||||
# this unlink method.
|
||||
inline=True,
|
||||
bodyInHeader=True)
|
||||
|
||||
def assignmentOperator(self):
|
||||
body = CGList([])
|
||||
if self.dictionary.parent:
|
||||
@ -12912,6 +12966,16 @@ class CGDictionary(CGThing):
|
||||
pass
|
||||
methods.append(self.traceDictionaryMethod())
|
||||
|
||||
try:
|
||||
if self.dictionaryNeedsCycleCollection(d):
|
||||
methods.append(self.traverseForCCMethod())
|
||||
methods.append(self.unlinkForCCMethod())
|
||||
except CycleCollectionUnsupported:
|
||||
# We have some member that we don't know how to CC. Don't output
|
||||
# our cycle collection overloads, so attempts to CC us will fail to
|
||||
# compile instead of misbehaving.
|
||||
pass
|
||||
|
||||
if CGDictionary.isDictionaryCopyConstructible(d):
|
||||
disallowCopyConstruction = False
|
||||
# Note: no base constructors because our operator= will
|
||||
|
@ -1401,7 +1401,9 @@ template <class Derived>
|
||||
void
|
||||
FetchBody<Derived>::Abort()
|
||||
{
|
||||
MOZ_ASSERT(mReadableStreamBody);
|
||||
if (!mReadableStreamBody) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(mOwner)) {
|
||||
|
@ -266,6 +266,13 @@ FetchStream::CancelCallback(JSContext* aCx, JS::HandleObject aStream,
|
||||
stream->mInputStream->CloseWithStatus(NS_BASE_STREAM_CLOSED);
|
||||
}
|
||||
|
||||
// It could be that we don't have mInputStream yet, but we still have the
|
||||
// original stream. We need to close that too.
|
||||
if (stream->mOriginalInputStream) {
|
||||
MOZ_ASSERT(!stream->mInputStream);
|
||||
stream->mOriginalInputStream->Close();
|
||||
}
|
||||
|
||||
stream->ReleaseObjects();
|
||||
return JS::UndefinedValue();
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "nsHostObjectProtocolHandler.h"
|
||||
|
||||
#include "DOMMediaStream.h"
|
||||
#include "mozilla/dom/ChromeUtils.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
@ -42,7 +41,6 @@ struct DataInfo
|
||||
{
|
||||
enum ObjectType {
|
||||
eBlobImpl,
|
||||
eMediaStream,
|
||||
eMediaSource
|
||||
};
|
||||
|
||||
@ -53,13 +51,6 @@ struct DataInfo
|
||||
, mRevoked(false)
|
||||
{}
|
||||
|
||||
DataInfo(DOMMediaStream* aMediaStream, nsIPrincipal* aPrincipal)
|
||||
: mObjectType(eMediaStream)
|
||||
, mMediaStream(aMediaStream)
|
||||
, mPrincipal(aPrincipal)
|
||||
, mRevoked(false)
|
||||
{}
|
||||
|
||||
DataInfo(MediaSource* aMediaSource, nsIPrincipal* aPrincipal)
|
||||
: mObjectType(eMediaSource)
|
||||
, mMediaSource(aMediaSource)
|
||||
@ -70,7 +61,6 @@ struct DataInfo
|
||||
ObjectType mObjectType;
|
||||
|
||||
RefPtr<BlobImpl> mBlobImpl;
|
||||
RefPtr<DOMMediaStream> mMediaStream;
|
||||
RefPtr<MediaSource> mMediaSource;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
@ -308,10 +298,9 @@ class BlobURLsReporter final : public nsIMemoryReporter
|
||||
continue;
|
||||
}
|
||||
|
||||
// Just report the path for the DOMMediaStream or MediaSource.
|
||||
// Just report the path for the MediaSource.
|
||||
nsAutoCString path;
|
||||
path = iter.UserData()->mObjectType == DataInfo::eMediaSource
|
||||
? "media-source-urls/" : "dom-media-stream-urls/";
|
||||
path = "media-source-urls/";
|
||||
BuildPath(path, key, info, aAnonymize);
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(desc,
|
||||
@ -629,22 +618,6 @@ nsHostObjectProtocolHandler::AddDataEntry(BlobImpl* aBlobImpl,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsHostObjectProtocolHandler::AddDataEntry(DOMMediaStream* aMediaStream,
|
||||
nsIPrincipal* aPrincipal,
|
||||
nsACString& aUri)
|
||||
{
|
||||
Init();
|
||||
|
||||
nsresult rv = GenerateURIStringForBlobURL(aPrincipal, aUri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AddDataEntryInternal(aUri, aMediaStream, aPrincipal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsHostObjectProtocolHandler::AddDataEntry(MediaSource* aMediaSource,
|
||||
nsIPrincipal* aPrincipal,
|
||||
@ -824,9 +797,6 @@ nsHostObjectProtocolHandler::Traverse(const nsACString& aUri,
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCallback, "HostObjectProtocolHandler DataInfo.mMediaSource");
|
||||
aCallback.NoteXPCOMChild(res->mMediaSource);
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCallback, "HostObjectProtocolHandler DataInfo.mMediaStream");
|
||||
aCallback.NoteXPCOMChild(res->mMediaStream);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -1074,19 +1044,6 @@ NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_GetStreamForMediaStreamURI(nsIURI* aURI, DOMMediaStream** aStream)
|
||||
{
|
||||
DataInfo* info = GetDataInfoFromURI(aURI);
|
||||
if (!info || info->mObjectType != DataInfo::eMediaStream) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
RefPtr<DOMMediaStream> mediaStream = info->mMediaStream;
|
||||
mediaStream.forget(aStream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFontTableProtocolHandler::NewURI(const nsACString& aSpec,
|
||||
const char *aCharset,
|
||||
@ -1187,11 +1144,6 @@ bool IsBlobURI(nsIURI* aUri)
|
||||
return IsType(aUri, DataInfo::eBlobImpl);
|
||||
}
|
||||
|
||||
bool IsMediaStreamURI(nsIURI* aUri)
|
||||
{
|
||||
return IsType(aUri, DataInfo::eMediaStream);
|
||||
}
|
||||
|
||||
bool IsMediaSourceURI(nsIURI* aUri)
|
||||
{
|
||||
return IsType(aUri, DataInfo::eMediaSource);
|
||||
|
@ -23,7 +23,6 @@ class nsIPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
class BlobURLsReporter;
|
||||
class DOMMediaStream;
|
||||
|
||||
namespace dom {
|
||||
class BlobImpl;
|
||||
@ -65,9 +64,6 @@ public:
|
||||
static nsresult AddDataEntry(mozilla::dom::BlobImpl* aBlobImpl,
|
||||
nsIPrincipal* aPrincipal,
|
||||
nsACString& aUri);
|
||||
static nsresult AddDataEntry(mozilla::DOMMediaStream* aMediaStream,
|
||||
nsIPrincipal* aPrincipal,
|
||||
nsACString& aUri);
|
||||
static nsresult AddDataEntry(mozilla::dom::MediaSource* aMediaSource,
|
||||
nsIPrincipal* aPrincipal,
|
||||
nsACString& aUri);
|
||||
@ -116,7 +112,6 @@ public:
|
||||
};
|
||||
|
||||
bool IsBlobURI(nsIURI* aUri);
|
||||
bool IsMediaStreamURI(nsIURI* aUri);
|
||||
bool IsMediaSourceURI(nsIURI* aUri);
|
||||
|
||||
inline bool IsRtspURI(nsIURI* aUri)
|
||||
@ -140,9 +135,6 @@ NS_GetBlobForBlobURISpec(const nsACString& aSpec, mozilla::dom::BlobImpl** aBlob
|
||||
extern nsresult
|
||||
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream);
|
||||
|
||||
extern nsresult
|
||||
NS_GetStreamForMediaStreamURI(nsIURI* aURI, mozilla::DOMMediaStream** aStream);
|
||||
|
||||
extern nsresult
|
||||
NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource);
|
||||
|
||||
|
@ -19,9 +19,8 @@
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
/**
|
||||
* These URIs refer to host objects: Blobs, with scheme "blob",
|
||||
* MediaStreams, with scheme "mediastream", and MediaSources, with scheme
|
||||
* "mediasource".
|
||||
* These URIs refer to host objects with "blob" scheme. The underlying objects
|
||||
* can be Blobs or MediaSources.
|
||||
*/
|
||||
class nsHostObjectURI final
|
||||
: public mozilla::net::nsSimpleURI
|
||||
|
@ -28,6 +28,14 @@
|
||||
#include "nsStyleLinkElement.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsWindowSizes.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "imgLoader.h"
|
||||
#include "MediaContainerType.h"
|
||||
#include "DecoderDoctorDiagnostics.h"
|
||||
#include "DecoderTraits.h"
|
||||
#include "MediaList.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
|
||||
#define LINK_ELEMENT_FLAG_BIT(n_) \
|
||||
NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_))
|
||||
@ -512,5 +520,119 @@ HTMLLinkElement::GetAs(nsAString& aResult)
|
||||
GetEnumAttr(nsGkAtoms::as, EmptyCString().get(), aResult);
|
||||
}
|
||||
|
||||
// We will use official mime-types from:
|
||||
// https://www.iana.org/assignments/media-types/media-types.xhtml#font
|
||||
// We do not support old deprecated mime-types for preload feature.
|
||||
// (We currectly do not support font/collection)
|
||||
static uint32_t StyleLinkElementFontMimeTypesNum = 5;
|
||||
static const char* StyleLinkElementFontMimeTypes[] = {
|
||||
"font/otf",
|
||||
"font/sfnt",
|
||||
"font/ttf",
|
||||
"font/woff",
|
||||
"font/woff2"
|
||||
};
|
||||
|
||||
bool
|
||||
IsFontMimeType(const nsAString& aType)
|
||||
{
|
||||
if (aType.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
for (uint32_t i = 0; i < StyleLinkElementFontMimeTypesNum; i++) {
|
||||
if (aType.EqualsASCII(StyleLinkElementFontMimeTypes[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLLinkElement::CheckPreloadAttrs(const nsAttrValue& aAs,
|
||||
const nsAString& aType,
|
||||
const nsAString& aMedia,
|
||||
nsIDocument* aDocument)
|
||||
{
|
||||
nsContentPolicyType policyType = Link::AsValueToContentPolicy(aAs);
|
||||
if (policyType == nsIContentPolicy::TYPE_INVALID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if media attribute is valid.
|
||||
if (!aMedia.IsEmpty()) {
|
||||
RefPtr<MediaList> mediaList = MediaList::Create(aMedia);
|
||||
nsPresContext* presContext = aDocument->GetPresContext();
|
||||
if (!presContext) {
|
||||
return false;
|
||||
}
|
||||
if (!mediaList->Matches(presContext)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (aType.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsString type = nsString(aType);
|
||||
ToLowerCase(type);
|
||||
|
||||
if (policyType == nsIContentPolicy::TYPE_OTHER) {
|
||||
return true;
|
||||
|
||||
} else if (policyType == nsIContentPolicy::TYPE_MEDIA) {
|
||||
if (aAs.GetEnumValue() == DESTINATION_TRACK) {
|
||||
if (type.EqualsASCII("text/vtt")) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Maybe<MediaContainerType> mimeType = MakeMediaContainerType(aType);
|
||||
if (!mimeType) {
|
||||
return false;
|
||||
}
|
||||
DecoderDoctorDiagnostics diagnostics;
|
||||
CanPlayStatus status = DecoderTraits::CanHandleContainerType(*mimeType,
|
||||
&diagnostics);
|
||||
// Preload if this return CANPLAY_YES and CANPLAY_MAYBE.
|
||||
if (status == CANPLAY_NO) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
} else if (policyType == nsIContentPolicy::TYPE_FONT) {
|
||||
if (IsFontMimeType(type)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (policyType == nsIContentPolicy::TYPE_IMAGE) {
|
||||
if (imgLoader::SupportImageWithMimeType(NS_ConvertUTF16toUTF8(type).get(),
|
||||
AcceptedMimeTypes::IMAGES_AND_DOCUMENTS)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (policyType == nsIContentPolicy::TYPE_SCRIPT) {
|
||||
if (nsContentUtils::IsJavascriptMIMEType(type)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (policyType == nsIContentPolicy::TYPE_STYLESHEET) {
|
||||
if (type.EqualsASCII("text/css")) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -202,6 +202,8 @@ public:
|
||||
nsGenericHTMLElement::NodeInfoChanged(aOldDoc);
|
||||
}
|
||||
|
||||
static bool CheckPreloadAttrs(const nsAttrValue& aAs, const nsAString& aType,
|
||||
const nsAString& aMedia, nsIDocument* aDocument);
|
||||
protected:
|
||||
virtual ~HTMLLinkElement();
|
||||
|
||||
|
@ -2097,8 +2097,7 @@ void HTMLMediaElement::SelectResource()
|
||||
mMediaSource = mSrcMediaSource;
|
||||
DDLINKCHILD("mediasource", mMediaSource.get());
|
||||
UpdatePreloadAction();
|
||||
if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE &&
|
||||
!IsMediaStreamURI(mLoadingSrc) && !mMediaSource) {
|
||||
if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE && !mMediaSource) {
|
||||
// preload:none media, suspend the load here before we make any
|
||||
// network requests.
|
||||
SuspendLoad();
|
||||
@ -2427,8 +2426,7 @@ void HTMLMediaElement::LoadFromSourceChildren()
|
||||
NS_ASSERTION(mNetworkState == NETWORK_LOADING,
|
||||
"Network state should be loading");
|
||||
|
||||
if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE &&
|
||||
!IsMediaStreamURI(mLoadingSrc) && !mMediaSource) {
|
||||
if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE && !mMediaSource) {
|
||||
// preload:none media, suspend the load here before we make any
|
||||
// network requests.
|
||||
SuspendLoad();
|
||||
@ -2577,20 +2575,6 @@ HTMLMediaElement::LoadResource()
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (IsMediaStreamURI(mLoadingSrc)) {
|
||||
RefPtr<DOMMediaStream> stream;
|
||||
nsresult rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, getter_AddRefs(stream));
|
||||
if (NS_FAILED(rv)) {
|
||||
nsAutoString spec;
|
||||
GetCurrentSrc(spec);
|
||||
const char16_t* params[] = { spec.get() };
|
||||
ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
|
||||
return MediaResult(rv, "MediaLoadInvalidURI");
|
||||
}
|
||||
SetupSrcMediaStreamPlayback(stream);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mMediaSource) {
|
||||
MediaDecoderInit decoderInit(
|
||||
this,
|
||||
|
@ -1130,9 +1130,6 @@ tags=msg capturestream
|
||||
[test_streams_element_capture.html]
|
||||
skip-if = toolkit == 'android' # bug 1372457
|
||||
tags=msg capturestream
|
||||
[test_streams_element_capture_createObjectURL.html]
|
||||
skip-if = android_version == '15' || android_version == '17' || (android_version == '19' && debug) # android(bug 1232305)
|
||||
tags=msg capturestream
|
||||
[test_streams_element_capture_playback.html]
|
||||
skip-if = toolkit == 'android' # android(bug 1232305)
|
||||
tags=msg capturestream
|
||||
|
@ -1,75 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test that a MediaStream captured from one element plays back in another</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var manager = new MediaTestManager;
|
||||
|
||||
function checkDrawImage(vout) {
|
||||
var canvas = document.createElement("canvas");
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(vout, 0, 0);
|
||||
var imgData = ctx.getImageData(0, 0, 1, 1);
|
||||
is(imgData.data[3], 255, "Check video frame pixel has been drawn");
|
||||
}
|
||||
|
||||
function isGreaterThanOrEqualEps(a, b, msg) {
|
||||
ok(a >= b - 0.01,
|
||||
"Got " + a + ", expected at least " + b + "; " + msg);
|
||||
}
|
||||
|
||||
function startTest(test, token) {
|
||||
manager.started(token);
|
||||
|
||||
var v = document.createElement('video');
|
||||
var vout = document.createElement('video');
|
||||
vout.token = token;
|
||||
|
||||
v.src = test.name;
|
||||
v.preload = "metadata"
|
||||
var stream;
|
||||
|
||||
var checkEnded = function() {
|
||||
is(stream.currentTime, vout.currentTime, test.name + " stream final currentTime");
|
||||
if (test.duration) {
|
||||
isGreaterThanOrEqualEps(vout.currentTime, test.duration,
|
||||
test.name + " current time at end");
|
||||
}
|
||||
is(vout.readyState, vout.HAVE_CURRENT_DATA, test.name + " checking readyState");
|
||||
ok(vout.ended, test.name + " checking playback has ended");
|
||||
if (test.type.match(/^video/)) {
|
||||
checkDrawImage(vout);
|
||||
}
|
||||
vout.remove();
|
||||
URL.revokeObjectURL(vout.src);
|
||||
manager.finished(vout.token);
|
||||
};
|
||||
vout.addEventListener("ended", checkEnded);
|
||||
|
||||
document.body.appendChild(vout);
|
||||
v.onloadedmetadata = function () {
|
||||
stream = v.mozCaptureStreamUntilEnded();
|
||||
is(stream.currentTime, 0, test.name + " stream initial currentTime");
|
||||
vout.src = URL.createObjectURL(stream);
|
||||
v.play();
|
||||
vout.play();
|
||||
};
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ "set": [["privacy.reduceTimerPrecision", false]]},
|
||||
function() {
|
||||
manager.runTests([getPlayableVideo(gSmallTests)], startTest);
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -31,9 +31,8 @@ async function startTest() {
|
||||
let video1 = document.getElementById('video1');
|
||||
let video2 = document.getElementById('video2');
|
||||
|
||||
let src = URL.createObjectURL(stream);
|
||||
video1.src = src;
|
||||
video2.src = src;
|
||||
video1.srcObject = stream;
|
||||
video2.srcObject = stream;
|
||||
|
||||
video1.onplaying = () => video1.pause();
|
||||
|
||||
|
@ -54,7 +54,7 @@ var startTest = function(test, token) {
|
||||
}
|
||||
|
||||
if (v === v2) {
|
||||
vout.src = URL.createObjectURL(v2.mozCaptureStreamUntilEnded());
|
||||
vout.srcObject = v2.mozCaptureStreamUntilEnded();
|
||||
v2.play();
|
||||
vout.play();
|
||||
}
|
||||
|
@ -668,17 +668,22 @@ AudioContext::CurrentTime()
|
||||
{
|
||||
MediaStream* stream = Destination()->Stream();
|
||||
|
||||
if (!mIsStarted &&
|
||||
stream->StreamTimeToSeconds(stream->GetCurrentTime()) == 0) {
|
||||
return 0;
|
||||
double rawTime = stream->StreamTimeToSeconds(stream->GetCurrentTime());
|
||||
|
||||
// CurrentTime increments in intervals of 128/sampleRate. If the Timer
|
||||
// Precision Reduction is smaller than this interval, the jittered time
|
||||
// can always be reversed to the raw step of the interval. In that case
|
||||
// we can simply return the un-reduced time; and avoid breaking tests.
|
||||
// We have to convert each variable into a common magnitude, we choose ms.
|
||||
if ((128/mSampleRate) * 1000.0 > nsRFPService::TimerResolution() / 1000.0) {
|
||||
return rawTime;
|
||||
}
|
||||
|
||||
// The value of a MediaStream's CurrentTime will always advance forward; it will never
|
||||
// reset (even if one rewinds a video.) Therefore we can use a single Random Seed
|
||||
// initialized at the same time as the object.
|
||||
return nsRFPService::ReduceTimePrecisionAsSecs(
|
||||
stream->StreamTimeToSeconds(stream->GetCurrentTime()),
|
||||
GetRandomTimelineSeed());
|
||||
rawTime, GetRandomTimelineSeed());
|
||||
}
|
||||
|
||||
void AudioContext::DisconnectFromOwner()
|
||||
|
@ -25,6 +25,18 @@ const SAME_ORIGIN = "http://mochi.test:8888/"
|
||||
const CROSS_ORIGIN = "http://example.com/";
|
||||
const PATH = "tests/dom/security/test/general/file_same_site_cookies_redirect.sjs";
|
||||
|
||||
const FRAME_META_REFRESH_SAME = `
|
||||
<html><head>
|
||||
<meta http-equiv="refresh" content="0;
|
||||
url='` + SAME_ORIGIN + PATH + `?loadFrame'">
|
||||
</head></html>`;
|
||||
|
||||
const FRAME_META_REFRESH_CROSS = `
|
||||
<html><head>
|
||||
<meta http-equiv="refresh" content="0;
|
||||
url='` + CROSS_ORIGIN + PATH + `?loadFrame'">
|
||||
</head></html>`;
|
||||
|
||||
function handleRequest(request, response)
|
||||
{
|
||||
// avoid confusing cache behaviors
|
||||
@ -37,6 +49,13 @@ function handleRequest(request, response)
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.queryString === "sameToSameRedirect") {
|
||||
let URL = SAME_ORIGIN + PATH + "?loadFrame";
|
||||
response.setStatusLine("1.1", 302, "Found");
|
||||
response.setHeader("Location", URL, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.queryString === "sameToCrossRedirect") {
|
||||
let URL = CROSS_ORIGIN + PATH + "?loadFrame";
|
||||
response.setStatusLine("1.1", 302, "Found");
|
||||
@ -51,6 +70,16 @@ function handleRequest(request, response)
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.queryString === "sameToCrossRedirectMeta") {
|
||||
response.write(FRAME_META_REFRESH_CROSS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.queryString === "crossToSameRedirectMeta") {
|
||||
response.write(FRAME_META_REFRESH_SAME);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.queryString === "loadFrame") {
|
||||
response.write(FRAME);
|
||||
return;
|
||||
|
@ -29,6 +29,12 @@ const PATH = "tests/dom/security/test/general/file_same_site_cookies_redirect.sj
|
||||
let curTest = 0;
|
||||
|
||||
var tests = [
|
||||
{
|
||||
description: "baseline: same-site cookie, redirect same-site to same-site",
|
||||
imgSRC: SAME_ORIGIN + PATH + "?setSameSiteCookie",
|
||||
frameSRC: SAME_ORIGIN + PATH + "?sameToSameRedirect",
|
||||
result: "myKey=strictSameSiteCookie",
|
||||
},
|
||||
{
|
||||
description: "same-site cookie, redirect same-site to cross-site",
|
||||
imgSRC: SAME_ORIGIN + PATH + "?setSameSiteCookie",
|
||||
@ -41,6 +47,18 @@ var tests = [
|
||||
frameSRC: CROSS_ORIGIN + PATH + "?crossToSameRedirect",
|
||||
result: "", // no cookie should be set
|
||||
},
|
||||
{
|
||||
description: "same-site cookie, meta redirect same-site to cross-site",
|
||||
imgSRC: SAME_ORIGIN + PATH + "?setSameSiteCookie",
|
||||
frameSRC: SAME_ORIGIN + PATH + "?sameToCrossRedirectMeta",
|
||||
result: "", // no cookie should be set
|
||||
},
|
||||
{
|
||||
description: "same-site cookie, meta redirect cross-site to same-site",
|
||||
imgSRC: SAME_ORIGIN + PATH + "?setSameSiteCookie",
|
||||
frameSRC: CROSS_ORIGIN + PATH + "?crossToSameRedirectMeta",
|
||||
result: "", // no cookie should be set
|
||||
},
|
||||
];
|
||||
|
||||
window.addEventListener("message", receiveMessage);
|
||||
|
256
dom/url/URL.cpp
256
dom/url/URL.cpp
@ -11,7 +11,9 @@
|
||||
#include "MainThreadUtils.h"
|
||||
#include "mozilla/dom/URLBinding.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIURIMutator.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -61,17 +63,6 @@ URL::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
URL::CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream,
|
||||
nsAString& aResult, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
DeprecationWarning(aGlobal, nsIDocument::eURLCreateObjectURL_MediaStream);
|
||||
|
||||
URLMainThread::CreateObjectURL(aGlobal, aStream, aResult, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
URL::CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
|
||||
nsAString& aResult, ErrorResult& aRv)
|
||||
@ -144,5 +135,248 @@ URL::URLSearchParamsUpdated(URLSearchParams* aSearchParams)
|
||||
SetSearchInternal(search);
|
||||
}
|
||||
|
||||
#define URL_GETTER( value, func ) \
|
||||
MOZ_ASSERT(mURI); \
|
||||
value.Truncate(); \
|
||||
nsAutoCString tmp; \
|
||||
nsresult rv = mURI->func(tmp); \
|
||||
if (NS_SUCCEEDED(rv)) { \
|
||||
CopyUTF8toUTF16(tmp, value); \
|
||||
}
|
||||
|
||||
void
|
||||
URL::GetHref(nsAString& aHref) const
|
||||
{
|
||||
URL_GETTER(aHref, GetSpec);
|
||||
}
|
||||
|
||||
void
|
||||
URL::GetProtocol(nsAString& aProtocol) const
|
||||
{
|
||||
URL_GETTER(aProtocol, GetScheme);
|
||||
aProtocol.Append(char16_t(':'));
|
||||
}
|
||||
|
||||
void
|
||||
URL::GetUsername(nsAString& aUsername) const
|
||||
{
|
||||
URL_GETTER(aUsername, GetUsername);
|
||||
}
|
||||
|
||||
void
|
||||
URL::SetUsername(const nsAString& aUsername)
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetUsername(NS_ConvertUTF16toUTF8(aUsername))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URL::GetPassword(nsAString& aPassword) const
|
||||
{
|
||||
URL_GETTER(aPassword, GetPassword);
|
||||
}
|
||||
|
||||
void
|
||||
URL::SetPassword(const nsAString& aPassword)
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetPassword(NS_ConvertUTF16toUTF8(aPassword))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URL::GetHost(nsAString& aHost) const
|
||||
{
|
||||
URL_GETTER(aHost, GetHostPort);
|
||||
}
|
||||
|
||||
void
|
||||
URL::SetHost(const nsAString& aHost)
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetHostPort(NS_ConvertUTF16toUTF8(aHost))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URL::GetHostname(nsAString& aHostname) const
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
aHostname.Truncate();
|
||||
nsContentUtils::GetHostOrIPv6WithBrackets(mURI, aHostname);
|
||||
}
|
||||
|
||||
void
|
||||
URL::SetHostname(const nsAString& aHostname)
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
// nsStandardURL returns NS_ERROR_UNEXPECTED for an empty hostname
|
||||
// The return code is silently ignored
|
||||
mozilla::Unused << NS_MutateURI(mURI)
|
||||
.SetHost(NS_ConvertUTF16toUTF8(aHostname))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URL::GetPort(nsAString& aPort) const
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
aPort.Truncate();
|
||||
|
||||
int32_t port;
|
||||
nsresult rv = mURI->GetPort(&port);
|
||||
if (NS_SUCCEEDED(rv) && port != -1) {
|
||||
nsAutoString portStr;
|
||||
portStr.AppendInt(port, 10);
|
||||
aPort.Assign(portStr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
URL::SetPort(const nsAString& aPort)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoString portStr(aPort);
|
||||
int32_t port = -1;
|
||||
|
||||
// nsIURI uses -1 as default value.
|
||||
if (!portStr.IsEmpty()) {
|
||||
port = portStr.ToInteger(&rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetPort(port)
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URL::GetPathname(nsAString& aPathname) const
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
aPathname.Truncate();
|
||||
|
||||
// Do not throw! Not having a valid URI or URL should result in an empty
|
||||
// string.
|
||||
|
||||
nsAutoCString file;
|
||||
nsresult rv = mURI->GetFilePath(file);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
CopyUTF8toUTF16(file, aPathname);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
URL::SetPathname(const nsAString& aPathname)
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
// Do not throw!
|
||||
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetFilePath(NS_ConvertUTF16toUTF8(aPathname))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URL::GetSearch(nsAString& aSearch) const
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
aSearch.Truncate();
|
||||
|
||||
// Do not throw! Not having a valid URI or URL should result in an empty
|
||||
// string.
|
||||
|
||||
nsAutoCString search;
|
||||
nsresult rv;
|
||||
|
||||
rv = mURI->GetQuery(search);
|
||||
if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
|
||||
aSearch.Assign(u'?');
|
||||
AppendUTF8toUTF16(search, aSearch);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
URL::GetHash(nsAString& aHash) const
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
aHash.Truncate();
|
||||
|
||||
nsAutoCString ref;
|
||||
nsresult rv = mURI->GetRef(ref);
|
||||
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
|
||||
aHash.Assign(char16_t('#'));
|
||||
AppendUTF8toUTF16(ref, aHash);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
URL::SetHash(const nsAString& aHash)
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetRef(NS_ConvertUTF16toUTF8(aHash))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URL::SetSearchInternal(const nsAString& aSearch)
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
|
||||
// Ignore failures to be compatible with NS4.
|
||||
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetQuery(NS_ConvertUTF16toUTF8(aSearch))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URL::UpdateURLSearchParams()
|
||||
{
|
||||
if (!mSearchParams) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString search;
|
||||
nsresult rv = GetURI()->GetQuery(search);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
search.Truncate();
|
||||
}
|
||||
|
||||
mSearchParams->ParseInput(search);
|
||||
}
|
||||
|
||||
void
|
||||
URL::SetURI(already_AddRefed<nsIURI> aURI)
|
||||
{
|
||||
mURI = Move(aURI);
|
||||
MOZ_ASSERT(mURI);
|
||||
}
|
||||
|
||||
nsIURI*
|
||||
URL::GetURI() const
|
||||
{
|
||||
MOZ_ASSERT(mURI);
|
||||
return mURI;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -19,7 +19,6 @@ class nsIURI;
|
||||
namespace mozilla {
|
||||
|
||||
class ErrorResult;
|
||||
class DOMMediaStream;
|
||||
|
||||
namespace dom {
|
||||
|
||||
@ -61,10 +60,6 @@ public:
|
||||
CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
|
||||
nsAString& aResult, ErrorResult& aRv);
|
||||
|
||||
static void
|
||||
CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream,
|
||||
nsAString& aResult, ErrorResult& aRv);
|
||||
|
||||
static void
|
||||
CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
|
||||
nsAString& aResult, ErrorResult& aRv);
|
||||
@ -77,8 +72,8 @@ public:
|
||||
IsValidURL(const GlobalObject& aGlobal, const nsAString& aURL,
|
||||
ErrorResult& aRv);
|
||||
|
||||
virtual void
|
||||
GetHref(nsAString& aHref) const = 0;
|
||||
void
|
||||
GetHref(nsAString& aHref) const;
|
||||
|
||||
virtual void
|
||||
SetHref(const nsAString& aHref, ErrorResult& aRv) = 0;
|
||||
@ -86,61 +81,61 @@ public:
|
||||
virtual void
|
||||
GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const = 0;
|
||||
|
||||
virtual void
|
||||
GetProtocol(nsAString& aProtocol) const = 0;
|
||||
void
|
||||
GetProtocol(nsAString& aProtocol) const;
|
||||
|
||||
virtual void
|
||||
SetProtocol(const nsAString& aProtocol, ErrorResult& aRv) = 0;
|
||||
|
||||
virtual void
|
||||
GetUsername(nsAString& aUsername) const = 0;
|
||||
void
|
||||
GetUsername(nsAString& aUsername) const;
|
||||
|
||||
virtual void
|
||||
SetUsername(const nsAString& aUsername) = 0;
|
||||
void
|
||||
SetUsername(const nsAString& aUsername);
|
||||
|
||||
virtual void
|
||||
GetPassword(nsAString& aPassword) const = 0;
|
||||
void
|
||||
GetPassword(nsAString& aPassword) const;
|
||||
|
||||
virtual void
|
||||
SetPassword(const nsAString& aPassword) = 0;
|
||||
void
|
||||
SetPassword(const nsAString& aPassword);
|
||||
|
||||
virtual void
|
||||
GetHost(nsAString& aHost) const = 0;
|
||||
void
|
||||
GetHost(nsAString& aHost) const;
|
||||
|
||||
virtual void
|
||||
SetHost(const nsAString& aHost) = 0;
|
||||
void
|
||||
SetHost(const nsAString& aHost);
|
||||
|
||||
virtual void
|
||||
GetHostname(nsAString& aHostname) const = 0;
|
||||
void
|
||||
GetHostname(nsAString& aHostname) const;
|
||||
|
||||
virtual void
|
||||
SetHostname(const nsAString& aHostname) = 0;
|
||||
void
|
||||
SetHostname(const nsAString& aHostname);
|
||||
|
||||
virtual void
|
||||
GetPort(nsAString& aPort) const = 0;
|
||||
void
|
||||
GetPort(nsAString& aPort) const;
|
||||
|
||||
virtual void
|
||||
SetPort(const nsAString& aPort) = 0;
|
||||
void
|
||||
SetPort(const nsAString& aPort);
|
||||
|
||||
virtual void
|
||||
GetPathname(nsAString& aPathname) const = 0;
|
||||
void
|
||||
GetPathname(nsAString& aPathname) const;
|
||||
|
||||
virtual void
|
||||
SetPathname(const nsAString& aPathname) = 0;
|
||||
void
|
||||
SetPathname(const nsAString& aPathname);
|
||||
|
||||
virtual void
|
||||
GetSearch(nsAString& aSearch) const = 0;
|
||||
void
|
||||
GetSearch(nsAString& aSearch) const;
|
||||
|
||||
virtual void
|
||||
SetSearch(const nsAString& aSearch);
|
||||
|
||||
URLSearchParams* SearchParams();
|
||||
|
||||
virtual void
|
||||
GetHash(nsAString& aHost) const = 0;
|
||||
void
|
||||
GetHash(nsAString& aHost) const;
|
||||
|
||||
virtual void
|
||||
SetHash(const nsAString& aHash) = 0;
|
||||
void
|
||||
SetHash(const nsAString& aHash);
|
||||
|
||||
void Stringify(nsAString& aRetval) const
|
||||
{
|
||||
@ -158,19 +153,26 @@ public:
|
||||
URLSearchParamsUpdated(URLSearchParams* aSearchParams) override;
|
||||
|
||||
protected:
|
||||
virtual ~URL()
|
||||
{}
|
||||
virtual ~URL() = default;
|
||||
|
||||
virtual void
|
||||
UpdateURLSearchParams() = 0;
|
||||
void
|
||||
SetURI(already_AddRefed<nsIURI> aURI);
|
||||
|
||||
virtual void
|
||||
SetSearchInternal(const nsAString& aSearch) = 0;
|
||||
nsIURI*
|
||||
GetURI() const;
|
||||
|
||||
void
|
||||
UpdateURLSearchParams();
|
||||
|
||||
private:
|
||||
void
|
||||
SetSearchInternal(const nsAString& aSearch);
|
||||
|
||||
void CreateSearchParamsIfNeeded();
|
||||
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
RefPtr<URLSearchParams> mSearchParams;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
};
|
||||
|
||||
bool IsChromeURI(nsIURI* aURI);
|
||||
|
@ -18,34 +18,6 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
CreateObjectURLInternal(const GlobalObject& aGlobal, T aObject,
|
||||
nsAString& aResult, ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (NS_WARN_IF(!global)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
nsContentUtils::ObjectPrincipal(aGlobal.Get());
|
||||
|
||||
nsAutoCString url;
|
||||
aRv = nsHostObjectProtocolHandler::AddDataEntry(aObject, principal, url);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
global->RegisterHostObjectURI(url);
|
||||
CopyASCIItoUTF16(url, aResult);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
/* static */ already_AddRefed<URLMainThread>
|
||||
URLMainThread::Constructor(const GlobalObject& aGlobal, const nsAString& aURL,
|
||||
const Optional<nsAString>& aBase, ErrorResult& aRv)
|
||||
@ -90,7 +62,8 @@ URLMainThread::Constructor(nsISupports* aParent, const nsAString& aURL,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<URLMainThread> url = new URLMainThread(aParent, uri.forget());
|
||||
RefPtr<URLMainThread> url = new URLMainThread(aParent);
|
||||
url->SetURI(uri.forget());
|
||||
return url.forget();
|
||||
}
|
||||
|
||||
@ -99,16 +72,24 @@ URLMainThread::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
|
||||
nsAString& aResult, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
CreateObjectURLInternal(aGlobal, aBlob.Impl(), aResult, aRv);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
URLMainThread::CreateObjectURL(const GlobalObject& aGlobal,
|
||||
DOMMediaStream& aStream,
|
||||
nsAString& aResult, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
CreateObjectURLInternal(aGlobal, &aStream, aResult, aRv);
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (NS_WARN_IF(!global)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
nsContentUtils::ObjectPrincipal(aGlobal.Get());
|
||||
|
||||
nsAutoCString url;
|
||||
aRv = nsHostObjectProtocolHandler::AddDataEntry(aBlob.Impl(), principal, url);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
global->RegisterHostObjectURI(url);
|
||||
CopyASCIItoUTF16(url, aResult);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
@ -161,10 +142,8 @@ URLMainThread::RevokeObjectURL(const GlobalObject& aGlobal,
|
||||
}
|
||||
}
|
||||
|
||||
URLMainThread::URLMainThread(nsISupports* aParent,
|
||||
already_AddRefed<nsIURI> aURI)
|
||||
URLMainThread::URLMainThread(nsISupports* aParent)
|
||||
: URL(aParent)
|
||||
, mURI(aURI)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
@ -183,18 +162,6 @@ URLMainThread::IsValidURL(const GlobalObject& aGlobal, const nsAString& aURL,
|
||||
return nsHostObjectProtocolHandler::HasDataEntry(asciiurl);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::GetHref(nsAString& aHref) const
|
||||
{
|
||||
aHref.Truncate();
|
||||
|
||||
nsAutoCString href;
|
||||
nsresult rv = mURI->GetSpec(href);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
CopyUTF8toUTF16(href, aHref);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::SetHref(const nsAString& aHref, ErrorResult& aRv)
|
||||
{
|
||||
@ -214,26 +181,14 @@ URLMainThread::SetHref(const nsAString& aHref, ErrorResult& aRv)
|
||||
return;
|
||||
}
|
||||
|
||||
mURI = uri;
|
||||
SetURI(uri.forget());
|
||||
UpdateURLSearchParams();
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const
|
||||
{
|
||||
nsContentUtils::GetUTFOrigin(mURI, aOrigin);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::GetProtocol(nsAString& aProtocol) const
|
||||
{
|
||||
nsAutoCString protocol;
|
||||
if (NS_SUCCEEDED(mURI->GetScheme(protocol))) {
|
||||
aProtocol.Truncate();
|
||||
}
|
||||
|
||||
CopyASCIItoUTF16(protocol, aProtocol);
|
||||
aProtocol.Append(char16_t(':'));
|
||||
nsContentUtils::GetUTFOrigin(GetURI(), aOrigin);
|
||||
}
|
||||
|
||||
void
|
||||
@ -250,7 +205,7 @@ URLMainThread::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv)
|
||||
// implementation. In order to do this properly, we have to serialize the
|
||||
// existing URL and reparse it in a new object.
|
||||
nsCOMPtr<nsIURI> clone;
|
||||
nsresult rv = NS_MutateURI(mURI)
|
||||
nsresult rv = NS_MutateURI(GetURI())
|
||||
.SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)))
|
||||
.Finalize(clone);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@ -269,205 +224,7 @@ URLMainThread::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv)
|
||||
return;
|
||||
}
|
||||
|
||||
mURI = uri;
|
||||
}
|
||||
|
||||
#define URL_GETTER( value, func ) \
|
||||
value.Truncate(); \
|
||||
nsAutoCString tmp; \
|
||||
nsresult rv = mURI->func(tmp); \
|
||||
if (NS_SUCCEEDED(rv)) { \
|
||||
CopyUTF8toUTF16(tmp, value); \
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::GetUsername(nsAString& aUsername) const
|
||||
{
|
||||
URL_GETTER(aUsername, GetUsername);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::SetUsername(const nsAString& aUsername)
|
||||
{
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetUsername(NS_ConvertUTF16toUTF8(aUsername))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::GetPassword(nsAString& aPassword) const
|
||||
{
|
||||
URL_GETTER(aPassword, GetPassword);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::SetPassword(const nsAString& aPassword)
|
||||
{
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetPassword(NS_ConvertUTF16toUTF8(aPassword))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::GetHost(nsAString& aHost) const
|
||||
{
|
||||
URL_GETTER(aHost, GetHostPort);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::SetHost(const nsAString& aHost)
|
||||
{
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetHostPort(NS_ConvertUTF16toUTF8(aHost))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::UpdateURLSearchParams()
|
||||
{
|
||||
if (!mSearchParams) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString search;
|
||||
nsresult rv = mURI->GetQuery(search);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
search.Truncate();
|
||||
}
|
||||
|
||||
mSearchParams->ParseInput(search);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::GetHostname(nsAString& aHostname) const
|
||||
{
|
||||
aHostname.Truncate();
|
||||
nsContentUtils::GetHostOrIPv6WithBrackets(mURI, aHostname);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::SetHostname(const nsAString& aHostname)
|
||||
{
|
||||
// nsStandardURL returns NS_ERROR_UNEXPECTED for an empty hostname
|
||||
// The return code is silently ignored
|
||||
mozilla::Unused << NS_MutateURI(mURI)
|
||||
.SetHost(NS_ConvertUTF16toUTF8(aHostname))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::GetPort(nsAString& aPort) const
|
||||
{
|
||||
aPort.Truncate();
|
||||
|
||||
int32_t port;
|
||||
nsresult rv = mURI->GetPort(&port);
|
||||
if (NS_SUCCEEDED(rv) && port != -1) {
|
||||
nsAutoString portStr;
|
||||
portStr.AppendInt(port, 10);
|
||||
aPort.Assign(portStr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::SetPort(const nsAString& aPort)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoString portStr(aPort);
|
||||
int32_t port = -1;
|
||||
|
||||
// nsIURI uses -1 as default value.
|
||||
if (!portStr.IsEmpty()) {
|
||||
port = portStr.ToInteger(&rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetPort(port)
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::GetPathname(nsAString& aPathname) const
|
||||
{
|
||||
aPathname.Truncate();
|
||||
|
||||
// Do not throw! Not having a valid URI or URL should result in an empty
|
||||
// string.
|
||||
|
||||
nsAutoCString file;
|
||||
nsresult rv = mURI->GetFilePath(file);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
CopyUTF8toUTF16(file, aPathname);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::SetPathname(const nsAString& aPathname)
|
||||
{
|
||||
// Do not throw!
|
||||
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetFilePath(NS_ConvertUTF16toUTF8(aPathname))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::GetSearch(nsAString& aSearch) const
|
||||
{
|
||||
aSearch.Truncate();
|
||||
|
||||
// Do not throw! Not having a valid URI or URL should result in an empty
|
||||
// string.
|
||||
|
||||
nsAutoCString search;
|
||||
nsresult rv;
|
||||
|
||||
rv = mURI->GetQuery(search);
|
||||
if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
|
||||
aSearch.Assign(u'?');
|
||||
AppendUTF8toUTF16(search, aSearch);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::GetHash(nsAString& aHash) const
|
||||
{
|
||||
aHash.Truncate();
|
||||
|
||||
nsAutoCString ref;
|
||||
nsresult rv = mURI->GetRef(ref);
|
||||
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
|
||||
aHash.Assign(char16_t('#'));
|
||||
AppendUTF8toUTF16(ref, aHash);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::SetHash(const nsAString& aHash)
|
||||
{
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetRef(NS_ConvertUTF16toUTF8(aHash))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
void
|
||||
URLMainThread::SetSearchInternal(const nsAString& aSearch)
|
||||
{
|
||||
// Ignore failures to be compatible with NS4.
|
||||
|
||||
Unused << NS_MutateURI(mURI)
|
||||
.SetQuery(NS_ConvertUTF16toUTF8(aSearch))
|
||||
.Finalize(mURI);
|
||||
}
|
||||
|
||||
nsIURI*
|
||||
URLMainThread::GetURI() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mURI;
|
||||
SetURI(uri.forget());
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -32,10 +32,6 @@ public:
|
||||
CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob,
|
||||
nsAString& aResult, ErrorResult& aRv);
|
||||
|
||||
static void
|
||||
CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream,
|
||||
nsAString& aResult, ErrorResult& aRv);
|
||||
|
||||
static void
|
||||
CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
|
||||
nsAString& aResult, ErrorResult& aRv);
|
||||
@ -48,10 +44,7 @@ public:
|
||||
IsValidURL(const GlobalObject& aGlobal, const nsAString& aURL,
|
||||
ErrorResult& aRv);
|
||||
|
||||
URLMainThread(nsISupports* aParent, already_AddRefed<nsIURI> aURI);
|
||||
|
||||
virtual void
|
||||
GetHref(nsAString& aHref) const override;
|
||||
explicit URLMainThread(nsISupports* aParent);
|
||||
|
||||
virtual void
|
||||
SetHref(const nsAString& aHref, ErrorResult& aRv) override;
|
||||
@ -59,69 +52,11 @@ public:
|
||||
virtual void
|
||||
GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const override;
|
||||
|
||||
virtual void
|
||||
GetProtocol(nsAString& aProtocol) const override;
|
||||
|
||||
virtual void
|
||||
SetProtocol(const nsAString& aProtocol, ErrorResult& aRv) override;
|
||||
|
||||
virtual void
|
||||
GetUsername(nsAString& aUsername) const override;
|
||||
|
||||
virtual void
|
||||
SetUsername(const nsAString& aUsername) override;
|
||||
|
||||
virtual void
|
||||
GetPassword(nsAString& aPassword) const override;
|
||||
|
||||
virtual void
|
||||
SetPassword(const nsAString& aPassword) override;
|
||||
|
||||
virtual void
|
||||
GetHost(nsAString& aHost) const override;
|
||||
|
||||
virtual void
|
||||
SetHost(const nsAString& aHost) override;
|
||||
|
||||
virtual void
|
||||
GetHostname(nsAString& aHostname) const override;
|
||||
|
||||
virtual void
|
||||
SetHostname(const nsAString& aHostname) override;
|
||||
|
||||
virtual void
|
||||
GetPort(nsAString& aPort) const override;
|
||||
|
||||
virtual void
|
||||
SetPort(const nsAString& aPort) override;
|
||||
|
||||
virtual void
|
||||
GetPathname(nsAString& aPathname) const override;
|
||||
|
||||
virtual void
|
||||
SetPathname(const nsAString& aPathname) override;
|
||||
|
||||
virtual void
|
||||
GetSearch(nsAString& aSearch) const override;
|
||||
|
||||
virtual void
|
||||
GetHash(nsAString& aHost) const override;
|
||||
|
||||
virtual void
|
||||
SetHash(const nsAString& aHash) override;
|
||||
|
||||
virtual void UpdateURLSearchParams() override;
|
||||
|
||||
virtual void
|
||||
SetSearchInternal(const nsAString& aSearch) override;
|
||||
|
||||
nsIURI*
|
||||
GetURI() const;
|
||||
|
||||
private:
|
||||
~URLMainThread();
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -22,32 +22,6 @@ using net::nsStandardURL;
|
||||
|
||||
namespace dom {
|
||||
|
||||
// Proxy class to forward all the requests to a URLMainThread object.
|
||||
class URLWorker::URLProxy final
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(URLProxy)
|
||||
|
||||
explicit URLProxy(already_AddRefed<URLMainThread> aURL)
|
||||
: mURL(aURL)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
URLMainThread* URL()
|
||||
{
|
||||
return mURL;
|
||||
}
|
||||
|
||||
private:
|
||||
~URLProxy()
|
||||
{
|
||||
NS_ReleaseOnMainThreadSystemGroup("URLMainThread", mURL.forget());
|
||||
}
|
||||
|
||||
RefPtr<URLMainThread> mURL;
|
||||
};
|
||||
|
||||
// This class creates an URL from a DOM Blob on the main thread.
|
||||
class CreateURLRunnable : public WorkerMainThreadRunnable
|
||||
{
|
||||
@ -213,7 +187,7 @@ private:
|
||||
|
||||
nsString mBase; // IsVoid() if we have no base URI string.
|
||||
|
||||
RefPtr<URLWorker::URLProxy> mRetval;
|
||||
nsCOMPtr<nsIURI> mRetval;
|
||||
|
||||
public:
|
||||
ConstructorRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
@ -235,25 +209,28 @@ public:
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<URLMainThread> url;
|
||||
nsCOMPtr<nsIURI> baseUri;
|
||||
if (!mBase.IsVoid()) {
|
||||
url = URLMainThread::Constructor(nullptr, mURL, mBase, rv);
|
||||
} else {
|
||||
url = URLMainThread::Constructor(nullptr, mURL, nullptr, rv);
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(baseUri), mBase, nullptr, nullptr,
|
||||
nsContentUtils::GetIOService());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv.Failed()) {
|
||||
rv.SuppressException();
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), mURL, nullptr, baseUri,
|
||||
nsContentUtils::GetIOService());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mRetval = new URLWorker::URLProxy(url.forget());
|
||||
mRetval = Move(uri);
|
||||
return true;
|
||||
}
|
||||
|
||||
URLWorker::URLProxy*
|
||||
GetURLProxy(ErrorResult& aRv) const
|
||||
nsIURI*
|
||||
GetURI(ErrorResult& aRv) const
|
||||
{
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
@ -271,13 +248,13 @@ class OriginGetterRunnable : public WorkerMainThreadRunnable
|
||||
public:
|
||||
OriginGetterRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
nsAString& aValue,
|
||||
URLWorker::URLProxy* aURLProxy)
|
||||
nsIURI* aURI)
|
||||
: WorkerMainThreadRunnable(aWorkerPrivate,
|
||||
// We can have telemetry keys for each getter when
|
||||
// needed.
|
||||
NS_LITERAL_CSTRING("URL :: getter"))
|
||||
, mValue(aValue)
|
||||
, mURLProxy(aURLProxy)
|
||||
, mURI(aURI)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
@ -287,8 +264,7 @@ public:
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
ErrorResult rv;
|
||||
mURLProxy->URL()->GetOrigin(mValue, rv);
|
||||
MOZ_ASSERT(!rv.Failed(), "Main-thread getters do not fail.");
|
||||
nsContentUtils::GetUTFOrigin(mURI, mValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -300,28 +276,19 @@ public:
|
||||
|
||||
private:
|
||||
nsAString& mValue;
|
||||
RefPtr<URLWorker::URLProxy> mURLProxy;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
};
|
||||
|
||||
class SetterRunnable : public WorkerMainThreadRunnable
|
||||
class ProtocolSetterRunnable : public WorkerMainThreadRunnable
|
||||
{
|
||||
public:
|
||||
enum SetterType {
|
||||
SetterHref,
|
||||
SetterProtocol,
|
||||
};
|
||||
|
||||
SetterRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
SetterType aType, const nsAString& aValue,
|
||||
URLWorker::URLProxy* aURLProxy)
|
||||
ProtocolSetterRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
const nsACString& aValue,
|
||||
nsIURI* aURI)
|
||||
: WorkerMainThreadRunnable(aWorkerPrivate,
|
||||
// We can have telemetry keys for each setter when
|
||||
// needed.
|
||||
NS_LITERAL_CSTRING("URL :: setter"))
|
||||
NS_LITERAL_CSTRING("ProtocolSetterRunnable"))
|
||||
, mValue(aValue)
|
||||
, mType(aType)
|
||||
, mURLProxy(aURLProxy)
|
||||
, mFailed(false)
|
||||
, mURI(aURI)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
@ -330,43 +297,47 @@ public:
|
||||
MainThreadRun() override
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
ErrorResult rv;
|
||||
|
||||
switch (mType) {
|
||||
case SetterHref: {
|
||||
mURLProxy->URL()->SetHref(mValue, rv);
|
||||
break;
|
||||
}
|
||||
|
||||
case SetterProtocol:
|
||||
mURLProxy->URL()->SetProtocol(mValue, rv);
|
||||
break;
|
||||
nsCOMPtr<nsIURI> clone;
|
||||
nsresult rv = NS_MutateURI(mURI)
|
||||
.SetScheme(mValue)
|
||||
.Finalize(clone);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
rv.SuppressException();
|
||||
mFailed = true;
|
||||
nsAutoCString href;
|
||||
rv = clone->GetSpec(href);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), href);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mRetval = Move(uri);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Failed() const
|
||||
{
|
||||
return mFailed;
|
||||
}
|
||||
|
||||
void
|
||||
Dispatch(ErrorResult& aRv)
|
||||
{
|
||||
WorkerMainThreadRunnable::Dispatch(Terminating, aRv);
|
||||
}
|
||||
|
||||
nsIURI*
|
||||
GetRetval() const
|
||||
{
|
||||
return mRetval;
|
||||
}
|
||||
|
||||
private:
|
||||
const nsString mValue;
|
||||
SetterType mType;
|
||||
RefPtr<URLWorker::URLProxy> mURLProxy;
|
||||
bool mFailed;
|
||||
const nsCString mValue;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIURI> mRetval;
|
||||
};
|
||||
|
||||
/* static */ already_AddRefed<URLWorker>
|
||||
@ -488,34 +459,6 @@ URLWorker::Init(const nsAString& aURL, const Optional<nsAString>& aBase,
|
||||
}
|
||||
}
|
||||
|
||||
if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) {
|
||||
nsCOMPtr<nsIURI> baseURL;
|
||||
if (aBase.WasPassed()) {
|
||||
// XXXcatalinb: SetSpec only writes a warning to the console on urls
|
||||
// without a valid scheme. I can't fix that because we've come to rely
|
||||
// on that behaviour in a bunch of different places.
|
||||
nsresult rv = NS_MutateURI(new nsStandardURL::Mutator())
|
||||
.SetSpec(NS_ConvertUTF16toUTF8(aBase.Value()))
|
||||
.Finalize(baseURL);
|
||||
nsAutoCString baseScheme;
|
||||
if (baseURL) {
|
||||
baseURL->GetScheme(baseScheme);
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) || baseScheme.IsEmpty()) {
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL>(aBase.Value());
|
||||
return;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aRv = NS_MutateURI(new nsStandardURL::Mutator())
|
||||
.Apply(NS_MutatorMethod(&nsIStandardURLMutator::Init,
|
||||
nsIStandardURL::URLTYPE_STANDARD,
|
||||
-1, NS_ConvertUTF16toUTF8(aURL),
|
||||
nullptr, baseURL, nullptr))
|
||||
.Finalize(mStdURL);
|
||||
return;
|
||||
}
|
||||
|
||||
// create url proxy
|
||||
RefPtr<ConstructorRunnable> runnable =
|
||||
new ConstructorRunnable(mWorkerPrivate, aURL, aBase);
|
||||
@ -523,37 +466,19 @@ URLWorker::Init(const nsAString& aURL, const Optional<nsAString>& aBase,
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
mURLProxy = runnable->GetURLProxy(aRv);
|
||||
|
||||
nsCOMPtr<nsIURI> uri = runnable->GetURI(aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetURI(uri.forget());
|
||||
}
|
||||
|
||||
URLWorker::~URLWorker() = default;
|
||||
|
||||
void
|
||||
URLWorker::GetHref(nsAString& aHref) const
|
||||
{
|
||||
aHref.Truncate();
|
||||
if (mStdURL) {
|
||||
nsAutoCString href;
|
||||
nsresult rv = mStdURL->GetSpec(href);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
CopyUTF8toUTF16(href, aHref);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->GetHref(aHref);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::SetHref(const nsAString& aHref, ErrorResult& aRv)
|
||||
{
|
||||
SetHrefInternal(aHref, eUseProxyIfNeeded, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::SetHrefInternal(const nsAString& aHref, Strategy aStrategy,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsAutoCString scheme;
|
||||
nsresult rv = net_ExtractURLScheme(NS_ConvertUTF16toUTF8(aHref), scheme);
|
||||
@ -562,78 +487,31 @@ URLWorker::SetHrefInternal(const nsAString& aHref, Strategy aStrategy,
|
||||
return;
|
||||
}
|
||||
|
||||
if (aStrategy == eUseProxyIfNeeded &&
|
||||
(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
aRv = NS_MutateURI(new nsStandardURL::Mutator())
|
||||
.SetSpec(NS_ConvertUTF16toUTF8(aHref))
|
||||
.Finalize(mStdURL);
|
||||
mURLProxy = nullptr;
|
||||
UpdateURLSearchParams();
|
||||
return;
|
||||
}
|
||||
|
||||
mStdURL = nullptr;
|
||||
// fallback to using a main thread url proxy
|
||||
if (mURLProxy) {
|
||||
RefPtr<SetterRunnable> runnable =
|
||||
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterHref, aHref,
|
||||
mURLProxy);
|
||||
|
||||
runnable->Dispatch(aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateURLSearchParams();
|
||||
return;
|
||||
}
|
||||
|
||||
// create the proxy now
|
||||
RefPtr<ConstructorRunnable> runnable =
|
||||
new ConstructorRunnable(mWorkerPrivate, aHref, Optional<nsAString>());
|
||||
runnable->Dispatch(Terminating, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
mURLProxy = runnable->GetURLProxy(aRv);
|
||||
|
||||
nsCOMPtr<nsIURI> uri = runnable->GetURI(aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetURI(uri.forget());
|
||||
UpdateURLSearchParams();
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const
|
||||
{
|
||||
if (mStdURL) {
|
||||
nsContentUtils::GetUTFOrigin(mStdURL, aOrigin);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
RefPtr<OriginGetterRunnable> runnable =
|
||||
new OriginGetterRunnable(mWorkerPrivate, aOrigin, mURLProxy);
|
||||
new OriginGetterRunnable(mWorkerPrivate, aOrigin, GetURI());
|
||||
|
||||
runnable->Dispatch(aRv);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::GetProtocol(nsAString& aProtocol) const
|
||||
{
|
||||
aProtocol.Truncate();
|
||||
nsAutoCString protocol;
|
||||
if (mStdURL) {
|
||||
if (NS_SUCCEEDED(mStdURL->GetScheme(protocol))) {
|
||||
CopyASCIItoUTF16(protocol, aProtocol);
|
||||
aProtocol.Append(char16_t(':'));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->GetProtocol(aProtocol);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv)
|
||||
{
|
||||
@ -645,289 +523,19 @@ URLWorker::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv)
|
||||
FindCharInReadable(':', iter, end);
|
||||
NS_ConvertUTF16toUTF8 scheme(Substring(start, iter));
|
||||
|
||||
// If we are using nsStandardURL on the owning thread, we can continue only if
|
||||
// the scheme is http or https.
|
||||
if (mStdURL &&
|
||||
(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))) {
|
||||
Unused << NS_MutateURI(mStdURL)
|
||||
.SetScheme(scheme)
|
||||
.Finalize(mStdURL);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we are using mStandardURL but the new scheme is not http nor https, we
|
||||
// have to migrate to the URL proxy.
|
||||
if (mStdURL) {
|
||||
nsAutoCString href;
|
||||
nsresult rv = mStdURL->GetSpec(href);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetHrefInternal(NS_ConvertUTF8toUTF16(href), eAlwaysUseProxy, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We want a proxy here.
|
||||
MOZ_ASSERT(!mStdURL);
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
|
||||
// Now we can restart setting the protocol.
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
RefPtr<SetterRunnable> runnable =
|
||||
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterProtocol,
|
||||
aProtocol, mURLProxy);
|
||||
|
||||
RefPtr<ProtocolSetterRunnable> runnable =
|
||||
new ProtocolSetterRunnable(mWorkerPrivate, scheme, GetURI());
|
||||
runnable->Dispatch(aRv);
|
||||
|
||||
MOZ_ASSERT(!runnable->Failed());
|
||||
}
|
||||
|
||||
#define STDURL_GETTER(value, method) \
|
||||
if (mStdURL) { \
|
||||
value.Truncate(); \
|
||||
nsAutoCString tmp; \
|
||||
nsresult rv = mStdURL->method(tmp); \
|
||||
if (NS_SUCCEEDED(rv)) { \
|
||||
CopyUTF8toUTF16(tmp, value); \
|
||||
} \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define STDURL_SETTER(value, method) \
|
||||
if (mStdURL) { \
|
||||
Unused << NS_MutateURI(mStdURL) \
|
||||
.method(NS_ConvertUTF16toUTF8(value)) \
|
||||
.Finalize(mStdURL); \
|
||||
return; \
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::GetUsername(nsAString& aUsername) const
|
||||
{
|
||||
STDURL_GETTER(aUsername, GetUsername);
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->GetUsername(aUsername);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::SetUsername(const nsAString& aUsername)
|
||||
{
|
||||
STDURL_SETTER(aUsername, SetUsername);
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->SetUsername(aUsername);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::GetPassword(nsAString& aPassword) const
|
||||
{
|
||||
STDURL_GETTER(aPassword, GetPassword);
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->GetPassword(aPassword);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::SetPassword(const nsAString& aPassword)
|
||||
{
|
||||
STDURL_SETTER(aPassword, SetPassword);
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->SetPassword(aPassword);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::GetHost(nsAString& aHost) const
|
||||
{
|
||||
STDURL_GETTER(aHost, GetHostPort);
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->GetHost(aHost);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::SetHost(const nsAString& aHost)
|
||||
{
|
||||
STDURL_SETTER(aHost, SetHostPort);
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->SetHost(aHost);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::GetHostname(nsAString& aHostname) const
|
||||
{
|
||||
aHostname.Truncate();
|
||||
if (mStdURL) {
|
||||
nsresult rv = nsContentUtils::GetHostOrIPv6WithBrackets(mStdURL, aHostname);
|
||||
if (NS_FAILED(rv)) {
|
||||
aHostname.Truncate();
|
||||
}
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->GetHostname(aHostname);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::SetHostname(const nsAString& aHostname)
|
||||
{
|
||||
STDURL_SETTER(aHostname, SetHost);
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->SetHostname(aHostname);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::GetPort(nsAString& aPort) const
|
||||
{
|
||||
aPort.Truncate();
|
||||
|
||||
if (mStdURL) {
|
||||
int32_t port;
|
||||
nsresult rv = mStdURL->GetPort(&port);
|
||||
if (NS_SUCCEEDED(rv) && port != -1) {
|
||||
nsAutoString portStr;
|
||||
portStr.AppendInt(port, 10);
|
||||
aPort.Assign(portStr);
|
||||
}
|
||||
nsCOMPtr<nsIURI> uri = runnable->GetRetval();
|
||||
if (NS_WARN_IF(!uri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->GetPort(aPort);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::SetPort(const nsAString& aPort)
|
||||
{
|
||||
if (mStdURL) {
|
||||
nsresult rv;
|
||||
nsAutoString portStr(aPort);
|
||||
int32_t port = -1;
|
||||
|
||||
// nsIURI uses -1 as default value.
|
||||
if (!portStr.IsEmpty()) {
|
||||
port = portStr.ToInteger(&rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Unused << NS_MutateURI(mStdURL)
|
||||
.SetPort(port)
|
||||
.Finalize(mStdURL);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->SetPort(aPort);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::GetPathname(nsAString& aPathname) const
|
||||
{
|
||||
aPathname.Truncate();
|
||||
|
||||
if (mStdURL) {
|
||||
nsAutoCString file;
|
||||
nsresult rv = mStdURL->GetFilePath(file);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
CopyUTF8toUTF16(file, aPathname);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->GetPathname(aPathname);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::SetPathname(const nsAString& aPathname)
|
||||
{
|
||||
STDURL_SETTER(aPathname, SetFilePath);
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->SetPathname(aPathname);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::GetSearch(nsAString& aSearch) const
|
||||
{
|
||||
aSearch.Truncate();
|
||||
|
||||
if (mStdURL) {
|
||||
nsAutoCString search;
|
||||
nsresult rv;
|
||||
|
||||
rv = mStdURL->GetQuery(search);
|
||||
if (NS_SUCCEEDED(rv) && !search.IsEmpty()) {
|
||||
aSearch.Assign(u'?');
|
||||
AppendUTF8toUTF16(search, aSearch);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->GetSearch(aSearch);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::GetHash(nsAString& aHash) const
|
||||
{
|
||||
aHash.Truncate();
|
||||
if (mStdURL) {
|
||||
nsAutoCString ref;
|
||||
nsresult rv = mStdURL->GetRef(ref);
|
||||
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
|
||||
aHash.Assign(char16_t('#'));
|
||||
AppendUTF8toUTF16(ref, aHash);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->GetHash(aHash);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::SetHash(const nsAString& aHash)
|
||||
{
|
||||
STDURL_SETTER(aHash, SetRef);
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->SetHash(aHash);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::SetSearchInternal(const nsAString& aSearch)
|
||||
{
|
||||
if (mStdURL) {
|
||||
// URLMainThread ignores failures here.
|
||||
Unused << NS_MutateURI(mStdURL)
|
||||
.SetQuery(NS_ConvertUTF16toUTF8(aSearch))
|
||||
.Finalize(mStdURL);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mURLProxy);
|
||||
mURLProxy->URL()->SetSearch(aSearch);
|
||||
}
|
||||
|
||||
void
|
||||
URLWorker::UpdateURLSearchParams()
|
||||
{
|
||||
if (mSearchParams) {
|
||||
nsAutoString search;
|
||||
GetSearch(search);
|
||||
mSearchParams->ParseInput(NS_ConvertUTF16toUTF8(Substring(search, 1)));
|
||||
}
|
||||
SetURI(uri.forget());
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -24,8 +24,6 @@ class WorkerPrivate;
|
||||
class URLWorker final : public URL
|
||||
{
|
||||
public:
|
||||
class URLProxy;
|
||||
|
||||
static already_AddRefed<URLWorker>
|
||||
Constructor(const GlobalObject& aGlobal, const nsAString& aURL,
|
||||
const Optional<nsAString>& aBase, ErrorResult& aRv);
|
||||
@ -52,87 +50,19 @@ public:
|
||||
Init(const nsAString& aURL, const Optional<nsAString>& aBase,
|
||||
ErrorResult& aRv);
|
||||
|
||||
virtual void
|
||||
GetHref(nsAString& aHref) const override;
|
||||
|
||||
virtual void
|
||||
SetHref(const nsAString& aHref, ErrorResult& aRv) override;
|
||||
|
||||
virtual void
|
||||
GetOrigin(nsAString& aOrigin, ErrorResult& aRv) const override;
|
||||
|
||||
virtual void
|
||||
GetProtocol(nsAString& aProtocol) const override;
|
||||
|
||||
virtual void
|
||||
SetProtocol(const nsAString& aProtocol, ErrorResult& aRv) override;
|
||||
|
||||
virtual void
|
||||
GetUsername(nsAString& aUsername) const override;
|
||||
|
||||
virtual void
|
||||
SetUsername(const nsAString& aUsername) override;
|
||||
|
||||
virtual void
|
||||
GetPassword(nsAString& aPassword) const override;
|
||||
|
||||
virtual void
|
||||
SetPassword(const nsAString& aPassword) override;
|
||||
|
||||
virtual void
|
||||
GetHost(nsAString& aHost) const override;
|
||||
|
||||
virtual void
|
||||
SetHost(const nsAString& aHost) override;
|
||||
|
||||
virtual void
|
||||
GetHostname(nsAString& aHostname) const override;
|
||||
|
||||
virtual void
|
||||
SetHostname(const nsAString& aHostname) override;
|
||||
|
||||
virtual void
|
||||
GetPort(nsAString& aPort) const override;
|
||||
|
||||
virtual void
|
||||
SetPort(const nsAString& aPort) override;
|
||||
|
||||
virtual void
|
||||
GetPathname(nsAString& aPathname) const override;
|
||||
|
||||
virtual void
|
||||
SetPathname(const nsAString& aPathname) override;
|
||||
|
||||
virtual void
|
||||
GetSearch(nsAString& aSearch) const override;
|
||||
|
||||
virtual void
|
||||
GetHash(nsAString& aHost) const override;
|
||||
|
||||
virtual void
|
||||
SetHash(const nsAString& aHash) override;
|
||||
|
||||
virtual void UpdateURLSearchParams() override;
|
||||
|
||||
virtual void
|
||||
SetSearchInternal(const nsAString& aSearch) override;
|
||||
|
||||
private:
|
||||
~URLWorker();
|
||||
|
||||
enum Strategy {
|
||||
eAlwaysUseProxy,
|
||||
eUseProxyIfNeeded,
|
||||
};
|
||||
|
||||
void
|
||||
SetHrefInternal(const nsAString& aHref,
|
||||
Strategy aStrategy,
|
||||
ErrorResult& aRv);
|
||||
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
RefPtr<URLProxy> mURLProxy;
|
||||
nsCOMPtr<nsIURI> mStdURL;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -6,7 +6,6 @@
|
||||
* The origins of this IDL file are
|
||||
* http://url.spec.whatwg.org/#api
|
||||
* http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking
|
||||
* http://dev.w3.org/2011/webrtc/editor/getusermedia.html#url
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
@ -45,8 +44,6 @@ partial interface URL {
|
||||
[Throws]
|
||||
static DOMString createObjectURL(Blob blob);
|
||||
[Throws]
|
||||
static DOMString createObjectURL(MediaStream stream);
|
||||
[Throws]
|
||||
static void revokeObjectURL(DOMString url);
|
||||
[ChromeOnly, Throws]
|
||||
static boolean isValidURL(DOMString url);
|
||||
|
@ -1553,6 +1553,7 @@ public:
|
||||
static void ShutDown();
|
||||
|
||||
static bool HasSSE2();
|
||||
static bool HasSSE4();
|
||||
|
||||
/**
|
||||
* Returns false if any of the following are true:
|
||||
|
@ -124,7 +124,7 @@ struct BaseRect {
|
||||
result.y = std::max<T>(y, aRect.y);
|
||||
result.width = std::min<T>(x - result.x + width, aRect.x - result.x + aRect.width);
|
||||
result.height = std::min<T>(y - result.y + height, aRect.y - result.y + aRect.height);
|
||||
if (result.width < 0 || result.height < 0) {
|
||||
if (result.width <= 0 || result.height <= 0) {
|
||||
result.SizeTo(0, 0);
|
||||
}
|
||||
return result;
|
||||
|
@ -87,7 +87,8 @@ enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 };
|
||||
#ifdef HAVE_CPUID_H
|
||||
|
||||
#if !(defined(__SSE2__) || defined(_M_X64) || \
|
||||
(defined(_M_IX86_FP) && _M_IX86_FP >= 2))
|
||||
(defined(_M_IX86_FP) && _M_IX86_FP >= 2)) || \
|
||||
!defined(__SSE4__)
|
||||
// cpuid.h is available on gcc 4.3 and higher on i386 and x86_64
|
||||
#include <cpuid.h>
|
||||
|
||||
@ -282,6 +283,29 @@ Factory::HasSSE2()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
Factory::HasSSE4()
|
||||
{
|
||||
#if defined(__SSE4__)
|
||||
// gcc with -msse2 (default on OSX and x86-64)
|
||||
// cl.exe with -arch:SSE2 (default on x64 compiler)
|
||||
return true;
|
||||
#elif defined(HAVE_CPU_DETECTION)
|
||||
static enum {
|
||||
UNINITIALIZED,
|
||||
NO_SSE4,
|
||||
HAS_SSE4
|
||||
} sDetectionState = UNINITIALIZED;
|
||||
|
||||
if (sDetectionState == UNINITIALIZED) {
|
||||
sDetectionState = HasCPUIDBit(1u, ecx, (1u << 19)) ? HAS_SSE4 : NO_SSE4;
|
||||
}
|
||||
return sDetectionState == HAS_SSE4;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// If the size is "reasonable", we want gfxCriticalError to assert, so
|
||||
// this is the option set up for it.
|
||||
inline int LoggerOptionsBasedOnSize(const IntSize& aSize)
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "APZCTreeManager.h"
|
||||
#include "AsyncPanZoomController.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/layers/APZThreadUtils.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/layers/LayerMetricsWrapper.h"
|
||||
@ -52,6 +53,11 @@ APZSampler::SetWebRenderWindowId(const wr::WindowId& aWindowId)
|
||||
mWindowId = Some(aWindowId);
|
||||
if (!sWindowIdMap) {
|
||||
sWindowIdMap = new std::unordered_map<uint64_t, APZSampler*>();
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction("APZUpdater::ClearOnShutdown", [] {
|
||||
ClearOnShutdown(&sWindowIdMap);
|
||||
}
|
||||
));
|
||||
}
|
||||
(*sWindowIdMap)[wr::AsUint64(aWindowId)] = this;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "APZCTreeManager.h"
|
||||
#include "AsyncPanZoomController.h"
|
||||
#include "base/task.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/layers/APZThreadUtils.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/layers/SynchronousTask.h"
|
||||
@ -59,6 +60,11 @@ APZUpdater::SetWebRenderWindowId(const wr::WindowId& aWindowId)
|
||||
mWindowId = Some(aWindowId);
|
||||
if (!sWindowIdMap) {
|
||||
sWindowIdMap = new std::unordered_map<uint64_t, APZUpdater*>();
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableFunction("APZUpdater::ClearOnShutdown", [] {
|
||||
ClearOnShutdown(&sWindowIdMap);
|
||||
}
|
||||
));
|
||||
}
|
||||
(*sWindowIdMap)[wr::AsUint64(aWindowId)] = this;
|
||||
}
|
||||
|
172
gfx/src/nsRect.h
172
gfx/src/nsRect.h
@ -13,12 +13,17 @@
|
||||
#include <algorithm> // for min/max
|
||||
#include "mozilla/Likely.h" // for MOZ_UNLIKELY
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "nsCoord.h" // for nscoord, etc
|
||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "nsPoint.h" // for nsIntPoint, nsPoint
|
||||
#include "nsMargin.h" // for nsIntMargin, nsMargin
|
||||
#include "nsSize.h" // for IntSize, nsSize
|
||||
#include "nscore.h" // for NS_BUILD_REFCNT_LOGGING
|
||||
#if !defined(ANDROID) && (defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
|
||||
#include "smmintrin.h"
|
||||
#endif
|
||||
|
||||
typedef mozilla::gfx::IntRect nsIntRect;
|
||||
|
||||
@ -120,6 +125,79 @@ struct nsRect :
|
||||
{
|
||||
*this = aRect1.Union(aRect2);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
// Only MSVC supports inlining intrinsics for archs you're not compiling for.
|
||||
MOZ_MUST_USE nsRect Intersect(const nsRect& aRect) const
|
||||
{
|
||||
nsRect result;
|
||||
if (mozilla::gfx::Factory::HasSSE4()) {
|
||||
__m128i rect1 = _mm_loadu_si128((__m128i*)&aRect); // x1, y1, w1, h1
|
||||
__m128i rect2 = _mm_loadu_si128((__m128i*)this); // x2, y2, w2, h2
|
||||
|
||||
__m128i resultRect = _mm_max_epi32(rect1, rect2); // xr, yr, zz, zz
|
||||
|
||||
|
||||
// result.width = std::min<int32_t>(x - result.x + width, aRect.x - result.x + aRect.width);
|
||||
// result.height = std::min<int32_t>(y - result.y + height, aRect.y - result.y + aRect.height);
|
||||
__m128i widthheight = _mm_min_epi32(_mm_add_epi32(_mm_sub_epi32(rect1, resultRect), _mm_srli_si128(rect1, 8)),
|
||||
_mm_add_epi32(_mm_sub_epi32(rect2, resultRect), _mm_srli_si128(rect2, 8))); // w, h, zz, zz
|
||||
widthheight = _mm_slli_si128(widthheight, 8); // 00, 00, wr, hr
|
||||
|
||||
resultRect = _mm_blend_epi16(resultRect, widthheight, 0xF0); // xr, yr, wr, hr
|
||||
|
||||
if ((_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpgt_epi32(resultRect, _mm_setzero_si128()))) & 0xC) != 0xC) {
|
||||
// It's potentially more efficient to store all 0s. But the non SSE4 code leaves x/y intact
|
||||
// so let's do the same here.
|
||||
resultRect = _mm_and_si128(resultRect, _mm_set_epi32(0, 0, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
_mm_storeu_si128((__m128i*)&result, resultRect);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
result.x = std::max<int32_t>(x, aRect.x);
|
||||
result.y = std::max<int32_t>(y, aRect.y);
|
||||
result.width = std::min<int32_t>(x - result.x + width, aRect.x - result.x + aRect.width);
|
||||
result.height = std::min<int32_t>(y - result.y + height, aRect.y - result.y + aRect.height);
|
||||
if (result.width <= 0 || result.height <= 0) {
|
||||
result.SizeTo(0, 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IntersectRect(const nsRect& aRect1, const nsRect& aRect2)
|
||||
{
|
||||
if (mozilla::gfx::Factory::HasSSE4()) {
|
||||
__m128i rect1 = _mm_loadu_si128((__m128i*)&aRect1); // x1, y1, w1, h1
|
||||
__m128i rect2 = _mm_loadu_si128((__m128i*)&aRect2); // x2, y2, w2, h2
|
||||
|
||||
__m128i resultRect = _mm_max_epi32(rect1, rect2); // xr, yr, zz, zz
|
||||
// result.width = std::min<int32_t>(x - result.x + width, aRect.x - result.x + aRect.width);
|
||||
// result.height = std::min<int32_t>(y - result.y + height, aRect.y - result.y + aRect.height);
|
||||
__m128i widthheight = _mm_min_epi32(_mm_add_epi32(_mm_sub_epi32(rect1, resultRect), _mm_srli_si128(rect1, 8)),
|
||||
_mm_add_epi32(_mm_sub_epi32(rect2, resultRect), _mm_srli_si128(rect2, 8))); // w, h, zz, zz
|
||||
widthheight = _mm_slli_si128(widthheight, 8); // 00, 00, wr, hr
|
||||
|
||||
resultRect = _mm_blend_epi16(resultRect, widthheight, 0xF0); // xr, yr, wr, hr
|
||||
|
||||
if ((_mm_movemask_ps(_mm_castsi128_ps(_mm_cmpgt_epi32(resultRect, _mm_setzero_si128()))) & 0xC) != 0xC) {
|
||||
// It's potentially more efficient to store all 0s. But the non SSE4 code leaves x/y intact
|
||||
// so let's do the same here.
|
||||
resultRect = _mm_and_si128(resultRect, _mm_set_epi32(0, 0, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
_mm_storeu_si128((__m128i*)this, resultRect);
|
||||
return false;
|
||||
}
|
||||
|
||||
_mm_storeu_si128((__m128i*)this, resultRect);
|
||||
|
||||
return true;
|
||||
}
|
||||
*static_cast<nsRect*>(this) = aRect1.Intersect(aRect2);
|
||||
return !IsEmpty();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void SaturatingUnionRect(const nsRect& aRect1, const nsRect& aRect2)
|
||||
@ -214,20 +292,74 @@ nsRect::ScaleToOtherAppUnitsRoundIn(int32_t aFromAPP, int32_t aToAPP) const
|
||||
return rect;
|
||||
}
|
||||
|
||||
#if !defined(ANDROID) && (defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
|
||||
// Life would be so much better if we had SSE4 here.
|
||||
static MOZ_ALWAYS_INLINE __m128i floor_ps2epi32(__m128 x)
|
||||
{
|
||||
__m128 one = _mm_set_ps(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
__m128 t = _mm_cvtepi32_ps(_mm_cvttps_epi32(x));
|
||||
__m128 r = _mm_sub_ps(t, _mm_and_ps(_mm_cmplt_ps(x, t), one));
|
||||
|
||||
return _mm_cvttps_epi32(r);
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE __m128i ceil_ps2epi32(__m128 x)
|
||||
{
|
||||
__m128 t = _mm_sub_ps(_mm_setzero_ps(), x);
|
||||
__m128i r = _mm_sub_epi32(_mm_setzero_si128(), floor_ps2epi32(t));
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
// scale the rect but round to preserve centers
|
||||
inline mozilla::gfx::IntRect
|
||||
nsRect::ScaleToNearestPixels(float aXScale, float aYScale,
|
||||
nscoord aAppUnitsPerPixel) const
|
||||
{
|
||||
mozilla::gfx::IntRect rect;
|
||||
rect.SetNonEmptyBox(NSToIntRoundUp(NSAppUnitsToDoublePixels(x,
|
||||
// Android x86 builds have bindgen issues.
|
||||
#if !defined(ANDROID) && (defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
|
||||
__m128 appUnitsPacked = _mm_set_ps(aAppUnitsPerPixel, aAppUnitsPerPixel, aAppUnitsPerPixel, aAppUnitsPerPixel);
|
||||
__m128 scalesPacked = _mm_set_ps(aYScale, aXScale, aYScale, aXScale);
|
||||
__m128 biasesPacked = _mm_set_ps(0.5f, 0.5f, 0.5f, 0.5f);
|
||||
|
||||
__m128i rectPacked = _mm_loadu_si128((__m128i*)this);
|
||||
__m128i topLeft = _mm_slli_si128(rectPacked, 8);
|
||||
|
||||
rectPacked = _mm_add_epi32(rectPacked, topLeft); // X, Y, XMost(), YMost()
|
||||
|
||||
__m128 rectFloat = _mm_cvtepi32_ps(rectPacked);
|
||||
|
||||
// Scale, i.e. ([ x y xmost ymost ] / aAppUnitsPerPixel) * [ aXScale aYScale aXScale aYScale ]
|
||||
rectFloat = _mm_mul_ps(_mm_div_ps(rectFloat, appUnitsPacked), scalesPacked);
|
||||
|
||||
// Floor
|
||||
// Executed with bias and roundmode down, since round-nearest rounds 0.5 downward half the time.
|
||||
rectFloat = _mm_add_ps(rectFloat, biasesPacked);
|
||||
rectPacked = floor_ps2epi32(rectFloat);
|
||||
|
||||
topLeft = _mm_slli_si128(rectPacked, 8);
|
||||
rectPacked = _mm_sub_epi32(rectPacked, topLeft); // X, Y, Width, Height
|
||||
|
||||
// Avoid negative width/height due to overflow.
|
||||
__m128i mask = _mm_or_si128(_mm_cmpgt_epi32(rectPacked, _mm_setzero_si128()),
|
||||
_mm_set_epi32(0, 0, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
// Mask will now contain [ 0xFFFFFFFF 0xFFFFFFFF (width <= 0 ? 0 : 0xFFFFFFFF) (height <= 0 ? 0 : 0xFFFFFFFF) ]
|
||||
rectPacked = _mm_and_si128(rectPacked, mask);
|
||||
|
||||
_mm_storeu_si128((__m128i*)&rect, rectPacked);
|
||||
#else
|
||||
rect.SetNonEmptyBox(NSToIntRoundUp(NSAppUnitsToFloatPixels(x,
|
||||
aAppUnitsPerPixel) * aXScale),
|
||||
NSToIntRoundUp(NSAppUnitsToDoublePixels(y,
|
||||
NSToIntRoundUp(NSAppUnitsToFloatPixels(y,
|
||||
aAppUnitsPerPixel) * aYScale),
|
||||
NSToIntRoundUp(NSAppUnitsToDoublePixels(XMost(),
|
||||
NSToIntRoundUp(NSAppUnitsToFloatPixels(XMost(),
|
||||
aAppUnitsPerPixel) * aXScale),
|
||||
NSToIntRoundUp(NSAppUnitsToDoublePixels(YMost(),
|
||||
NSToIntRoundUp(NSAppUnitsToFloatPixels(YMost(),
|
||||
aAppUnitsPerPixel) * aYScale));
|
||||
#endif
|
||||
return rect;
|
||||
}
|
||||
|
||||
@ -237,6 +369,37 @@ nsRect::ScaleToOutsidePixels(float aXScale, float aYScale,
|
||||
nscoord aAppUnitsPerPixel) const
|
||||
{
|
||||
mozilla::gfx::IntRect rect;
|
||||
// Android x86 builds have bindgen issues.
|
||||
#if !defined(ANDROID) && (defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
|
||||
__m128 appUnitsPacked = _mm_set_ps(aAppUnitsPerPixel, aAppUnitsPerPixel, aAppUnitsPerPixel, aAppUnitsPerPixel);
|
||||
__m128 scalesPacked = _mm_set_ps(aYScale, aXScale, aYScale, aXScale);
|
||||
|
||||
__m128i rectPacked = _mm_loadu_si128((__m128i*)this); // x, y, w, h
|
||||
__m128i topLeft = _mm_slli_si128(rectPacked, 8); // 0, 0, x, y
|
||||
|
||||
rectPacked = _mm_add_epi32(rectPacked, topLeft); // X, Y, XMost(), YMost()
|
||||
|
||||
__m128 rectFloat = _mm_cvtepi32_ps(rectPacked);
|
||||
|
||||
// Scale i.e. ([ x y xmost ymost ] / aAppUnitsPerPixel) * [ aXScale aYScale aXScale aYScale ]
|
||||
rectFloat = _mm_mul_ps(_mm_div_ps(rectFloat, appUnitsPacked), scalesPacked);
|
||||
rectPacked = ceil_ps2epi32(rectFloat); // xx, xx, XMost(), YMost()
|
||||
__m128i tmp = floor_ps2epi32(rectFloat); // x, y, xx, xx
|
||||
|
||||
// _mm_move_sd is 1 cycle method of getting the blending we want.
|
||||
rectPacked = _mm_castpd_si128(_mm_move_sd(_mm_castsi128_pd(rectPacked), _mm_castsi128_pd(tmp))); // x, y, XMost(), YMost()
|
||||
|
||||
topLeft = _mm_slli_si128(rectPacked, 8); // 0, 0, r.x, r.y
|
||||
rectPacked = _mm_sub_epi32(rectPacked, topLeft); // r.x, r.y, r.w, r.h
|
||||
|
||||
// Avoid negative width/height due to overflow.
|
||||
__m128i mask = _mm_or_si128(_mm_cmpgt_epi32(rectPacked, _mm_setzero_si128()),
|
||||
_mm_set_epi32(0, 0, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
// Mask will now contain [ 0xFFFFFFFF 0xFFFFFFFF (width <= 0 ? 0 : 0xFFFFFFFF) (height <= 0 ? 0 : 0xFFFFFFFF) ]
|
||||
rectPacked = _mm_and_si128(rectPacked, mask);
|
||||
|
||||
_mm_storeu_si128((__m128i*)&rect, rectPacked);
|
||||
#else
|
||||
rect.SetNonEmptyBox(NSToIntFloor(NSAppUnitsToFloatPixels(x,
|
||||
float(aAppUnitsPerPixel)) * aXScale),
|
||||
NSToIntFloor(NSAppUnitsToFloatPixels(y,
|
||||
@ -245,6 +408,7 @@ nsRect::ScaleToOutsidePixels(float aXScale, float aYScale,
|
||||
float(aAppUnitsPerPixel)) * aXScale),
|
||||
NSToIntCeil(NSAppUnitsToFloatPixels(YMost(),
|
||||
float(aAppUnitsPerPixel)) * aYScale));
|
||||
#endif
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ AnimationFrameBuffer::AnimationFrameBuffer()
|
||||
, mInsertIndex(0)
|
||||
, mGetIndex(0)
|
||||
, mSizeKnown(false)
|
||||
, mRedecodeError(false)
|
||||
{ }
|
||||
|
||||
void
|
||||
@ -71,7 +72,16 @@ AnimationFrameBuffer::Insert(RawAccessFrameRef&& aFrame)
|
||||
// and we did not keep all of the frames. Replace whatever is there
|
||||
// (probably an empty frame) with the new frame.
|
||||
MOZ_ASSERT(MayDiscard());
|
||||
MOZ_ASSERT(mInsertIndex < mFrames.Length());
|
||||
|
||||
// The first decode produced fewer frames than the redecodes, presumably
|
||||
// because it hit an out-of-memory error which later attempts avoided. Just
|
||||
// stop the animation because we can't tell the image that we have more
|
||||
// frames now.
|
||||
if (mInsertIndex >= mFrames.Length()) {
|
||||
mRedecodeError = true;
|
||||
mPending = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mInsertIndex > 0) {
|
||||
MOZ_ASSERT(!mFrames[mInsertIndex]);
|
||||
@ -127,9 +137,23 @@ AnimationFrameBuffer::Insert(RawAccessFrameRef&& aFrame)
|
||||
bool
|
||||
AnimationFrameBuffer::MarkComplete()
|
||||
{
|
||||
// We may have stopped decoding at a different point in the animation than we
|
||||
// did previously. That means the decoder likely hit a new error, e.g. OOM.
|
||||
// This will prevent us from advancing as well, because we are missing the
|
||||
// required frames to blend.
|
||||
//
|
||||
// XXX(aosmond): In an ideal world, we would be generating full frames, and
|
||||
// the consumer of our data doesn't care about our internal state. It simply
|
||||
// knows about the first frame, the current frame, and how long to display the
|
||||
// current frame.
|
||||
if (NS_WARN_IF(mInsertIndex != mFrames.Length())) {
|
||||
MOZ_ASSERT(mSizeKnown);
|
||||
mRedecodeError = true;
|
||||
mPending = 0;
|
||||
}
|
||||
|
||||
// We reached the end of the animation, the next frame we get, if we get
|
||||
// another, will be the first frame again.
|
||||
MOZ_ASSERT(mInsertIndex == mFrames.Length());
|
||||
mInsertIndex = 0;
|
||||
|
||||
// Since we only request advancing when we want to resume at a certain point
|
||||
@ -231,7 +255,7 @@ AnimationFrameBuffer::AdvanceInternal()
|
||||
}
|
||||
}
|
||||
|
||||
if (!mSizeKnown || MayDiscard()) {
|
||||
if (!mRedecodeError && (!mSizeKnown || MayDiscard())) {
|
||||
// Calculate how many frames we have requested ahead of the current frame.
|
||||
size_t buffered = mPending;
|
||||
if (mGetIndex > mInsertIndex) {
|
||||
@ -276,13 +300,6 @@ AnimationFrameBuffer::Reset()
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we are over the threshold, then we know we will have missing frames in
|
||||
// our buffer. The easiest thing to do is to drop everything but the first
|
||||
// frame and go back to the initial state.
|
||||
bool restartDecoder = mPending == 0;
|
||||
mInsertIndex = 0;
|
||||
mPending = 2 * mBatch;
|
||||
|
||||
// Discard all frames besides the first, because the decoder always expects
|
||||
// that when it re-inserts a frame, it is not present. (It doesn't re-insert
|
||||
// the first frame.)
|
||||
@ -290,6 +307,16 @@ AnimationFrameBuffer::Reset()
|
||||
RawAccessFrameRef discard = Move(mFrames[i]);
|
||||
}
|
||||
|
||||
mInsertIndex = 0;
|
||||
|
||||
// If we hit an error after redecoding, we never want to restart decoding.
|
||||
if (mRedecodeError) {
|
||||
MOZ_ASSERT(mPending == 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool restartDecoder = mPending == 0;
|
||||
mPending = 2 * mBatch;
|
||||
return restartDecoder;
|
||||
}
|
||||
|
||||
|
@ -129,6 +129,12 @@ public:
|
||||
*/
|
||||
bool SizeKnown() const { return mSizeKnown; }
|
||||
|
||||
/**
|
||||
* @returns True if encountered an error during redecode which should cause
|
||||
* the caller to stop inserting frames.
|
||||
*/
|
||||
bool HasRedecodeError() const { return mRedecodeError; }
|
||||
|
||||
/**
|
||||
* @returns The current frame index we have advanced to.
|
||||
*/
|
||||
@ -187,6 +193,9 @@ private:
|
||||
|
||||
// True if the total number of frames is known.
|
||||
bool mSizeKnown;
|
||||
|
||||
// True if we encountered an error while redecoding.
|
||||
bool mRedecodeError;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
|
@ -224,13 +224,17 @@ AnimationSurfaceProvider::Run()
|
||||
FinishDecoding();
|
||||
|
||||
// Even if it is the last frame, we may not have enough frames buffered
|
||||
// ahead of the current.
|
||||
if (continueDecoding) {
|
||||
MOZ_ASSERT(mDecoder);
|
||||
continue;
|
||||
// ahead of the current. If we are shutting down, we want to ensure we
|
||||
// release the thread as soon as possible. The animation may advance even
|
||||
// during shutdown, which keeps us decoding, and thus blocking the decode
|
||||
// pool during teardown.
|
||||
if (!mDecoder || !continueDecoding ||
|
||||
DecodePool::Singleton()->IsShuttingDown()) {
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
// Restart from the very beginning because the decoder was recreated.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Notify for the progress we've made so far.
|
||||
@ -245,9 +249,13 @@ AnimationSurfaceProvider::Run()
|
||||
}
|
||||
|
||||
// There's new output available - a new frame! Grab it. If we don't need any
|
||||
// more for the moment we can break out of the loop.
|
||||
// more for the moment we can break out of the loop. If we are shutting
|
||||
// down, we want to ensure we release the thread as soon as possible. The
|
||||
// animation may advance even during shutdown, which keeps us decoding, and
|
||||
// thus blocking the decode pool during teardown.
|
||||
MOZ_ASSERT(result == LexerResult(Yield::OUTPUT_AVAILABLE));
|
||||
if (!CheckForNewFrameAtYield()) {
|
||||
if (!CheckForNewFrameAtYield() ||
|
||||
DecodePool::Singleton()->IsShuttingDown()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -294,10 +302,7 @@ AnimationSurfaceProvider::CheckForNewFrameAtYield()
|
||||
AnnounceSurfaceAvailable();
|
||||
}
|
||||
|
||||
// If we are shutting down, we want to ensure we release the thread as soon
|
||||
// as possible. The animation may advance even during shutdown, which keeps
|
||||
// us decoding, and thus blocking the decode pool during teardown.
|
||||
return continueDecoding && !DecodePool::Singleton()->IsShuttingDown();
|
||||
return continueDecoding;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -347,10 +352,7 @@ AnimationSurfaceProvider::CheckForNewFrameAtTerminalState()
|
||||
AnnounceSurfaceAvailable();
|
||||
}
|
||||
|
||||
// If we are shutting down, we want to ensure we release the thread as soon
|
||||
// as possible. The animation may advance even during shutdown, which keeps
|
||||
// us decoding, and thus blocking the decode pool during teardown.
|
||||
return continueDecoding && !DecodePool::Singleton()->IsShuttingDown();
|
||||
return continueDecoding;
|
||||
}
|
||||
|
||||
void
|
||||
@ -378,15 +380,15 @@ AnimationSurfaceProvider::FinishDecoding()
|
||||
NotifyDecodeComplete(WrapNotNull(mImage), WrapNotNull(mDecoder));
|
||||
}
|
||||
|
||||
// Destroy our decoder; we don't need it anymore.
|
||||
bool mayDiscard;
|
||||
// Determine if we need to recreate the decoder, in case we are discarding
|
||||
// frames and need to loop back to the beginning.
|
||||
bool recreateDecoder;
|
||||
{
|
||||
MutexAutoLock lock(mFramesMutex);
|
||||
mayDiscard = mFrames.MayDiscard();
|
||||
recreateDecoder = !mFrames.HasRedecodeError() && mFrames.MayDiscard();
|
||||
}
|
||||
|
||||
if (mayDiscard) {
|
||||
// Recreate the decoder so we can regenerate the frames again.
|
||||
if (recreateDecoder) {
|
||||
mDecoder = DecoderFactory::CloneAnimationDecoder(mDecoder);
|
||||
MOZ_ASSERT(mDecoder);
|
||||
} else {
|
||||
|
@ -143,6 +143,7 @@ TEST_F(ImageAnimationFrameBuffer, FinishUnderBatchAndThreshold)
|
||||
EXPECT_FALSE(keepDecoding);
|
||||
EXPECT_TRUE(buffer.SizeKnown());
|
||||
EXPECT_EQ(size_t(0), buffer.PendingDecode());
|
||||
EXPECT_FALSE(buffer.HasRedecodeError());
|
||||
}
|
||||
|
||||
EXPECT_FALSE(buffer.MayDiscard());
|
||||
@ -220,6 +221,7 @@ TEST_F(ImageAnimationFrameBuffer, FinishMultipleBatchesUnderThreshold)
|
||||
EXPECT_TRUE(buffer.SizeKnown());
|
||||
EXPECT_EQ(size_t(0), buffer.PendingDecode());
|
||||
EXPECT_EQ(size_t(5), frames.Length());
|
||||
EXPECT_FALSE(buffer.HasRedecodeError());
|
||||
|
||||
// Finish progressing through the animation.
|
||||
for ( ; i < frames.Length(); ++i) {
|
||||
@ -330,6 +332,7 @@ TEST_F(ImageAnimationFrameBuffer, MayDiscard)
|
||||
EXPECT_TRUE(buffer.SizeKnown());
|
||||
EXPECT_EQ(size_t(2), buffer.PendingDecode());
|
||||
EXPECT_EQ(size_t(10), frames.Length());
|
||||
EXPECT_FALSE(buffer.HasRedecodeError());
|
||||
|
||||
// Use remaining pending room. It shouldn't add new frames, only replace.
|
||||
do {
|
||||
@ -513,3 +516,159 @@ TEST_F(ImageAnimationFrameBuffer, StartAfterBeginningAndReset)
|
||||
EXPECT_EQ(size_t(0), buffer.PendingAdvance());
|
||||
}
|
||||
|
||||
TEST_F(ImageAnimationFrameBuffer, RedecodeMoreFrames)
|
||||
{
|
||||
const size_t kThreshold = 5;
|
||||
const size_t kBatch = 2;
|
||||
AnimationFrameBuffer buffer;
|
||||
buffer.Initialize(kThreshold, kBatch, 0);
|
||||
const auto& frames = buffer.Frames();
|
||||
|
||||
// Add frames until we exceed the threshold.
|
||||
bool keepDecoding;
|
||||
bool restartDecoder;
|
||||
size_t i = 0;
|
||||
do {
|
||||
keepDecoding = buffer.Insert(CreateEmptyFrame());
|
||||
EXPECT_TRUE(keepDecoding);
|
||||
if (i > 0) {
|
||||
restartDecoder = buffer.AdvanceTo(i);
|
||||
EXPECT_FALSE(restartDecoder);
|
||||
}
|
||||
++i;
|
||||
} while (!buffer.MayDiscard());
|
||||
|
||||
// Should have threshold + 1 frames, and still not complete.
|
||||
EXPECT_EQ(size_t(6), frames.Length());
|
||||
EXPECT_FALSE(buffer.SizeKnown());
|
||||
|
||||
// Now we lock in at 6 frames.
|
||||
keepDecoding = buffer.MarkComplete();
|
||||
EXPECT_TRUE(keepDecoding);
|
||||
EXPECT_TRUE(buffer.SizeKnown());
|
||||
EXPECT_FALSE(buffer.HasRedecodeError());
|
||||
|
||||
// Reinsert 6 frames first.
|
||||
i = 0;
|
||||
do {
|
||||
keepDecoding = buffer.Insert(CreateEmptyFrame());
|
||||
EXPECT_TRUE(keepDecoding);
|
||||
restartDecoder = buffer.AdvanceTo(i);
|
||||
EXPECT_FALSE(restartDecoder);
|
||||
++i;
|
||||
} while (i < 6);
|
||||
|
||||
// We should now encounter an error and shutdown further decodes.
|
||||
keepDecoding = buffer.Insert(CreateEmptyFrame());
|
||||
EXPECT_FALSE(keepDecoding);
|
||||
EXPECT_EQ(size_t(0), buffer.PendingDecode());
|
||||
EXPECT_TRUE(buffer.HasRedecodeError());
|
||||
}
|
||||
|
||||
TEST_F(ImageAnimationFrameBuffer, RedecodeFewerFrames)
|
||||
{
|
||||
const size_t kThreshold = 5;
|
||||
const size_t kBatch = 2;
|
||||
AnimationFrameBuffer buffer;
|
||||
buffer.Initialize(kThreshold, kBatch, 0);
|
||||
const auto& frames = buffer.Frames();
|
||||
|
||||
// Add frames until we exceed the threshold.
|
||||
bool keepDecoding;
|
||||
bool restartDecoder;
|
||||
size_t i = 0;
|
||||
do {
|
||||
keepDecoding = buffer.Insert(CreateEmptyFrame());
|
||||
EXPECT_TRUE(keepDecoding);
|
||||
if (i > 0) {
|
||||
restartDecoder = buffer.AdvanceTo(i);
|
||||
EXPECT_FALSE(restartDecoder);
|
||||
}
|
||||
++i;
|
||||
} while (!buffer.MayDiscard());
|
||||
|
||||
// Should have threshold + 1 frames, and still not complete.
|
||||
EXPECT_EQ(size_t(6), frames.Length());
|
||||
EXPECT_FALSE(buffer.SizeKnown());
|
||||
|
||||
// Now we lock in at 6 frames.
|
||||
keepDecoding = buffer.MarkComplete();
|
||||
EXPECT_TRUE(keepDecoding);
|
||||
EXPECT_TRUE(buffer.SizeKnown());
|
||||
EXPECT_FALSE(buffer.HasRedecodeError());
|
||||
|
||||
// Reinsert 5 frames before marking complete.
|
||||
i = 0;
|
||||
do {
|
||||
keepDecoding = buffer.Insert(CreateEmptyFrame());
|
||||
EXPECT_TRUE(keepDecoding);
|
||||
restartDecoder = buffer.AdvanceTo(i);
|
||||
EXPECT_FALSE(restartDecoder);
|
||||
++i;
|
||||
} while (i < 5);
|
||||
|
||||
// We should now encounter an error and shutdown further decodes.
|
||||
keepDecoding = buffer.MarkComplete();
|
||||
EXPECT_FALSE(keepDecoding);
|
||||
EXPECT_EQ(size_t(0), buffer.PendingDecode());
|
||||
EXPECT_TRUE(buffer.HasRedecodeError());
|
||||
}
|
||||
|
||||
TEST_F(ImageAnimationFrameBuffer, RedecodeFewerFramesAndBehindAdvancing)
|
||||
{
|
||||
const size_t kThreshold = 5;
|
||||
const size_t kBatch = 2;
|
||||
AnimationFrameBuffer buffer;
|
||||
buffer.Initialize(kThreshold, kBatch, 0);
|
||||
const auto& frames = buffer.Frames();
|
||||
|
||||
// Add frames until we exceed the threshold.
|
||||
bool keepDecoding;
|
||||
bool restartDecoder;
|
||||
size_t i = 0;
|
||||
do {
|
||||
keepDecoding = buffer.Insert(CreateEmptyFrame());
|
||||
EXPECT_TRUE(keepDecoding);
|
||||
if (i > 0) {
|
||||
restartDecoder = buffer.AdvanceTo(i);
|
||||
EXPECT_FALSE(restartDecoder);
|
||||
}
|
||||
++i;
|
||||
} while (!buffer.MayDiscard());
|
||||
|
||||
// Should have threshold + 1 frames, and still not complete.
|
||||
EXPECT_EQ(size_t(6), frames.Length());
|
||||
EXPECT_FALSE(buffer.SizeKnown());
|
||||
|
||||
// Now we lock in at 6 frames.
|
||||
keepDecoding = buffer.MarkComplete();
|
||||
EXPECT_TRUE(keepDecoding);
|
||||
EXPECT_TRUE(buffer.SizeKnown());
|
||||
EXPECT_FALSE(buffer.HasRedecodeError());
|
||||
|
||||
// Reinsert frames without advancing until we exhaust our pending space. This
|
||||
// should be less than the current buffer length by definition.
|
||||
i = 0;
|
||||
do {
|
||||
keepDecoding = buffer.Insert(CreateEmptyFrame());
|
||||
++i;
|
||||
} while (keepDecoding);
|
||||
|
||||
EXPECT_EQ(size_t(2), i);
|
||||
|
||||
// We should now encounter an error and shutdown further decodes.
|
||||
keepDecoding = buffer.MarkComplete();
|
||||
EXPECT_FALSE(keepDecoding);
|
||||
EXPECT_EQ(size_t(0), buffer.PendingDecode());
|
||||
EXPECT_TRUE(buffer.HasRedecodeError());
|
||||
|
||||
// We should however be able to continue advancing to the last decoded frame
|
||||
// without it requesting the decoder to restart.
|
||||
i = 0;
|
||||
do {
|
||||
restartDecoder = buffer.AdvanceTo(i);
|
||||
EXPECT_FALSE(restartDecoder);
|
||||
++i;
|
||||
} while (i < 2);
|
||||
}
|
||||
|
||||
|
@ -4483,7 +4483,6 @@ BytecodeEmitter::emitSwitch(ParseNode* pn)
|
||||
if (caseCount == 0 ||
|
||||
(caseCount == 1 && (hasDefault = firstCase->isDefault())))
|
||||
{
|
||||
caseCount = 0;
|
||||
low = 0;
|
||||
high = -1;
|
||||
} else {
|
||||
|
@ -247,6 +247,7 @@ PropertyDescriptor::trace(JSTracer* trc)
|
||||
void
|
||||
js::gc::GCRuntime::traceRuntimeForMajorGC(JSTracer* trc, AutoTraceSession& session)
|
||||
{
|
||||
MOZ_ASSERT(!TlsContext.get()->suppressGC);
|
||||
MOZ_ASSERT_IF(atomsZone->isCollecting(), session.maybeLock.isSome());
|
||||
|
||||
// FinishRoots will have asserted that every root that we do not expect
|
||||
@ -264,6 +265,8 @@ js::gc::GCRuntime::traceRuntimeForMajorGC(JSTracer* trc, AutoTraceSession& sessi
|
||||
void
|
||||
js::gc::GCRuntime::traceRuntimeForMinorGC(JSTracer* trc, AutoTraceSession& session)
|
||||
{
|
||||
MOZ_ASSERT(!TlsContext.get()->suppressGC);
|
||||
|
||||
// Note that we *must* trace the runtime during the SHUTDOWN_GC's minor GC
|
||||
// despite having called FinishRoots already. This is because FinishRoots
|
||||
// does not clear the crossCompartmentWrapper map. It cannot do this
|
||||
@ -314,8 +317,6 @@ void
|
||||
js::gc::GCRuntime::traceRuntimeCommon(JSTracer* trc, TraceOrMarkRuntime traceOrMark,
|
||||
AutoTraceSession& session)
|
||||
{
|
||||
MOZ_ASSERT(!TlsContext.get()->suppressGC);
|
||||
|
||||
{
|
||||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::MARK_STACK);
|
||||
|
||||
|
@ -1189,11 +1189,8 @@ class IonBuilder
|
||||
|
||||
public:
|
||||
|
||||
// These are only valid for IonBuilders that have moved to background
|
||||
// This is only valid for IonBuilders that have moved to background
|
||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
};
|
||||
|
||||
class CallInfo
|
||||
|
@ -1051,21 +1051,26 @@ FormatFrame(JSContext* cx, const FrameIter& iter, JS::UniqueChars&& inBuf, int n
|
||||
static JS::UniqueChars
|
||||
FormatWasmFrame(JSContext* cx, const FrameIter& iter, JS::UniqueChars&& inBuf, int num)
|
||||
{
|
||||
JSAtom* functionDisplayAtom = iter.functionDisplayAtom();
|
||||
UniqueChars nameStr;
|
||||
if (functionDisplayAtom)
|
||||
if (JSAtom* functionDisplayAtom = iter.functionDisplayAtom()) {
|
||||
nameStr = StringToNewUTF8CharsZ(cx, *functionDisplayAtom);
|
||||
if (!nameStr)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JS::UniqueChars buf = sprintf_append(cx, Move(inBuf), "%d %s()",
|
||||
num,
|
||||
nameStr ? nameStr.get() : "<wasm-function>");
|
||||
if (!buf)
|
||||
return nullptr;
|
||||
|
||||
const char* filename = iter.filename();
|
||||
uint32_t lineno = iter.computeLine();
|
||||
buf = sprintf_append(cx, Move(buf), " [\"%s\":%d]\n",
|
||||
filename ? filename : "<unknown>",
|
||||
lineno);
|
||||
if (!buf)
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(!cx->isExceptionPending());
|
||||
return buf;
|
||||
|
@ -1171,11 +1171,11 @@ GlobalHelperThreadState::addSizeOfIncludingThis(JS::GlobalStats* stats,
|
||||
|
||||
// Report IonBuilders on wait lists
|
||||
for (auto builder : ionWorklist_)
|
||||
htStats.ionBuilder += builder->sizeOfIncludingThis(mallocSizeOf);
|
||||
htStats.ionBuilder += builder->sizeOfExcludingThis(mallocSizeOf);
|
||||
for (auto builder : ionFinishedList_)
|
||||
htStats.ionBuilder += builder->sizeOfIncludingThis(mallocSizeOf);
|
||||
htStats.ionBuilder += builder->sizeOfExcludingThis(mallocSizeOf);
|
||||
for (auto builder : ionFreeList_)
|
||||
htStats.ionBuilder += builder->sizeOfIncludingThis(mallocSizeOf);
|
||||
htStats.ionBuilder += builder->sizeOfExcludingThis(mallocSizeOf);
|
||||
|
||||
// Report wasm::CompileTasks on wait lists
|
||||
for (auto task : wasmWorklist_tier1_)
|
||||
|
@ -2244,8 +2244,11 @@ AstDecodeModuleTail(AstDecodeContext& c)
|
||||
return false;
|
||||
|
||||
for (DataSegment& s : c.env().dataSegments) {
|
||||
const uint8_t* src = c.d.begin() + s.bytecodeOffset;
|
||||
char16_t* buffer = static_cast<char16_t*>(c.lifo.alloc(s.length * sizeof(char16_t)));
|
||||
if (!buffer)
|
||||
return false;
|
||||
|
||||
const uint8_t* src = c.d.begin() + s.bytecodeOffset;
|
||||
for (size_t i = 0; i < s.length; i++)
|
||||
buffer[i] = src[i];
|
||||
|
||||
|
@ -1971,6 +1971,9 @@ ParseCallIndirect(WasmParseContext& c, bool inParens)
|
||||
index = new(c.lifo) AstPop();
|
||||
}
|
||||
|
||||
if (!index)
|
||||
return nullptr;
|
||||
|
||||
return new(c.lifo) AstCallIndirect(sig, ExprType::Void, Move(args), index);
|
||||
}
|
||||
|
||||
|
@ -1930,7 +1930,7 @@ public:
|
||||
mBSize = 0;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize)));
|
||||
MOZ_ASSERT((rectDebug.IsEmpty() && (mISize == 0 || mBSize == 0)) || rectDebug.IsEqualEdges(nsRect(mIStart, mBStart, mISize, mBSize)));
|
||||
return mISize > 0 && mBSize > 0;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,9 @@ if CONFIG['CPU_ARCH'] == 'x86_64':
|
||||
ASFLAGS += [ '-I%s/media/libaom/config/win/x64/' % TOPSRCDIR ]
|
||||
LOCAL_INCLUDES += [ '/media/libaom/config/win/x64/' ]
|
||||
EXPORTS.aom += [ 'config/win/x64/aom_config.h' ]
|
||||
# This code is not included in our PGO profile, and pointlessly
|
||||
# PGO-optimizing it slows down our builds a lot.
|
||||
NO_PGO = True
|
||||
elif CONFIG['OS_TARGET'] == 'Darwin':
|
||||
ASFLAGS += [ '-I%s/media/libaom/config/mac/x64/' % TOPSRCDIR ]
|
||||
LOCAL_INCLUDES += [ '/media/libaom/config/mac/x64/' ]
|
||||
|
@ -199,7 +199,6 @@ pref("extensions.dss.enabled", false);
|
||||
pref("extensions.ignoreMTimeChanges", false);
|
||||
pref("extensions.logging.enabled", false);
|
||||
pref("extensions.hideInstallButton", true);
|
||||
pref("extensions.showMismatchUI", false);
|
||||
pref("extensions.hideUpdateButton", false);
|
||||
pref("extensions.strictCompatibility", false);
|
||||
pref("extensions.minCompatibleAppVersion", "11.0");
|
||||
|
@ -57,6 +57,7 @@ import org.mozilla.gecko.util.PackageUtil;
|
||||
import org.mozilla.gecko.webapps.WebApps;
|
||||
import org.mozilla.gecko.widget.ActionModePresenter;
|
||||
import org.mozilla.gecko.widget.GeckoPopupMenu;
|
||||
import org.mozilla.geckoview.GeckoResponse;
|
||||
import org.mozilla.geckoview.GeckoRuntime;
|
||||
import org.mozilla.geckoview.GeckoSession;
|
||||
import org.mozilla.geckoview.GeckoSessionSettings;
|
||||
@ -600,7 +601,7 @@ public class CustomTabsActivity extends AppCompatActivity
|
||||
@Override
|
||||
public void onLoadRequest(final GeckoSession session, final String urlStr,
|
||||
final int target,
|
||||
final GeckoSession.Response<Boolean> response) {
|
||||
final GeckoResponse<Boolean> response) {
|
||||
if (target != GeckoSession.NavigationDelegate.TARGET_WINDOW_NEW) {
|
||||
response.respond(false);
|
||||
return;
|
||||
@ -641,7 +642,7 @@ public class CustomTabsActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
public void onNewSession(final GeckoSession session, final String uri,
|
||||
final GeckoSession.Response<GeckoSession> response) {
|
||||
final GeckoResponse<GeckoSession> response) {
|
||||
// We should never get here because we abort loads that need a new session in onLoadRequest()
|
||||
throw new IllegalStateException("Unexpected new session");
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import org.mozilla.gecko.text.TextSelection;
|
||||
import org.mozilla.gecko.util.ActivityUtils;
|
||||
import org.mozilla.gecko.util.ColorUtil;
|
||||
import org.mozilla.gecko.widget.ActionModePresenter;
|
||||
import org.mozilla.geckoview.GeckoResponse;
|
||||
import org.mozilla.geckoview.GeckoRuntime;
|
||||
import org.mozilla.geckoview.GeckoSession;
|
||||
import org.mozilla.geckoview.GeckoSessionSettings;
|
||||
@ -369,7 +370,7 @@ public class WebAppActivity extends AppCompatActivity
|
||||
@Override
|
||||
public void onLoadRequest(final GeckoSession session, final String urlStr,
|
||||
final int target,
|
||||
final GeckoSession.Response<Boolean> response) {
|
||||
final GeckoResponse<Boolean> response) {
|
||||
final Uri uri = Uri.parse(urlStr);
|
||||
if (uri == null) {
|
||||
// We can't really handle this, so deny it?
|
||||
@ -421,7 +422,7 @@ public class WebAppActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
public void onNewSession(final GeckoSession session, final String uri,
|
||||
final GeckoSession.Response<GeckoSession> response) {
|
||||
final GeckoResponse<GeckoSession> response) {
|
||||
// We should never get here because we abort loads that need a new session in onLoadRequest()
|
||||
throw new IllegalStateException("Unexpected new session");
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package org.mozilla.geckoview.test
|
||||
|
||||
import org.mozilla.geckoview.GeckoResponse
|
||||
import org.mozilla.geckoview.GeckoSession
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
|
||||
import org.mozilla.geckoview.test.util.Callbacks
|
||||
@ -37,12 +38,12 @@ class ContentDelegateTest : BaseSessionTest() {
|
||||
sessionRule.waitUntilCalled(object : Callbacks.NavigationDelegate, Callbacks.ContentDelegate {
|
||||
|
||||
@AssertCalled(count = 2)
|
||||
override fun onLoadRequest(session: GeckoSession, uri: String, where: Int, response: GeckoSession.Response<Boolean>) {
|
||||
override fun onLoadRequest(session: GeckoSession, uri: String, where: Int, response: GeckoResponse<Boolean>) {
|
||||
response.respond(false)
|
||||
}
|
||||
|
||||
@AssertCalled(false)
|
||||
override fun onNewSession(session: GeckoSession, uri: String, response: GeckoSession.Response<GeckoSession>) {
|
||||
override fun onNewSession(session: GeckoSession, uri: String, response: GeckoResponse<GeckoSession>) {
|
||||
}
|
||||
|
||||
@AssertCalled(count = 1)
|
||||
@ -55,4 +56,4 @@ class ContentDelegateTest : BaseSessionTest() {
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
package org.mozilla.geckoview.test
|
||||
|
||||
import android.support.test.InstrumentationRegistry
|
||||
import org.mozilla.geckoview.GeckoResponse
|
||||
import org.mozilla.geckoview.GeckoSession
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDisplay
|
||||
@ -29,7 +30,7 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||
override fun onLoadRequest(session: GeckoSession, uri: String,
|
||||
where: Int,
|
||||
response: GeckoSession.Response<Boolean>) {
|
||||
response: GeckoResponse<Boolean>) {
|
||||
assertThat("Session should not be null", session, notNullValue())
|
||||
assertThat("URI should not be null", uri, notNullValue())
|
||||
assertThat("URI should match", uri, endsWith(HELLO_HTML_PATH))
|
||||
@ -60,7 +61,7 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||
|
||||
@AssertCalled(false)
|
||||
override fun onNewSession(session: GeckoSession, uri: String,
|
||||
response: GeckoSession.Response<GeckoSession>) {
|
||||
response: GeckoResponse<GeckoSession>) {
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -190,7 +191,7 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||
override fun onLoadRequest(session: GeckoSession, uri: String,
|
||||
where: Int,
|
||||
response: GeckoSession.Response<Boolean>) {
|
||||
response: GeckoResponse<Boolean>) {
|
||||
assertThat("URI should match", uri, endsWith(HELLO_HTML_PATH))
|
||||
assertThat("Where should match", where,
|
||||
equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_CURRENT))
|
||||
@ -214,7 +215,7 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||
|
||||
@AssertCalled(false)
|
||||
override fun onNewSession(session: GeckoSession, uri: String,
|
||||
response: GeckoSession.Response<GeckoSession>) {
|
||||
response: GeckoResponse<GeckoSession>) {
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -240,7 +241,7 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||
override fun onLoadRequest(session: GeckoSession, uri: String,
|
||||
where: Int,
|
||||
response: GeckoSession.Response<Boolean>) {
|
||||
response: GeckoResponse<Boolean>) {
|
||||
assertThat("URI should match", uri, endsWith(HELLO_HTML_PATH))
|
||||
assertThat("Where should match", where,
|
||||
equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_CURRENT))
|
||||
@ -264,7 +265,7 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||
|
||||
@AssertCalled(false)
|
||||
override fun onNewSession(session: GeckoSession, uri: String,
|
||||
response: GeckoSession.Response<GeckoSession>) {
|
||||
response: GeckoResponse<GeckoSession>) {
|
||||
}
|
||||
})
|
||||
|
||||
@ -275,7 +276,7 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||
@AssertCalled(count = 1, order = intArrayOf(1))
|
||||
override fun onLoadRequest(session: GeckoSession, uri: String,
|
||||
where: Int,
|
||||
response: GeckoSession.Response<Boolean>) {
|
||||
response: GeckoResponse<Boolean>) {
|
||||
assertThat("URI should match", uri, endsWith(HELLO2_HTML_PATH))
|
||||
assertThat("Where should match", where,
|
||||
equalTo(GeckoSession.NavigationDelegate.TARGET_WINDOW_CURRENT))
|
||||
@ -299,7 +300,7 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||
|
||||
@AssertCalled(false)
|
||||
override fun onNewSession(session: GeckoSession, uri: String,
|
||||
response: GeckoSession.Response<GeckoSession>) {
|
||||
response: GeckoResponse<GeckoSession>) {
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -309,7 +310,7 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||
@AssertCalled(count = 2)
|
||||
override fun onLoadRequest(session: GeckoSession, uri: String,
|
||||
where: Int,
|
||||
response: GeckoSession.Response<Boolean>) {
|
||||
response: GeckoResponse<Boolean>) {
|
||||
response.respond(uri.endsWith(HELLO_HTML_PATH))
|
||||
}
|
||||
})
|
||||
@ -338,7 +339,7 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||
|
||||
sessionRule.delegateDuringNextWait(object : Callbacks.NavigationDelegate {
|
||||
@AssertCalled(count = 1)
|
||||
override fun onNewSession(session: GeckoSession, uri: String, response: GeckoSession.Response<GeckoSession>) {
|
||||
override fun onNewSession(session: GeckoSession, uri: String, response: GeckoResponse<GeckoSession>) {
|
||||
response.respond(null)
|
||||
}
|
||||
})
|
||||
@ -355,7 +356,7 @@ class NavigationDelegateTest : BaseSessionTest() {
|
||||
|
||||
sessionRule.delegateDuringNextWait(object : Callbacks.NavigationDelegate {
|
||||
@AssertCalled(count = 1)
|
||||
override fun onNewSession(session: GeckoSession, uri: String, response: GeckoSession.Response<GeckoSession>) {
|
||||
override fun onNewSession(session: GeckoSession, uri: String, response: GeckoResponse<GeckoSession>) {
|
||||
val newSession = sessionRule.createClosedSession(session.settings)
|
||||
newSession.open()
|
||||
response.respond(newSession)
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package org.mozilla.geckoview.test
|
||||
|
||||
import org.mozilla.geckoview.GeckoResponse
|
||||
import org.mozilla.geckoview.GeckoSession
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
|
||||
import org.mozilla.geckoview.test.util.Callbacks
|
||||
@ -61,7 +62,7 @@ class ProgressDelegateTest : BaseSessionTest() {
|
||||
@AssertCalled(count = 2)
|
||||
override fun onLoadRequest(session: GeckoSession, uri: String,
|
||||
where: Int,
|
||||
response: GeckoSession.Response<Boolean>) {
|
||||
response: GeckoResponse<Boolean>) {
|
||||
if (sessionRule.currentCall.counter == 1) {
|
||||
assertThat("URI should be " + testUri, uri, equalTo(testUri));
|
||||
} else {
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package org.mozilla.geckoview.test;
|
||||
|
||||
import org.mozilla.geckoview.GeckoResponse;
|
||||
import org.mozilla.geckoview.GeckoSession;
|
||||
import org.mozilla.geckoview.GeckoSessionSettings;
|
||||
import org.mozilla.geckoview.GeckoView;
|
||||
@ -43,13 +44,13 @@ public class TestRunnerActivity extends Activity {
|
||||
|
||||
@Override
|
||||
public void onLoadRequest(GeckoSession session, String uri, int target,
|
||||
GeckoSession.Response<Boolean> response) {
|
||||
GeckoResponse<Boolean> response) {
|
||||
// Allow Gecko to load all URIs
|
||||
response.respond(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewSession(GeckoSession session, String uri, GeckoSession.Response<GeckoSession> response) {
|
||||
public void onNewSession(GeckoSession session, String uri, GeckoResponse<GeckoSession> response) {
|
||||
response.respond(createSession(session.getSettings()));
|
||||
}
|
||||
};
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
package org.mozilla.geckoview.test.util
|
||||
|
||||
import org.mozilla.geckoview.GeckoResponse
|
||||
import org.mozilla.geckoview.GeckoSession
|
||||
|
||||
class Callbacks private constructor() {
|
||||
@ -45,11 +46,11 @@ class Callbacks private constructor() {
|
||||
}
|
||||
|
||||
override fun onLoadRequest(session: GeckoSession, uri: String, where: Int,
|
||||
response: GeckoSession.Response<Boolean>) {
|
||||
response: GeckoResponse<Boolean>) {
|
||||
response.respond(false)
|
||||
}
|
||||
|
||||
override fun onNewSession(session: GeckoSession, uri: String, response: GeckoSession.Response<GeckoSession>) {
|
||||
override fun onNewSession(session: GeckoSession, uri: String, response: GeckoResponse<GeckoSession>) {
|
||||
response.respond(null)
|
||||
}
|
||||
}
|
||||
@ -124,7 +125,7 @@ class Callbacks private constructor() {
|
||||
}
|
||||
|
||||
interface SelectionActionDelegate : GeckoSession.SelectionActionDelegate {
|
||||
override fun onShowActionRequest(session: GeckoSession, selection: GeckoSession.SelectionActionDelegate.Selection, actions: Array<out String>, response: GeckoSession.Response<String>) {
|
||||
override fun onShowActionRequest(session: GeckoSession, selection: GeckoSession.SelectionActionDelegate.Selection, actions: Array<out String>, response: GeckoResponse<String>) {
|
||||
}
|
||||
|
||||
override fun onHideAction(session: GeckoSession, reason: Int) {
|
||||
|
@ -64,7 +64,7 @@ public class BasicSelectionActionDelegate implements ActionMode.Callback,
|
||||
protected GeckoSession mSession;
|
||||
protected Selection mSelection;
|
||||
protected List<String> mActions;
|
||||
protected GeckoSession.Response<String> mResponse;
|
||||
protected GeckoResponse<String> mResponse;
|
||||
protected boolean mRepopulatedMenu;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
@ -350,7 +350,7 @@ public class BasicSelectionActionDelegate implements ActionMode.Callback,
|
||||
@Override
|
||||
public void onShowActionRequest(final GeckoSession session, final Selection selection,
|
||||
final String[] actions,
|
||||
final GeckoSession.Response<String> response) {
|
||||
final GeckoResponse<String> response) {
|
||||
mSession = session;
|
||||
mSelection = selection;
|
||||
mActions = Arrays.asList(actions);
|
||||
|
@ -0,0 +1,19 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* vim: ts=4 sw=4 expandtab:
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.geckoview;
|
||||
|
||||
/**
|
||||
* This is used to receive async responses from delegate methods.
|
||||
*/
|
||||
public interface GeckoResponse<T> {
|
||||
/**
|
||||
* Called when async processing has finished.
|
||||
*
|
||||
* @param value The value contained in the response.
|
||||
*/
|
||||
void respond(T value);
|
||||
}
|
@ -20,6 +20,7 @@ import org.mozilla.gecko.PrefsHelper;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
public final class GeckoRuntime implements Parcelable {
|
||||
private static final String LOGTAG = "GeckoRuntime";
|
||||
@ -32,7 +33,7 @@ public final class GeckoRuntime implements Parcelable {
|
||||
* This will create and initialize the runtime with the default settings.
|
||||
*
|
||||
* Note: Only use this for session-less apps.
|
||||
* For regular apps, use create() and createSession() instead.
|
||||
* For regular apps, use create() instead.
|
||||
*
|
||||
* @param context An application context for the default runtime.
|
||||
* @return The (static) default runtime for the context.
|
||||
@ -51,6 +52,7 @@ public final class GeckoRuntime implements Parcelable {
|
||||
|
||||
private GeckoRuntimeSettings mSettings;
|
||||
private Delegate mDelegate;
|
||||
private RuntimeTelemetry mTelemetry;
|
||||
|
||||
/**
|
||||
* Attach the runtime to the given context.
|
||||
@ -195,6 +197,21 @@ public final class GeckoRuntime implements Parcelable {
|
||||
PrefsHelper.setPref(name, value, /* flush */ false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the telemetry object for this runtime.
|
||||
*
|
||||
* @return The telemetry object.
|
||||
*/
|
||||
public RuntimeTelemetry getTelemetry() {
|
||||
ThreadUtils.assertOnUiThread();
|
||||
|
||||
if (mTelemetry == null) {
|
||||
mTelemetry = new RuntimeTelemetry(this);
|
||||
}
|
||||
return mTelemetry;
|
||||
|
||||
}
|
||||
|
||||
@Override // Parcelable
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
|
@ -181,7 +181,7 @@ public class GeckoSession extends LayerSession
|
||||
final String uri = message.getString("uri");
|
||||
final int where = convertGeckoTarget(message.getInt("where"));
|
||||
delegate.onLoadRequest(GeckoSession.this, uri, where,
|
||||
new Response<Boolean>() {
|
||||
new GeckoResponse<Boolean>() {
|
||||
@Override
|
||||
public void respond(Boolean handled) {
|
||||
callback.sendSuccess(handled);
|
||||
@ -190,7 +190,7 @@ public class GeckoSession extends LayerSession
|
||||
} else if ("GeckoView:OnNewSession".equals(event)) {
|
||||
final String uri = message.getString("uri");
|
||||
delegate.onNewSession(GeckoSession.this, uri,
|
||||
new Response<GeckoSession>() {
|
||||
new GeckoResponse<GeckoSession>() {
|
||||
@Override
|
||||
public void respond(GeckoSession session) {
|
||||
if (session == null) {
|
||||
@ -363,7 +363,7 @@ public class GeckoSession extends LayerSession
|
||||
|
||||
final String[] actions = message.getStringArray("actions");
|
||||
final int seqNo = message.getInt("seqNo");
|
||||
final Response<String> response = new Response<String>() {
|
||||
final GeckoResponse<String> response = new GeckoResponse<String>() {
|
||||
@Override
|
||||
public void respond(final String action) {
|
||||
final GeckoBundle response = new GeckoBundle(2);
|
||||
@ -1124,7 +1124,7 @@ public class GeckoSession extends LayerSession
|
||||
* @param response This is a response which will be called with the state once it has been
|
||||
* saved. Can be null if we fail to save the state for any reason.
|
||||
*/
|
||||
public void saveState(final Response<SessionState> response) {
|
||||
public void saveState(final GeckoResponse<SessionState> response) {
|
||||
mEventDispatcher.dispatch("GeckoView:SaveState", null, new EventCallback() {
|
||||
@Override
|
||||
public void sendSuccess(final Object result) {
|
||||
@ -2005,7 +2005,7 @@ public class GeckoSession extends LayerSession
|
||||
* multiple times to perform multiple actions at once.
|
||||
*/
|
||||
void onShowActionRequest(GeckoSession session, Selection selection,
|
||||
@Action String[] actions, Response<String> response);
|
||||
@Action String[] actions, GeckoResponse<String> response);
|
||||
|
||||
@IntDef({HIDE_REASON_NO_SELECTION,
|
||||
HIDE_REASON_INVISIBLE_SELECTION,
|
||||
@ -2048,16 +2048,6 @@ public class GeckoSession extends LayerSession
|
||||
void onHideAction(GeckoSession session, @HideReason int reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to send responses in delegate methods that have asynchronous responses.
|
||||
*/
|
||||
public interface Response<T> {
|
||||
/**
|
||||
* @param val The value contained in the response
|
||||
*/
|
||||
void respond(T val);
|
||||
}
|
||||
|
||||
public interface NavigationDelegate {
|
||||
/**
|
||||
* A view has started loading content from the network.
|
||||
@ -2103,7 +2093,7 @@ public class GeckoSession extends LayerSession
|
||||
*/
|
||||
void onLoadRequest(GeckoSession session, String uri,
|
||||
@TargetWindow int target,
|
||||
Response<Boolean> response);
|
||||
GeckoResponse<Boolean> response);
|
||||
|
||||
/**
|
||||
* A request has been made to open a new session. The URI is provided only for
|
||||
@ -2115,7 +2105,7 @@ public class GeckoSession extends LayerSession
|
||||
*
|
||||
* @param response A Response which will hold the returned GeckoSession
|
||||
*/
|
||||
void onNewSession(GeckoSession session, String uri, Response<GeckoSession> response);
|
||||
void onNewSession(GeckoSession session, String uri, GeckoResponse<GeckoSession> response);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,130 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* vim: ts=4 sw=4 expandtab:
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.geckoview;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
|
||||
/**
|
||||
* The telemetry API gives access to telemetry data of the Gecko runtime.
|
||||
*/
|
||||
public final class RuntimeTelemetry {
|
||||
private final static String LOGTAG = "GeckoViewTelemetry";
|
||||
private final static boolean DEBUG = false;
|
||||
|
||||
private final GeckoRuntime mRuntime;
|
||||
private final EventDispatcher mEventDispatcher;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({ DATASET_BASE, DATASET_EXTENDED })
|
||||
public @interface DatasetType {}
|
||||
|
||||
// Match with nsITelemetry.
|
||||
/**
|
||||
* The base dataset suitable for release builds.
|
||||
*/
|
||||
public static final int DATASET_BASE = 0;
|
||||
/**
|
||||
* The extended dataset suitable for pre-release builds.
|
||||
*/
|
||||
public static final int DATASET_EXTENDED = 1;
|
||||
|
||||
@IntDef(flag = true,
|
||||
value = { SNAPSHOT_HISTOGRAMS, SNAPSHOT_KEYED_HISTOGRAMS,
|
||||
SNAPSHOT_SCALARS, SNAPSHOT_KEYED_SCALARS,
|
||||
SNAPSHOT_ALL })
|
||||
public @interface SnapshotType {}
|
||||
|
||||
// Match with GeckoViewTelemetryController.
|
||||
/**
|
||||
* Adds a "histogram" object entry to the snapshot response.
|
||||
*/
|
||||
public static final int SNAPSHOT_HISTOGRAMS = 1 << 0;
|
||||
/**
|
||||
* Adds a "keyedHistogram" object entry to the snapshot response.
|
||||
*/
|
||||
public static final int SNAPSHOT_KEYED_HISTOGRAMS = 1 << 1;
|
||||
/**
|
||||
* Adds a "scalars" object entry to the snapshot response.
|
||||
*/
|
||||
public static final int SNAPSHOT_SCALARS = 1 << 2;
|
||||
/**
|
||||
* Adds a "keyedScalars" object entry to the snapshot response.
|
||||
*/
|
||||
public static final int SNAPSHOT_KEYED_SCALARS = 1 << 3;
|
||||
/**
|
||||
* Adds all snapshot types to the response.
|
||||
*/
|
||||
public static final int SNAPSHOT_ALL = (1 << 4) - 1;
|
||||
|
||||
/* package */ RuntimeTelemetry(final @NonNull GeckoRuntime runtime) {
|
||||
mRuntime = runtime;
|
||||
mEventDispatcher = EventDispatcher.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all telemetry snapshots.
|
||||
*
|
||||
* @param dataset The dataset type to retreive.
|
||||
* One of {@link #RuntimeTelemetry.DATASET_BASE DATASET_*} flags.
|
||||
* @param clear Whether the retrieved snapshots should be cleared.
|
||||
* @param response Used to return the async response.
|
||||
*/
|
||||
public void getSnapshots(
|
||||
final @DatasetType int dataset,
|
||||
final boolean clear,
|
||||
final @NonNull GeckoResponse<GeckoBundle> response) {
|
||||
getSnapshots(SNAPSHOT_ALL, dataset, clear, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the requested telemetry snapshots.
|
||||
*
|
||||
* @param types The requested snapshot types.
|
||||
* One or more of {@link #RuntimeTelemetry.SNAPSHOT_HISTOGRAMS SNAPSHOT_*} flags.
|
||||
* @param dataset The dataset type to retreive.
|
||||
* One of {@link #RuntimeTelemetry.DATASET_BASE DATASET_*} flags.
|
||||
* @param clear Whether the retrieved snapshots should be cleared.
|
||||
* @param response Used to return the async response.
|
||||
*/
|
||||
public void getSnapshots(
|
||||
final @SnapshotType int types,
|
||||
final @DatasetType int dataset,
|
||||
final boolean clear,
|
||||
final @NonNull GeckoResponse<GeckoBundle> response) {
|
||||
final GeckoBundle msg = new GeckoBundle(3);
|
||||
msg.putInt("types", types);
|
||||
msg.putInt("dataset", dataset);
|
||||
msg.putBoolean("clear", clear);
|
||||
|
||||
mEventDispatcher.dispatch("GeckoView:TelemetrySnapshots", msg,
|
||||
new EventCallback() {
|
||||
@Override
|
||||
public void sendSuccess(final Object result) {
|
||||
response.respond((GeckoBundle) result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(final Object error) {
|
||||
Log.e(LOGTAG, "getSnapshots failed: " + error);
|
||||
response.respond(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -17,9 +17,9 @@ import android.view.WindowManager;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.mozilla.geckoview.GeckoResponse;
|
||||
import org.mozilla.geckoview.GeckoSession;
|
||||
import org.mozilla.geckoview.GeckoSessionSettings;
|
||||
import org.mozilla.geckoview.GeckoSession.Response;
|
||||
import org.mozilla.geckoview.GeckoSession.TrackingProtectionDelegate;
|
||||
import org.mozilla.geckoview.GeckoView;
|
||||
import org.mozilla.geckoview.GeckoRuntime;
|
||||
@ -360,13 +360,13 @@ public class GeckoViewActivity extends Activity {
|
||||
|
||||
@Override
|
||||
public void onLoadRequest(final GeckoSession session, final String uri,
|
||||
final int target, Response<Boolean> response) {
|
||||
final int target, GeckoResponse<Boolean> response) {
|
||||
Log.d(LOGTAG, "onLoadRequest=" + uri + " where=" + target);
|
||||
response.respond(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewSession(final GeckoSession session, final String uri, Response<GeckoSession> response) {
|
||||
public void onNewSession(final GeckoSession session, final String uri, GeckoResponse<GeckoSession> response) {
|
||||
response.respond(null);
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ with Files('**/Makefile.in'):
|
||||
FINAL = True
|
||||
|
||||
with Files("**/*.js"):
|
||||
SCHEDULES.inclusive += ['test-verify', 'docs']
|
||||
SCHEDULES.inclusive += ['test-verify', 'test-verify-gpu', 'docs']
|
||||
|
||||
with Files("**/*.jsm"):
|
||||
SCHEDULES.inclusive += ['docs']
|
||||
@ -71,13 +71,13 @@ with Files("**/*.md"):
|
||||
SCHEDULES.inclusive += ['docs']
|
||||
|
||||
with Files("**/*.html"):
|
||||
SCHEDULES.inclusive += ['test-verify']
|
||||
SCHEDULES.inclusive += ['test-verify', 'test-verify-gpu']
|
||||
|
||||
with Files("**/*.xhtml"):
|
||||
SCHEDULES.inclusive += ['test-verify']
|
||||
SCHEDULES.inclusive += ['test-verify', 'test-verify-gpu']
|
||||
|
||||
with Files("**/*.xul"):
|
||||
SCHEDULES.inclusive += ['test-verify']
|
||||
SCHEDULES.inclusive += ['test-verify', 'test-verify-gpu']
|
||||
|
||||
CONFIGURE_SUBST_FILES += [
|
||||
'config/autoconf.mk',
|
||||
|
@ -54,8 +54,8 @@ mozilla::detail::ConditionVariableImpl::notify_all()
|
||||
void
|
||||
mozilla::detail::ConditionVariableImpl::wait(MutexImpl& lock)
|
||||
{
|
||||
CRITICAL_SECTION* cs = &lock.platformData()->criticalSection;
|
||||
bool r = SleepConditionVariableCS(&platformData()->cv_, cs, INFINITE);
|
||||
SRWLOCK* srwlock = &lock.platformData()->lock;
|
||||
bool r = SleepConditionVariableSRW(&platformData()->cv_, srwlock, INFINITE, 0);
|
||||
MOZ_RELEASE_ASSERT(r);
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ mozilla::detail::ConditionVariableImpl::wait_for(MutexImpl& lock,
|
||||
return CVStatus::NoTimeout;
|
||||
}
|
||||
|
||||
CRITICAL_SECTION* cs = &lock.platformData()->criticalSection;
|
||||
SRWLOCK* srwlock = &lock.platformData()->lock;
|
||||
|
||||
// Note that DWORD is unsigned, so we have to be careful to clamp at 0. If
|
||||
// rel_time is Forever, then ToMilliseconds is +inf, which evaluates as
|
||||
@ -89,7 +89,7 @@ mozilla::detail::ConditionVariableImpl::wait_for(MutexImpl& lock,
|
||||
}
|
||||
}
|
||||
|
||||
BOOL r = SleepConditionVariableCS(&platformData()->cv_, cs, msec);
|
||||
BOOL r = SleepConditionVariableSRW(&platformData()->cv_, srwlock, msec, 0);
|
||||
if (r)
|
||||
return CVStatus::NoTimeout;
|
||||
MOZ_RELEASE_ASSERT(GetLastError() == ERROR_TIMEOUT);
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
struct mozilla::detail::MutexImpl::PlatformData
|
||||
{
|
||||
CRITICAL_SECTION criticalSection;
|
||||
SRWLOCK lock;
|
||||
};
|
||||
|
||||
#endif // MutexPlatformData_windows_h
|
||||
|
@ -14,38 +14,23 @@
|
||||
|
||||
mozilla::detail::MutexImpl::MutexImpl()
|
||||
{
|
||||
// This number was adopted from NSPR.
|
||||
const static DWORD LockSpinCount = 1500;
|
||||
|
||||
#if defined(RELEASE_OR_BETA)
|
||||
// Vista and later automatically allocate and subsequently leak a debug info
|
||||
// object for each critical section that we allocate unless we tell the
|
||||
// system not to do that.
|
||||
DWORD flags = CRITICAL_SECTION_NO_DEBUG_INFO;
|
||||
#else
|
||||
DWORD flags = 0;
|
||||
#endif // defined(RELEASE_OR_BETA)
|
||||
|
||||
BOOL r = InitializeCriticalSectionEx(&platformData()->criticalSection,
|
||||
LockSpinCount, flags);
|
||||
MOZ_RELEASE_ASSERT(r);
|
||||
InitializeSRWLock(&platformData()->lock);
|
||||
}
|
||||
|
||||
mozilla::detail::MutexImpl::~MutexImpl()
|
||||
{
|
||||
DeleteCriticalSection(&platformData()->criticalSection);
|
||||
}
|
||||
|
||||
void
|
||||
mozilla::detail::MutexImpl::lock()
|
||||
{
|
||||
EnterCriticalSection(&platformData()->criticalSection);
|
||||
AcquireSRWLockExclusive(&platformData()->lock);
|
||||
}
|
||||
|
||||
void
|
||||
mozilla::detail::MutexImpl::unlock()
|
||||
{
|
||||
LeaveCriticalSection(&platformData()->criticalSection);
|
||||
ReleaseSRWLockExclusive(&platformData()->lock);
|
||||
}
|
||||
|
||||
mozilla::detail::MutexImpl::PlatformData*
|
||||
|
@ -139,8 +139,8 @@ public:
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
SIZE_T result = ::VirtualQuery(aVAddress, &mbi, sizeof(mbi));
|
||||
|
||||
return result && mbi.AllocationProtect && mbi.State == MEM_COMMIT &&
|
||||
mbi.Protect != PAGE_NOACCESS;
|
||||
return result && mbi.AllocationProtect && (mbi.Type & MEM_IMAGE) &&
|
||||
mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS;
|
||||
}
|
||||
|
||||
bool FlushInstructionCache() const
|
||||
|
@ -45,35 +45,47 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
origFn += 2 + offset;
|
||||
return ReadOnlyTargetFunction<MMPolicyT>(mVMPolicy, origFn.GetAddress());
|
||||
uintptr_t abstarget = (origFn + 2 + offset).GetAddress();
|
||||
return EnsureTargetIsAccessible(Move(origFn), abstarget);
|
||||
}
|
||||
|
||||
#if defined(_M_IX86)
|
||||
// If function entry is jmp [disp32] such as used by kernel32,
|
||||
// we resolve redirected address from import table.
|
||||
if (origFn[0] == 0xff && origFn[1] == 0x25) {
|
||||
return ReadOnlyTargetFunction<MMPolicyT>(mVMPolicy,
|
||||
reinterpret_cast<const void*>((origFn + 2).template ChasePointer<uintptr_t*>()));
|
||||
uintptr_t abstarget = (origFn + 2).template ChasePointer<uintptr_t*>();
|
||||
return EnsureTargetIsAccessible(Move(origFn), abstarget);
|
||||
}
|
||||
#elif defined(_M_X64)
|
||||
// If function entry is jmp [disp32] such as used by kernel32,
|
||||
// we resolve redirected address from import table.
|
||||
if (origFn[0] == 0x48 && origFn[1] == 0xff && origFn[2] == 0x25) {
|
||||
return ReadOnlyTargetFunction<MMPolicyT>(mVMPolicy,
|
||||
reinterpret_cast<const void*>((origFn + 3).ChasePointerFromDisp()));
|
||||
uintptr_t abstarget = (origFn + 3).ChasePointerFromDisp();
|
||||
return EnsureTargetIsAccessible(Move(origFn), abstarget);
|
||||
}
|
||||
|
||||
if (origFn[0] == 0xe9) {
|
||||
// require for TestDllInterceptor with --disable-optimize
|
||||
uintptr_t abstarget = (origFn + 1).ReadDisp32AsAbsolute();
|
||||
return ReadOnlyTargetFunction<MMPolicyT>(mVMPolicy, abstarget);
|
||||
return EnsureTargetIsAccessible(Move(origFn), abstarget);
|
||||
}
|
||||
#endif
|
||||
|
||||
return Move(origFn);
|
||||
}
|
||||
|
||||
private:
|
||||
ReadOnlyTargetFunction<MMPolicyT>
|
||||
EnsureTargetIsAccessible(ReadOnlyTargetFunction<MMPolicyT> aOrigFn,
|
||||
uintptr_t aRedirAddress)
|
||||
{
|
||||
if (!mVMPolicy.IsPageAccessible(reinterpret_cast<void*>(aRedirAddress))) {
|
||||
return Move(aOrigFn);
|
||||
}
|
||||
|
||||
return ReadOnlyTargetFunction<MMPolicyT>(mVMPolicy, aRedirAddress);
|
||||
}
|
||||
|
||||
protected:
|
||||
VMPolicy mVMPolicy;
|
||||
};
|
||||
|
@ -291,6 +291,7 @@ public:
|
||||
, mTrampSize(0)
|
||||
, mNumTramps(0)
|
||||
, mPrevProt(0)
|
||||
, mCS(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@ -303,6 +304,7 @@ public:
|
||||
, mTrampSize(aTrampSize)
|
||||
, mNumTramps(aNumTramps)
|
||||
, mPrevProt(0)
|
||||
, mCS(nullptr)
|
||||
{
|
||||
if (!aNumTramps) {
|
||||
return;
|
||||
@ -321,6 +323,20 @@ public:
|
||||
|
||||
mMMPolicy.Protect(mLocalBase, mNumTramps * mTrampSize,
|
||||
mPrevProt, &mPrevProt);
|
||||
|
||||
if (mCS) {
|
||||
::LeaveCriticalSection(mCS);
|
||||
}
|
||||
}
|
||||
|
||||
void Lock(CRITICAL_SECTION& aCS)
|
||||
{
|
||||
if (!mPrevProt || mCS) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCS = &aCS;
|
||||
::EnterCriticalSection(&aCS);
|
||||
}
|
||||
|
||||
TrampolineIterator begin() const
|
||||
@ -348,17 +364,20 @@ public:
|
||||
, mTrampSize(aOther.mTrampSize)
|
||||
, mNumTramps(aOther.mNumTramps)
|
||||
, mPrevProt(aOther.mPrevProt)
|
||||
, mCS(aOther.mCS)
|
||||
{
|
||||
aOther.mPrevProt = 0;
|
||||
aOther.mCS = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
const MMPolicy& mMMPolicy;
|
||||
uint8_t* const mLocalBase;
|
||||
const uintptr_t mRemoteBase;
|
||||
const uint32_t mTrampSize;
|
||||
const uint32_t mNumTramps;
|
||||
uint32_t mPrevProt;
|
||||
const MMPolicy& mMMPolicy;
|
||||
uint8_t* const mLocalBase;
|
||||
const uintptr_t mRemoteBase;
|
||||
const uint32_t mTrampSize;
|
||||
const uint32_t mNumTramps;
|
||||
uint32_t mPrevProt;
|
||||
CRITICAL_SECTION* mCS;
|
||||
|
||||
friend class TrampolineIterator;
|
||||
};
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace interceptor {
|
||||
@ -83,6 +84,213 @@ private:
|
||||
uint32_t mNextChunkIndex;
|
||||
};
|
||||
|
||||
template <typename MMPolicy, uint32_t kChunkSize>
|
||||
class VMSharingPolicyShared : public MMPolicyBase
|
||||
{
|
||||
typedef VMSharingPolicyUnique<MMPolicy, kChunkSize> ValueT;
|
||||
|
||||
// We use pid instead of HANDLE for mapping, since more than one handle may
|
||||
// map to the same pid. We don't worry about pid reuse becuase each mVMPolicy
|
||||
// holds an open handle to pid, thus keeping the pid reserved at least for the
|
||||
// lifetime of mVMPolicy.
|
||||
struct ProcMapEntry
|
||||
{
|
||||
ProcMapEntry()
|
||||
: mPid(::GetCurrentProcessId())
|
||||
{
|
||||
}
|
||||
|
||||
explicit ProcMapEntry(HANDLE aProc)
|
||||
: mPid(::GetProcessId(aProc))
|
||||
, mVMPolicy(aProc)
|
||||
{
|
||||
}
|
||||
|
||||
ProcMapEntry(ProcMapEntry&& aOther)
|
||||
: mPid(aOther.mPid)
|
||||
, mVMPolicy(Move(aOther.mVMPolicy))
|
||||
{
|
||||
aOther.mPid = 0;
|
||||
}
|
||||
|
||||
ProcMapEntry(const ProcMapEntry&) = delete;
|
||||
ProcMapEntry& operator=(const ProcMapEntry&) = delete;
|
||||
|
||||
ProcMapEntry& operator=(ProcMapEntry&& aOther)
|
||||
{
|
||||
mPid = aOther.mPid;
|
||||
mVMPolicy = Move(aOther.mVMPolicy);
|
||||
aOther.mPid = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(DWORD aPid) const
|
||||
{
|
||||
return mPid == aPid;
|
||||
}
|
||||
|
||||
DWORD mPid;
|
||||
ValueT mVMPolicy;
|
||||
};
|
||||
|
||||
// We normally expect to reference only one other process at a time, but this
|
||||
// is not a requirement.
|
||||
typedef Vector<ProcMapEntry, 1> MapT;
|
||||
|
||||
public:
|
||||
typedef MMPolicy MMPolicyT;
|
||||
|
||||
template <typename... Args>
|
||||
explicit VMSharingPolicyShared(Args... aArgs)
|
||||
: mPid(GetPid(aArgs...))
|
||||
{
|
||||
static const bool isAlloc = []() -> bool {
|
||||
sPerProcVM = new MapT();
|
||||
DWORD flags = 0;
|
||||
#if defined(RELEASE_OR_BETA)
|
||||
flags |= CRITICAL_SECTION_NO_DEBUG_INFO;
|
||||
#endif // defined(RELEASE_OR_BETA)
|
||||
::InitializeCriticalSectionEx(&sCS, 4000, flags);
|
||||
return true;
|
||||
}();
|
||||
|
||||
MOZ_ASSERT(mPid);
|
||||
if (!mPid) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoCriticalSection lock(&sCS);
|
||||
|
||||
if (find(mPid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(sPerProcVM->append(ProcMapEntry(aArgs...)));
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
AutoCriticalSection lock(&sCS);
|
||||
|
||||
ProcMapEntry* entry;
|
||||
MOZ_RELEASE_ASSERT(find(mPid, &entry));
|
||||
|
||||
return !!entry->mVMPolicy;
|
||||
}
|
||||
|
||||
operator const MMPolicy&() const
|
||||
{
|
||||
AutoCriticalSection lock(&sCS);
|
||||
|
||||
ProcMapEntry* entry;
|
||||
MOZ_RELEASE_ASSERT(find(mPid, &entry));
|
||||
|
||||
return entry->mVMPolicy;
|
||||
}
|
||||
|
||||
bool ShouldUnhookUponDestruction() const
|
||||
{
|
||||
AutoCriticalSection lock(&sCS);
|
||||
|
||||
ProcMapEntry* entry;
|
||||
if (!find(mPid, &entry)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return entry->mVMPolicy.ShouldUnhookUponDestruction();
|
||||
}
|
||||
|
||||
bool Reserve(uint32_t aCount)
|
||||
{
|
||||
AutoCriticalSection lock(&sCS);
|
||||
|
||||
ProcMapEntry* entry;
|
||||
if (!find(mPid, &entry)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return entry->mVMPolicy.Reserve(aCount);
|
||||
}
|
||||
|
||||
Trampoline<MMPolicy> GetNextTrampoline()
|
||||
{
|
||||
AutoCriticalSection lock(&sCS);
|
||||
|
||||
ProcMapEntry* entry;
|
||||
if (!find(mPid, &entry)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return entry->mVMPolicy.GetNextTrampoline();
|
||||
}
|
||||
|
||||
TrampolineCollection<MMPolicy> Items() const
|
||||
{
|
||||
AutoCriticalSection lock(&sCS);
|
||||
|
||||
ProcMapEntry* entry;
|
||||
MOZ_RELEASE_ASSERT(find(mPid, &entry));
|
||||
|
||||
TrampolineCollection<MMPolicy> items(Move(entry->mVMPolicy.Items()));
|
||||
|
||||
// We need to continue holding the lock until items is destroyed.
|
||||
items.Lock(sCS);
|
||||
|
||||
return Move(items);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
// This must be a no-op for shared VM policy; we can't have one interceptor
|
||||
// wiping out trampolines for all interceptors in the process.
|
||||
}
|
||||
|
||||
~VMSharingPolicyShared() = default;
|
||||
|
||||
VMSharingPolicyShared(const VMSharingPolicyShared&) = delete;
|
||||
VMSharingPolicyShared(VMSharingPolicyShared&&) = delete;
|
||||
VMSharingPolicyShared& operator=(const VMSharingPolicyShared&) = delete;
|
||||
VMSharingPolicyShared& operator=(VMSharingPolicyShared&&) = delete;
|
||||
|
||||
private:
|
||||
static bool find(DWORD aPid, ProcMapEntry** aOutEntry = nullptr)
|
||||
{
|
||||
MOZ_ASSERT(sPerProcVM);
|
||||
if (!sPerProcVM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aOutEntry) {
|
||||
*aOutEntry = nullptr;
|
||||
}
|
||||
|
||||
for (auto&& mapping : *sPerProcVM) {
|
||||
if (mapping == aPid) {
|
||||
if (aOutEntry) {
|
||||
*aOutEntry = &mapping;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static DWORD GetPid() { return ::GetCurrentProcessId(); }
|
||||
static DWORD GetPid(HANDLE aHandle) { return ::GetProcessId(aHandle); }
|
||||
|
||||
DWORD mPid;
|
||||
static StaticAutoPtr<MapT> sPerProcVM;
|
||||
static CRITICAL_SECTION sCS;
|
||||
};
|
||||
|
||||
template <typename MMPolicy, uint32_t kChunkSize>
|
||||
StaticAutoPtr<typename VMSharingPolicyShared<MMPolicy, kChunkSize>::MapT>
|
||||
VMSharingPolicyShared<MMPolicy, kChunkSize>::sPerProcVM;
|
||||
|
||||
template <typename MMPolicy, uint32_t kChunkSize>
|
||||
CRITICAL_SECTION VMSharingPolicyShared<MMPolicy, kChunkSize>::sCS;
|
||||
|
||||
} // namespace interceptor
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -150,7 +150,7 @@ MODERN_MERCURIAL_VERSION = LooseVersion('4.2.3')
|
||||
MODERN_PYTHON_VERSION = LooseVersion('2.7.3')
|
||||
|
||||
# Upgrade rust older than this.
|
||||
MODERN_RUST_VERSION = LooseVersion('1.25.0')
|
||||
MODERN_RUST_VERSION = LooseVersion('1.24.0')
|
||||
|
||||
|
||||
class BaseBootstrapper(object):
|
||||
|
@ -23,6 +23,7 @@ INCLUSIVE_COMPONENTS = [
|
||||
# inclusive test suites -- these *only* run when certain files have changed
|
||||
'jittest',
|
||||
'test-verify',
|
||||
'test-verify-gpu',
|
||||
'test-verify-wpt',
|
||||
'test-coverage',
|
||||
'test-coverage-wpt',
|
||||
|
@ -4,3 +4,4 @@ add_WOW64_flags_to_allowed_registry_read_flags.patch
|
||||
consult_PermissionsService_for_file_access.patch
|
||||
allow_flash_temporary_files.patch
|
||||
use_STARTF_FORCEOFFFEEDBACK_flag.patch
|
||||
remove_dynamic_GetUserDefaultLocaleName_call.patch
|
||||
|
@ -0,0 +1,66 @@
|
||||
# HG changeset patch
|
||||
# User Bob Owen <bobowencode@gmail.com>
|
||||
# Date 1524480221 -3600
|
||||
# Mon Apr 23 11:43:41 2018 +0100
|
||||
# Node ID c881904b6139ba0c6f5072f7577a94812021913a
|
||||
# Parent e96685584bf7d3c1d7a4c1861716da89fd650c51
|
||||
Bug 1444699: Remove dynamic load and call for GetUserDefaultLocaleName. r=handyman
|
||||
|
||||
This was only required because it is not available on Windows XP, which is no
|
||||
longer supported. Patch already landed upstream in chromium.
|
||||
|
||||
diff --git a/security/sandbox/chromium/sandbox/win/src/target_services.cc b/security/sandbox/chromium/sandbox/win/src/target_services.cc
|
||||
--- a/security/sandbox/chromium/sandbox/win/src/target_services.cc
|
||||
+++ b/security/sandbox/chromium/sandbox/win/src/target_services.cc
|
||||
@@ -75,50 +75,30 @@ bool CloseOpenHandles(bool* is_csrss_con
|
||||
}
|
||||
}
|
||||
if (!handle_closer.CloseHandles())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
-// GetUserDefaultLocaleName is not available on WIN XP. So we'll
|
||||
-// load it on-the-fly.
|
||||
-const wchar_t kKernel32DllName[] = L"kernel32.dll";
|
||||
-typedef decltype(GetUserDefaultLocaleName)* GetUserDefaultLocaleNameFunction;
|
||||
-
|
||||
// Warm up language subsystems before the sandbox is turned on.
|
||||
// Tested on Win8.1 x64:
|
||||
// This needs to happen after RevertToSelf() is called, because (at least) in
|
||||
// the case of GetUserDefaultLCID() it checks the TEB to see if the process is
|
||||
// impersonating (TEB!IsImpersonating). If it is, the cached locale information
|
||||
// is not used, nor is it set. Therefore, calls after RevertToSelf() will not
|
||||
// have warmed-up values to use.
|
||||
bool WarmupWindowsLocales() {
|
||||
// NOTE(liamjm): When last checked (Win 8.1 x64) it wasn't necessary to
|
||||
// warmup all of these functions, but let's not assume that.
|
||||
::GetUserDefaultLangID();
|
||||
::GetUserDefaultLCID();
|
||||
- static GetUserDefaultLocaleNameFunction GetUserDefaultLocaleName_func =
|
||||
- NULL;
|
||||
- if (!GetUserDefaultLocaleName_func) {
|
||||
- HMODULE kernel32_dll = ::GetModuleHandle(kKernel32DllName);
|
||||
- if (!kernel32_dll) {
|
||||
- return false;
|
||||
- }
|
||||
- GetUserDefaultLocaleName_func =
|
||||
- reinterpret_cast<GetUserDefaultLocaleNameFunction>(
|
||||
- GetProcAddress(kernel32_dll, "GetUserDefaultLocaleName"));
|
||||
- if (!GetUserDefaultLocaleName_func) {
|
||||
- return false;
|
||||
- }
|
||||
- }
|
||||
wchar_t localeName[LOCALE_NAME_MAX_LENGTH] = {0};
|
||||
- return (0 != GetUserDefaultLocaleName_func(
|
||||
- localeName, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t)));
|
||||
+ return (0 != ::GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH));
|
||||
}
|
||||
|
||||
// Used as storage for g_target_services, because other allocation facilities
|
||||
// are not available early. We can't use a regular function static because on
|
||||
// VS2015, because the CRT tries to acquire a lock to guard initialization, but
|
||||
// this code runs before the CRT is initialized.
|
||||
char g_target_services_memory[sizeof(TargetServicesBase)];
|
||||
TargetServicesBase* g_target_services = nullptr;
|
@ -80,11 +80,6 @@ bool CloseOpenHandles(bool* is_csrss_connected) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// GetUserDefaultLocaleName is not available on WIN XP. So we'll
|
||||
// load it on-the-fly.
|
||||
const wchar_t kKernel32DllName[] = L"kernel32.dll";
|
||||
typedef decltype(GetUserDefaultLocaleName)* GetUserDefaultLocaleNameFunction;
|
||||
|
||||
// Warm up language subsystems before the sandbox is turned on.
|
||||
// Tested on Win8.1 x64:
|
||||
// This needs to happen after RevertToSelf() is called, because (at least) in
|
||||
@ -97,23 +92,8 @@ bool WarmupWindowsLocales() {
|
||||
// warmup all of these functions, but let's not assume that.
|
||||
::GetUserDefaultLangID();
|
||||
::GetUserDefaultLCID();
|
||||
static GetUserDefaultLocaleNameFunction GetUserDefaultLocaleName_func =
|
||||
NULL;
|
||||
if (!GetUserDefaultLocaleName_func) {
|
||||
HMODULE kernel32_dll = ::GetModuleHandle(kKernel32DllName);
|
||||
if (!kernel32_dll) {
|
||||
return false;
|
||||
}
|
||||
GetUserDefaultLocaleName_func =
|
||||
reinterpret_cast<GetUserDefaultLocaleNameFunction>(
|
||||
GetProcAddress(kernel32_dll, "GetUserDefaultLocaleName"));
|
||||
if (!GetUserDefaultLocaleName_func) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
wchar_t localeName[LOCALE_NAME_MAX_LENGTH] = {0};
|
||||
return (0 != GetUserDefaultLocaleName_func(
|
||||
localeName, LOCALE_NAME_MAX_LENGTH * sizeof(wchar_t)));
|
||||
return (0 != ::GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH));
|
||||
}
|
||||
|
||||
// Used as storage for g_target_services, because other allocation facilities
|
||||
|
@ -98,6 +98,51 @@ test-verify:
|
||||
extra-options:
|
||||
- --verify
|
||||
|
||||
test-verify-gpu:
|
||||
description: "Extra verification of tests modified on this push on gpu instances"
|
||||
suite: test-verify
|
||||
treeherder-symbol: TVg
|
||||
loopback-video: true
|
||||
virtualization: virtual-with-gpu
|
||||
instance-size:
|
||||
by-test-platform:
|
||||
android.*: xlarge
|
||||
default: default
|
||||
max-run-time: 10800
|
||||
allow-software-gl-layers: false
|
||||
run-on-projects:
|
||||
by-test-platform:
|
||||
# do not run on ccov; see also the enable_code_coverage transform
|
||||
linux64-ccov/.*: []
|
||||
windows10-64-ccov/debug: []
|
||||
# do not run on beta or release: usually just confirms earlier results
|
||||
default: ['trunk', 'try']
|
||||
tier:
|
||||
by-test-platform:
|
||||
windows10-64-asan.*: 3
|
||||
default: 2
|
||||
mozharness:
|
||||
script:
|
||||
by-test-platform:
|
||||
android.*: android_emulator_unittest.py
|
||||
default: desktop_unittest.py
|
||||
config:
|
||||
by-test-platform:
|
||||
android.*:
|
||||
- android/android_common.py
|
||||
- android/androidarm_4_3.py
|
||||
linux.*:
|
||||
- unittests/linux_unittest.py
|
||||
- remove_executables.py
|
||||
macosx.*:
|
||||
- unittests/mac_unittest.py
|
||||
windows.*:
|
||||
- unittests/win_taskcluster_unittest.py
|
||||
no-read-buildbot-config: true
|
||||
extra-options:
|
||||
- --verify
|
||||
- --gpu-required
|
||||
|
||||
test-coverage:
|
||||
description: "Per-test coverage"
|
||||
suite: test-coverage
|
||||
|
@ -40,6 +40,7 @@ common-tests:
|
||||
- test-coverage
|
||||
- test-coverage-wpt
|
||||
- test-verify
|
||||
- test-verify-gpu
|
||||
- test-verify-wpt
|
||||
- xpcshell
|
||||
|
||||
@ -190,6 +191,7 @@ windows-tests:
|
||||
- test-coverage
|
||||
- test-coverage-wpt
|
||||
- test-verify
|
||||
- test-verify-gpu
|
||||
- test-verify-wpt
|
||||
- web-platform-tests
|
||||
- web-platform-tests-reftests
|
||||
@ -253,6 +255,7 @@ macosx64-tests:
|
||||
- mochitest-webgl
|
||||
- reftest
|
||||
- test-verify
|
||||
- test-verify-gpu
|
||||
- test-verify-wpt
|
||||
- web-platform-tests
|
||||
- web-platform-tests-reftests
|
||||
|
@ -382,7 +382,7 @@ linux64-android-gradle-dependencies:
|
||||
# Aliases aren't allowed for toolchains depending on toolchains.
|
||||
- linux64-android-sdk-linux-repack
|
||||
|
||||
linux64-rust-1.25:
|
||||
linux64-rust-1.24:
|
||||
description: "rust repack"
|
||||
treeherder:
|
||||
kind: build
|
||||
@ -398,7 +398,7 @@ linux64-rust-1.25:
|
||||
using: toolchain-script
|
||||
script: repack_rust.py
|
||||
arguments: [
|
||||
'--channel', '1.25.0',
|
||||
'--channel', '1.24.0',
|
||||
'--host', 'x86_64-unknown-linux-gnu',
|
||||
'--target', 'x86_64-unknown-linux-gnu',
|
||||
'--target', 'i686-unknown-linux-gnu',
|
||||
@ -406,30 +406,7 @@ linux64-rust-1.25:
|
||||
toolchain-alias: linux64-rust
|
||||
toolchain-artifact: public/build/rustc.tar.xz
|
||||
|
||||
linux64-rust-1.24:
|
||||
description: "rust repack"
|
||||
treeherder:
|
||||
kind: build
|
||||
platform: toolchains/opt
|
||||
symbol: TL(rust-1.24)
|
||||
tier: 1
|
||||
worker-type: aws-provisioner-v1/gecko-{level}-b-linux
|
||||
worker:
|
||||
max-run-time: 7200
|
||||
env:
|
||||
UPLOAD_DIR: artifacts
|
||||
run:
|
||||
using: toolchain-script
|
||||
script: repack_rust.py
|
||||
arguments: [
|
||||
'--channel', '1.24.0',
|
||||
'--host', 'x86_64-unknown-linux-gnu',
|
||||
'--target', 'x86_64-unknown-linux-gnu',
|
||||
'--target', 'i686-unknown-linux-gnu',
|
||||
]
|
||||
toolchain-artifact: public/build/rustc.tar.xz
|
||||
|
||||
linux64-rust-macos-1.25:
|
||||
linux64-rust-macos-1.24:
|
||||
description: "rust repack with macos-cross support"
|
||||
treeherder:
|
||||
kind: build
|
||||
@ -445,7 +422,7 @@ linux64-rust-macos-1.25:
|
||||
using: toolchain-script
|
||||
script: repack_rust.py
|
||||
arguments: [
|
||||
'--channel', '1.25.0',
|
||||
'--channel', '1.24.0',
|
||||
'--host', 'x86_64-unknown-linux-gnu',
|
||||
'--target', 'x86_64-unknown-linux-gnu',
|
||||
'--target', 'x86_64-apple-darwin',
|
||||
@ -453,7 +430,7 @@ linux64-rust-macos-1.25:
|
||||
toolchain-alias: linux64-rust-macos
|
||||
toolchain-artifact: public/build/rustc.tar.xz
|
||||
|
||||
linux64-rust-android-1.25:
|
||||
linux64-rust-android-1.24:
|
||||
description: "rust repack with android-cross support"
|
||||
treeherder:
|
||||
kind: build
|
||||
@ -469,7 +446,7 @@ linux64-rust-android-1.25:
|
||||
using: toolchain-script
|
||||
script: repack_rust.py
|
||||
arguments: [
|
||||
'--channel', '1.25.0',
|
||||
'--channel', '1.24.0',
|
||||
'--host', 'x86_64-unknown-linux-gnu',
|
||||
'--target', 'x86_64-unknown-linux-gnu',
|
||||
'--target', 'armv7-linux-androideabi',
|
||||
@ -496,7 +473,7 @@ linux64-sccache:
|
||||
- 'taskcluster/scripts/misc/tooltool-download.sh'
|
||||
toolchain-artifact: public/build/sccache2.tar.xz
|
||||
toolchains:
|
||||
- linux64-rust-1.25
|
||||
- linux64-rust-1.24
|
||||
|
||||
linux64-gn:
|
||||
description: "gn toolchain build"
|
||||
|
@ -118,7 +118,7 @@ win64-clang-tidy:
|
||||
- 'taskcluster/scripts/misc/build-clang-windows-helper64.sh'
|
||||
toolchain-artifact: public/build/clang-tidy.tar.bz2
|
||||
|
||||
win64-rust-1.25:
|
||||
win64-rust-1.24:
|
||||
description: "rust repack"
|
||||
treeherder:
|
||||
kind: build
|
||||
@ -135,7 +135,7 @@ win64-rust-1.25:
|
||||
using: toolchain-script
|
||||
script: repack_rust.py
|
||||
arguments: [
|
||||
'--channel', '1.25.0',
|
||||
'--channel', '1.24.0',
|
||||
'--host', 'x86_64-pc-windows-msvc',
|
||||
'--target', 'x86_64-pc-windows-msvc',
|
||||
'--target', 'i686-pc-windows-msvc',
|
||||
@ -143,7 +143,7 @@ win64-rust-1.25:
|
||||
toolchain-alias: win64-rust
|
||||
toolchain-artifact: public/build/rustc.tar.bz2
|
||||
|
||||
win32-rust-1.25:
|
||||
win32-rust-1.24:
|
||||
description: "rust repack"
|
||||
treeherder:
|
||||
kind: build
|
||||
@ -160,14 +160,14 @@ win32-rust-1.25:
|
||||
using: toolchain-script
|
||||
script: repack_rust.py
|
||||
arguments: [
|
||||
'--channel', '1.25.0',
|
||||
'--channel', '1.24.0',
|
||||
'--host', 'i686-pc-windows-msvc',
|
||||
'--target', 'i686-pc-windows-msvc',
|
||||
]
|
||||
toolchain-alias: win32-rust
|
||||
toolchain-artifact: public/build/rustc.tar.bz2
|
||||
|
||||
mingw32-rust-1.25:
|
||||
mingw32-rust-1.24:
|
||||
description: "rust repack"
|
||||
treeherder:
|
||||
kind: build
|
||||
@ -184,7 +184,7 @@ mingw32-rust-1.25:
|
||||
using: toolchain-script
|
||||
script: repack_rust.py
|
||||
arguments: [
|
||||
'--channel', '1.25.0',
|
||||
'--channel', '1.24.0',
|
||||
'--host', 'i686-unknown-linux-gnu',
|
||||
'--target', 'i686-pc-windows-gnu',
|
||||
'--target', 'x86_64-unknown-linux-gnu',
|
||||
@ -212,7 +212,7 @@ win64-sccache:
|
||||
- 'taskcluster/scripts/misc/tooltool-download.sh'
|
||||
toolchain-artifact: public/build/sccache2.tar.bz2
|
||||
toolchains:
|
||||
- win64-rust-1.25
|
||||
- win64-rust-1.24
|
||||
|
||||
win32-gn:
|
||||
description: "gn toolchain build"
|
||||
|
@ -282,6 +282,9 @@ def target_tasks_mozilla_esr60(full_task_graph, parameters, graph_config):
|
||||
of builds and signing, but does not include beetmover or balrog jobs."""
|
||||
|
||||
def filter(task):
|
||||
if not filter_beta_release_tasks(task, parameters):
|
||||
return False
|
||||
|
||||
platform = task.attributes.get('build_platform')
|
||||
|
||||
# Android is not built on esr.
|
||||
@ -291,10 +294,7 @@ def target_tasks_mozilla_esr60(full_task_graph, parameters, graph_config):
|
||||
# All else was already filtered
|
||||
return True
|
||||
|
||||
tasks = [l for l, t in full_task_graph.tasks.iteritems() if
|
||||
filter_beta_release_tasks(t, parameters)]
|
||||
|
||||
return [l for l, t in tasks.iteritems() if filter(t)]
|
||||
return [l for l, t in full_task_graph.tasks.iteritems() if filter(t)]
|
||||
|
||||
|
||||
@_target_task('promote_firefox')
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user