зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to fx-team
This commit is contained in:
Коммит
94388a5225
|
@ -18,22 +18,26 @@
|
|||
src="../layout.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
var kX = 10, kY = 10, kWidth = 150, kHeight = 100;
|
||||
function doTest()
|
||||
{
|
||||
var canv = document.getElementById("c");
|
||||
var context = canv.getContext('2d');
|
||||
var element = document.getElementById("showA");
|
||||
context.beginPath();
|
||||
context.rect(10, 10, 150, 100);
|
||||
context.rect(kX, kY, kWidth, kHeight);
|
||||
context.addHitRegion({control: element});
|
||||
var input = getAccessible("showA");
|
||||
|
||||
var input = getAccessible("showA");
|
||||
var [cnvX, cnvY, cnvWidth, cnvHeight] = getBoundsForDOMElm(canv);
|
||||
var [accX, accY, accWidth, accHeight] = getBounds(input);
|
||||
is(accX, cnvX + 10, "accX should be 10 and not " + accX);
|
||||
is(accY, cnvY + 10, "accY should be 10 and not " + accY);
|
||||
is(accWidth, 150, "accWidth should be 150 and not " + accWidth);
|
||||
is(accHeight, 100, "accHeight should be 100 and not " + accHeight);
|
||||
|
||||
var [x, y, w, h] = CSSToDevicePixels(window, kX, kY, kWidth, kHeight);
|
||||
is(accX, cnvX + x, "wrong accX");
|
||||
is(accY, cnvY + y, "wrong accY");
|
||||
is(accWidth, w, "wrong accWidth");
|
||||
is(accHeight, h, "wrong accHeight");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
|
|
@ -345,10 +345,17 @@ function eventQueue(aEventType)
|
|||
var msg = "Test with ID = '" + this.getEventID(checker) +
|
||||
"' succeed. ";
|
||||
|
||||
if (checker.unexpected)
|
||||
ok(true, msg + "There's no unexpected " + typeStr + " event.");
|
||||
else
|
||||
if (checker.unexpected) {
|
||||
if (checker.todo) {
|
||||
todo(false, "Event " + typeStr + " event is still missing");
|
||||
}
|
||||
else {
|
||||
ok(true, msg + "There's no unexpected " + typeStr + " event.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
ok(true, msg + "Event " + typeStr + " was handled.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -371,8 +378,13 @@ function eventQueue(aEventType)
|
|||
ok(false, msg + "Dupe " + typeStr + " event.");
|
||||
|
||||
if (checker.unexpected) {
|
||||
if (checker.wasCaught)
|
||||
if (checker.todo) {
|
||||
todo(checker.wasCaught,
|
||||
"Event " + typeStr + " event is still missing");
|
||||
}
|
||||
else if (checker.wasCaught) {
|
||||
ok(false, msg + "There's unexpected " + typeStr + " event.");
|
||||
}
|
||||
} else if (!checker.wasCaught) {
|
||||
ok(false, msg + typeStr + " event was missed.");
|
||||
}
|
||||
|
@ -1667,6 +1679,18 @@ function invokerChecker(aEventType, aTargetOrFunc, aTargetFuncArg, aIsAsync)
|
|||
this.mTargetFuncArg = aTargetFuncArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic invoker checker for todo events.
|
||||
*/
|
||||
function todo_invokerChecker(aEventType, aTargetOrFunc, aTargetFuncArg)
|
||||
{
|
||||
this.__proto__ = new invokerChecker(aEventType, aTargetOrFunc,
|
||||
aTargetFuncArg, true);
|
||||
|
||||
this.unexpected = true;
|
||||
this.todo = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic invoker checker for unexpected events.
|
||||
*/
|
||||
|
|
|
@ -358,6 +358,25 @@
|
|||
}
|
||||
}
|
||||
|
||||
function showHiddenParentOfVisibleChild()
|
||||
{
|
||||
this.eventSeq = [
|
||||
new todo_invokerChecker(EVENT_HIDE, getNode("c4_child")),
|
||||
new invokerChecker(EVENT_SHOW, getNode("c4_middle")),
|
||||
new invokerChecker(EVENT_REORDER, getNode("c4"))
|
||||
];
|
||||
|
||||
this.invoke = function showHiddenParentOfVisibleChild_invoke()
|
||||
{
|
||||
getNode("c4_middle").style.visibility = 'visible';
|
||||
}
|
||||
|
||||
this.getID = function showHiddenParentOfVisibleChild_getID()
|
||||
{
|
||||
return "show hidden parent of visible child";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Target getters.
|
||||
*/
|
||||
|
@ -484,6 +503,7 @@
|
|||
gQueue.push(new test2("testContainer", "testNestedContainer"));
|
||||
gQueue.push(new test3("testContainer"));
|
||||
gQueue.push(new insertReferredElm("testContainer3"));
|
||||
gQueue.push(new showHiddenParentOfVisibleChild());
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
@ -544,5 +564,11 @@
|
|||
</div>
|
||||
<div id="testContainer2"></div>
|
||||
<div id="testContainer3"></div>
|
||||
|
||||
<div id="c4">
|
||||
<div style="visibility:hidden" id="c4_middle">
|
||||
<div style="visibility:visible" id="c4_child"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -41,29 +41,31 @@
|
|||
|
||||
function doTest()
|
||||
{
|
||||
var offsetX = 20, offsetY = 40;
|
||||
getNode("hitcanvas").scrollIntoView(true);
|
||||
|
||||
var context = document.getElementById("hitcanvas").getContext('2d');
|
||||
redrawCheckbox(context, document.getElementById('hitcheck'), 20, 40);
|
||||
redrawCheckbox(context, document.getElementById('hitcheck'),
|
||||
offsetX, offsetY);
|
||||
|
||||
var hitcanvas = getAccessible("hitcanvas");
|
||||
var hitcheck = getAccessible("hitcheck");
|
||||
|
||||
var [hitX, hitY, hitWidth, hitHeight] = getBounds(hitcanvas);
|
||||
var [deltaX, deltaY] = CSSToDevicePixels(window, offsetX, offsetY);
|
||||
|
||||
var docAcc = getAccessible(document);
|
||||
var tgtX = hitX+25;
|
||||
var tgtY = hitY+45;
|
||||
hitAcc = docAcc.getDeepestChildAtPoint(tgtX, tgtY);
|
||||
// test if we hit the region associated with the shadow dom checkbox
|
||||
is(hitAcc, hitcheck, "Hit match at " + tgtX + "," + tgtY +
|
||||
". Found: " + prettyName(hitAcc));
|
||||
|
||||
tgtY = hitY+75;
|
||||
// test if we hit the region associated with the shadow dom checkbox
|
||||
var tgtX = hitX + deltaX;
|
||||
var tgtY = hitY + deltaY;
|
||||
hitAcc = docAcc.getDeepestChildAtPoint(tgtX, tgtY);
|
||||
isObject(hitAcc, hitcheck, `Hit match at (${tgtX}, ${tgtY}`);
|
||||
|
||||
// test that we don't hit the region associated with the shadow dom checkbox
|
||||
is(hitAcc, hitcanvas, "Hit match at " + tgtX + "," + tgtY +
|
||||
". Found: " + prettyName(hitAcc));
|
||||
tgtY = hitY + deltaY * 2;
|
||||
hitAcc = docAcc.getDeepestChildAtPoint(tgtX, tgtY);
|
||||
isObject(hitAcc, hitcanvas, `Hit match at (${tgtX}, ${tgtY}`);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
[test_bindings.xhtml]
|
||||
[test_embeds.xul]
|
||||
skip-if = (os == "linux" && (debug || asan)) # Bug 845176
|
||||
[test_general.html]
|
||||
[test_general.xul]
|
||||
[test_tabbrowser.xul]
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_REORDER, currentBrowser)
|
||||
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument)
|
||||
];
|
||||
|
||||
this.finalCheck = function loadURI_finalCheck()
|
||||
|
@ -52,27 +52,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
function browserReorderChecker()
|
||||
{
|
||||
this.type = EVENT_REORDER;
|
||||
|
||||
this.match = function browserReorderChecker_match(aEvent)
|
||||
{
|
||||
if (!isAccessible(currentBrowser()))
|
||||
return false;
|
||||
|
||||
// Reorder event might be duped because of temporary document creation.
|
||||
if (aEvent.accessible == getAccessible(currentBrowser())) {
|
||||
this.cnt++;
|
||||
return this.cnt != 2;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
this.cnt = 0;
|
||||
}
|
||||
|
||||
function loadOneTab(aURI)
|
||||
{
|
||||
this.invoke = function loadOneTab_invoke()
|
||||
|
@ -81,7 +60,7 @@
|
|||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new browserReorderChecker()
|
||||
new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument)
|
||||
];
|
||||
|
||||
this.finalCheck = function loadURI_finalCheck()
|
||||
|
@ -99,7 +78,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
// Testing
|
||||
|
||||
gA11yEventDumpToConsole = true; // debug
|
||||
//gA11yEventDumpToConsole = true; // debug
|
||||
|
||||
var gQueue = null;
|
||||
function doTests()
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
anchor = getAccessible("bottom2");
|
||||
var [x, y] = getPos(anchor);
|
||||
var wnd = getRootAccessible().DOMDocument.defaultView;
|
||||
var scrollToX = docX - wnd.screenX, scrollToY = docY - wnd.screenY;
|
||||
var [screenX, screenY] = CSSToDevicePixels(wnd, wnd.screenX, wnd.screenY);
|
||||
var scrollToX = docX - screenX, scrollToY = docY - screenY;
|
||||
|
||||
anchor.scrollToPoint(COORDTYPE_WINDOW_RELATIVE, scrollToX, scrollToY);
|
||||
testPos(anchor, [x, docY]);
|
||||
|
|
|
@ -16,6 +16,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429659
|
|||
src="role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="attributes.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="layout.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function testCoordinates(aID, aAcc, aWidth, aHeight)
|
||||
|
@ -70,10 +72,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429659
|
|||
// "Wrong screen y coordinate for " + aID + "!");
|
||||
}
|
||||
|
||||
var [expected_w, expected_h] = CSSToDevicePixels(window, aWidth, aHeight);
|
||||
var width = {}, height = {};
|
||||
aAcc.getImageSize(width, height);
|
||||
is(width.value, aWidth, "Wrong width for " + aID + "!");
|
||||
is(height.value, aHeight, "wrong height for " + aID + "!");
|
||||
is(width.value, expected_w, "Wrong width for " + aID + "!");
|
||||
is(height.value, expected_h, "wrong height for " + aID + "!");
|
||||
}
|
||||
|
||||
function testThis(aID, aSRC, aWidth, aHeight,
|
||||
|
|
|
@ -407,6 +407,8 @@ XULMenupopupAccessible::
|
|||
mSelectControl = do_QueryInterface(mContent->GetFlattenedTreeParent());
|
||||
if (!mSelectControl)
|
||||
mGenericTypes &= ~eSelect;
|
||||
|
||||
mStateFlags |= eNoXBLKids;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
|
|
|
@ -157,10 +157,11 @@ const Utils = {
|
|||
// We also reject handlers registered from a different host (see bug 402287)
|
||||
// The pref allows us to test the feature
|
||||
let pb = Services.prefs;
|
||||
if ((!pb.prefHasUserValue(PREF_ALLOW_DIFFERENT_HOST) ||
|
||||
!pb.getBoolPref(PREF_ALLOW_DIFFERENT_HOST)) &&
|
||||
aContentWindow.location.hostname != uri.host)
|
||||
if (!pb.getBoolPref(PREF_ALLOW_DIFFERENT_HOST) &&
|
||||
(!["http:", "https:"].includes(aContentWindow.location.protocol) ||
|
||||
aContentWindow.location.hostname != uri.host)) {
|
||||
throw("Permission denied to add " + uri.spec + " as a content or protocol handler");
|
||||
}
|
||||
|
||||
// If the uri doesn't contain '%s', it won't be a good handler
|
||||
if (uri.spec.indexOf("%s") < 0)
|
||||
|
|
|
@ -27,6 +27,8 @@ If you would like to use a different directory, hit CTRL+c and set the
|
|||
MOZBUILD_STATE_PATH environment variable to the directory you would like to
|
||||
use and re-run mach. For this change to take effect forever, you'll likely
|
||||
want to export this environment variable from your shell's init scripts.
|
||||
|
||||
Press ENTER/RETURN to continue or CTRL+c to abort.
|
||||
'''.lstrip()
|
||||
|
||||
NO_MERCURIAL_SETUP = '''
|
||||
|
@ -254,8 +256,26 @@ def bootstrap(topsrcdir, mozilla_dir=None):
|
|||
raise
|
||||
|
||||
# Add common metadata to help submit sorted data later on.
|
||||
# For now, we'll just record the mach command that was invoked.
|
||||
data['argv'] = sys.argv
|
||||
data.setdefault('system', {}).update(dict(
|
||||
architecture=list(platform.architecture()),
|
||||
machine=platform.machine(),
|
||||
python_version=platform.python_version(),
|
||||
release=platform.release(),
|
||||
system=platform.system(),
|
||||
version=platform.version(),
|
||||
))
|
||||
|
||||
if platform.system() == 'Linux':
|
||||
dist = list(platform.linux_distribution())
|
||||
data['system']['linux_distribution'] = dist
|
||||
elif platform.system() == 'Windows':
|
||||
win32_ver=list((platform.win32_ver())),
|
||||
data['system']['win32_ver'] = win32_ver
|
||||
elif platform.system() == 'Darwin':
|
||||
# mac version is a special Cupertino snowflake
|
||||
r, v, m = platform.mac_ver()
|
||||
data['system']['mac_ver'] = [r, list(v), m]
|
||||
|
||||
with open(os.path.join(outgoing_dir, str(uuid.uuid4()) + '.json'),
|
||||
'w') as f:
|
||||
|
@ -383,25 +403,18 @@ def bootstrap(topsrcdir, mozilla_dir=None):
|
|||
if is_environ:
|
||||
if not os.path.exists(state_dir):
|
||||
print('Creating global state directory from environment variable: %s'
|
||||
% state_dir)
|
||||
% state_dir)
|
||||
os.makedirs(state_dir, mode=0o770)
|
||||
print('Please re-run mach.')
|
||||
sys.exit(1)
|
||||
else:
|
||||
if not os.path.exists(state_dir):
|
||||
print(STATE_DIR_FIRST_RUN.format(userdir=state_dir))
|
||||
try:
|
||||
for i in range(20, -1, -1):
|
||||
time.sleep(1)
|
||||
sys.stdout.write('%d ' % i)
|
||||
sys.stdout.flush()
|
||||
sys.stdin.readline()
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(1)
|
||||
|
||||
print('\nCreating default state directory: %s' % state_dir)
|
||||
os.mkdir(state_dir)
|
||||
print('Please re-run mach.')
|
||||
sys.exit(1)
|
||||
os.makedirs(state_dir, mode=0o770)
|
||||
|
||||
return state_dir
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"argv": {"type": "array"},
|
||||
"system": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"architecture": {"type": "array"},
|
||||
"linux_distribution": {"type": "array"},
|
||||
"mac_ver": {"type": "array"},
|
||||
"machine": {"type": "string"},
|
||||
"python_version": {"type": "string"},
|
||||
"release": {"type": "string"},
|
||||
"system": {"type": "string"},
|
||||
"version": {"type": "string"},
|
||||
"win_ver": {"type": "array"}
|
||||
},
|
||||
"required": ["architecture", "machine", "python_version",
|
||||
"release", "system", "version"]
|
||||
}
|
||||
},
|
||||
"required": ["argv", "system"]
|
||||
}
|
20
configure.in
20
configure.in
|
@ -3851,18 +3851,6 @@ MOZ_ARG_WITH_STRING(gcm-senderid-keyfile,
|
|||
MOZ_ANDROID_GCM_SENDERID=`cat $withval`)
|
||||
AC_SUBST(MOZ_ANDROID_GCM_SENDERID)
|
||||
|
||||
# Whether to include optional-but-large font files in the final APK.
|
||||
# We want this in mobile/android/confvars.sh, so it goes early.
|
||||
MOZ_ARG_DISABLE_BOOL(android-include-fonts,
|
||||
[ --disable-android-include-fonts
|
||||
Disable the inclusion of fonts into the final APK],
|
||||
MOZ_ANDROID_EXCLUDE_FONTS=1)
|
||||
|
||||
if test -n "$MOZ_ANDROID_EXCLUDE_FONTS"; then
|
||||
AC_DEFINE(MOZ_ANDROID_EXCLUDE_FONTS)
|
||||
fi
|
||||
AC_SUBST(MOZ_ANDROID_EXCLUDE_FONTS)
|
||||
|
||||
# Whether this APK is destined for resource constrained devices.
|
||||
# We want this in mobile/android/confvars.sh, so it goes early.
|
||||
MOZ_ARG_ENABLE_BOOL(android-resource-constrained,
|
||||
|
@ -4775,6 +4763,13 @@ if test -n "$MOZ_ANDROID_MLS_STUMBLER"; then
|
|||
AC_DEFINE(MOZ_ANDROID_MLS_STUMBLER)
|
||||
fi
|
||||
|
||||
dnl =========================================================
|
||||
dnl = Whether to exclude font files in the build
|
||||
dnl =========================================================
|
||||
if test -n "$MOZ_ANDROID_EXCLUDE_FONTS"; then
|
||||
AC_DEFINE(MOZ_ANDROID_EXCLUDE_FONTS)
|
||||
fi
|
||||
|
||||
dnl =========================================================
|
||||
dnl = Whether to exclude hyphenations files in the build
|
||||
dnl =========================================================
|
||||
|
@ -8457,6 +8452,7 @@ AC_SUBST(MOZ_ANDROID_APPLICATION_CLASS)
|
|||
AC_SUBST(MOZ_ANDROID_BROWSER_INTENT_CLASS)
|
||||
AC_SUBST(MOZ_ANDROID_SEARCH_INTENT_CLASS)
|
||||
AC_SUBST(MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE)
|
||||
AC_SUBST(MOZ_ANDROID_EXCLUDE_FONTS)
|
||||
AC_SUBST(MOZ_EXCLUDE_HYPHENATION_DICTIONARIES)
|
||||
AC_SUBST(MOZ_INSTALL_TRACKING)
|
||||
AC_SUBST(MOZ_SWITCHBOARD)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
load 1239889-1.html
|
||||
load 1244595-1.html
|
||||
load 1216842-1.html
|
||||
load 1216842-2.html
|
||||
load 1216842-3.html
|
||||
load 1216842-4.html
|
||||
load 1216842-5.html
|
||||
load 1216842-6.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1239889-1.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1244595-1.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-1.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-2.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-3.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-4.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-5.html
|
||||
pref(dom.animations-api.core.enabled,true) load 1216842-6.html
|
||||
|
|
|
@ -125,7 +125,7 @@ FormData::Append(const nsAString& aName, Blob& aBlob,
|
|||
return;
|
||||
}
|
||||
|
||||
AddNameBlobPair(aName, file);
|
||||
AddNameBlobOrNullPair(aName, file);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -179,12 +179,18 @@ FormData::Has(const nsAString& aName)
|
|||
}
|
||||
|
||||
nsresult
|
||||
FormData::AddNameBlobPair(const nsAString& aName, Blob* aBlob)
|
||||
FormData::AddNameBlobOrNullPair(const nsAString& aName, Blob* aBlob)
|
||||
{
|
||||
MOZ_ASSERT(aBlob);
|
||||
RefPtr<File> file;
|
||||
|
||||
if (!aBlob) {
|
||||
FormDataTuple* data = mFormData.AppendElement();
|
||||
SetNameValuePair(data, aName, EmptyString(), true /* aWasNullBlob */);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<File> file = GetOrCreateFileCalledBlob(*aBlob, rv);
|
||||
file = GetOrCreateFileCalledBlob(*aBlob, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
@ -269,10 +275,12 @@ FormData::GetValueAtIndex(uint32_t aIndex) const
|
|||
void
|
||||
FormData::SetNameValuePair(FormDataTuple* aData,
|
||||
const nsAString& aName,
|
||||
const nsAString& aValue)
|
||||
const nsAString& aValue,
|
||||
bool aWasNullBlob)
|
||||
{
|
||||
MOZ_ASSERT(aData);
|
||||
aData->name = aName;
|
||||
aData->wasNullBlob = aWasNullBlob;
|
||||
aData->value.SetAsUSVString() = aValue;
|
||||
}
|
||||
|
||||
|
@ -285,6 +293,7 @@ FormData::SetNameFilePair(FormDataTuple* aData,
|
|||
MOZ_ASSERT(aFile);
|
||||
|
||||
aData->name = aName;
|
||||
aData->wasNullBlob = false;
|
||||
aData->value.SetAsBlob() = aFile;
|
||||
}
|
||||
|
||||
|
@ -366,13 +375,16 @@ FormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
|
|||
nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"), nullptr);
|
||||
|
||||
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
|
||||
if (mFormData[i].value.IsBlob()) {
|
||||
fs.AddNameBlobPair(mFormData[i].name, mFormData[i].value.GetAsBlob());
|
||||
if (mFormData[i].wasNullBlob) {
|
||||
MOZ_ASSERT(mFormData[i].value.IsUSVString());
|
||||
fs.AddNameBlobOrNullPair(mFormData[i].name, nullptr);
|
||||
} else if (mFormData[i].value.IsUSVString()) {
|
||||
fs.AddNameValuePair(mFormData[i].name,
|
||||
mFormData[i].value.GetAsUSVString());
|
||||
} else {
|
||||
MOZ_CRASH("This should no be possible.");
|
||||
MOZ_ASSERT(mFormData[i].value.IsBlob());
|
||||
fs.AddNameBlobOrNullPair(mFormData[i].name,
|
||||
mFormData[i].value.GetAsBlob());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ private:
|
|||
struct FormDataTuple
|
||||
{
|
||||
nsString name;
|
||||
bool wasNullBlob;
|
||||
OwningBlobOrUSVString value;
|
||||
};
|
||||
|
||||
|
@ -45,7 +46,8 @@ private:
|
|||
|
||||
void SetNameValuePair(FormDataTuple* aData,
|
||||
const nsAString& aName,
|
||||
const nsAString& aValue);
|
||||
const nsAString& aValue,
|
||||
bool aWasNullBlob = false);
|
||||
|
||||
void SetNameFilePair(FormDataTuple* aData,
|
||||
const nsAString& aName,
|
||||
|
@ -114,8 +116,8 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual nsresult AddNameBlobPair(const nsAString& aName,
|
||||
Blob* aBlob) override;
|
||||
virtual nsresult AddNameBlobOrNullPair(const nsAString& aName,
|
||||
Blob* aBlob) override;
|
||||
|
||||
typedef bool (*FormDataEntryCallback)(const nsString& aName,
|
||||
const OwningBlobOrUSVString& aValue,
|
||||
|
|
|
@ -1824,16 +1824,8 @@ WebSocket::CreateAndDispatchMessageEvent(const nsACString& aData,
|
|||
}
|
||||
}
|
||||
|
||||
return CreateAndDispatchMessageEvent(jsapi.cx(), aData, aIsBinary);
|
||||
}
|
||||
|
||||
nsresult
|
||||
WebSocket::CreateAndDispatchMessageEvent(JSContext* aCx,
|
||||
const nsACString& aData,
|
||||
bool aIsBinary)
|
||||
{
|
||||
MOZ_ASSERT(mImpl);
|
||||
AssertIsOnTargetThread();
|
||||
jsapi.TakeOwnershipOfErrorReporting();
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
nsresult rv = CheckInnerWindowCorrectness();
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -1843,19 +1835,19 @@ WebSocket::CreateAndDispatchMessageEvent(JSContext* aCx,
|
|||
uint16_t messageType = nsIWebSocketEventListener::TYPE_STRING;
|
||||
|
||||
// Create appropriate JS object for message
|
||||
JS::Rooted<JS::Value> jsData(aCx);
|
||||
JS::Rooted<JS::Value> jsData(cx);
|
||||
if (aIsBinary) {
|
||||
if (mBinaryType == dom::BinaryType::Blob) {
|
||||
messageType = nsIWebSocketEventListener::TYPE_BLOB;
|
||||
|
||||
nsresult rv = nsContentUtils::CreateBlobBuffer(aCx, GetOwner(), aData,
|
||||
nsresult rv = nsContentUtils::CreateBlobBuffer(cx, GetOwner(), aData,
|
||||
&jsData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else if (mBinaryType == dom::BinaryType::Arraybuffer) {
|
||||
messageType = nsIWebSocketEventListener::TYPE_ARRAYBUFFER;
|
||||
|
||||
JS::Rooted<JSObject*> arrayBuf(aCx);
|
||||
nsresult rv = nsContentUtils::CreateArrayBuffer(aCx, aData,
|
||||
JS::Rooted<JSObject*> arrayBuf(cx);
|
||||
nsresult rv = nsContentUtils::CreateArrayBuffer(cx, aData,
|
||||
arrayBuf.address());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
jsData.setObject(*arrayBuf);
|
||||
|
@ -1867,7 +1859,7 @@ WebSocket::CreateAndDispatchMessageEvent(JSContext* aCx,
|
|||
// JS string
|
||||
NS_ConvertUTF8toUTF16 utf16Data(aData);
|
||||
JSString* jsString;
|
||||
jsString = JS_NewUCStringCopyN(aCx, utf16Data.get(), utf16Data.Length());
|
||||
jsString = JS_NewUCStringCopyN(cx, utf16Data.get(), utf16Data.Length());
|
||||
NS_ENSURE_TRUE(jsString, NS_ERROR_FAILURE);
|
||||
|
||||
jsData.setString(jsString);
|
||||
|
|
|
@ -138,9 +138,6 @@ private: // constructor && distructor
|
|||
nsresult CreateAndDispatchSimpleEvent(const nsAString& aName);
|
||||
nsresult CreateAndDispatchMessageEvent(const nsACString& aData,
|
||||
bool aIsBinary);
|
||||
nsresult CreateAndDispatchMessageEvent(JSContext* aCx,
|
||||
const nsACString& aData,
|
||||
bool aIsBinary);
|
||||
nsresult CreateAndDispatchCloseEvent(bool aWasClean,
|
||||
uint16_t aCode,
|
||||
const nsAString& aReason);
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
#include "MediaDecoder.h"
|
||||
// nsNPAPIPluginInstance must be included before nsIDocument.h, which is included in mozAutoDocUpdate.h.
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "gfxDrawable.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "ImageOps.h"
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
@ -200,6 +202,7 @@
|
|||
#include "nsICookieService.h"
|
||||
#include "mozilla/EnumSet.h"
|
||||
#include "mozilla/BloomFilter.h"
|
||||
#include "SourceSurfaceRawData.h"
|
||||
|
||||
#include "nsIBidiKeyboard.h"
|
||||
|
||||
|
@ -216,6 +219,7 @@ extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end,
|
|||
class imgLoader;
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::widget;
|
||||
using namespace mozilla;
|
||||
|
@ -7427,6 +7431,48 @@ nsContentUtils::IsFileImage(nsIFile* aFile, nsACString& aType)
|
|||
return StringBeginsWith(aType, NS_LITERAL_CSTRING("image/"));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentUtils::DataTransferItemToImage(const IPCDataTransferItem& aItem,
|
||||
imgIContainer** aContainer)
|
||||
{
|
||||
MOZ_ASSERT(aItem.data().type() == IPCDataTransferData::TnsCString);
|
||||
MOZ_ASSERT(IsFlavorImage(aItem.flavor()));
|
||||
|
||||
const IPCDataTransferImage& imageDetails = aItem.imageDetails();
|
||||
const IntSize size(imageDetails.width(), imageDetails.height());
|
||||
if (!size.width || !size.height) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
const nsCString& text = aItem.data().get_nsCString();
|
||||
|
||||
// InitWrappingData takes a non-const pointer for reading.
|
||||
nsCString& nonConstText = const_cast<nsCString&>(text);
|
||||
RefPtr<SourceSurfaceRawData> image = new SourceSurfaceRawData();
|
||||
image->InitWrappingData(reinterpret_cast<uint8_t*>(nonConstText.BeginWriting()),
|
||||
size, imageDetails.stride(),
|
||||
static_cast<SurfaceFormat>(imageDetails.format()),
|
||||
false);
|
||||
image->GuaranteePersistance();
|
||||
|
||||
RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(image, size);
|
||||
nsCOMPtr<imgIContainer> imageContainer =
|
||||
image::ImageOps::CreateFromDrawable(drawable);
|
||||
imageContainer.forget(aContainer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::IsFlavorImage(const nsACString& aFlavor)
|
||||
{
|
||||
return aFlavor.EqualsLiteral(kNativeImageMime) ||
|
||||
aFlavor.EqualsLiteral(kJPEGImageMime) ||
|
||||
aFlavor.EqualsLiteral(kJPGImageMime) ||
|
||||
aFlavor.EqualsLiteral(kPNGImageMime) ||
|
||||
aFlavor.EqualsLiteral(kGIFImageMime);
|
||||
}
|
||||
|
||||
void
|
||||
nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
|
||||
IPCDataTransfer* aIPCDataTransfer,
|
||||
|
|
|
@ -121,6 +121,7 @@ class DocumentFragment;
|
|||
class Element;
|
||||
class EventTarget;
|
||||
class IPCDataTransfer;
|
||||
class IPCDataTransferItem;
|
||||
class NodeInfo;
|
||||
class nsIContentChild;
|
||||
class nsIContentParent;
|
||||
|
@ -2428,6 +2429,21 @@ public:
|
|||
*/
|
||||
static bool IsFileImage(nsIFile* aFile, nsACString& aType);
|
||||
|
||||
/**
|
||||
* Given an IPCDataTransferItem that has a flavor for which IsFlavorImage
|
||||
* returns true and whose IPCDataTransferData is of type nsCString (raw image
|
||||
* data), construct an imgIContainer for the image encoded by the transfer
|
||||
* item.
|
||||
*/
|
||||
static nsresult DataTransferItemToImage(const mozilla::dom::IPCDataTransferItem& aItem,
|
||||
imgIContainer** aContainer);
|
||||
|
||||
/**
|
||||
* Given a flavor obtained from an IPCDataTransferItem or nsITransferable,
|
||||
* returns true if we should treat the data as an image.
|
||||
*/
|
||||
static bool IsFlavorImage(const nsACString& aFlavor);
|
||||
|
||||
static void TransferablesToIPCTransferables(nsISupportsArray* aTransferables,
|
||||
nsTArray<mozilla::dom::IPCDataTransfer>& aIPC,
|
||||
bool aInSyncMessage,
|
||||
|
|
|
@ -3171,7 +3171,7 @@ nsDOMWindowUtils::ExitFullscreen()
|
|||
// Although we would not use the old size if we have already exited
|
||||
// fullscreen, we still want to cleanup in case we haven't.
|
||||
nsSize oldSize = OldWindowSize::GetAndRemove(doc->GetWindow());
|
||||
if (!doc->IsFullScreenDoc()) {
|
||||
if (!doc->GetFullscreenElement()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -9286,7 +9286,7 @@ nsDocument::OnPageHide(bool aPersisted,
|
|||
EnumerateActivityObservers(NotifyActivityChanged, nullptr);
|
||||
|
||||
ClearPendingFullscreenRequests(this);
|
||||
if (IsFullScreenDoc()) {
|
||||
if (GetFullscreenElement()) {
|
||||
// If this document was fullscreen, we should exit fullscreen in this
|
||||
// doctree branch. This ensures that if the user navigates while in
|
||||
// fullscreen mode we don't leave its still visible ancestor documents
|
||||
|
@ -11099,7 +11099,7 @@ nsIDocument::AsyncExitFullscreen(nsIDocument* aDoc)
|
|||
static bool
|
||||
CountFullscreenSubDocuments(nsIDocument* aDoc, void* aData)
|
||||
{
|
||||
if (aDoc->IsFullScreenDoc()) {
|
||||
if (aDoc->GetFullscreenElement()) {
|
||||
uint32_t* count = static_cast<uint32_t*>(aData);
|
||||
(*count)++;
|
||||
}
|
||||
|
@ -11119,7 +11119,7 @@ nsDocument::IsFullscreenLeaf()
|
|||
{
|
||||
// A fullscreen leaf document is fullscreen, and has no fullscreen
|
||||
// subdocuments.
|
||||
if (!IsFullScreenDoc()) {
|
||||
if (!GetFullscreenElement()) {
|
||||
return false;
|
||||
}
|
||||
return CountFullscreenSubDocuments(this) == 0;
|
||||
|
@ -11128,11 +11128,12 @@ nsDocument::IsFullscreenLeaf()
|
|||
static bool
|
||||
ResetFullScreen(nsIDocument* aDocument, void* aData)
|
||||
{
|
||||
if (aDocument->IsFullScreenDoc()) {
|
||||
if (aDocument->GetFullscreenElement()) {
|
||||
NS_ASSERTION(CountFullscreenSubDocuments(aDocument) <= 1,
|
||||
"Should have at most 1 fullscreen subdocument.");
|
||||
static_cast<nsDocument*>(aDocument)->CleanupFullscreenState();
|
||||
NS_ASSERTION(!aDocument->IsFullScreenDoc(), "Should reset full-screen");
|
||||
NS_ASSERTION(!aDocument->GetFullscreenElement(),
|
||||
"Should reset full-screen");
|
||||
auto changed = reinterpret_cast<nsCOMArray<nsIDocument>*>(aData);
|
||||
changed->AppendElement(aDocument);
|
||||
aDocument->EnumerateSubDocuments(ResetFullScreen, aData);
|
||||
|
@ -11179,7 +11180,7 @@ nsIDocument::ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
|
|||
UnlockPointer();
|
||||
|
||||
nsCOMPtr<nsIDocument> root = aMaybeNotARootDoc->GetFullscreenRoot();
|
||||
if (!root || !root->IsFullScreenDoc()) {
|
||||
if (!root || !root->GetFullscreenElement()) {
|
||||
// If a document was detached before exiting from fullscreen, it is
|
||||
// possible that the root had left fullscreen state. In this case,
|
||||
// we would not get anything from the ResetFullScreen() call. Root's
|
||||
|
@ -11208,7 +11209,7 @@ nsIDocument::ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
|
|||
DispatchFullScreenChange(changed[changed.Length() - i - 1]);
|
||||
}
|
||||
|
||||
NS_ASSERTION(!root->IsFullScreenDoc(),
|
||||
NS_ASSERTION(!root->GetFullscreenElement(),
|
||||
"Fullscreen root should no longer be a fullscreen doc...");
|
||||
|
||||
// Move the top-level window out of fullscreen mode.
|
||||
|
@ -11225,7 +11226,7 @@ GetFullscreenLeaf(nsIDocument* aDoc, void* aData)
|
|||
nsIDocument** result = static_cast<nsIDocument**>(aData);
|
||||
*result = aDoc;
|
||||
return false;
|
||||
} else if (aDoc->IsFullScreenDoc()) {
|
||||
} else if (aDoc->GetFullscreenElement()) {
|
||||
aDoc->EnumerateSubDocuments(GetFullscreenLeaf, aData);
|
||||
}
|
||||
return true;
|
||||
|
@ -11244,7 +11245,7 @@ GetFullscreenLeaf(nsIDocument* aDoc)
|
|||
nsIDocument* root = nsContentUtils::GetRootDocument(aDoc);
|
||||
// Check that the root is actually fullscreen so we don't waste time walking
|
||||
// around its descendants.
|
||||
if (!root->IsFullScreenDoc()) {
|
||||
if (!root->GetFullscreenElement()) {
|
||||
return nullptr;
|
||||
}
|
||||
GetFullscreenLeaf(root, &leaf);
|
||||
|
@ -11254,10 +11255,10 @@ GetFullscreenLeaf(nsIDocument* aDoc)
|
|||
void
|
||||
nsDocument::RestorePreviousFullScreenState()
|
||||
{
|
||||
NS_ASSERTION(!IsFullScreenDoc() || !FullscreenRoots::IsEmpty(),
|
||||
NS_ASSERTION(!GetFullscreenElement() || !FullscreenRoots::IsEmpty(),
|
||||
"Should have at least 1 fullscreen root when fullscreen!");
|
||||
|
||||
if (!IsFullScreenDoc() || !GetWindow() || FullscreenRoots::IsEmpty()) {
|
||||
if (!GetFullscreenElement() || !GetWindow() || FullscreenRoots::IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -11337,12 +11338,6 @@ nsDocument::RestorePreviousFullScreenState()
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsDocument::IsFullScreenDoc()
|
||||
{
|
||||
return GetFullscreenElement() != nullptr;
|
||||
}
|
||||
|
||||
class nsCallRequestFullScreen : public nsRunnable
|
||||
{
|
||||
public:
|
||||
|
@ -11814,7 +11809,7 @@ ShouldApplyFullscreenDirectly(nsIDocument* aDoc,
|
|||
// If we are in the content process, we can apply the fullscreen
|
||||
// state directly only if we have been in DOM fullscreen, because
|
||||
// otherwise we always need to notify the chrome.
|
||||
return nsContentUtils::GetRootDocument(aDoc)->IsFullScreenDoc();
|
||||
return !!nsContentUtils::GetRootDocument(aDoc)->GetFullscreenElement();
|
||||
} else {
|
||||
// If we are in the chrome process, and the window has not been in
|
||||
// fullscreen, we certainly need to make that fullscreen first.
|
||||
|
@ -12151,7 +12146,7 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (doc->IsFullScreenDoc() || doc->mAllowRelocking) {
|
||||
if (doc->GetFullscreenElement() || doc->mAllowRelocking) {
|
||||
Allow(JS::UndefinedHandleValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -1200,7 +1200,6 @@ public:
|
|||
mozilla::UniquePtr<FullscreenRequest>&& aRequest) override;
|
||||
virtual void RestorePreviousFullScreenState() override;
|
||||
virtual bool IsFullscreenLeaf() override;
|
||||
virtual bool IsFullScreenDoc() override;
|
||||
virtual nsresult
|
||||
RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement) override;
|
||||
|
||||
|
|
|
@ -1230,7 +1230,8 @@ nsFocusManager::SetFocusInner(nsIContent* aNewContent, int32_t aFlags,
|
|||
// to guard against phishing.
|
||||
#ifndef XP_MACOSX
|
||||
if (contentToFocus &&
|
||||
nsContentUtils::GetRootDocument(contentToFocus->OwnerDoc())->IsFullScreenDoc() &&
|
||||
nsContentUtils::
|
||||
GetRootDocument(contentToFocus->OwnerDoc())->GetFullscreenElement() &&
|
||||
nsContentUtils::HasPluginWithUncontrolledEventDispatch(contentToFocus)) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DOM"),
|
||||
|
|
|
@ -1175,11 +1175,6 @@ public:
|
|||
*/
|
||||
virtual void RestorePreviousFullScreenState() = 0;
|
||||
|
||||
/**
|
||||
* Returns true if this document is in full-screen mode.
|
||||
*/
|
||||
virtual bool IsFullScreenDoc() = 0;
|
||||
|
||||
/**
|
||||
* Returns true if this document is a fullscreen leaf document, i.e. it
|
||||
* is in fullscreen mode and has no fullscreen children.
|
||||
|
@ -2505,7 +2500,7 @@ public:
|
|||
virtual Element* GetFullscreenElement() = 0;
|
||||
bool MozFullScreen()
|
||||
{
|
||||
return IsFullScreenDoc();
|
||||
return !!GetFullscreenElement();
|
||||
}
|
||||
void ExitFullscreen();
|
||||
Element* GetMozPointerLockElement();
|
||||
|
|
|
@ -2091,7 +2091,7 @@ nsRange::CutContents(DocumentFragment** aFragment)
|
|||
} else if (nodeToResult) {
|
||||
nsMutationGuard guard;
|
||||
nsCOMPtr<nsINode> node = nodeToResult;
|
||||
nsINode* parent = node->GetParentNode();
|
||||
nsCOMPtr<nsINode> parent = node->GetParentNode();
|
||||
if (parent) {
|
||||
mozilla::ErrorResult error;
|
||||
parent->RemoveChild(*node, error);
|
||||
|
|
|
@ -58,8 +58,7 @@ nsStructuredCloneContainer::InitFromJSVal(JS::Handle<JS::Value> aData,
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsStructuredCloneContainer::InitFromBase64(const nsAString &aData,
|
||||
uint32_t aFormatVersion,
|
||||
JSContext* aCx)
|
||||
uint32_t aFormatVersion)
|
||||
{
|
||||
if (DataLength()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -1415,8 +1415,8 @@ nsTreeSanitizer::SanitizeChildren(nsINode* aRoot)
|
|||
}
|
||||
if (MustFlatten(ns, localName)) {
|
||||
RemoveAllAttributes(node);
|
||||
nsIContent* next = node->GetNextNode(aRoot);
|
||||
nsIContent* parent = node->GetParent();
|
||||
nsCOMPtr<nsIContent> next = node->GetNextNode(aRoot);
|
||||
nsCOMPtr<nsIContent> parent = node->GetParent();
|
||||
nsCOMPtr<nsIContent> child; // Must keep the child alive during move
|
||||
ErrorResult rv;
|
||||
while ((child = node->GetFirstChild())) {
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
const CC = Components.Constructor;
|
||||
const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
|
||||
"nsIBinaryInputStream",
|
||||
"setInputStream");
|
||||
|
||||
function utf8decode(s) {
|
||||
return decodeURIComponent(escape(s));
|
||||
}
|
||||
|
||||
function utf8encode(s) {
|
||||
return unescape(encodeURIComponent(s));
|
||||
}
|
||||
|
||||
function handleRequest(request, response) {
|
||||
var bodyStream = new BinaryInputStream(request.bodyInputStream);
|
||||
|
||||
var requestBody = "";
|
||||
while ((bodyAvail = bodyStream.available()) > 0) {
|
||||
requestBody += bodyStream.readBytes(bodyAvail);
|
||||
}
|
||||
|
||||
var result = [];
|
||||
|
||||
if (request.method == "POST") {
|
||||
var contentTypeParams = {};
|
||||
request.getHeader("Content-Type").split(/\s*\;\s*/).forEach(function(s) {
|
||||
if (s.indexOf('=') >= 0) {
|
||||
let [name, value] = s.split('=');
|
||||
contentTypeParams[name] = value;
|
||||
}
|
||||
else {
|
||||
contentTypeParams[''] = s;
|
||||
}
|
||||
});
|
||||
|
||||
if (contentTypeParams[''] == "multipart/form-data" &&
|
||||
request.queryString == "") {
|
||||
requestBody.split("--" + contentTypeParams.boundary).slice(1, -1).forEach(function (s) {
|
||||
|
||||
let headers = {};
|
||||
let headerEnd = s.indexOf("\r\n\r\n");
|
||||
s.substr(2, headerEnd-2).split("\r\n").forEach(function(s) {
|
||||
// We're assuming UTF8 for now
|
||||
let [name, value] = s.split(': ');
|
||||
headers[name] = utf8decode(value);
|
||||
});
|
||||
|
||||
let body = s.substring(headerEnd + 4, s.length - 2);
|
||||
if (!headers["Content-Type"] || headers["Content-Type"] == "text/plain") {
|
||||
// We're assuming UTF8 for now
|
||||
body = utf8decode(body);
|
||||
}
|
||||
result.push({ headers: headers, body: body});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
||||
response.write(utf8encode(JSON.stringify(result)));
|
||||
}
|
|
@ -258,6 +258,7 @@ support-files =
|
|||
referrer_change_server.sjs
|
||||
file_change_policy_redirect.html
|
||||
file_bug1198095.js
|
||||
file_bug1250148.sjs
|
||||
|
||||
[test_anonymousContent_api.html]
|
||||
[test_anonymousContent_append_after_reflow.html]
|
||||
|
@ -870,3 +871,4 @@ skip-if = buildapp == 'b2g' #no ssl support
|
|||
[test_bug1198095.html]
|
||||
[test_bug1187157.html]
|
||||
[test_bug769117.html]
|
||||
[test_bug1250148.html]
|
||||
|
|
|
@ -15,14 +15,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=789315
|
|||
|
||||
<script type="text/javascript">
|
||||
var obj = new FormData(document.getElementById('a')).get('b');
|
||||
is(obj, "", "We want an empty string.");
|
||||
|
||||
ok(obj instanceof Blob, "This should return an empty Blob");
|
||||
is(obj.size, 0, "Size should be 0");
|
||||
is(obj.type, "application/octet-stream", "Type should be application/octet-stream");
|
||||
|
||||
var o = obj.slice(10, 100, "foo/bar");
|
||||
is(o.size, 0, "The new blob has size 0");
|
||||
is(o.type, "foo/bar", "The new blob has type foo/bar");
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1250148
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1250148 - FormData and HTML submission compatibility</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<form id="form" enctype="multipart/form-data"><input type="file" name="test" /></form>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var f = document.getElementById('form');
|
||||
var fd = new FormData(f);
|
||||
is(fd.get("test"), "", "We want an empty string.");
|
||||
|
||||
var getAll = fd.getAll("test");
|
||||
ok(Array.isArray(getAll), "We want an array with 1 empty string.");
|
||||
is(getAll.length, 1, "We want an array with 1 empty string.");
|
||||
is(getAll[0], "", "We want an array with 1 empty string.");
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "file_bug1250148.sjs", true);
|
||||
xhr.onload = function() {
|
||||
var obj = JSON.parse(xhr.responseText);
|
||||
|
||||
ok(Array.isArray(obj), "XHR response is an array.");
|
||||
is(obj.length, 1, "XHR response array contains 1 result.");
|
||||
|
||||
ok("headers" in obj[0], "XHR response has an header value");
|
||||
|
||||
ok("Content-Disposition" in obj[0].headers, "XHR response.headers array has a Content-Desposition value");
|
||||
is(obj[0].headers["Content-Disposition"], "form-data; name=\"test\"; filename=\"\"", "Correct Content-Disposition");
|
||||
|
||||
ok("Content-Type" in obj[0].headers, "XHR response.headers array has a Content-Type value");
|
||||
is(obj[0].headers["Content-Type"], "application/octet-stream", "Correct Content-Type");
|
||||
|
||||
ok("body" in obj[0], "XHR response has a body value");
|
||||
is(obj[0].body, "", "Correct body value");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
xhr.send(fd);
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -2,6 +2,8 @@
|
|||
# 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/.
|
||||
|
||||
ifdef COMPILE_ENVIRONMENT
|
||||
|
||||
include ../webidlsrcs.mk
|
||||
|
||||
# $(test_sources) comes from webidlsrcs.mk.
|
||||
|
@ -12,6 +14,8 @@ CPPSRCS += $(addprefix ../,$(test_sources))
|
|||
# rules.mk and running make with no target in this dir does the right thing.
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
endif
|
||||
|
||||
check::
|
||||
PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
|
||||
$(PLY_INCLUDE) $(srcdir)/../parser/runtests.py
|
||||
|
|
|
@ -177,7 +177,7 @@ public:
|
|||
// Getter for the window that this Geolocation is owned by
|
||||
nsIWeakReference* GetOwner() { return mOwner; }
|
||||
|
||||
// Check to see if the widnow still exists
|
||||
// Check to see if the window still exists
|
||||
bool WindowOwnerStillExists();
|
||||
|
||||
// Check to see if any active request requires high accuracy
|
||||
|
|
|
@ -5582,14 +5582,11 @@ HTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
|
|||
const nsTArray<RefPtr<File>>& files = GetFilesInternal();
|
||||
|
||||
for (uint32_t i = 0; i < files.Length(); ++i) {
|
||||
aFormSubmission->AddNameBlobPair(name, files[i]);
|
||||
aFormSubmission->AddNameBlobOrNullPair(name, files[i]);
|
||||
}
|
||||
|
||||
if (files.IsEmpty()) {
|
||||
RefPtr<BlobImpl> blobImpl =
|
||||
new EmptyBlobImpl(NS_LITERAL_STRING("application/octet-stream"));
|
||||
RefPtr<Blob> blob = Blob::Create(OwnerDoc()->GetInnerWindow(), blobImpl);
|
||||
aFormSubmission->AddNameBlobPair(name, blob);
|
||||
aFormSubmission->AddNameBlobOrNullPair(name, nullptr);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -577,7 +577,7 @@ HTMLSelectElement::Add(nsGenericHTMLElement& aElement,
|
|||
|
||||
// Just in case we're not the parent, get the parent of the reference
|
||||
// element
|
||||
nsINode* parent = aBefore->Element::GetParentNode();
|
||||
nsCOMPtr<nsINode> parent = aBefore->Element::GetParentNode();
|
||||
if (!parent || !nsContentUtils::ContentIsDescendantOf(parent, this)) {
|
||||
// NOT_FOUND_ERR: Raised if before is not a descendant of the SELECT
|
||||
// element.
|
||||
|
|
|
@ -521,8 +521,8 @@ HTMLTableElement::InsertRow(int32_t aIndex, ErrorResult& aError)
|
|||
refIndex = rowCount - 1;
|
||||
}
|
||||
|
||||
Element* refRow = rows->Item(refIndex);
|
||||
nsINode* parent = refRow->GetParentNode();
|
||||
RefPtr<Element> refRow = rows->Item(refIndex);
|
||||
nsCOMPtr<nsINode> parent = refRow->GetParentNode();
|
||||
|
||||
// create the row
|
||||
RefPtr<mozilla::dom::NodeInfo> nodeInfo;
|
||||
|
|
|
@ -57,7 +57,9 @@ SendJSWarning(nsIDocument* aDocument,
|
|||
static void
|
||||
RetrieveFileName(Blob* aBlob, nsAString& aFilename)
|
||||
{
|
||||
MOZ_ASSERT(aBlob);
|
||||
if (!aBlob) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<File> file = aBlob->ToFile();
|
||||
if (file) {
|
||||
|
@ -88,8 +90,8 @@ public:
|
|||
|
||||
virtual nsresult AddNameValuePair(const nsAString& aName,
|
||||
const nsAString& aValue) override;
|
||||
virtual nsresult AddNameBlobPair(const nsAString& aName,
|
||||
Blob* aBlob) override;
|
||||
virtual nsresult AddNameBlobOrNullPair(const nsAString& aName,
|
||||
Blob* aBlob) override;
|
||||
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
|
||||
nsIInputStream** aPostDataStream)
|
||||
override;
|
||||
|
@ -175,11 +177,9 @@ nsFSURLEncoded::AddIsindex(const nsAString& aValue)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsFSURLEncoded::AddNameBlobPair(const nsAString& aName,
|
||||
Blob* aBlob)
|
||||
nsFSURLEncoded::AddNameBlobOrNullPair(const nsAString& aName,
|
||||
Blob* aBlob)
|
||||
{
|
||||
MOZ_ASSERT(aBlob);
|
||||
|
||||
if (!mWarnedFileControl) {
|
||||
SendJSWarning(mDocument, "ForgotFileEnctypeWarning", nullptr, 0);
|
||||
mWarnedFileControl = true;
|
||||
|
@ -436,7 +436,7 @@ nsFSMultipartFormData::AddNameValuePair(const nsAString& aName,
|
|||
// Make MIME block for name/value pair
|
||||
|
||||
// XXX: name parameter should be encoded per RFC 2231
|
||||
// RFC 2388 specifies that RFC 2047 be used, but I think it's not
|
||||
// RFC 2388 specifies that RFC 2047 be used, but I think it's not
|
||||
// consistent with MIME standard.
|
||||
mPostDataChunk += NS_LITERAL_CSTRING("--") + mBoundary
|
||||
+ NS_LITERAL_CSTRING(CRLF)
|
||||
|
@ -448,66 +448,69 @@ nsFSMultipartFormData::AddNameValuePair(const nsAString& aName,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsFSMultipartFormData::AddNameBlobPair(const nsAString& aName,
|
||||
Blob* aBlob)
|
||||
nsFSMultipartFormData::AddNameBlobOrNullPair(const nsAString& aName,
|
||||
Blob* aBlob)
|
||||
{
|
||||
MOZ_ASSERT(aBlob);
|
||||
|
||||
// Encode the control name
|
||||
nsAutoCString nameStr;
|
||||
nsresult rv = EncodeVal(aName, nameStr, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString filename16;
|
||||
RetrieveFileName(aBlob, filename16);
|
||||
nsAutoCString filename;
|
||||
nsAutoCString contentType;
|
||||
nsCOMPtr<nsIInputStream> fileStream;
|
||||
|
||||
ErrorResult error;
|
||||
nsAutoString filepath16;
|
||||
RefPtr<File> file = aBlob->ToFile();
|
||||
if (file) {
|
||||
file->GetPath(filepath16, error);
|
||||
if (aBlob) {
|
||||
nsAutoString filename16;
|
||||
RetrieveFileName(aBlob, filename16);
|
||||
|
||||
ErrorResult error;
|
||||
nsAutoString filepath16;
|
||||
RefPtr<File> file = aBlob->ToFile();
|
||||
if (file) {
|
||||
file->GetPath(filepath16, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
}
|
||||
|
||||
if (!filepath16.IsEmpty()) {
|
||||
// File.path includes trailing "/"
|
||||
filename16 = filepath16 + filename16;
|
||||
}
|
||||
|
||||
rv = EncodeVal(filename16, filename, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get content type
|
||||
nsAutoString contentType16;
|
||||
aBlob->GetType(contentType16);
|
||||
if (contentType16.IsEmpty()) {
|
||||
contentType16.AssignLiteral("application/octet-stream");
|
||||
}
|
||||
|
||||
contentType.Adopt(nsLinebreakConverter::
|
||||
ConvertLineBreaks(NS_ConvertUTF16toUTF8(contentType16).get(),
|
||||
nsLinebreakConverter::eLinebreakAny,
|
||||
nsLinebreakConverter::eLinebreakSpace));
|
||||
|
||||
// Get input stream
|
||||
aBlob->GetInternalStream(getter_AddRefs(fileStream), error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
}
|
||||
|
||||
if (!filepath16.IsEmpty()) {
|
||||
// File.path includes trailing "/"
|
||||
filename16 = filepath16 + filename16;
|
||||
}
|
||||
if (fileStream) {
|
||||
// Create buffered stream (for efficiency)
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||
fileStream, 8192);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString filename;
|
||||
rv = EncodeVal(filename16, filename, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get content type
|
||||
nsAutoString contentType16;
|
||||
aBlob->GetType(contentType16);
|
||||
if (contentType16.IsEmpty()) {
|
||||
contentType16.AssignLiteral("application/octet-stream");
|
||||
}
|
||||
|
||||
nsAutoCString contentType;
|
||||
contentType.Adopt(nsLinebreakConverter::
|
||||
ConvertLineBreaks(NS_ConvertUTF16toUTF8(contentType16).get(),
|
||||
nsLinebreakConverter::eLinebreakAny,
|
||||
nsLinebreakConverter::eLinebreakSpace));
|
||||
|
||||
// Get input stream
|
||||
nsCOMPtr<nsIInputStream> fileStream;
|
||||
aBlob->GetInternalStream(getter_AddRefs(fileStream), error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
||||
if (fileStream) {
|
||||
// Create buffered stream (for efficiency)
|
||||
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||
fileStream, 8192);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
fileStream = bufferedStream;
|
||||
fileStream = bufferedStream;
|
||||
}
|
||||
} else {
|
||||
contentType.AssignLiteral("application/octet-stream");
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -517,7 +520,7 @@ nsFSMultipartFormData::AddNameBlobPair(const nsAString& aName,
|
|||
mPostDataChunk += NS_LITERAL_CSTRING("--") + mBoundary
|
||||
+ NS_LITERAL_CSTRING(CRLF);
|
||||
// XXX: name/filename parameter should be encoded per RFC 2231
|
||||
// RFC 2388 specifies that RFC 2047 be used, but I think it's not
|
||||
// RFC 2388 specifies that RFC 2047 be used, but I think it's not
|
||||
// consistent with the MIME standard.
|
||||
mPostDataChunk +=
|
||||
NS_LITERAL_CSTRING("Content-Disposition: form-data; name=\"")
|
||||
|
@ -576,7 +579,7 @@ nsresult
|
|||
nsFSMultipartFormData::AddPostDataStream()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
||||
nsCOMPtr<nsIInputStream> postDataChunkStream;
|
||||
rv = NS_NewCStringInputStream(getter_AddRefs(postDataChunkStream),
|
||||
mPostDataChunk);
|
||||
|
@ -603,8 +606,8 @@ public:
|
|||
|
||||
virtual nsresult AddNameValuePair(const nsAString& aName,
|
||||
const nsAString& aValue) override;
|
||||
virtual nsresult AddNameBlobPair(const nsAString& aName,
|
||||
Blob* aBlob) override;
|
||||
virtual nsresult AddNameBlobOrNullPair(const nsAString& aName,
|
||||
Blob* aBlob) override;
|
||||
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
|
||||
nsIInputStream** aPostDataStream)
|
||||
override;
|
||||
|
@ -627,11 +630,9 @@ nsFSTextPlain::AddNameValuePair(const nsAString& aName,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsFSTextPlain::AddNameBlobPair(const nsAString& aName,
|
||||
Blob* aBlob)
|
||||
nsFSTextPlain::AddNameBlobOrNullPair(const nsAString& aName,
|
||||
Blob* aBlob)
|
||||
{
|
||||
MOZ_ASSERT(aBlob);
|
||||
|
||||
nsAutoString filename;
|
||||
RetrieveFileName(aBlob, filename);
|
||||
AddNameValuePair(aName, filename);
|
||||
|
|
|
@ -49,10 +49,11 @@ public:
|
|||
*
|
||||
* @param aName the name of the parameter
|
||||
* @param aBlob the blob to submit. The file's name will be used if the Blob
|
||||
* is actually a File, otherwise 'blob' string is used instead.
|
||||
* is actually a File, otherwise 'blob' string is used instead if the aBlob is
|
||||
* not null.
|
||||
*/
|
||||
virtual nsresult AddNameBlobPair(const nsAString& aName,
|
||||
mozilla::dom::Blob* aBlob) = 0;
|
||||
virtual nsresult AddNameBlobOrNullPair(const nsAString& aName,
|
||||
mozilla::dom::Blob* aBlob) = 0;
|
||||
|
||||
/**
|
||||
* Reports whether the instance supports AddIsindex().
|
||||
|
@ -160,8 +161,8 @@ public:
|
|||
|
||||
virtual nsresult AddNameValuePair(const nsAString& aName,
|
||||
const nsAString& aValue) override;
|
||||
virtual nsresult AddNameBlobPair(const nsAString& aName,
|
||||
mozilla::dom::Blob* aBlob) override;
|
||||
virtual nsresult AddNameBlobOrNullPair(const nsAString& aName,
|
||||
mozilla::dom::Blob* aBlob) override;
|
||||
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
|
||||
nsIInputStream** aPostDataStream) override;
|
||||
|
||||
|
|
|
@ -486,7 +486,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g
|
|||
[test_iframe_sandbox_popups.html]
|
||||
skip-if = buildapp == 'b2g' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
|
||||
[test_iframe_sandbox_popups_inheritance.html]
|
||||
skip-if = buildapp == 'b2g' || e10s || toolkit == 'android' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage) android(bug 939642)
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage) android(bug 939642)
|
||||
[test_iframe_sandbox_redirect.html]
|
||||
[test_iframe_sandbox_refresh.html]
|
||||
[test_iframe_sandbox_same_origin.html]
|
||||
|
@ -582,7 +582,7 @@ skip-if = toolkit == 'android'
|
|||
[test_bug677495.html]
|
||||
[test_bug677495-1.html]
|
||||
[test_bug741266.html]
|
||||
skip-if = buildapp == "mulet" || buildapp == "b2g" || toolkit == "android" || toolkit == "windows" || e10s # b2g(needs control of popup window size) b2g-debug(needs control of popup window size) b2g-desktop(needs control of popup window size) windows(bug 1234520)
|
||||
skip-if = buildapp == "mulet" || buildapp == "b2g" || toolkit == "android" || toolkit == "windows" # b2g(needs control of popup window size) b2g-debug(needs control of popup window size) b2g-desktop(needs control of popup window size) windows(bug 1234520)
|
||||
[test_non-ascii-cookie.html]
|
||||
skip-if = buildapp == 'b2g'
|
||||
support-files = file_cookiemanager.js
|
||||
|
|
|
@ -590,7 +590,7 @@ var expectedAugment = [
|
|||
//{ name: "aNameUndef", value: "undefined" },
|
||||
];
|
||||
|
||||
function checkMPSubmission(sub, expected, test, isFormData = false) {
|
||||
function checkMPSubmission(sub, expected, test) {
|
||||
function getPropCount(o) {
|
||||
var x, l = 0;
|
||||
for (x in o) ++l;
|
||||
|
@ -625,7 +625,7 @@ function checkMPSubmission(sub, expected, test, isFormData = false) {
|
|||
else {
|
||||
is(sub[i].headers["Content-Disposition"],
|
||||
"form-data; name=\"" + mpquote(expected[i].name) + "\"; filename=\"" +
|
||||
mpquote(expected[i].fileName != "" || !isFormData ? expected[i].fileName : "blob") + "\"",
|
||||
mpquote(expected[i].fileName) + "\"",
|
||||
"Correct name in " + test);
|
||||
is(sub[i].headers["Content-Type"],
|
||||
expected[i].contentType,
|
||||
|
@ -782,14 +782,14 @@ function runTest() {
|
|||
xhr.open("POST", "form_submit_server.sjs");
|
||||
xhr.send(new FormData(form));
|
||||
yield undefined; // Wait for XHR load
|
||||
checkMPSubmission(JSON.parse(xhr.responseText), expectedSub, "send form using XHR and FormData", true);
|
||||
checkMPSubmission(JSON.parse(xhr.responseText), expectedSub, "send form using XHR and FormData");
|
||||
|
||||
// Send disabled form using XHR and FormData
|
||||
setDisabled(document.querySelectorAll("input, select, textarea"), true);
|
||||
xhr.open("POST", "form_submit_server.sjs");
|
||||
xhr.send(new FormData(form));
|
||||
yield undefined;
|
||||
checkMPSubmission(JSON.parse(xhr.responseText), [], "send disabled form using XHR and FormData", true);
|
||||
checkMPSubmission(JSON.parse(xhr.responseText), [], "send disabled form using XHR and FormData");
|
||||
setDisabled(document.querySelectorAll("input, select, textarea"), false);
|
||||
|
||||
// Send FormData
|
||||
|
@ -804,7 +804,7 @@ function runTest() {
|
|||
xhr.open("POST", "form_submit_server.sjs");
|
||||
xhr.send(fd);
|
||||
yield undefined;
|
||||
checkMPSubmission(JSON.parse(xhr.responseText), expectedAugment, "send FormData", true);
|
||||
checkMPSubmission(JSON.parse(xhr.responseText), expectedAugment, "send FormData");
|
||||
|
||||
// Augment <form> using FormData
|
||||
fd = new FormData(form);
|
||||
|
@ -813,7 +813,7 @@ function runTest() {
|
|||
xhr.send(fd);
|
||||
yield undefined;
|
||||
checkMPSubmission(JSON.parse(xhr.responseText),
|
||||
expectedSub.concat(expectedAugment), "send augmented FormData", true);
|
||||
expectedSub.concat(expectedAugment), "send augmented FormData");
|
||||
|
||||
SimpleTest.finish();
|
||||
yield undefined;
|
||||
|
|
|
@ -308,7 +308,7 @@ struct FullObjectStoreMetadata
|
|||
|
||||
// These two members are only ever touched on a transaction thread!
|
||||
int64_t mNextAutoIncrementId;
|
||||
int64_t mComittedAutoIncrementId;
|
||||
int64_t mCommittedAutoIncrementId;
|
||||
|
||||
bool mDeleted;
|
||||
|
||||
|
@ -316,7 +316,7 @@ public:
|
|||
FullObjectStoreMetadata()
|
||||
: mCommonMetadata(0, nsString(), KeyPath(0), false)
|
||||
, mNextAutoIncrementId(0)
|
||||
, mComittedAutoIncrementId(0)
|
||||
, mCommittedAutoIncrementId(0)
|
||||
, mDeleted(false)
|
||||
{
|
||||
// This can happen either on the QuotaManager IO thread or on a
|
||||
|
@ -12618,7 +12618,7 @@ FullDatabaseMetadata::Duplicate() const
|
|||
|
||||
newOSMetadata->mCommonMetadata = value->mCommonMetadata;
|
||||
newOSMetadata->mNextAutoIncrementId = value->mNextAutoIncrementId;
|
||||
newOSMetadata->mComittedAutoIncrementId = value->mComittedAutoIncrementId;
|
||||
newOSMetadata->mCommittedAutoIncrementId = value->mCommittedAutoIncrementId;
|
||||
|
||||
for (auto iter = value->mIndexes.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
auto key = iter.Key();
|
||||
|
@ -15138,7 +15138,7 @@ VersionChangeTransaction::RecvCreateObjectStore(
|
|||
RefPtr<FullObjectStoreMetadata> newMetadata = new FullObjectStoreMetadata();
|
||||
newMetadata->mCommonMetadata = aMetadata;
|
||||
newMetadata->mNextAutoIncrementId = aMetadata.autoIncrement() ? 1 : 0;
|
||||
newMetadata->mComittedAutoIncrementId = newMetadata->mNextAutoIncrementId;
|
||||
newMetadata->mCommittedAutoIncrementId = newMetadata->mNextAutoIncrementId;
|
||||
|
||||
if (NS_WARN_IF(!dbMetadata->mObjectStores.Put(aMetadata.id(), newMetadata,
|
||||
fallible))) {
|
||||
|
@ -20270,7 +20270,7 @@ OpenDatabaseOp::LoadDatabaseInformation(mozIStorageConnection* aConnection)
|
|||
|
||||
metadata->mCommonMetadata.autoIncrement() = !!nextAutoIncrementId;
|
||||
metadata->mNextAutoIncrementId = nextAutoIncrementId;
|
||||
metadata->mComittedAutoIncrementId = nextAutoIncrementId;
|
||||
metadata->mCommittedAutoIncrementId = nextAutoIncrementId;
|
||||
|
||||
if (NS_WARN_IF(!objectStores.Put(objectStoreId, metadata, fallible))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -21062,13 +21062,16 @@ OpenDatabaseOp::AssertMetadataConsistency(const FullDatabaseMetadata* aMetadata)
|
|||
otherObjectStore->mCommonMetadata.autoIncrement());
|
||||
MOZ_ASSERT(thisObjectStore->mCommonMetadata.keyPath() ==
|
||||
otherObjectStore->mCommonMetadata.keyPath());
|
||||
// mNextAutoIncrementId and mComittedAutoIncrementId may be modified
|
||||
// mNextAutoIncrementId and mCommittedAutoIncrementId may be modified
|
||||
// concurrently with this OpenOp, so it is not possible to assert equality
|
||||
// here.
|
||||
// here. It's also possible that we've written the new ids to disk but not
|
||||
// yet updated the in-memory count.
|
||||
MOZ_ASSERT(thisObjectStore->mNextAutoIncrementId <=
|
||||
otherObjectStore->mNextAutoIncrementId);
|
||||
MOZ_ASSERT(thisObjectStore->mComittedAutoIncrementId <=
|
||||
otherObjectStore->mComittedAutoIncrementId);
|
||||
MOZ_ASSERT(thisObjectStore->mCommittedAutoIncrementId <=
|
||||
otherObjectStore->mCommittedAutoIncrementId ||
|
||||
thisObjectStore->mCommittedAutoIncrementId ==
|
||||
otherObjectStore->mNextAutoIncrementId);
|
||||
MOZ_ASSERT(!otherObjectStore->mDeleted);
|
||||
|
||||
MOZ_ASSERT(thisObjectStore->mIndexes.Count() ==
|
||||
|
@ -22151,9 +22154,9 @@ CommitOp::CommitOrRollbackAutoIncrementCounts()
|
|||
RefPtr<FullObjectStoreMetadata>& metadata = metadataArray[index];
|
||||
|
||||
if (committed) {
|
||||
metadata->mComittedAutoIncrementId = metadata->mNextAutoIncrementId;
|
||||
metadata->mCommittedAutoIncrementId = metadata->mNextAutoIncrementId;
|
||||
} else {
|
||||
metadata->mNextAutoIncrementId = metadata->mComittedAutoIncrementId;
|
||||
metadata->mNextAutoIncrementId = metadata->mCommittedAutoIncrementId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,8 +42,7 @@ interface nsIStructuredCloneContainer : nsISupports
|
|||
* stream, stored in aData. aFormatVersion should be the version of the
|
||||
* structured clone algorithm which was used to generate aData.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void initFromBase64(in AString aData,in unsigned long aFormatVersion);
|
||||
void initFromBase64(in AString aData, in unsigned long aFormatVersion);
|
||||
|
||||
/**
|
||||
* Deserializes this structured clone container returning it as a jsval.
|
||||
|
|
|
@ -156,8 +156,6 @@
|
|||
#include "nsPIWindowWatcher.h"
|
||||
#include "nsWindowWatcher.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "gfxDrawable.h"
|
||||
#include "ImageOps.h"
|
||||
#include "mozilla/dom/nsMixedContentBlocker.h"
|
||||
#include "nsMemoryInfoDumper.h"
|
||||
#include "nsMemoryReporterManager.h"
|
||||
|
@ -2865,75 +2863,56 @@ ContentParent::RecvSetClipboard(const IPCDataTransfer& aDataTransfer,
|
|||
nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
nsCOMPtr<nsITransferable> trans = do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
|
||||
nsCOMPtr<nsITransferable> trans =
|
||||
do_CreateInstance("@mozilla.org/widget/transferable;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
trans->Init(nullptr);
|
||||
|
||||
const nsTArray<IPCDataTransferItem>& items = aDataTransfer.items();
|
||||
for (uint32_t j = 0; j < items.Length(); ++j) {
|
||||
const IPCDataTransferItem& item = items[j];
|
||||
|
||||
for (const auto& item : items) {
|
||||
trans->AddDataFlavor(item.flavor().get());
|
||||
|
||||
if (item.data().type() == IPCDataTransferData::TnsString) {
|
||||
nsCOMPtr<nsISupportsString> dataWrapper =
|
||||
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
nsString text = item.data().get_nsString();
|
||||
rv = dataWrapper->SetData(text);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
rv = trans->SetTransferData(item.flavor().get(), dataWrapper,
|
||||
text.Length() * sizeof(char16_t));
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
} else if (item.data().type() == IPCDataTransferData::TnsCString) {
|
||||
if (item.flavor().EqualsLiteral(kNativeImageMime) ||
|
||||
item.flavor().EqualsLiteral(kJPEGImageMime) ||
|
||||
item.flavor().EqualsLiteral(kJPGImageMime) ||
|
||||
item.flavor().EqualsLiteral(kPNGImageMime) ||
|
||||
item.flavor().EqualsLiteral(kGIFImageMime)) {
|
||||
const IPCDataTransferImage& imageDetails = item.imageDetails();
|
||||
const gfx::IntSize size(imageDetails.width(), imageDetails.height());
|
||||
if (!size.width || !size.height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCString text = item.data().get_nsCString();
|
||||
RefPtr<gfx::DataSourceSurface> image =
|
||||
new mozilla::gfx::SourceSurfaceRawData();
|
||||
mozilla::gfx::SourceSurfaceRawData* raw =
|
||||
static_cast<mozilla::gfx::SourceSurfaceRawData*>(image.get());
|
||||
raw->InitWrappingData(
|
||||
reinterpret_cast<uint8_t*>(const_cast<nsCString&>(text).BeginWriting()),
|
||||
size, imageDetails.stride(),
|
||||
static_cast<mozilla::gfx::SurfaceFormat>(imageDetails.format()), false);
|
||||
raw->GuaranteePersistance();
|
||||
|
||||
RefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(image, size);
|
||||
nsCOMPtr<imgIContainer> imageContainer(image::ImageOps::CreateFromDrawable(drawable));
|
||||
|
||||
nsCOMPtr<nsISupportsInterfacePointer>
|
||||
imgPtr(do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv));
|
||||
|
||||
rv = imgPtr->SetData(imageContainer);
|
||||
nsCOMPtr<nsISupportsString> dataWrapper =
|
||||
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
trans->SetTransferData(item.flavor().get(), imgPtr, sizeof(nsISupports*));
|
||||
} else {
|
||||
nsCOMPtr<nsISupportsCString> dataWrapper =
|
||||
do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
const nsCString& text = item.data().get_nsCString();
|
||||
const nsString& text = item.data().get_nsString();
|
||||
rv = dataWrapper->SetData(text);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
rv = trans->SetTransferData(item.flavor().get(), dataWrapper, text.Length());
|
||||
rv = trans->SetTransferData(item.flavor().get(), dataWrapper,
|
||||
text.Length() * sizeof(char16_t));
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
}
|
||||
} else if (item.data().type() == IPCDataTransferData::TnsCString) {
|
||||
if (nsContentUtils::IsFlavorImage(item.flavor())) {
|
||||
nsCOMPtr<imgIContainer> imageContainer;
|
||||
rv = nsContentUtils::DataTransferItemToImage(item,
|
||||
getter_AddRefs(imageContainer));
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
nsCOMPtr<nsISupportsInterfacePointer> imgPtr =
|
||||
do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(imgPtr, true);
|
||||
|
||||
rv = imgPtr->SetData(imageContainer);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
trans->SetTransferData(item.flavor().get(), imgPtr, sizeof(nsISupports*));
|
||||
} else {
|
||||
nsCOMPtr<nsISupportsCString> dataWrapper =
|
||||
do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
const nsCString& text = item.data().get_nsCString();
|
||||
rv = dataWrapper->SetData(text);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
rv = trans->SetTransferData(item.flavor().get(), dataWrapper, text.Length());
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3152,24 +3152,7 @@ TabParent::RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
|
|||
|
||||
EventStateManager* esm = shell->GetPresContext()->EventStateManager();
|
||||
for (uint32_t i = 0; i < aTransfers.Length(); ++i) {
|
||||
auto& items = aTransfers[i].items();
|
||||
nsTArray<DataTransferItem>* itemArray = mInitialDataTransferItems.AppendElement();
|
||||
for (uint32_t j = 0; j < items.Length(); ++j) {
|
||||
const IPCDataTransferItem& item = items[j];
|
||||
DataTransferItem* localItem = itemArray->AppendElement();
|
||||
localItem->mFlavor = item.flavor();
|
||||
if (item.data().type() == IPCDataTransferData::TnsString) {
|
||||
localItem->mType = DataTransferItem::DataType::eString;
|
||||
localItem->mStringData = item.data().get_nsString();
|
||||
} else if (item.data().type() == IPCDataTransferData::TPBlobChild) {
|
||||
localItem->mType = DataTransferItem::DataType::eBlob;
|
||||
BlobParent* blobParent =
|
||||
static_cast<BlobParent*>(item.data().get_PBlobParent());
|
||||
if (blobParent) {
|
||||
localItem->mBlobData = blobParent->GetBlobImpl();
|
||||
}
|
||||
}
|
||||
}
|
||||
mInitialDataTransferItems.AppendElement(mozilla::Move(aTransfers[i].items()));
|
||||
}
|
||||
if (Manager()->IsContentParent()) {
|
||||
nsCOMPtr<nsIDragService> dragService =
|
||||
|
@ -3205,24 +3188,37 @@ void
|
|||
TabParent::AddInitialDnDDataTo(DataTransfer* aDataTransfer)
|
||||
{
|
||||
for (uint32_t i = 0; i < mInitialDataTransferItems.Length(); ++i) {
|
||||
nsTArray<DataTransferItem>& itemArray = mInitialDataTransferItems[i];
|
||||
for (uint32_t j = 0; j < itemArray.Length(); ++j) {
|
||||
DataTransferItem& item = itemArray[j];
|
||||
nsTArray<IPCDataTransferItem>& itemArray = mInitialDataTransferItems[i];
|
||||
for (auto& item : itemArray) {
|
||||
RefPtr<nsVariantCC> variant = new nsVariantCC();
|
||||
// Special case kFilePromiseMime so that we get the right
|
||||
// nsIFlavorDataProvider for it.
|
||||
if (item.mFlavor.EqualsLiteral(kFilePromiseMime)) {
|
||||
if (item.flavor().EqualsLiteral(kFilePromiseMime)) {
|
||||
RefPtr<nsISupports> flavorDataProvider =
|
||||
new nsContentAreaDragDropDataProvider();
|
||||
variant->SetAsISupports(flavorDataProvider);
|
||||
} else if (item.mType == DataTransferItem::DataType::eString) {
|
||||
variant->SetAsAString(item.mStringData);
|
||||
} else if (item.mType == DataTransferItem::DataType::eBlob) {
|
||||
variant->SetAsISupports(item.mBlobData);
|
||||
} else if (item.data().type() == IPCDataTransferData::TnsString) {
|
||||
variant->SetAsAString(item.data().get_nsString());
|
||||
} else if (item.data().type() == IPCDataTransferData::TPBlobParent) {
|
||||
auto* parent = static_cast<BlobParent*>(item.data().get_PBlobParent());
|
||||
RefPtr<BlobImpl> impl = parent->GetBlobImpl();
|
||||
variant->SetAsISupports(impl);
|
||||
} else if (item.data().type() == IPCDataTransferData::TnsCString &&
|
||||
nsContentUtils::IsFlavorImage(item.flavor())) {
|
||||
// An image! Get the imgIContainer for it and set it in the variant.
|
||||
nsCOMPtr<imgIContainer> imageContainer;
|
||||
nsresult rv =
|
||||
nsContentUtils::DataTransferItemToImage(item,
|
||||
getter_AddRefs(imageContainer));
|
||||
if (NS_FAILED(rv)) {
|
||||
continue;
|
||||
}
|
||||
variant->SetAsISupports(imageContainer);
|
||||
}
|
||||
|
||||
// Using system principal here, since once the data is on parent process
|
||||
// side, it can be handled as being from browser chrome or OS.
|
||||
aDataTransfer->SetDataWithPrincipal(NS_ConvertUTF8toUTF16(item.mFlavor),
|
||||
aDataTransfer->SetDataWithPrincipal(NS_ConvertUTF8toUTF16(item.flavor()),
|
||||
variant, i,
|
||||
nsContentUtils::GetSystemPrincipal());
|
||||
}
|
||||
|
|
|
@ -644,19 +644,7 @@ private:
|
|||
|
||||
uint32_t mChromeFlags;
|
||||
|
||||
struct DataTransferItem
|
||||
{
|
||||
nsCString mFlavor;
|
||||
nsString mStringData;
|
||||
RefPtr<mozilla::dom::BlobImpl> mBlobData;
|
||||
enum DataType
|
||||
{
|
||||
eString,
|
||||
eBlob
|
||||
};
|
||||
DataType mType;
|
||||
};
|
||||
nsTArray<nsTArray<DataTransferItem>> mInitialDataTransferItems;
|
||||
nsTArray<nsTArray<IPCDataTransferItem>> mInitialDataTransferItems;
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> mDnDVisualization;
|
||||
int32_t mDragAreaX;
|
||||
|
|
|
@ -2052,6 +2052,17 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
|
|||
RemoveFromWindowList(windowID, listener);
|
||||
return NS_OK;
|
||||
}
|
||||
} else if (loop) {
|
||||
// Record that we gave Loop permission to use camera access.
|
||||
nsCOMPtr<nsIPermissionManager> permManager =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = permManager->Add(docURI, "camera",
|
||||
nsIPermissionManager::ALLOW_ACTION,
|
||||
nsIPermissionManager::EXPIRE_SESSION,
|
||||
0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
#if defined(MOZ_B2G_CAMERA) && defined(MOZ_WIDGET_GONK)
|
||||
|
|
|
@ -137,17 +137,6 @@ GetPluginFile(const nsAString& aPluginPath,
|
|||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
GetInfoFile(const nsAString& aPluginPath,
|
||||
nsCOMPtr<nsIFile>& aInfoFile)
|
||||
{
|
||||
nsAutoString baseName;
|
||||
GetFileBase(aPluginPath, aInfoFile, baseName);
|
||||
nsAutoString infoFileName = baseName + NS_LITERAL_STRING(".info");
|
||||
aInfoFile->AppendRelativePath(infoFileName);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
|
||||
static nsCString
|
||||
GetNativeTarget(nsIFile* aFile)
|
||||
|
@ -268,14 +257,6 @@ GMPChild::Init(const nsAString& aPluginPath,
|
|||
mPluginPath = aPluginPath;
|
||||
mSandboxVoucherPath = aVoucherPath;
|
||||
|
||||
nsCOMPtr<nsIFile> infoFile;
|
||||
if (!GetInfoFile(mPluginPath, infoFile) || !infoFile) {
|
||||
return false;
|
||||
}
|
||||
if (!mInfoParser.Init(infoFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -300,12 +281,12 @@ GMPChild::GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI)
|
|||
return mGMPLoader->GetAPI(aAPIName, aHostAPI, aPluginAPI);
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Pre-load DLLs that need to be used by the EME plugin but that can't be
|
||||
// loaded after the sandbox has started
|
||||
bool
|
||||
GMPChild::PreLoadLibraries()
|
||||
GMPChild::RecvPreloadLibs(const nsCString& aLibs)
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
// Pre-load DLLs that need to be used by the EME plugin but that can't be
|
||||
// loaded after the sandbox has started
|
||||
// Items in this must be lowercase!
|
||||
static const char* whitelist[] = {
|
||||
"d3d9.dll", // Create an `IDirect3D9` to get adapter information
|
||||
|
@ -319,12 +300,8 @@ GMPChild::PreLoadLibraries()
|
|||
"msmpeg2vdec.dll", // H.264 decoder
|
||||
};
|
||||
|
||||
if (!mInfoParser.Contains(NS_LITERAL_CSTRING("libraries"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsTArray<nsCString> libs;
|
||||
SplitAt(", ", mInfoParser.Get(NS_LITERAL_CSTRING("libraries")), libs);
|
||||
SplitAt(", ", aLibs, libs);
|
||||
for (nsCString lib : libs) {
|
||||
ToLowerCase(lib);
|
||||
for (const char* whiteListedLib : whitelist) {
|
||||
|
@ -334,10 +311,9 @@ GMPChild::PreLoadLibraries()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
GMPChild::GetUTF8LibPath(nsACString& aOutLibPath)
|
||||
|
@ -373,9 +349,6 @@ GMPChild::AnswerStartPlugin()
|
|||
{
|
||||
LOGD("%s", __FUNCTION__);
|
||||
|
||||
#if defined(XP_WIN)
|
||||
PreLoadLibraries();
|
||||
#endif
|
||||
if (!PreLoadPluginVoucher()) {
|
||||
NS_WARNING("Plugin voucher failed to load!");
|
||||
return false;
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "gmp-async-shutdown.h"
|
||||
#include "gmp-entrypoints.h"
|
||||
#include "prlink.h"
|
||||
#include "GMPUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
@ -32,9 +31,6 @@ public:
|
|||
base::ProcessId aParentPid,
|
||||
MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel);
|
||||
#ifdef XP_WIN
|
||||
bool PreLoadLibraries();
|
||||
#endif
|
||||
MessageLoop* GMPMessageLoop();
|
||||
|
||||
// Main thread only.
|
||||
|
@ -58,6 +54,7 @@ private:
|
|||
|
||||
bool RecvSetNodeId(const nsCString& aNodeId) override;
|
||||
bool AnswerStartPlugin() override;
|
||||
bool RecvPreloadLibs(const nsCString& aLibs) override;
|
||||
|
||||
PCrashReporterChild* AllocPCrashReporterChild(const NativeThreadId& aThread) override;
|
||||
bool DeallocPCrashReporterChild(PCrashReporterChild*) override;
|
||||
|
@ -94,7 +91,6 @@ private:
|
|||
GMPLoader* mGMPLoader;
|
||||
nsTArray<uint8_t> mPluginVoucher;
|
||||
nsTArray<uint8_t> mSandboxVoucher;
|
||||
GMPInfoFileParser mInfoParser;
|
||||
};
|
||||
|
||||
} // namespace gmp
|
||||
|
|
|
@ -162,6 +162,17 @@ GMPParent::LoadProcess()
|
|||
}
|
||||
LOGD("%s: Sent node id to child process", __FUNCTION__);
|
||||
|
||||
#ifdef XP_WIN
|
||||
if (!mLibs.IsEmpty()) {
|
||||
bool ok = SendPreloadLibs(mLibs);
|
||||
if (!ok) {
|
||||
LOGD("%s: Failed to send preload-libs to child process", __FUNCTION__);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
LOGD("%s: Sent preload-libs ('%s') to child process", __FUNCTION__, mLibs.get());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Intr call to block initialization on plugin load.
|
||||
ok = CallStartPlugin();
|
||||
if (!ok) {
|
||||
|
@ -731,7 +742,7 @@ GMPParent::DeallocPGMPTimerParent(PGMPTimerParent* aActor)
|
|||
}
|
||||
|
||||
bool
|
||||
ReadRequiredField(GMPInfoFileParser& aParser, const nsCString& aKey, nsACString& aOutValue)
|
||||
ReadInfoField(GMPInfoFileParser& aParser, const nsCString& aKey, nsACString& aOutValue)
|
||||
{
|
||||
if (!aParser.Contains(aKey) || aParser.Get(aKey).IsEmpty()) {
|
||||
return false;
|
||||
|
@ -759,13 +770,18 @@ GMPParent::ReadGMPMetaData()
|
|||
}
|
||||
|
||||
nsAutoCString apis;
|
||||
if (!ReadRequiredField(parser, NS_LITERAL_CSTRING("name"), mDisplayName) ||
|
||||
!ReadRequiredField(parser, NS_LITERAL_CSTRING("description"), mDescription) ||
|
||||
!ReadRequiredField(parser, NS_LITERAL_CSTRING("version"), mVersion) ||
|
||||
!ReadRequiredField(parser, NS_LITERAL_CSTRING("apis"), apis)) {
|
||||
if (!ReadInfoField(parser, NS_LITERAL_CSTRING("name"), mDisplayName) ||
|
||||
!ReadInfoField(parser, NS_LITERAL_CSTRING("description"), mDescription) ||
|
||||
!ReadInfoField(parser, NS_LITERAL_CSTRING("version"), mVersion) ||
|
||||
!ReadInfoField(parser, NS_LITERAL_CSTRING("apis"), apis)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
// "Libraries" field is optional.
|
||||
ReadInfoField(parser, NS_LITERAL_CSTRING("libraries"), mLibs);
|
||||
#endif
|
||||
|
||||
nsTArray<nsCString> apiTokens;
|
||||
SplitAt(", ", apis, apiTokens);
|
||||
for (nsCString api : apiTokens) {
|
||||
|
|
|
@ -193,6 +193,9 @@ private:
|
|||
nsCString mDisplayName; // name of plugin displayed to users
|
||||
nsCString mDescription; // description of plugin for display to users
|
||||
nsCString mVersion;
|
||||
#ifdef XP_WIN
|
||||
nsCString mLibs;
|
||||
#endif
|
||||
uint32_t mPluginId;
|
||||
nsTArray<nsAutoPtr<GMPCapability>> mCapabilities;
|
||||
GMPProcessParent* mProcess;
|
||||
|
|
|
@ -36,6 +36,7 @@ child:
|
|||
async CrashPluginNow();
|
||||
intr StartPlugin();
|
||||
async SetNodeId(nsCString nodeId);
|
||||
async PreloadLibs(nsCString libs);
|
||||
async CloseActive();
|
||||
};
|
||||
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// The scoped_ptr.h our IPC copy of Chromium's code does not include
|
||||
// scoped_array, so adapt it to nsAutoArrayPtr here.
|
||||
|
||||
#ifndef FAKE_SCOPED_PTR_H_
|
||||
#define FAKE_SCOPED_PTR_H_
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
template<class T>
|
||||
class scoped_array : public nsAutoArrayPtr<T> {
|
||||
public:
|
||||
scoped_array(T* t) : nsAutoArrayPtr<T>(t) {}
|
||||
void reset(T* t) {
|
||||
scoped_array<T> other(t);
|
||||
this->operator=(other);
|
||||
}
|
||||
};
|
||||
|
||||
#define arraysize mozilla::ArrayLength
|
||||
|
||||
#endif
|
|
@ -6,8 +6,8 @@
|
|||
#include <sddl.h> // For ConvertSidToStringSidW.
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "rlz/lib/assert.h"
|
||||
|
||||
namespace rlz_lib {
|
||||
|
@ -41,13 +41,13 @@ bool GetSystemVolumeSerialNumber(int* number) {
|
|||
bool GetComputerSid(const wchar_t* account_name, SID* sid, DWORD sid_size) {
|
||||
static const DWORD kStartDomainLength = 128; // reasonable to start with
|
||||
|
||||
scoped_array<wchar_t> domain_buffer(new wchar_t[kStartDomainLength]);
|
||||
std::vector<wchar_t> domain_buffer(kStartDomainLength, 0);
|
||||
DWORD domain_size = kStartDomainLength;
|
||||
DWORD sid_dword_size = sid_size;
|
||||
SID_NAME_USE sid_name_use;
|
||||
|
||||
BOOL success = ::LookupAccountNameW(NULL, account_name, sid,
|
||||
&sid_dword_size, domain_buffer.get(),
|
||||
&sid_dword_size, &domain_buffer.front(),
|
||||
&domain_size, &sid_name_use);
|
||||
if (!success && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
// We could have gotten the insufficient buffer error because
|
||||
|
@ -57,10 +57,10 @@ bool GetComputerSid(const wchar_t* account_name, SID* sid, DWORD sid_size) {
|
|||
return false;
|
||||
|
||||
if (domain_size > kStartDomainLength)
|
||||
domain_buffer.reset(new wchar_t[domain_size]);
|
||||
domain_buffer.resize(domain_size);
|
||||
|
||||
success = ::LookupAccountNameW(NULL, account_name, sid, &sid_dword_size,
|
||||
domain_buffer.get(), &domain_size,
|
||||
&domain_buffer.front(), &domain_size,
|
||||
&sid_name_use);
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ bool GetRawMachineId(std::vector<uint8_t>* sid_bytes, int* volume_id) {
|
|||
// Calculate the Windows SID.
|
||||
|
||||
wchar_t computer_name[MAX_COMPUTERNAME_LENGTH + 1] = {0};
|
||||
DWORD size = arraysize(computer_name);
|
||||
DWORD size = mozilla::ArrayLength(computer_name);
|
||||
|
||||
if (!GetComputerNameW(computer_name, &size)) {
|
||||
return false;
|
||||
|
|
|
@ -1084,20 +1084,16 @@ Notification::ConstructFromFields(
|
|||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
DebugOnly<bool> ok = jsapi.Init(aGlobal);
|
||||
MOZ_ASSERT(ok);
|
||||
|
||||
RootedDictionary<NotificationOptions> options(jsapi.cx());
|
||||
RootedDictionary<NotificationOptions> options(nsContentUtils::RootingCxForThread());
|
||||
options.mDir = Notification::StringToDirection(nsString(aDir));
|
||||
options.mLang = aLang;
|
||||
options.mBody = aBody;
|
||||
options.mTag = aTag;
|
||||
options.mIcon = aIcon;
|
||||
RefPtr<Notification> notification = CreateInternal(aGlobal, aID, aTitle,
|
||||
options);
|
||||
options);
|
||||
|
||||
notification->InitFromBase64(jsapi.cx(), aData, aRv);
|
||||
notification->InitFromBase64(aData, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2341,8 +2337,7 @@ Notification::GetData(JSContext* aCx,
|
|||
nsresult rv;
|
||||
RefPtr<nsStructuredCloneContainer> container =
|
||||
new nsStructuredCloneContainer();
|
||||
rv = container->InitFromBase64(mDataAsBase64, JS_STRUCTURED_CLONE_VERSION,
|
||||
aCx);
|
||||
rv = container->InitFromBase64(mDataAsBase64, JS_STRUCTURED_CLONE_VERSION);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aRetval.setNull();
|
||||
return;
|
||||
|
@ -2386,8 +2381,7 @@ Notification::InitFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aData,
|
|||
dataObjectContainer->GetDataAsBase64(mDataAsBase64);
|
||||
}
|
||||
|
||||
void Notification::InitFromBase64(JSContext* aCx, const nsAString& aData,
|
||||
ErrorResult& aRv)
|
||||
void Notification::InitFromBase64(const nsAString& aData, ErrorResult& aRv)
|
||||
{
|
||||
if (!mDataAsBase64.IsEmpty() || aData.IsEmpty()) {
|
||||
return;
|
||||
|
@ -2396,8 +2390,7 @@ void Notification::InitFromBase64(JSContext* aCx, const nsAString& aData,
|
|||
// To and fro to ensure it is valid base64.
|
||||
RefPtr<nsStructuredCloneContainer> container =
|
||||
new nsStructuredCloneContainer();
|
||||
aRv = container->InitFromBase64(aData, JS_STRUCTURED_CLONE_VERSION,
|
||||
aCx);
|
||||
aRv = container->InitFromBase64(aData, JS_STRUCTURED_CLONE_VERSION);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -279,7 +279,7 @@ public:
|
|||
|
||||
void InitFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aData, ErrorResult& aRv);
|
||||
|
||||
void InitFromBase64(JSContext* aCx, const nsAString& aData, ErrorResult& aRv);
|
||||
void InitFromBase64(const nsAString& aData, ErrorResult& aRv);
|
||||
|
||||
void AssertIsOnTargetThread() const
|
||||
{
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for B2G PresentationReceiver on a non-receiver inner iframe of the receiver page at receiver side (OOP)</title>
|
||||
</head>
|
||||
<body onload="testConnectionAvailable()">
|
||||
<div id="content"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
"use strict";
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK ' : 'KO ') + msg);
|
||||
}
|
||||
|
||||
function testConnectionAvailable() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
ok(!navigator.presentation, "navigator.presentation shouldn't be available in inner iframes with different origins from receiving OOP pages.");
|
||||
aResolve();
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for B2G PresentationReceiver in an inner iframe of the receiver page at receiver side (OOP)</title>
|
||||
</head>
|
||||
<body onload="testConnectionAvailable()">
|
||||
<div id="content"></div>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
"use strict";
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((a ? 'OK ' : 'KO ') + msg);
|
||||
}
|
||||
|
||||
function testConnectionAvailable() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
ok(navigator.presentation, "navigator.presentation should be available in same-origin inner iframes of receiving OOP pages.");
|
||||
aResolve();
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -54,7 +54,7 @@ function testConnectionAvailable() {
|
|||
});
|
||||
}
|
||||
|
||||
function testConnectionAvailableInnerIframe() {
|
||||
function testConnectionAvailableSameOriginInnerIframe() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('src', './file_presentation_receiver_inner_iframe_oop.html');
|
||||
|
@ -64,6 +64,16 @@ function testConnectionAvailableInnerIframe() {
|
|||
});
|
||||
}
|
||||
|
||||
function testConnectionUnavailableDiffOriginInnerIframe() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('src', 'http://example.com/tests/dom/presentation/tests/mochitest/file_presentation_non_receiver_inner_iframe_oop.html');
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
aResolve();
|
||||
});
|
||||
}
|
||||
|
||||
function testConnectionReady() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
connection.onstatechange = function() {
|
||||
|
@ -104,7 +114,11 @@ function testTerminateConnection() {
|
|||
}
|
||||
|
||||
testConnectionAvailable().
|
||||
then(testConnectionAvailableInnerIframe).
|
||||
// TODO Bug 1234128 - Fix the timing issue for navigator.presentation.receiver.
|
||||
// This test fails intermittently under some edge cases. Disable it for now until
|
||||
// the issue gets fixed.
|
||||
// then(testConnectionAvailableSameOriginInnerIframe).
|
||||
then(testConnectionUnavailableDiffOriginInnerIframe).
|
||||
then(testConnectionReady).
|
||||
then(testIncomingMessage).
|
||||
then(testTerminateConnection).
|
||||
|
|
|
@ -6,6 +6,8 @@ support-files =
|
|||
file_presentation_receiver_oop.html
|
||||
file_presentation_non_receiver_oop.html
|
||||
file_presentation_receiver_establish_connection_error.html
|
||||
file_presentation_receiver_inner_iframe_oop.html
|
||||
file_presentation_non_receiver_inner_iframe_oop.html
|
||||
|
||||
[test_presentation_device_info.html]
|
||||
[test_presentation_device_info_permission.html]
|
||||
|
|
|
@ -404,10 +404,20 @@ this.PushDB.prototype = {
|
|||
aKeyID, newRecord);
|
||||
return;
|
||||
}
|
||||
aStore.put(newRecord).onsuccess = aEvent => {
|
||||
console.debug("update: Update successful", aKeyID, newRecord);
|
||||
aTxn.result = newRecord;
|
||||
};
|
||||
function putRecord() {
|
||||
let req = aStore.put(newRecord);
|
||||
req.onsuccess = aEvent => {
|
||||
console.debug("update: Update successful", aKeyID, newRecord);
|
||||
aTxn.result = newRecord;
|
||||
};
|
||||
}
|
||||
if (aKeyID === newRecord.keyID) {
|
||||
putRecord();
|
||||
} else {
|
||||
// If we changed the primary key, delete the old record to avoid
|
||||
// unique constraint errors.
|
||||
aStore.delete(aKeyID).onsuccess = putRecord;
|
||||
}
|
||||
};
|
||||
},
|
||||
resolve,
|
||||
|
|
|
@ -39,14 +39,21 @@ function handleRequest(request, response)
|
|||
data.push(bodyStream.readByteArray(available));
|
||||
size += available;
|
||||
}
|
||||
xhr.send(concatUint8Arrays(data, size));
|
||||
|
||||
function reply(statusCode, statusText) {
|
||||
response.setStatusLine(request.httpVersion, statusCode, statusText);
|
||||
response.finish();
|
||||
}
|
||||
|
||||
xhr.onload = function(e) {
|
||||
debug("xhr : " + this.status);
|
||||
}
|
||||
reply(this.status, this.statusText);
|
||||
};
|
||||
xhr.onerror = function(e) {
|
||||
debug("xhr error: " + e);
|
||||
}
|
||||
reply(500, "Internal Server Error");
|
||||
};
|
||||
|
||||
response.setStatusLine(request.httpVersion, "200", "OK");
|
||||
response.processAsync();
|
||||
xhr.send(concatUint8Arrays(data, size));
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
function waitForMessage(pushSubscription, message) {
|
||||
return Promise.all([
|
||||
controlledFrame.waitOnWorkerMessage("finished"),
|
||||
webpush(pushSubscription, message),
|
||||
webpush(pushSubscription, message, 120),
|
||||
]).then(([message]) => message);
|
||||
}
|
||||
|
||||
|
@ -167,6 +167,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
headers: {
|
||||
"X-Push-Method": "POST",
|
||||
"X-Push-Server": pushSubscription.endpoint,
|
||||
"TTL": "120",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
|
|
@ -71,6 +71,7 @@ http://creativecommons.org/licenses/publicdomain/
|
|||
headers: {
|
||||
"X-Push-Method": "POST",
|
||||
"X-Push-Server": pushSubscription.endpoint,
|
||||
"TTL": "120",
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
|
|
@ -75,9 +75,10 @@
|
|||
// Work around CORS for now.
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', "http://mochi.test:8888/tests/dom/push/test/push-server.sjs", true);
|
||||
xhr.setRequestHeader("X-Push-Method", "PUT");
|
||||
xhr.setRequestHeader("X-Push-Method", "POST");
|
||||
xhr.setRequestHeader("X-Push-Server", pushEndpoint);
|
||||
xhr.send("version=24601");
|
||||
xhr.setRequestHeader("TTL", "120");
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
function unregisterPushNotification(ctx) {
|
||||
|
|
|
@ -169,7 +169,7 @@
|
|||
* parameters.
|
||||
* @param data The message to send.
|
||||
*/
|
||||
function webpush(subscription, data) {
|
||||
function webpush(subscription, data, ttl) {
|
||||
data = ensureView(data);
|
||||
|
||||
var salt = g.crypto.getRandomValues(new Uint8Array(16));
|
||||
|
@ -189,13 +189,14 @@
|
|||
'X-Push-Method': 'POST',
|
||||
'Encryption-Key': 'keyid=p256dh;dh=' + base64url.encode(pubkey),
|
||||
Encryption: 'keyid=p256dh;salt=' + base64url.encode(salt),
|
||||
'Content-Encoding': 'aesgcm128'
|
||||
'Content-Encoding': 'aesgcm128',
|
||||
'TTL': ttl,
|
||||
},
|
||||
body: payload,
|
||||
};
|
||||
return fetch('http://mochi.test:8888/tests/dom/push/test/push-server.sjs', options);
|
||||
}).then(response => {
|
||||
if (response.status / 100 !== 2) {
|
||||
if (Math.floor(response.status / 100) !== 2) {
|
||||
throw new Error('Unable to deliver message');
|
||||
}
|
||||
return response;
|
||||
|
|
|
@ -14,15 +14,18 @@ XPCOMUtils.defineLazyGetter(this, "serverPort", function() {
|
|||
return httpServer.identity.primaryPort;
|
||||
});
|
||||
|
||||
var handlerDone;
|
||||
var handlerPromise = new Promise(r => handlerDone = after(3, r));
|
||||
|
||||
function listen4xxCodeHandler(metadata, response) {
|
||||
ok(true, "Listener point error")
|
||||
do_test_finished();
|
||||
handlerDone();
|
||||
response.setStatusLine(metadata.httpVersion, 410, "GONE");
|
||||
}
|
||||
|
||||
function resubscribeHandler(metadata, response) {
|
||||
ok(true, "Ask for new subscription");
|
||||
do_test_finished();
|
||||
handlerDone();
|
||||
response.setHeader("Location",
|
||||
'http://localhost:' + serverPort + '/newSubscription')
|
||||
response.setHeader("Link",
|
||||
|
@ -33,7 +36,7 @@ function resubscribeHandler(metadata, response) {
|
|||
|
||||
function listenSuccessHandler(metadata, response) {
|
||||
do_check_true(true, "New listener point");
|
||||
httpServer.stop(do_test_finished);
|
||||
httpServer.stop(handlerDone);
|
||||
response.setStatusLine(metadata.httpVersion, 204, "Try again");
|
||||
}
|
||||
|
||||
|
@ -61,10 +64,6 @@ add_task(function* test1() {
|
|||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
|
||||
var serverURL = "http://localhost:" + httpServer.identity.primaryPort;
|
||||
|
||||
let records = [{
|
||||
|
@ -85,4 +84,17 @@ add_task(function* test1() {
|
|||
db
|
||||
});
|
||||
|
||||
yield handlerPromise;
|
||||
|
||||
let record = yield db.getByIdentifiers({
|
||||
scope: 'https://example.com/page',
|
||||
originAttributes: '',
|
||||
});
|
||||
equal(record.keyID, serverURL + '/newSubscription',
|
||||
'Should update subscription URL');
|
||||
equal(record.pushEndpoint, serverURL + '/newPushEndpoint',
|
||||
'Should update push endpoint');
|
||||
equal(record.pushReceiptEndpoint, serverURL + '/newReceiptPushEndpoint',
|
||||
'Should update push receipt endpoint');
|
||||
|
||||
});
|
||||
|
|
|
@ -14,11 +14,13 @@ XPCOMUtils.defineLazyGetter(this, "serverPort", function() {
|
|||
return httpServer.identity.primaryPort;
|
||||
});
|
||||
|
||||
var retries = 0
|
||||
var retries = 0;
|
||||
var handlerDone;
|
||||
var handlerPromise = new Promise(r => handlerDone = after(5, r));
|
||||
|
||||
function listen5xxCodeHandler(metadata, response) {
|
||||
ok(true, "Listener 5xx code");
|
||||
do_test_finished();
|
||||
handlerDone();
|
||||
retries++;
|
||||
response.setHeader("Retry-After", '1');
|
||||
response.setStatusLine(metadata.httpVersion, 500, "Retry");
|
||||
|
@ -27,7 +29,7 @@ function listen5xxCodeHandler(metadata, response) {
|
|||
function resubscribeHandler(metadata, response) {
|
||||
ok(true, "Ask for new subscription");
|
||||
ok(retries == 3, "Should retry 2 times.");
|
||||
do_test_finished();
|
||||
handlerDone();
|
||||
response.setHeader("Location",
|
||||
'http://localhost:' + serverPort + '/newSubscription')
|
||||
response.setHeader("Link",
|
||||
|
@ -38,7 +40,7 @@ function resubscribeHandler(metadata, response) {
|
|||
|
||||
function listenSuccessHandler(metadata, response) {
|
||||
do_check_true(true, "New listener point");
|
||||
httpServer.stop(do_test_finished);
|
||||
httpServer.stop(handlerDone);
|
||||
response.setStatusLine(metadata.httpVersion, 204, "Try again");
|
||||
}
|
||||
|
||||
|
@ -67,12 +69,6 @@ add_task(function* test1() {
|
|||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
|
||||
var serverURL = "http://localhost:" + httpServer.identity.primaryPort;
|
||||
|
||||
let records = [{
|
||||
|
@ -93,4 +89,17 @@ add_task(function* test1() {
|
|||
db
|
||||
});
|
||||
|
||||
yield handlerPromise;
|
||||
|
||||
let record = yield db.getByIdentifiers({
|
||||
scope: 'https://example.com/page',
|
||||
originAttributes: '',
|
||||
});
|
||||
equal(record.keyID, serverURL + '/newSubscription',
|
||||
'Should update subscription URL');
|
||||
equal(record.pushEndpoint, serverURL + '/newPushEndpoint',
|
||||
'Should update push endpoint');
|
||||
equal(record.pushReceiptEndpoint, serverURL + '/newReceiptPushEndpoint',
|
||||
'Should update push receipt endpoint');
|
||||
|
||||
});
|
||||
|
|
|
@ -14,9 +14,12 @@ XPCOMUtils.defineLazyGetter(this, "serverPort", function() {
|
|||
return httpServer.identity.primaryPort;
|
||||
});
|
||||
|
||||
var handlerDone;
|
||||
var handlerPromise = new Promise(r => handlerDone = after(2, r));
|
||||
|
||||
function resubscribeHandler(metadata, response) {
|
||||
ok(true, "Ask for new subscription");
|
||||
do_test_finished();
|
||||
handlerDone();
|
||||
response.setHeader("Location",
|
||||
'http://localhost:' + serverPort + '/newSubscription')
|
||||
response.setHeader("Link",
|
||||
|
@ -27,7 +30,7 @@ function resubscribeHandler(metadata, response) {
|
|||
|
||||
function listenSuccessHandler(metadata, response) {
|
||||
do_check_true(true, "New listener point");
|
||||
httpServer.stop(do_test_finished);
|
||||
httpServer.stop(handlerDone);
|
||||
response.setStatusLine(metadata.httpVersion, 204, "Try again");
|
||||
}
|
||||
|
||||
|
@ -55,9 +58,6 @@ add_task(function* test1() {
|
|||
return db.drop().then(_ => db.close());
|
||||
});
|
||||
|
||||
do_test_pending();
|
||||
do_test_pending();
|
||||
|
||||
var serverURL = "http://localhost:" + httpServer.identity.primaryPort;
|
||||
|
||||
let records = [{
|
||||
|
@ -88,4 +88,17 @@ add_task(function* test1() {
|
|||
db
|
||||
});
|
||||
|
||||
yield handlerPromise;
|
||||
|
||||
let record = yield db.getByIdentifiers({
|
||||
scope: 'https://example.com/page',
|
||||
originAttributes: '',
|
||||
});
|
||||
equal(record.keyID, serverURL + '/newSubscription',
|
||||
'Should update subscription URL');
|
||||
equal(record.pushEndpoint, serverURL + '/newPushEndpoint',
|
||||
'Should update push endpoint');
|
||||
equal(record.pushReceiptEndpoint, serverURL + '/newReceiptPushEndpoint',
|
||||
'Should update push receipt endpoint');
|
||||
|
||||
});
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace {
|
|||
|
||||
static const char* gSupportedRegistrarVersions[] = {
|
||||
SERVICEWORKERREGISTRAR_VERSION,
|
||||
"3",
|
||||
"2"
|
||||
};
|
||||
|
||||
|
@ -330,6 +331,7 @@ ServiceWorkerRegistrar::ReadData()
|
|||
nsTArray<ServiceWorkerRegistrationData> tmpData;
|
||||
|
||||
bool overwrite = false;
|
||||
bool dedupe = false;
|
||||
while (hasMoreLines) {
|
||||
ServiceWorkerRegistrationData* entry = tmpData.AppendElement();
|
||||
|
||||
|
@ -343,6 +345,7 @@ ServiceWorkerRegistrar::ReadData()
|
|||
}
|
||||
|
||||
nsAutoCString line;
|
||||
nsAutoCString unused;
|
||||
if (version.EqualsLiteral(SERVICEWORKERREGISTRAR_VERSION)) {
|
||||
nsAutoCString suffix;
|
||||
GET_LINE(suffix);
|
||||
|
@ -352,18 +355,19 @@ ServiceWorkerRegistrar::ReadData()
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
GET_LINE(line);
|
||||
entry->principal() =
|
||||
mozilla::ipc::ContentPrincipalInfo(attrs, line);
|
||||
|
||||
GET_LINE(entry->scope());
|
||||
|
||||
entry->principal() =
|
||||
mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope());
|
||||
|
||||
GET_LINE(entry->currentWorkerURL());
|
||||
|
||||
nsAutoCString cacheName;
|
||||
GET_LINE(cacheName);
|
||||
CopyUTF8toUTF16(cacheName, entry->cacheName());
|
||||
} else if (version.EqualsLiteral("2")) {
|
||||
} else if (version.EqualsLiteral("3")) {
|
||||
overwrite = true;
|
||||
dedupe = true;
|
||||
|
||||
nsAutoCString suffix;
|
||||
GET_LINE(suffix);
|
||||
|
@ -373,14 +377,40 @@ ServiceWorkerRegistrar::ReadData()
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
GET_LINE(line);
|
||||
entry->principal() =
|
||||
mozilla::ipc::ContentPrincipalInfo(attrs, line);
|
||||
// principal spec is no longer used; we use scope directly instead
|
||||
GET_LINE(unused);
|
||||
|
||||
GET_LINE(entry->scope());
|
||||
|
||||
entry->principal() =
|
||||
mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope());
|
||||
|
||||
GET_LINE(entry->currentWorkerURL());
|
||||
|
||||
nsAutoCString cacheName;
|
||||
GET_LINE(cacheName);
|
||||
CopyUTF8toUTF16(cacheName, entry->cacheName());
|
||||
} else if (version.EqualsLiteral("2")) {
|
||||
overwrite = true;
|
||||
dedupe = true;
|
||||
|
||||
nsAutoCString suffix;
|
||||
GET_LINE(suffix);
|
||||
|
||||
PrincipalOriginAttributes attrs;
|
||||
if (!attrs.PopulateFromSuffix(suffix)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// principal spec is no longer used; we use scope directly instead
|
||||
GET_LINE(unused);
|
||||
|
||||
GET_LINE(entry->scope());
|
||||
|
||||
entry->principal() =
|
||||
mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope());
|
||||
|
||||
// scriptSpec is no more used in latest version.
|
||||
nsAutoCString unused;
|
||||
GET_LINE(unused);
|
||||
|
||||
GET_LINE(entry->currentWorkerURL());
|
||||
|
@ -409,22 +439,32 @@ ServiceWorkerRegistrar::ReadData()
|
|||
|
||||
stream->Close();
|
||||
|
||||
// Dedupe data in file. Old profiles had many duplicates. In theory
|
||||
// we can remove this in the future. (Bug 1248449)
|
||||
// Copy data over to mData.
|
||||
for (uint32_t i = 0; i < tmpData.Length(); ++i) {
|
||||
bool match = false;
|
||||
for (uint32_t j = 0; j < mData.Length(); ++j) {
|
||||
// Use same comparison as RegisterServiceWorker. Scope contains
|
||||
// basic origin information. Combine with any principal attributes.
|
||||
if (Equivalent(tmpData[i], mData[j])) {
|
||||
// Last match wins, just like legacy loading used to do in
|
||||
// the ServiceWorkerManager.
|
||||
mData[j] = tmpData[i];
|
||||
// Dupe found, so overwrite file with reduced list.
|
||||
overwrite = true;
|
||||
match = true;
|
||||
break;
|
||||
if (dedupe) {
|
||||
MOZ_ASSERT(overwrite);
|
||||
// If this is an old profile, then we might need to deduplicate. In
|
||||
// theory this can be removed in the future (Bug 1248449)
|
||||
for (uint32_t j = 0; j < mData.Length(); ++j) {
|
||||
// Use same comparison as RegisterServiceWorker. Scope contains
|
||||
// basic origin information. Combine with any principal attributes.
|
||||
if (Equivalent(tmpData[i], mData[j])) {
|
||||
// Last match wins, just like legacy loading used to do in
|
||||
// the ServiceWorkerManager.
|
||||
mData[j] = tmpData[i];
|
||||
// Dupe found, so overwrite file with reduced list.
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
// Otherwise assert no duplications in debug builds.
|
||||
for (uint32_t j = 0; j < mData.Length(); ++j) {
|
||||
MOZ_ASSERT(!Equivalent(tmpData[i], mData[j]));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (!match) {
|
||||
mData.AppendElement(tmpData[i]);
|
||||
|
@ -647,9 +687,6 @@ ServiceWorkerRegistrar::WriteData()
|
|||
buffer.Append(suffix.get());
|
||||
buffer.Append('\n');
|
||||
|
||||
buffer.Append(cInfo.spec());
|
||||
buffer.Append('\n');
|
||||
|
||||
buffer.Append(data[i].scope());
|
||||
buffer.Append('\n');
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "nsTArray.h"
|
||||
|
||||
#define SERVICEWORKERREGISTRAR_FILE "serviceworker.txt"
|
||||
#define SERVICEWORKERREGISTRAR_VERSION "3"
|
||||
#define SERVICEWORKERREGISTRAR_VERSION "4"
|
||||
#define SERVICEWORKERREGISTRAR_TERMINATOR "#"
|
||||
#define SERVICEWORKERREGISTRAR_TRUE "true"
|
||||
#define SERVICEWORKERREGISTRAR_FALSE "false"
|
||||
|
|
|
@ -30,16 +30,6 @@ const nsIID kWorkerRunnableIID = {
|
|||
0x320cc0b5, 0xef12, 0x4084, { 0x88, 0x6e, 0xca, 0x6a, 0x81, 0xe4, 0x1d, 0x68 }
|
||||
};
|
||||
|
||||
void
|
||||
MaybeReportMainThreadException(JSContext* aCx, bool aResult)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
if (aCx && !aResult) {
|
||||
JS_ReportPendingException(aCx);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -421,7 +411,15 @@ WorkerDebuggerRunnable::PostDispatch(JSContext* aCx,
|
|||
WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult)
|
||||
{
|
||||
MaybeReportMainThreadException(aCx, aDispatchResult);
|
||||
// The only way aDispatchResult can be false here is if either PreDispatch or
|
||||
// DispatchInternal returned false.
|
||||
//
|
||||
// Our PreDispatch always returns true and is final. We inherit
|
||||
// DispatchInternal from WorkerRunnable and don't allow overriding it in our
|
||||
// subclasses. WorkerRunnable::DispatchInternal only fails if one of its
|
||||
// runnable dispatching functions fails, and none of those cases can throw a
|
||||
// JS exception. So we can never have a JS exception here.
|
||||
MOZ_ASSERT_IF(aCx, !JS_IsExceptionPending(aCx));
|
||||
}
|
||||
|
||||
WorkerSyncRunnable::WorkerSyncRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
|
@ -469,7 +467,18 @@ MainThreadWorkerSyncRunnable::PostDispatch(JSContext* aCx,
|
|||
WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult)
|
||||
{
|
||||
MaybeReportMainThreadException(aCx, aDispatchResult);
|
||||
// The only way aDispatchResult can be false here is if either PreDispatch or
|
||||
// DispatchInternal returned false.
|
||||
//
|
||||
// Our PreDispatch always returns true and is final. We inherit
|
||||
// DispatchInternal from WorkerSyncRunnable and don't allow overriding it in
|
||||
// our subclasses. WorkerSyncRunnable::DispatchInternal only returns false if
|
||||
// if dispatch to the syncloop target fails or if calling up to
|
||||
// WorkerRunnable::DispatchInternal fails. WorkerRunnable::DispatchInternal
|
||||
// only fails if one of its runnable dispatching functions fails, and none of
|
||||
// those cases can throw a JS exception. So we can never have a JS exception
|
||||
// here.
|
||||
MOZ_ASSERT_IF(aCx, !JS_IsExceptionPending(aCx));
|
||||
}
|
||||
|
||||
StopSyncLoopRunnable::StopSyncLoopRunnable(
|
||||
|
@ -527,7 +536,14 @@ MainThreadStopSyncLoopRunnable::PostDispatch(JSContext* aCx,
|
|||
WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult)
|
||||
{
|
||||
MaybeReportMainThreadException(aCx, aDispatchResult);
|
||||
// The only way aDispatchResult can be false here is if either PreDispatch or
|
||||
// DispatchInternal returned false.
|
||||
//
|
||||
// Our PreDispatch always returns true and is final. We inherit
|
||||
// DispatchInternal from StopSyncLoopRunnable, and that itself is final and
|
||||
// only returns false if dispatch to the syncloop target fails. So we can
|
||||
// never have a JS exception here.
|
||||
MOZ_ASSERT_IF(aCx, !JS_IsExceptionPending(aCx));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -185,13 +185,22 @@ private:
|
|||
}
|
||||
|
||||
virtual bool
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override final
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// We want to be able to assert in PostDispatch that no exceptions were thrown
|
||||
// on aCx. We can do that if we know no one is subclassing our
|
||||
// DispatchInternal to do weird things.
|
||||
virtual bool
|
||||
DispatchInternal() override final
|
||||
{
|
||||
return WorkerRunnable::DispatchInternal();
|
||||
}
|
||||
|
||||
virtual void
|
||||
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult) override;
|
||||
|
@ -213,7 +222,6 @@ protected:
|
|||
|
||||
virtual ~WorkerSyncRunnable();
|
||||
|
||||
private:
|
||||
virtual bool
|
||||
DispatchInternal() override;
|
||||
};
|
||||
|
@ -242,14 +250,34 @@ protected:
|
|||
virtual ~MainThreadWorkerSyncRunnable()
|
||||
{ }
|
||||
|
||||
// Hook for subclasses that want to override our PreDispatch. This override
|
||||
// must be infallible and must not leave an exception hanging out on the
|
||||
// JSContext. We pass the JSContext through so callees that expect to be able
|
||||
// to do something with script have a way to do it. We'd pass an AutoJSAPI,
|
||||
// but some of our subclasses are dispatched with a null JSContext*, so we
|
||||
// can't do that sort of thing ourselves.
|
||||
virtual void InfalliblePreDispatch(JSContext* aCx)
|
||||
{}
|
||||
|
||||
private:
|
||||
virtual bool
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override final
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
InfalliblePreDispatch(aCx);
|
||||
MOZ_ASSERT_IF(aCx, !JS_IsExceptionPending(aCx));
|
||||
return true;
|
||||
}
|
||||
|
||||
// We want to be able to assert in PostDispatch that no exceptions were thrown
|
||||
// on aCx. We can do that if we know no one is subclassing our
|
||||
// DispatchInternal to do weird things.
|
||||
virtual bool
|
||||
DispatchInternal() override final
|
||||
{
|
||||
return WorkerSyncRunnable::DispatchInternal();
|
||||
}
|
||||
|
||||
virtual void
|
||||
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult) override;
|
||||
|
@ -286,8 +314,10 @@ private:
|
|||
virtual bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override;
|
||||
|
||||
// If this stops being final, reevaluate the assumptions
|
||||
// MainThreadWorkerSyncRunnable::PostDispatch makes.
|
||||
virtual bool
|
||||
DispatchInternal() override;
|
||||
DispatchInternal() override final;
|
||||
};
|
||||
|
||||
// This runnable is identical to StopSyncLoopRunnable except it is meant to be
|
||||
|
@ -310,8 +340,10 @@ protected:
|
|||
{ }
|
||||
|
||||
private:
|
||||
// If this function stops being final, reevaluate the assumptions PostDispatch
|
||||
// makes.
|
||||
virtual bool
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override final
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
return true;
|
||||
|
|
|
@ -591,8 +591,8 @@ private:
|
|||
~EventRunnable()
|
||||
{ }
|
||||
|
||||
virtual bool
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override;
|
||||
virtual void
|
||||
InfalliblePreDispatch(JSContext* aCx) override final;
|
||||
|
||||
virtual bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override;
|
||||
|
@ -1170,10 +1170,19 @@ LoadStartDetectionRunnable::HandleEvent(nsIDOMEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
EventRunnable::PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
void
|
||||
EventRunnable::InfalliblePreDispatch(JSContext* aCx)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
DebugOnly<bool> ok =
|
||||
jsapi.Init(xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx)), aCx);
|
||||
MOZ_ASSERT(ok);
|
||||
MOZ_ASSERT(jsapi.cx() == aCx);
|
||||
jsapi.TakeOwnershipOfErrorReporting();
|
||||
|
||||
RefPtr<nsXMLHttpRequest>& xhr = mProxy->mXHR;
|
||||
MOZ_ASSERT(xhr);
|
||||
|
@ -1244,8 +1253,6 @@ EventRunnable::PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
|||
mReadyState = xhr->ReadyState();
|
||||
|
||||
xhr->GetResponseURL(mResponseURL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -142,11 +142,11 @@ TEST(ServiceWorkerRegistrar, TestReadData)
|
|||
nsAutoCString buffer(SERVICEWORKERREGISTRAR_VERSION "\n");
|
||||
|
||||
buffer.Append("^appId=123&inBrowser=1\n");
|
||||
buffer.Append("spec 0\nscope 0\ncurrentWorkerURL 0\ncacheName 0\n");
|
||||
buffer.Append("scope 0\ncurrentWorkerURL 0\ncacheName 0\n");
|
||||
buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
|
||||
|
||||
buffer.Append("\n");
|
||||
buffer.Append("spec 1\nscope 1\ncurrentWorkerURL 1\ncacheName 1\n");
|
||||
buffer.Append("scope 1\ncurrentWorkerURL 1\ncacheName 1\n");
|
||||
buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
|
||||
|
||||
ASSERT_TRUE(CreateFile(buffer)) << "CreateFile should not fail";
|
||||
|
@ -167,7 +167,7 @@ TEST(ServiceWorkerRegistrar, TestReadData)
|
|||
cInfo0.attrs().CreateSuffix(suffix0);
|
||||
|
||||
ASSERT_STREQ("^appId=123&inBrowser=1", suffix0.get());
|
||||
ASSERT_STREQ("spec 0", cInfo0.spec().get());
|
||||
ASSERT_STREQ("scope 0", cInfo0.spec().get());
|
||||
ASSERT_STREQ("scope 0", data[0].scope().get());
|
||||
ASSERT_STREQ("currentWorkerURL 0", data[0].currentWorkerURL().get());
|
||||
ASSERT_STREQ("cacheName 0", NS_ConvertUTF16toUTF8(data[0].cacheName()).get());
|
||||
|
@ -180,7 +180,7 @@ TEST(ServiceWorkerRegistrar, TestReadData)
|
|||
cInfo1.attrs().CreateSuffix(suffix1);
|
||||
|
||||
ASSERT_STREQ("", suffix1.get());
|
||||
ASSERT_STREQ("spec 1", cInfo1.spec().get());
|
||||
ASSERT_STREQ("scope 1", cInfo1.spec().get());
|
||||
ASSERT_STREQ("scope 1", data[1].scope().get());
|
||||
ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get());
|
||||
ASSERT_STREQ("cacheName 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get());
|
||||
|
@ -246,7 +246,7 @@ TEST(ServiceWorkerRegistrar, TestWriteData)
|
|||
|
||||
ASSERT_STREQ(expectSuffix.get(), suffix.get());
|
||||
|
||||
test.AppendPrintf("spec write %d", i);
|
||||
test.AppendPrintf("scope write %d", i);
|
||||
ASSERT_STREQ(test.get(), cInfo.spec().get());
|
||||
|
||||
test.Truncate();
|
||||
|
@ -283,7 +283,7 @@ TEST(ServiceWorkerRegistrar, TestVersion2Migration)
|
|||
ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
|
||||
|
||||
const nsTArray<ServiceWorkerRegistrationData>& data = swr->TestGetData();
|
||||
ASSERT_EQ((uint32_t)2, data.Length()) << "4 entries should be found";
|
||||
ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
|
||||
|
||||
const mozilla::ipc::PrincipalInfo& info0 = data[0].principal();
|
||||
ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) << "First principal must be content";
|
||||
|
@ -293,7 +293,7 @@ TEST(ServiceWorkerRegistrar, TestVersion2Migration)
|
|||
cInfo0.attrs().CreateSuffix(suffix0);
|
||||
|
||||
ASSERT_STREQ("^appId=123&inBrowser=1", suffix0.get());
|
||||
ASSERT_STREQ("spec 0", cInfo0.spec().get());
|
||||
ASSERT_STREQ("scope 0", cInfo0.spec().get());
|
||||
ASSERT_STREQ("scope 0", data[0].scope().get());
|
||||
ASSERT_STREQ("currentWorkerURL 0", data[0].currentWorkerURL().get());
|
||||
ASSERT_STREQ("activeCache 0", NS_ConvertUTF16toUTF8(data[0].cacheName()).get());
|
||||
|
@ -306,15 +306,64 @@ TEST(ServiceWorkerRegistrar, TestVersion2Migration)
|
|||
cInfo1.attrs().CreateSuffix(suffix1);
|
||||
|
||||
ASSERT_STREQ("", suffix1.get());
|
||||
ASSERT_STREQ("spec 1", cInfo1.spec().get());
|
||||
ASSERT_STREQ("scope 1", cInfo1.spec().get());
|
||||
ASSERT_STREQ("scope 1", data[1].scope().get());
|
||||
ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get());
|
||||
ASSERT_STREQ("activeCache 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get());
|
||||
}
|
||||
|
||||
TEST(ServiceWorkerRegistrar, TestVersion3Migration)
|
||||
{
|
||||
nsAutoCString buffer("3" "\n");
|
||||
|
||||
buffer.Append("^appId=123&inBrowser=1\n");
|
||||
buffer.Append("spec 0\nscope 0\ncurrentWorkerURL 0\ncacheName 0\n");
|
||||
buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
|
||||
|
||||
buffer.Append("\n");
|
||||
buffer.Append("spec 1\nscope 1\ncurrentWorkerURL 1\ncacheName 1\n");
|
||||
buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
|
||||
|
||||
ASSERT_TRUE(CreateFile(buffer)) << "CreateFile should not fail";
|
||||
|
||||
RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
|
||||
|
||||
nsresult rv = swr->TestReadData();
|
||||
ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
|
||||
|
||||
const nsTArray<ServiceWorkerRegistrationData>& data = swr->TestGetData();
|
||||
ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
|
||||
|
||||
const mozilla::ipc::PrincipalInfo& info0 = data[0].principal();
|
||||
ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) << "First principal must be content";
|
||||
const mozilla::ipc::ContentPrincipalInfo& cInfo0 = data[0].principal();
|
||||
|
||||
nsAutoCString suffix0;
|
||||
cInfo0.attrs().CreateSuffix(suffix0);
|
||||
|
||||
ASSERT_STREQ("^appId=123&inBrowser=1", suffix0.get());
|
||||
ASSERT_STREQ("scope 0", cInfo0.spec().get());
|
||||
ASSERT_STREQ("scope 0", data[0].scope().get());
|
||||
ASSERT_STREQ("currentWorkerURL 0", data[0].currentWorkerURL().get());
|
||||
ASSERT_STREQ("cacheName 0", NS_ConvertUTF16toUTF8(data[0].cacheName()).get());
|
||||
|
||||
const mozilla::ipc::PrincipalInfo& info1 = data[1].principal();
|
||||
ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) << "First principal must be content";
|
||||
const mozilla::ipc::ContentPrincipalInfo& cInfo1 = data[1].principal();
|
||||
|
||||
nsAutoCString suffix1;
|
||||
cInfo1.attrs().CreateSuffix(suffix1);
|
||||
|
||||
ASSERT_STREQ("", suffix1.get());
|
||||
ASSERT_STREQ("scope 1", cInfo1.spec().get());
|
||||
ASSERT_STREQ("scope 1", data[1].scope().get());
|
||||
ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get());
|
||||
ASSERT_STREQ("cacheName 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get());
|
||||
}
|
||||
|
||||
TEST(ServiceWorkerRegistrar, TestDedupe)
|
||||
{
|
||||
nsAutoCString buffer(SERVICEWORKERREGISTRAR_VERSION "\n");
|
||||
nsAutoCString buffer("3" "\n");
|
||||
|
||||
// unique entries
|
||||
buffer.Append("^appId=123&inBrowser=1\n");
|
||||
|
@ -356,7 +405,7 @@ TEST(ServiceWorkerRegistrar, TestDedupe)
|
|||
cInfo0.attrs().CreateSuffix(suffix0);
|
||||
|
||||
ASSERT_STREQ("^appId=123&inBrowser=1", suffix0.get());
|
||||
ASSERT_STREQ("spec 2", cInfo0.spec().get());
|
||||
ASSERT_STREQ("scope 0", cInfo0.spec().get());
|
||||
ASSERT_STREQ("scope 0", data[0].scope().get());
|
||||
ASSERT_STREQ("currentWorkerURL 0", data[0].currentWorkerURL().get());
|
||||
ASSERT_STREQ("cacheName 0", NS_ConvertUTF16toUTF8(data[0].cacheName()).get());
|
||||
|
@ -369,7 +418,7 @@ TEST(ServiceWorkerRegistrar, TestDedupe)
|
|||
cInfo1.attrs().CreateSuffix(suffix1);
|
||||
|
||||
ASSERT_STREQ("", suffix1.get());
|
||||
ASSERT_STREQ("spec 3", cInfo1.spec().get());
|
||||
ASSERT_STREQ("scope 1", cInfo1.spec().get());
|
||||
ASSERT_STREQ("scope 1", data[1].scope().get());
|
||||
ASSERT_STREQ("currentWorkerURL 1", data[1].currentWorkerURL().get());
|
||||
ASSERT_STREQ("cacheName 1", NS_ConvertUTF16toUTF8(data[1].cacheName()).get());
|
||||
|
|
|
@ -613,7 +613,8 @@ DrawTargetCairo::~DrawTargetCairo()
|
|||
bool
|
||||
DrawTargetCairo::IsValid() const
|
||||
{
|
||||
return mSurface && !cairo_surface_status(mSurface) && !cairo_surface_status(cairo_get_group_target(mContext));
|
||||
return mSurface && !cairo_surface_status(mSurface) &&
|
||||
mContext && !cairo_surface_status(cairo_get_group_target(mContext));
|
||||
}
|
||||
|
||||
DrawTargetType
|
||||
|
@ -1287,6 +1288,10 @@ DrawTargetCairo::FillGlyphs(ScaledFont *aFont,
|
|||
return;
|
||||
}
|
||||
|
||||
if (!aFont) {
|
||||
gfxDevCrash(LogReason::InvalidFont) << "Invalid scaled font";
|
||||
}
|
||||
|
||||
AutoPrepareForDrawing prep(this, mContext);
|
||||
AutoClearDeviceOffset clear(aPattern);
|
||||
|
||||
|
|
|
@ -77,6 +77,14 @@ JobScheduler::SubmitJob(Job* aJob)
|
|||
GetQueueForJob(aJob)->SubmitJob(aJob);
|
||||
}
|
||||
|
||||
void
|
||||
JobScheduler::Join(SyncObject* aCompletion)
|
||||
{
|
||||
RefPtr<EventObject> waitForCompletion = new EventObject();
|
||||
JobScheduler::SubmitJob(new SetEventJob(waitForCompletion, aCompletion));
|
||||
waitForCompletion->Wait();
|
||||
}
|
||||
|
||||
MultiThreadedJobQueue*
|
||||
JobScheduler::GetQueueForJob(Job* aJob)
|
||||
{
|
||||
|
|
|
@ -71,6 +71,12 @@ public:
|
|||
/// The caller looses ownership of the task buffer.
|
||||
static void SubmitJob(Job* aJobs);
|
||||
|
||||
/// Convenience function to block the current thread until a given SyncObject
|
||||
/// is in the signaled state.
|
||||
///
|
||||
/// The current thread will first try to steal jobs before blocking.
|
||||
static void Join(SyncObject* aCompletionSync);
|
||||
|
||||
/// Process commands until the command buffer needs to block on a sync object,
|
||||
/// completes, yields, or encounters an error.
|
||||
///
|
||||
|
|
|
@ -131,6 +131,7 @@ enum class LogReason : int {
|
|||
InvalidRect,
|
||||
CannotDraw3D, // 20
|
||||
IncompatibleBasicTexturedEffect,
|
||||
InvalidFont,
|
||||
// End
|
||||
MustBeLessThanThis = 101,
|
||||
};
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <android/log.h>
|
||||
#include "AndroidSurfaceTexture.h"
|
||||
|
@ -27,9 +26,57 @@ using namespace mozilla::widget::sdk;
|
|||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
// UGH
|
||||
static std::map<int, AndroidSurfaceTexture*> sInstances;
|
||||
static int sNextID = 0;
|
||||
// Maintains a mapping between AndroidSurfaceTexture instances and their
|
||||
// unique numerical IDs. [thread-safe]
|
||||
class InstanceMap
|
||||
{
|
||||
typedef AndroidSurfaceTexture* InstancePtr;
|
||||
typedef std::map<int, InstancePtr> MapType;
|
||||
|
||||
public:
|
||||
InstanceMap()
|
||||
: mNextId(0)
|
||||
, mMonitor("AndroidSurfaceTexture::InstanceMap::mMonitor")
|
||||
{}
|
||||
|
||||
int Add(InstancePtr aInstance)
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mInstances.insert({++mNextId, aInstance});
|
||||
return mNextId;
|
||||
}
|
||||
|
||||
void Remove(int aId)
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mInstances.erase(aId);
|
||||
}
|
||||
|
||||
InstancePtr Get(int aId) const
|
||||
{
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
auto it = mInstances.find(aId);
|
||||
if (it == mInstances.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
private:
|
||||
MapType mInstances;
|
||||
int mNextId;
|
||||
|
||||
mutable Monitor mMonitor;
|
||||
};
|
||||
|
||||
static InstanceMap sInstances;
|
||||
|
||||
AndroidSurfaceTexture*
|
||||
AndroidSurfaceTexture::Find(int aId)
|
||||
{
|
||||
return sInstances.Get(aId);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsSTSupported()
|
||||
|
@ -59,19 +106,6 @@ AndroidSurfaceTexture::Create(GLContext* aContext, GLuint aTexture)
|
|||
return st.forget();
|
||||
}
|
||||
|
||||
AndroidSurfaceTexture*
|
||||
AndroidSurfaceTexture::Find(int id)
|
||||
{
|
||||
std::map<int, AndroidSurfaceTexture*>::iterator it;
|
||||
|
||||
it = sInstances.find(id);
|
||||
if (it == sInstances.end())
|
||||
return nullptr;
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
AndroidSurfaceTexture::Attach(GLContext* aContext, PRIntervalTime aTimeout)
|
||||
{
|
||||
|
@ -170,8 +204,7 @@ AndroidSurfaceTexture::Init(GLContext* aContext, GLuint aTexture)
|
|||
mSurface.Get());
|
||||
MOZ_ASSERT(mNativeWindow, "Failed to create native window from surface");
|
||||
|
||||
mID = ++sNextID;
|
||||
sInstances.insert(std::pair<int, AndroidSurfaceTexture*>(mID, this));
|
||||
mID = sInstances.Add(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -180,15 +213,15 @@ AndroidSurfaceTexture::AndroidSurfaceTexture()
|
|||
: mTexture(0)
|
||||
, mSurfaceTexture()
|
||||
, mSurface()
|
||||
, mMonitor("AndroidSurfaceTexture::mContextMonitor")
|
||||
, mAttachedContext(nullptr)
|
||||
, mCanDetach(false)
|
||||
, mMonitor("AndroidSurfaceTexture::mContextMonitor")
|
||||
{
|
||||
}
|
||||
|
||||
AndroidSurfaceTexture::~AndroidSurfaceTexture()
|
||||
{
|
||||
sInstances.erase(mID);
|
||||
sInstances.Remove(mID);
|
||||
|
||||
mFrameAvailableCallback = nullptr;
|
||||
|
||||
|
@ -205,7 +238,7 @@ AndroidSurfaceTexture::UpdateTexImage()
|
|||
}
|
||||
|
||||
void
|
||||
AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix)
|
||||
AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix) const
|
||||
{
|
||||
JNIEnv* const env = jni::GetEnvForThread();
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
// Android Jelly Bean.
|
||||
static already_AddRefed<AndroidSurfaceTexture> Create();
|
||||
|
||||
static AndroidSurfaceTexture* Find(int id);
|
||||
static AndroidSurfaceTexture* Find(int aId);
|
||||
|
||||
// If we are on Jelly Bean, the SurfaceTexture can be detached and reattached
|
||||
// to allow consumption from different GLContexts. It is recommended to only
|
||||
|
@ -58,19 +58,19 @@ public:
|
|||
|
||||
// Ability to detach is based on API version (16+), and we also block PowerVR since it has some type
|
||||
// of fencing problem. Bug 1100126.
|
||||
bool CanDetach() { return mCanDetach; }
|
||||
bool CanDetach() const { return mCanDetach; }
|
||||
|
||||
GLContext* GetAttachedContext() { return mAttachedContext; }
|
||||
GLContext* AttachedContext() const { return mAttachedContext; }
|
||||
|
||||
AndroidNativeWindow* NativeWindow() {
|
||||
AndroidNativeWindow* NativeWindow() const {
|
||||
return mNativeWindow;
|
||||
}
|
||||
|
||||
// This attaches the updated data to the TEXTURE_EXTERNAL target
|
||||
void UpdateTexImage();
|
||||
|
||||
void GetTransformMatrix(mozilla::gfx::Matrix4x4& aMatrix);
|
||||
int ID() { return mID; }
|
||||
void GetTransformMatrix(mozilla::gfx::Matrix4x4& aMatrix) const;
|
||||
int ID() const { return mID; }
|
||||
|
||||
void SetDefaultSize(mozilla::gfx::IntSize size);
|
||||
|
||||
|
@ -82,8 +82,8 @@ public:
|
|||
// callback from the underlying SurfaceTexture instance
|
||||
void NotifyFrameAvailable();
|
||||
|
||||
GLuint Texture() { return mTexture; }
|
||||
const widget::sdk::Surface::Ref& JavaSurface() { return mSurface; }
|
||||
GLuint Texture() const { return mTexture; }
|
||||
const widget::sdk::Surface::Ref& JavaSurface() const { return mSurface; }
|
||||
|
||||
private:
|
||||
AndroidSurfaceTexture();
|
||||
|
@ -96,13 +96,14 @@ private:
|
|||
widget::sdk::SurfaceTexture::GlobalRef mSurfaceTexture;
|
||||
widget::sdk::Surface::GlobalRef mSurface;
|
||||
|
||||
Monitor mMonitor;
|
||||
GLContext* mAttachedContext;
|
||||
bool mCanDetach;
|
||||
|
||||
RefPtr<AndroidNativeWindow> mNativeWindow;
|
||||
int mID;
|
||||
nsCOMPtr<nsIRunnable> mFrameAvailableCallback;
|
||||
|
||||
mutable Monitor mMonitor;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#ifndef GFX_GLIMAGES_H
|
||||
#define GFX_GLIMAGES_H
|
||||
|
||||
#include "AndroidSurfaceTexture.h"
|
||||
#include "GLContextTypes.h"
|
||||
#include "GLTypes.h"
|
||||
#include "ImageContainer.h" // for Image
|
||||
|
@ -14,9 +15,6 @@
|
|||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
class AndroidSurfaceTexture;
|
||||
} // namespace gl
|
||||
namespace layers {
|
||||
|
||||
class GLImage : public Image {
|
||||
|
@ -79,7 +77,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
gl::AndroidSurfaceTexture* mSurfaceTexture;
|
||||
RefPtr<gl::AndroidSurfaceTexture> mSurfaceTexture;
|
||||
gfx::IntSize mSize;
|
||||
gl::OriginPos mOriginPos;
|
||||
};
|
||||
|
|
|
@ -170,3 +170,10 @@ function synthesizeNativeDrag(aElement, aX, aY, aDeltaX, aDeltaY, aObserver = nu
|
|||
synthesizeNativeTouch(aElement, aX + aDeltaX, aY + aDeltaY, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchId);
|
||||
return synthesizeNativeTouch(aElement, aX + aDeltaX, aY + aDeltaY, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, aObserver, aTouchId);
|
||||
}
|
||||
|
||||
function synthesizeNativeTap(aElement, aX, aY, aObserver = null) {
|
||||
var pt = coordinatesRelativeToWindow(aX, aY, aElement);
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeTouchTap(pt.x, pt.y, false, aObserver);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity touch-tapping test</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function clickButton() {
|
||||
if (!window.TouchEvent) {
|
||||
window.opener.ok(true, "Touch events are not supported on this platform, sorry!\n");
|
||||
window.opener.testDone();
|
||||
return;
|
||||
}
|
||||
|
||||
document.addEventListener('click', clicked, false);
|
||||
|
||||
synthesizeNativeTap(document.getElementById('b'), 5, 5, function() {
|
||||
dump("Finished synthesizing tap, waiting for button to be clicked...\n");
|
||||
});
|
||||
}
|
||||
|
||||
function clicked(e) {
|
||||
window.opener.is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
|
||||
window.opener.testDone();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
waitForAllPaints(function() {
|
||||
flushApzRepaints(clickButton);
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="b" style="width: 10px; height: 10px"></button>
|
||||
</body>
|
||||
</html>
|
|
@ -10,6 +10,7 @@ support-files =
|
|||
helper_basic_pan.html
|
||||
helper_div_pan.html
|
||||
helper_iframe_pan.html
|
||||
helper_tap.html
|
||||
tags = apz
|
||||
[test_bug982141.html]
|
||||
skip-if = toolkit != 'gonk' # bug 991198
|
||||
|
@ -32,3 +33,7 @@ skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel ev
|
|||
[test_scroll_subframe_scrollbar.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
||||
[test_frame_reconstruction.html]
|
||||
[test_tap.html]
|
||||
# Windows touch injection doesn't work in automation, but this test can be run locally on a windows touch device.
|
||||
# On OS X we don't support touch events at all.
|
||||
skip-if = (toolkit == 'windows') || (toolkit == 'cocoa')
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Sanity panning test</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// this page just serially loads each one of the following test helper pages in
|
||||
// a new window and waits for it to call testDone()
|
||||
var tests = [
|
||||
'helper_tap.html',
|
||||
];
|
||||
|
||||
var testIndex = -1;
|
||||
var w = null;
|
||||
|
||||
function testDone() {
|
||||
if (w) {
|
||||
w.close();
|
||||
}
|
||||
testIndex++;
|
||||
if (testIndex < tests.length) {
|
||||
w = window.open(tests[testIndex], "_blank");
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
if (!SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled) {
|
||||
ok(true, "APZ is not enabled, this test is not relevant, sorry!\n");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
testDone();
|
||||
};
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -434,7 +434,7 @@ BasicCompositor::DrawQuad(const gfx::Rect& aRect,
|
|||
MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!");
|
||||
MOZ_ASSERT(!effectMask->mIs3D);
|
||||
maskTransform = effectMask->mMaskTransform.As2D();
|
||||
maskTransform.PreTranslate(-offset.x, -offset.y);
|
||||
maskTransform.PostTranslate(-offset.x, -offset.y);
|
||||
}
|
||||
|
||||
CompositionOp blendMode = CompositionOp::OP_OVER;
|
||||
|
|
|
@ -820,7 +820,8 @@ TextureClient::CreateForRawBufferAccess(ISurfaceAllocator* aAllocator,
|
|||
TextureFlags aTextureFlags,
|
||||
TextureAllocationFlags aAllocFlags)
|
||||
{
|
||||
MOZ_ASSERT(aAllocator->IPCOpen());
|
||||
// also test the validity of aAllocator
|
||||
MOZ_ASSERT(aAllocator && aAllocator->IPCOpen());
|
||||
if (!aAllocator || !aAllocator->IPCOpen()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -91,6 +91,8 @@ public:
|
|||
virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) override;
|
||||
|
||||
protected:
|
||||
virtual bool RecvSyncWithCompositor() override { return true; }
|
||||
|
||||
virtual bool RecvShutdown() override;
|
||||
|
||||
virtual bool RecvUpdate(EditArray&& cset,
|
||||
|
|
|
@ -123,6 +123,8 @@ parent:
|
|||
async ChildAsyncMessages(AsyncChildMessageData[] aMessages);
|
||||
|
||||
async Shutdown();
|
||||
|
||||
sync SyncWithCompositor();
|
||||
child:
|
||||
async __delete__();
|
||||
};
|
||||
|
|
|
@ -40,6 +40,23 @@ class Shmem;
|
|||
|
||||
namespace layers {
|
||||
|
||||
static int sShmemCreationCounter = 0;
|
||||
|
||||
static void ResetShmemCounter()
|
||||
{
|
||||
sShmemCreationCounter = 0;
|
||||
}
|
||||
|
||||
static void ShmemAllocated(LayerTransactionChild* aProtocol)
|
||||
{
|
||||
sShmemCreationCounter++;
|
||||
if (sShmemCreationCounter > 256) {
|
||||
aProtocol->SendSyncWithCompositor();
|
||||
ResetShmemCounter();
|
||||
MOZ_PERFORMANCE_WARNING("gfx", "The number of shmem allocations is too damn high!");
|
||||
}
|
||||
}
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gl;
|
||||
using namespace mozilla::ipc;
|
||||
|
@ -552,6 +569,8 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
|
|||
{
|
||||
*aSent = false;
|
||||
|
||||
ResetShmemCounter();
|
||||
|
||||
MOZ_ASSERT(aId);
|
||||
|
||||
PROFILER_LABEL("ShadowLayerForwarder", "EndTransaction",
|
||||
|
@ -744,6 +763,8 @@ ShadowLayerForwarder::AllocShmem(size_t aSize,
|
|||
!mShadowManager->IPCOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ShmemAllocated(mShadowManager);
|
||||
return mShadowManager->AllocShmem(aSize, aType, aShmem);
|
||||
}
|
||||
bool
|
||||
|
@ -756,6 +777,7 @@ ShadowLayerForwarder::AllocUnsafeShmem(size_t aSize,
|
|||
!mShadowManager->IPCOpen()) {
|
||||
return false;
|
||||
}
|
||||
ShmemAllocated(mShadowManager);
|
||||
return mShadowManager->AllocUnsafeShmem(aSize, aType, aShmem);
|
||||
}
|
||||
void
|
||||
|
|
|
@ -374,7 +374,7 @@ public:
|
|||
|
||||
protected:
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
mozilla::gl::AndroidSurfaceTexture* const mSurfTex;
|
||||
RefPtr<gl::AndroidSurfaceTexture> const mSurfTex;
|
||||
const gfx::SurfaceFormat mFormat;
|
||||
const GLenum mTextureTarget;
|
||||
const GLenum mWrapMode;
|
||||
|
@ -419,7 +419,7 @@ public:
|
|||
virtual const char* Name() { return "SurfaceTextureHost"; }
|
||||
|
||||
protected:
|
||||
mozilla::gl::AndroidSurfaceTexture* const mSurfTex;
|
||||
RefPtr<gl::AndroidSurfaceTexture> const mSurfTex;
|
||||
const gfx::IntSize mSize;
|
||||
RefPtr<CompositorOGL> mCompositor;
|
||||
RefPtr<SurfaceTextureSource> mTextureSource;
|
||||
|
|
|
@ -145,13 +145,7 @@ void TestSchedulerJoin(uint32_t aNumThreads, uint32_t aNumCmdBuffers)
|
|||
}
|
||||
completion->FreezePrerequisites();
|
||||
|
||||
RefPtr<EventObject> waitForCompletion = new EventObject();
|
||||
auto evtJob = new SetEventJob(waitForCompletion, completion);
|
||||
JobScheduler::SubmitJob(evtJob);
|
||||
|
||||
MaybeYieldThread();
|
||||
|
||||
waitForCompletion->Wait();
|
||||
JobScheduler::Join(completion);
|
||||
|
||||
MaybeYieldThread();
|
||||
|
||||
|
@ -205,13 +199,7 @@ void TestSchedulerChain(uint32_t aNumThreads, uint32_t aNumCmdBuffers)
|
|||
}
|
||||
completion->FreezePrerequisites();
|
||||
|
||||
RefPtr<EventObject> waitForCompletion = new EventObject();
|
||||
auto evtJob = new SetEventJob(waitForCompletion, completion);
|
||||
JobScheduler::SubmitJob(evtJob);
|
||||
|
||||
MaybeYieldThread();
|
||||
|
||||
waitForCompletion->Wait();
|
||||
JobScheduler::Join(completion);
|
||||
|
||||
for (auto advancement : check.mAdvancements) {
|
||||
EXPECT_TRUE(advancement == numJobs);
|
||||
|
|
|
@ -682,10 +682,11 @@ nsBMPDecoder::ReadBitfields(const char* aData, size_t aLength)
|
|||
|
||||
if (mDownscaler) {
|
||||
// BMPs store their rows in reverse order, so the downscaler needs to
|
||||
// reverse them again when writing its output.
|
||||
// reverse them again when writing its output. Unless the height is
|
||||
// negative!
|
||||
rv = mDownscaler->BeginFrame(GetSize(), Nothing(),
|
||||
mImageData, mMayHaveTransparency,
|
||||
/* aFlipVertically = */ true);
|
||||
/* aFlipVertically = */ mH.mHeight >= 0);
|
||||
if (NS_FAILED(rv)) {
|
||||
return Transition::TerminateFailure();
|
||||
}
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 879 B |
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
<title>Image reftest wrapper</title>
|
||||
<style type="text/css">
|
||||
#image1 { background-color: rgb(10, 250, 100); }
|
||||
</style>
|
||||
<script>
|
||||
// The image is loaded async after the page loads.
|
||||
// Wait for it to finish loading.
|
||||
function onImageLoad() {
|
||||
document.documentElement.removeAttribute("class");
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<img width="8px" id="image1">
|
||||
<script>
|
||||
// Use as "wrapper.html?image.png"
|
||||
var imgURL = document.location.search.substr(1);
|
||||
document.images[0].onload = onImageLoad;
|
||||
document.images[0].onerror = onImageLoad;
|
||||
document.images[0].alt = "";
|
||||
document.images[0].src = imgURL;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -91,8 +91,11 @@ fuzzy(20,999) fails-if(OSX>=1008&&!skiaContent) != downscale-2e.html?205,53,bott
|
|||
== downscale-png.html?24,24,interlaced downscale-png.html?24,24,normal
|
||||
|
||||
# Non-transparent and transparent ICO images
|
||||
== downscale-ff.html?ff-0RGB.ico downscale-ff.html?ff-0RGB.png
|
||||
fuzzy(1,1) == downscale-ff.html?ff-ARGB.ico downscale-ff.html?ff-ARGB.png
|
||||
== downscale-16px.html?ff-0RGB.ico downscale-16px.html?ff-0RGB.png
|
||||
fuzzy(1,1) == downscale-16px.html?ff-ARGB.ico downscale-16px.html?ff-ARGB.png
|
||||
|
||||
# Upside-down (negative height) BMP
|
||||
== downscale-8px.html?top-to-bottom-16x16-24bpp.bmp downscale-8px.html?bmp-size-16x16-24bpp.png
|
||||
|
||||
# RUN TESTS WITH DOWNSCALE-DURING-DECODE ENABLED:
|
||||
# ===============================================
|
||||
|
@ -160,5 +163,9 @@ fuzzy(20,999) != downscale-2f.html?205,53,bottom about:blank
|
|||
== downscale-png.html?24,24,interlaced downscale-png.html?24,24,normal
|
||||
|
||||
# Non-transparent and transparent ICO images
|
||||
fuzzy(1,3) == downscale-ff.html?ff-0RGB.ico downscale-ff.html?ff-0RGB.png
|
||||
fuzzy(3,32) == downscale-ff.html?ff-ARGB.ico downscale-ff.html?ff-ARGB.png
|
||||
fuzzy(1,3) == downscale-16px.html?ff-0RGB.ico downscale-16px.html?ff-0RGB.png
|
||||
fuzzy(3,32) == downscale-16px.html?ff-ARGB.ico downscale-16px.html?ff-ARGB.png
|
||||
|
||||
# Upside-down (negative height) BMP
|
||||
== downscale-8px.html?top-to-bottom-16x16-24bpp.bmp downscale-8px.html?bmp-size-16x16-24bpp.png
|
||||
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 822 B |
|
@ -112,7 +112,7 @@ struct JS_PUBLIC_API(ShortestPaths)
|
|||
BackEdge* back, bool first)
|
||||
{
|
||||
MOZ_ASSERT(back);
|
||||
MOZ_ASSERT(traversal.visited.has(origin));
|
||||
MOZ_ASSERT(origin == shortestPaths.root_ || traversal.visited.has(origin));
|
||||
MOZ_ASSERT(totalPathsRecorded < totalMaxPathsToRecord);
|
||||
|
||||
if (first && !back->init(origin, edge))
|
||||
|
@ -128,9 +128,7 @@ struct JS_PUBLIC_API(ShortestPaths)
|
|||
// `back->clone()` in the first branch, and the `init` call in the
|
||||
// second branch.
|
||||
|
||||
auto ptr = shortestPaths.paths_.lookupForAdd(edge.referent);
|
||||
if (first) {
|
||||
MOZ_ASSERT(!ptr);
|
||||
BackEdgeVector paths;
|
||||
if (!paths.reserve(shortestPaths.maxNumPaths_))
|
||||
return false;
|
||||
|
@ -138,16 +136,23 @@ struct JS_PUBLIC_API(ShortestPaths)
|
|||
if (!cloned)
|
||||
return false;
|
||||
paths.infallibleAppend(mozilla::Move(cloned));
|
||||
if (!shortestPaths.paths_.add(ptr, edge.referent, mozilla::Move(paths)))
|
||||
if (!shortestPaths.paths_.putNew(edge.referent, mozilla::Move(paths)))
|
||||
return false;
|
||||
totalPathsRecorded++;
|
||||
} else if (ptr->value().length() < shortestPaths.maxNumPaths_) {
|
||||
MOZ_ASSERT(ptr);
|
||||
BackEdge::Ptr thisBackEdge(js_new<BackEdge>());
|
||||
if (!thisBackEdge || !thisBackEdge->init(origin, edge))
|
||||
return false;
|
||||
ptr->value().infallibleAppend(mozilla::Move(thisBackEdge));
|
||||
totalPathsRecorded++;
|
||||
} else {
|
||||
auto ptr = shortestPaths.paths_.lookup(edge.referent);
|
||||
MOZ_ASSERT(ptr,
|
||||
"This isn't the first time we have seen the target node `edge.referent`. "
|
||||
"We should have inserted it into shortestPaths.paths_ the first time we "
|
||||
"saw it.");
|
||||
|
||||
if (ptr->value().length() < shortestPaths.maxNumPaths_) {
|
||||
BackEdge::Ptr thisBackEdge(js_new<BackEdge>());
|
||||
if (!thisBackEdge || !thisBackEdge->init(origin, edge))
|
||||
return false;
|
||||
ptr->value().infallibleAppend(mozilla::Move(thisBackEdge));
|
||||
totalPathsRecorded++;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(totalPathsRecorded <= totalMaxPathsToRecord);
|
||||
|
@ -251,7 +256,7 @@ struct JS_PUBLIC_API(ShortestPaths)
|
|||
Handler handler(paths);
|
||||
Traversal traversal(rt, handler, noGC);
|
||||
traversal.wantNames = true;
|
||||
if (!traversal.init() || !traversal.addStartVisited(root) || !traversal.traverse())
|
||||
if (!traversal.init() || !traversal.addStart(root) || !traversal.traverse())
|
||||
return mozilla::Nothing();
|
||||
|
||||
// Take ownership of the back edges we created while traversing the
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче