зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to fx-team
This commit is contained in:
Коммит
dd4e976e4a
2
.flake8
2
.flake8
|
@ -1,3 +1,3 @@
|
|||
[flake8]
|
||||
max-line-length = 99
|
||||
filename = *.py, *.lint
|
||||
filename = *.py, +.lint
|
||||
|
|
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1276696 - New Android dependencies
|
||||
Bug 1267887 - Build skew after updating rust mp4parse
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
"gecko_l10n_root": "https://hg.mozilla.org/l10n-central",
|
||||
"gaia": {
|
||||
"l10n": {
|
||||
"vcs": "hgtool",
|
||||
"vcs": "hg",
|
||||
"root": "https://hg.mozilla.org/gaia-l10n"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,22 @@
|
|||
[
|
||||
{
|
||||
"version": "Android NDK r11b for B2G",
|
||||
"algorithm": "sha512",
|
||||
"visibility": "internal",
|
||||
"filename": "android-ndk-b2g.tar.xz",
|
||||
"unpack": true,
|
||||
"digest": "bc37c6b2e38f4ff19e3326786312d8f893600e155d35dfba45163bd909e022db852b9c6920863cb498bbe7da8b86a6a387fa024bc9444ce3a8d1715cf2c24b21",
|
||||
"size": 292442020
|
||||
},
|
||||
{
|
||||
"algorithm": "sha512",
|
||||
"visibility": "internal",
|
||||
"filename": "backup-aries_23.0.1.A.5.77.tar.xz",
|
||||
"unpack": true,
|
||||
"digest": "79c8e390e88cc4765ff7f5f29f3d5337c9037b7eb9414006947d38d34acefdbcf7090c18a366948c682b1c2c9d9ef51012e7be44daa28fdde7b837ade647c257",
|
||||
"size": 227555180
|
||||
},
|
||||
{
|
||||
"version": "gcc 4.8.5 + PR64905",
|
||||
"size": 80160264,
|
||||
"digest": "c1a9dc9da289b8528874d16300b9d13a997cec99195bb0bc46ff665216d8535d6d6cb5af6b4b1f2749af6815dab12e703fdb3849014e5c23a70eff351a0baf4e",
|
||||
|
|
|
@ -6,23 +6,21 @@
|
|||
<remote fetch="https://git.mozilla.org/external/aosp" name="aosp"/>
|
||||
<!--original fetch url was git://github.com/apitrace/-->
|
||||
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
|
||||
<!--original fetch url was git://github.com/mozilla-b2g/-->
|
||||
<remote fetch="https://git.mozilla.org/b2g" name="b2g"/>
|
||||
<remote fetch="git://github.com/mozilla-b2g/" name="b2g"/>
|
||||
<!--original fetch url was https://git.mozilla.org/b2g-->
|
||||
<remote fetch="https://git.mozilla.org/b2g" name="b2gmozilla"/>
|
||||
<!--original fetch url was git://codeaurora.org/-->
|
||||
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
|
||||
<!--original fetch url was http://android.git.linaro.org/git-ro/-->
|
||||
<remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
|
||||
<!--original fetch url was git://github.com/mozilla/-->
|
||||
<remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
|
||||
<remote fetch="git://github.com/mozilla/" name="mozilla"/>
|
||||
<!--original fetch url was https://git.mozilla.org/releases-->
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a954bd2954c422b7d24d92cfd73000cb455dce44"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="19150d320e6802ec211ccc5e74c254ae9992312d"/>
|
||||
<project name="gaia" path="gaia" remote="b2g" revision="99c01f5646b2d8aa5ebf1968114ab2f5db5ac6a8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="31f2fbb02035c18b84f3387317aab75adf65da87"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="34adfb400e031f3dd3353d92413572db5e3a7376"/>
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
"gecko_l10n_root": "https://hg.mozilla.org/l10n-central",
|
||||
"gaia": {
|
||||
"l10n": {
|
||||
"vcs": "hgtool",
|
||||
"vcs": "hg",
|
||||
"root": "https://hg.mozilla.org/gaia-l10n"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
[{
|
||||
[
|
||||
{
|
||||
"version": "Android NDK r11b for B2G",
|
||||
"algorithm": "sha512",
|
||||
"visibility": "internal",
|
||||
"filename": "android-ndk-b2g.tar.xz",
|
||||
"unpack": true,
|
||||
"digest": "bc37c6b2e38f4ff19e3326786312d8f893600e155d35dfba45163bd909e022db852b9c6920863cb498bbe7da8b86a6a387fa024bc9444ce3a8d1715cf2c24b21",
|
||||
"size": 292442020
|
||||
},
|
||||
{
|
||||
"version": "gcc 4.8.5 + PR64905",
|
||||
"size": 80160264,
|
||||
"digest": "c1a9dc9da289b8528874d16300b9d13a997cec99195bb0bc46ff665216d8535d6d6cb5af6b4b1f2749af6815dab12e703fdb3849014e5c23a70eff351a0baf4e",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gcc.tar.xz",
|
||||
"unpack": "True"
|
||||
}]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -6,23 +6,21 @@
|
|||
<remote fetch="https://git.mozilla.org/external/aosp" name="aosp"/>
|
||||
<!--original fetch url was git://github.com/apitrace/-->
|
||||
<remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
|
||||
<!--original fetch url was git://github.com/mozilla-b2g/-->
|
||||
<remote fetch="https://git.mozilla.org/b2g" name="b2g"/>
|
||||
<remote fetch="git://github.com/mozilla-b2g/" name="b2g"/>
|
||||
<!--original fetch url was https://git.mozilla.org/b2g-->
|
||||
<remote fetch="https://git.mozilla.org/b2g" name="b2gmozilla"/>
|
||||
<!--original fetch url was git://codeaurora.org/-->
|
||||
<remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
|
||||
<!--original fetch url was http://android.git.linaro.org/git-ro/-->
|
||||
<remote fetch="https://git.mozilla.org/external/linaro" name="linaro"/>
|
||||
<!--original fetch url was git://github.com/mozilla/-->
|
||||
<remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
|
||||
<remote fetch="git://github.com/mozilla/" name="mozilla"/>
|
||||
<!--original fetch url was https://git.mozilla.org/releases-->
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a954bd2954c422b7d24d92cfd73000cb455dce44"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="19150d320e6802ec211ccc5e74c254ae9992312d"/>
|
||||
<project name="gaia" path="gaia" remote="b2g" revision="99c01f5646b2d8aa5ebf1968114ab2f5db5ac6a8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="31f2fbb02035c18b84f3387317aab75adf65da87"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="34adfb400e031f3dd3353d92413572db5e3a7376"/>
|
||||
|
|
|
@ -611,7 +611,6 @@ if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
|
|||
|
||||
|
||||
var DOMFullscreenHandler = {
|
||||
_fullscreenDoc: null,
|
||||
|
||||
init: function() {
|
||||
addMessageListener("DOMFullscreen:Entered", this);
|
||||
|
@ -646,11 +645,14 @@ var DOMFullscreenHandler = {
|
|||
break;
|
||||
}
|
||||
case "DOMFullscreen:CleanUp": {
|
||||
if (windowUtils) {
|
||||
// If we've exited fullscreen at this point, no need to record
|
||||
// transaction id or call exit fullscreen. This is especially
|
||||
// important for non-e10s, since in that case, it is possible
|
||||
// that no more paint would be triggered after this point.
|
||||
if (content.document.fullscreenElement && windowUtils) {
|
||||
this._lastTransactionId = windowUtils.lastTransactionId;
|
||||
windowUtils.exitFullscreen();
|
||||
}
|
||||
this._fullscreenDoc = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -663,9 +665,8 @@ var DOMFullscreenHandler = {
|
|||
break;
|
||||
}
|
||||
case "MozDOMFullscreen:NewOrigin": {
|
||||
this._fullscreenDoc = aEvent.target;
|
||||
sendAsyncMessage("DOMFullscreen:NewOrigin", {
|
||||
originNoSuffix: this._fullscreenDoc.nodePrincipal.originNoSuffix,
|
||||
originNoSuffix: aEvent.target.nodePrincipal.originNoSuffix,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -687,7 +688,10 @@ var DOMFullscreenHandler = {
|
|||
case "MozAfterPaint": {
|
||||
// Only send Painted signal after we actually finish painting
|
||||
// the transition for the fullscreen change.
|
||||
if (aEvent.transactionId > this._lastTransactionId) {
|
||||
// Note that this._lastTransactionId is not set when in non-e10s
|
||||
// mode, so we need to check that explicitly.
|
||||
if (!this._lastTransactionId ||
|
||||
aEvent.transactionId > this._lastTransactionId) {
|
||||
removeEventListener("MozAfterPaint", this);
|
||||
sendAsyncMessage("DOMFullscreen:Painted");
|
||||
}
|
||||
|
|
|
@ -56,13 +56,16 @@ const AutoMigrate = {
|
|||
}
|
||||
Services.obs.removeObserver(migrationObserver, "Migration:Ended");
|
||||
Services.obs.removeObserver(migrationObserver, "Migration:ItemError");
|
||||
Services.prefs.setCharPref(kAutoMigrateStartedPref, startTime.toString());
|
||||
Services.prefs.setCharPref(kAutoMigrateFinishedPref, Date.now().toString());
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(migrationObserver, "Migration:Ended", false);
|
||||
Services.obs.addObserver(migrationObserver, "Migration:ItemError", false);
|
||||
Services.prefs.setCharPref(kAutoMigrateStartedPref, Date.now().toString());
|
||||
// We'll save this when the migration has finished, at which point the pref
|
||||
// service will be available.
|
||||
let startTime = Date.now();
|
||||
migrator.migrate(this.resourceTypesToUse, profileStartup, profileToMigrate);
|
||||
histogram.add(20);
|
||||
},
|
||||
|
|
|
@ -529,6 +529,7 @@ this.MigrationUtils = Object.freeze({
|
|||
// Canary uses the same description as Chrome so we can't distinguish them.
|
||||
const APP_DESC_TO_KEY = {
|
||||
"Internet Explorer": "ie",
|
||||
"Microsoft Edge": "edge",
|
||||
"Safari": "safari",
|
||||
"Firefox": "firefox",
|
||||
"Google Chrome": "chrome", // Windows, Linux
|
||||
|
|
|
@ -53,6 +53,8 @@ PluginContent.prototype = {
|
|||
global.addMessageListener("BrowserPlugins:NPAPIPluginProcessCrashed", this);
|
||||
global.addMessageListener("BrowserPlugins:CrashReportSubmitted", this);
|
||||
global.addMessageListener("BrowserPlugins:Test:ClearCrashData", this);
|
||||
|
||||
Services.obs.addObserver(this, "Plugin::HiddenPluginTouched", false);
|
||||
},
|
||||
|
||||
uninit: function() {
|
||||
|
@ -75,6 +77,8 @@ PluginContent.prototype = {
|
|||
global.removeMessageListener("BrowserPlugins:Test:ClearCrashData", this);
|
||||
delete this.global;
|
||||
delete this.content;
|
||||
|
||||
Services.obs.removeObserver(this, "Plugin::HiddenPluginTouched");
|
||||
},
|
||||
|
||||
receiveMessage: function (msg) {
|
||||
|
@ -116,6 +120,15 @@ PluginContent.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
let pluginTag = aSubject.QueryInterface(Ci.nsIPluginTag);
|
||||
if (aTopic == "Plugin::HiddenPluginTouched") {
|
||||
this._showClickToPlayNotification(pluginTag, false);
|
||||
} else {
|
||||
Cu.reportError("unknown topic observed: " + aTopic);
|
||||
}
|
||||
},
|
||||
|
||||
onPageShow: function (event) {
|
||||
// Ignore events that aren't from the main document.
|
||||
if (!this.content || event.target != this.content.document) {
|
||||
|
@ -194,6 +207,45 @@ PluginContent.prototype = {
|
|||
};
|
||||
},
|
||||
|
||||
_getPluginInfoForTag: function (pluginTag, tagMimetype) {
|
||||
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
|
||||
let pluginName = gNavigatorBundle.GetStringFromName("pluginInfo.unknownPlugin");
|
||||
let permissionString = null;
|
||||
let blocklistState = null;
|
||||
|
||||
if (pluginTag) {
|
||||
pluginName = BrowserUtils.makeNicePluginName(pluginTag.name);
|
||||
|
||||
permissionString = pluginHost.getPermissionStringForTag(pluginTag);
|
||||
blocklistState = pluginTag.blocklistState;
|
||||
|
||||
// Convert this from nsIPluginTag so it can be serialized.
|
||||
let properties = ["name", "description", "filename", "version", "enabledState", "niceName"];
|
||||
let pluginTagCopy = {};
|
||||
for (let prop of properties) {
|
||||
pluginTagCopy[prop] = pluginTag[prop];
|
||||
}
|
||||
pluginTag = pluginTagCopy;
|
||||
|
||||
// Make state-softblocked == state-notblocked for our purposes,
|
||||
// they have the same UI. STATE_OUTDATED should not exist for plugin
|
||||
// items, but let's alias it anyway, just in case.
|
||||
if (blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED ||
|
||||
blocklistState == Ci.nsIBlocklistService.STATE_OUTDATED) {
|
||||
blocklistState = Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
return { mimetype: tagMimetype,
|
||||
pluginName: pluginName,
|
||||
pluginTag: pluginTag,
|
||||
permissionString: permissionString,
|
||||
fallbackType: null,
|
||||
blocklistState: blocklistState,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the visibility of the plugin overlay.
|
||||
*/
|
||||
|
@ -710,7 +762,13 @@ PluginContent.prototype = {
|
|||
let location = this.content.document.location.href;
|
||||
|
||||
for (let p of plugins) {
|
||||
let pluginInfo = this._getPluginInfo(p);
|
||||
let pluginInfo;
|
||||
if (p instanceof Ci.nsIPluginTag) {
|
||||
let mimeType = p.getMimeTypes() > 0 ? p.getMimeTypes()[0] : null;
|
||||
pluginInfo = this._getPluginInfoForTag(p, mimeType);
|
||||
} else {
|
||||
pluginInfo = this._getPluginInfo(p);
|
||||
}
|
||||
if (pluginInfo.permissionString === null) {
|
||||
Cu.reportError("No permission string for active plugin.");
|
||||
continue;
|
||||
|
|
|
@ -27,6 +27,7 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
|||
private final Member[] mObjects;
|
||||
private AnnotatableEntity mNextReturnValue;
|
||||
private int mElementIndex;
|
||||
private AnnotationInfo mClassInfo;
|
||||
|
||||
private boolean mIterateEveryEntry;
|
||||
|
||||
|
@ -55,8 +56,8 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
|||
|
||||
// Check for "Wrap ALL the things" flag.
|
||||
for (Annotation annotation : aClass.getDeclaredAnnotations()) {
|
||||
final String annotationTypeName = annotation.annotationType().getName();
|
||||
if (annotationTypeName.equals("org.mozilla.gecko.annotation.WrapForJNI")) {
|
||||
mClassInfo = buildAnnotationInfo(aClass, annotation);
|
||||
if (mClassInfo != null) {
|
||||
mIterateEveryEntry = true;
|
||||
break;
|
||||
}
|
||||
|
@ -115,6 +116,73 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
|||
return ret;
|
||||
}
|
||||
|
||||
private AnnotationInfo buildAnnotationInfo(AnnotatedElement element, Annotation annotation) {
|
||||
Class<? extends Annotation> annotationType = annotation.annotationType();
|
||||
final String annotationTypeName = annotationType.getName();
|
||||
if (!annotationTypeName.equals("org.mozilla.gecko.annotation.WrapForJNI")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String stubName = null;
|
||||
boolean isMultithreadedStub = false;
|
||||
boolean noThrow = false;
|
||||
boolean narrowChars = false;
|
||||
boolean catchException = false;
|
||||
try {
|
||||
// Determine the explicitly-given name of the stub to generate, if any.
|
||||
final Method stubNameMethod = annotationType.getDeclaredMethod("stubName");
|
||||
stubNameMethod.setAccessible(true);
|
||||
stubName = (String) stubNameMethod.invoke(annotation);
|
||||
|
||||
if (element instanceof Class<?>) {
|
||||
// Make @WrapForJNI always allow multithread by default, individual methods can then
|
||||
// override with their own annotation
|
||||
isMultithreadedStub = true;
|
||||
} else {
|
||||
// Determine if the generated stub is to allow calls from multiple threads.
|
||||
final Method multithreadedStubMethod = annotationType.getDeclaredMethod("allowMultithread");
|
||||
multithreadedStubMethod.setAccessible(true);
|
||||
isMultithreadedStub = (Boolean) multithreadedStubMethod.invoke(annotation);
|
||||
}
|
||||
|
||||
// Determine if ignoring exceptions
|
||||
final Method noThrowMethod = annotationType.getDeclaredMethod("noThrow");
|
||||
noThrowMethod.setAccessible(true);
|
||||
noThrow = (Boolean) noThrowMethod.invoke(annotation);
|
||||
|
||||
// Determine if strings should be wide or narrow
|
||||
final Method narrowCharsMethod = annotationType.getDeclaredMethod("narrowChars");
|
||||
narrowCharsMethod.setAccessible(true);
|
||||
narrowChars = (Boolean) narrowCharsMethod.invoke(annotation);
|
||||
|
||||
// Determine if we should catch exceptions
|
||||
final Method catchExceptionMethod = annotationType.getDeclaredMethod("catchException");
|
||||
catchExceptionMethod.setAccessible(true);
|
||||
catchException = (Boolean) catchExceptionMethod.invoke(annotation);
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
System.err.println("Unable to find expected field on WrapForJNI annotation. Did the signature change?");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(3);
|
||||
} catch (IllegalAccessException e) {
|
||||
System.err.println("IllegalAccessException reading fields on WrapForJNI annotation. Seems the semantics of Reflection have changed...");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(4);
|
||||
} catch (InvocationTargetException e) {
|
||||
System.err.println("InvocationTargetException reading fields on WrapForJNI annotation. This really shouldn't happen.");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(5);
|
||||
}
|
||||
|
||||
// If the method name was not explicitly given in the annotation generate one...
|
||||
if (stubName.isEmpty()) {
|
||||
stubName = Utils.getNativeName(element);
|
||||
}
|
||||
|
||||
return new AnnotationInfo(
|
||||
stubName, isMultithreadedStub, noThrow, narrowChars, catchException);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and cache the next appropriately annotated method, plus the annotation parameter, if
|
||||
* one exists. Otherwise cache null, so hasNext returns false.
|
||||
|
@ -124,63 +192,9 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
|||
Member candidateElement = mObjects[mElementIndex];
|
||||
mElementIndex++;
|
||||
for (Annotation annotation : ((AnnotatedElement) candidateElement).getDeclaredAnnotations()) {
|
||||
// WrappedJNIMethod has parameters. Use Reflection to obtain them.
|
||||
Class<? extends Annotation> annotationType = annotation.annotationType();
|
||||
final String annotationTypeName = annotationType.getName();
|
||||
if (annotationTypeName.equals("org.mozilla.gecko.annotation.WrapForJNI")) {
|
||||
String stubName = null;
|
||||
boolean isMultithreadedStub = false;
|
||||
boolean noThrow = false;
|
||||
boolean narrowChars = false;
|
||||
boolean catchException = false;
|
||||
try {
|
||||
// Determine the explicitly-given name of the stub to generate, if any.
|
||||
final Method stubNameMethod = annotationType.getDeclaredMethod("stubName");
|
||||
stubNameMethod.setAccessible(true);
|
||||
stubName = (String) stubNameMethod.invoke(annotation);
|
||||
|
||||
// Determine if the generated stub is to allow calls from multiple threads.
|
||||
final Method multithreadedStubMethod = annotationType.getDeclaredMethod("allowMultithread");
|
||||
multithreadedStubMethod.setAccessible(true);
|
||||
isMultithreadedStub = (Boolean) multithreadedStubMethod.invoke(annotation);
|
||||
|
||||
// Determine if ignoring exceptions
|
||||
final Method noThrowMethod = annotationType.getDeclaredMethod("noThrow");
|
||||
noThrowMethod.setAccessible(true);
|
||||
noThrow = (Boolean) noThrowMethod.invoke(annotation);
|
||||
|
||||
// Determine if strings should be wide or narrow
|
||||
final Method narrowCharsMethod = annotationType.getDeclaredMethod("narrowChars");
|
||||
narrowCharsMethod.setAccessible(true);
|
||||
narrowChars = (Boolean) narrowCharsMethod.invoke(annotation);
|
||||
|
||||
// Determine if we should catch exceptions
|
||||
final Method catchExceptionMethod = annotationType.getDeclaredMethod("catchException");
|
||||
catchExceptionMethod.setAccessible(true);
|
||||
catchException = (Boolean) catchExceptionMethod.invoke(annotation);
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
System.err.println("Unable to find expected field on WrapForJNI annotation. Did the signature change?");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(3);
|
||||
} catch (IllegalAccessException e) {
|
||||
System.err.println("IllegalAccessException reading fields on WrapForJNI annotation. Seems the semantics of Reflection have changed...");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(4);
|
||||
} catch (InvocationTargetException e) {
|
||||
System.err.println("InvocationTargetException reading fields on WrapForJNI annotation. This really shouldn't happen.");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(5);
|
||||
}
|
||||
|
||||
// If the method name was not explicitly given in the annotation generate one...
|
||||
if (stubName.isEmpty()) {
|
||||
stubName = Utils.getNativeName(candidateElement);
|
||||
}
|
||||
|
||||
AnnotationInfo annotationInfo = new AnnotationInfo(
|
||||
stubName, isMultithreadedStub, noThrow, narrowChars, catchException);
|
||||
mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
|
||||
AnnotationInfo info = buildAnnotationInfo((AnnotatedElement)candidateElement, annotation);
|
||||
if (info != null) {
|
||||
mNextReturnValue = new AnnotatableEntity(candidateElement, info);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -190,10 +204,10 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
|||
if (mIterateEveryEntry) {
|
||||
AnnotationInfo annotationInfo = new AnnotationInfo(
|
||||
Utils.getNativeName(candidateElement),
|
||||
/* multithreaded */ true,
|
||||
/* noThrow */ false,
|
||||
/* narrowChars */ false,
|
||||
/* catchException */ false);
|
||||
mClassInfo.isMultithreaded,
|
||||
mClassInfo.noThrow,
|
||||
mClassInfo.narrowChars,
|
||||
mClassInfo.catchException);
|
||||
mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package org.mozilla.gecko.annotationProcessors.utils;
|
|||
|
||||
import org.mozilla.gecko.annotationProcessors.AnnotationInfo;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
|
@ -212,6 +213,33 @@ public class Utils {
|
|||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the C++ name for a member.
|
||||
*
|
||||
* @param member Member to get the name for.
|
||||
* @return JNI name as a string
|
||||
*/
|
||||
public static String getNativeName(Class<?> clz) {
|
||||
final String name = clz.getName();
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the C++ name for a member.
|
||||
*
|
||||
* @param member Member to get the name for.
|
||||
* @return JNI name as a string
|
||||
*/
|
||||
public static String getNativeName(AnnotatedElement element) {
|
||||
if (element instanceof Class<?>) {
|
||||
return getNativeName((Class<?>)element);
|
||||
} else if (element instanceof Member) {
|
||||
return getNativeName((Member)element);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JNI name for a member.
|
||||
*
|
||||
|
|
|
@ -557,7 +557,6 @@ SECMOD_DeleteInternalModule
|
|||
SECMOD_DeleteModule
|
||||
SECMOD_DestroyModule
|
||||
SECMOD_FindModule
|
||||
SECMOD_FindSlot
|
||||
SECMOD_GetDeadModuleList
|
||||
SECMOD_GetDefaultModuleList
|
||||
SECMOD_GetDefaultModuleListLock
|
||||
|
|
|
@ -7,6 +7,7 @@ import unittest
|
|||
import inspect
|
||||
from StringIO import StringIO
|
||||
import os
|
||||
import sys
|
||||
|
||||
'''Helper to make python unit tests report the way that the Mozilla
|
||||
unit test infrastructure expects tests to report.
|
||||
|
@ -107,6 +108,17 @@ class MockedFile(StringIO):
|
|||
def __exit__(self, type, value, traceback):
|
||||
self.close()
|
||||
|
||||
def normcase(path):
|
||||
'''
|
||||
Normalize the case of `path`.
|
||||
|
||||
Don't use `os.path.normcase` because that also normalizes forward slashes
|
||||
to backslashes on Windows.
|
||||
'''
|
||||
if sys.platform.startswith('win'):
|
||||
return path.lower()
|
||||
return path
|
||||
|
||||
class MockedOpen(object):
|
||||
'''
|
||||
Context manager diverting the open builtin such that opening files
|
||||
|
@ -129,10 +141,10 @@ class MockedOpen(object):
|
|||
def __init__(self, files = {}):
|
||||
self.files = {}
|
||||
for name, content in files.iteritems():
|
||||
self.files[os.path.abspath(name)] = content
|
||||
self.files[normcase(os.path.abspath(name))] = content
|
||||
|
||||
def __call__(self, name, mode = 'r'):
|
||||
absname = os.path.abspath(name)
|
||||
absname = normcase(os.path.abspath(name))
|
||||
if 'w' in mode:
|
||||
file = MockedFile(self, absname)
|
||||
elif absname in self.files:
|
||||
|
@ -169,6 +181,7 @@ class MockedOpen(object):
|
|||
self._orig_path_exists(p))
|
||||
|
||||
def _wrapped_isfile(self, p):
|
||||
p = normcase(p)
|
||||
if p in self.files:
|
||||
return True
|
||||
|
||||
|
@ -179,6 +192,7 @@ class MockedOpen(object):
|
|||
return self._orig_path_isfile(p)
|
||||
|
||||
def _wrapped_isdir(self, p):
|
||||
p = normcase(p)
|
||||
p = p if p.endswith(('/', '\\')) else p + os.sep
|
||||
if any(f.startswith(p) for f in self.files):
|
||||
return True
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsICookieService.h"
|
||||
#include "nsIConsoleReportCollector.h"
|
||||
#include "nsObjectLoadingContent.h"
|
||||
|
||||
// we want to explore making the document own the load group
|
||||
// so we can associate the document URI with the load group.
|
||||
|
@ -2524,15 +2525,35 @@ nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
|
|||
if (frameElement && !frameElement->IsXULElement()) {
|
||||
// We do not allow document inside any containing element other
|
||||
// than iframe to enter fullscreen.
|
||||
if (!frameElement->IsHTMLElement(nsGkAtoms::iframe)) {
|
||||
return NS_OK;
|
||||
}
|
||||
// If any ancestor iframe does not have allowfullscreen attribute
|
||||
// set, then fullscreen is not allowed.
|
||||
if (!frameElement->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::allowfullscreen) &&
|
||||
!frameElement->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::mozallowfullscreen)) {
|
||||
if (frameElement->IsHTMLElement(nsGkAtoms::iframe)) {
|
||||
// If any ancestor iframe does not have allowfullscreen attribute
|
||||
// set, then fullscreen is not allowed.
|
||||
if (!frameElement->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::allowfullscreen) &&
|
||||
!frameElement->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::mozallowfullscreen)) {
|
||||
return NS_OK;
|
||||
}
|
||||
} else if (frameElement->IsHTMLElement(nsGkAtoms::embed)) {
|
||||
// Respect allowfullscreen only if this is a rewritten YouTube embed.
|
||||
nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent =
|
||||
do_QueryInterface(frameElement);
|
||||
if (!objectLoadingContent) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsObjectLoadingContent* olc =
|
||||
static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
|
||||
if (!olc->IsRewrittenYoutubeEmbed()) {
|
||||
return NS_OK;
|
||||
}
|
||||
// We don't have to check prefixed attributes because Flash does not
|
||||
// support them.
|
||||
if (!frameElement->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::allowfullscreen)) {
|
||||
return NS_OK;
|
||||
}
|
||||
} else {
|
||||
// neither iframe nor embed
|
||||
return NS_OK;
|
||||
}
|
||||
nsIDocument* doc = frameElement->GetUncomposedDoc();
|
||||
|
|
|
@ -1733,18 +1733,17 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
|
|||
if (HasPointerLock()) {
|
||||
nsIDocument::UnlockPointer();
|
||||
}
|
||||
if (mState.HasState(NS_EVENT_STATE_FULL_SCREEN)) {
|
||||
// The element being removed is an ancestor of the full-screen element,
|
||||
// exit full-screen state.
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DOM"), OwnerDoc(),
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"RemovedFullscreenElement");
|
||||
// Fully exit full-screen.
|
||||
nsIDocument::ExitFullscreenInDocTree(OwnerDoc());
|
||||
}
|
||||
if (aNullParent) {
|
||||
if (IsFullScreenAncestor()) {
|
||||
// The element being removed is an ancestor of the full-screen element,
|
||||
// exit full-screen state.
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DOM"), OwnerDoc(),
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"RemovedFullscreenElement");
|
||||
// Fully exit full-screen.
|
||||
nsIDocument::ExitFullscreenInDocTree(OwnerDoc());
|
||||
}
|
||||
|
||||
if (GetParent() && GetParent()->IsInUncomposedDoc()) {
|
||||
// Update the editable descendant count in the ancestors before we
|
||||
// lose the reference to the parent.
|
||||
|
|
|
@ -192,15 +192,6 @@ public:
|
|||
*/
|
||||
void UpdateLinkState(EventStates aState);
|
||||
|
||||
/**
|
||||
* Returns true if this element is either a full-screen element or an
|
||||
* ancestor of the full-screen element.
|
||||
*/
|
||||
bool IsFullScreenAncestor() const {
|
||||
return mState.HasAtLeastOneOfStates(NS_EVENT_STATE_FULL_SCREEN_ANCESTOR |
|
||||
NS_EVENT_STATE_FULL_SCREEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* The style state of this element. This is the real state of the element
|
||||
* with any style locks applied for pseudo-class inspecting.
|
||||
|
|
|
@ -1846,6 +1846,12 @@ WebSocketImpl::InitializeConnection(nsIPrincipal* aPrincipal)
|
|||
// are not thread-safe.
|
||||
mOriginDocument = nullptr;
|
||||
|
||||
|
||||
// The TriggeringPrincipal for websockets must always be a script.
|
||||
// Let's make sure that the doc's principal (if a doc exists)
|
||||
// and aPrincipal are same origin.
|
||||
MOZ_ASSERT(!doc || doc->NodePrincipal()->Equals(aPrincipal));
|
||||
|
||||
wsChannel->InitLoadInfo(doc ? doc->AsDOMNode() : nullptr,
|
||||
doc ? doc->NodePrincipal() : aPrincipal,
|
||||
aPrincipal,
|
||||
|
|
|
@ -1344,6 +1344,80 @@ nsContentUtils::GetParserService()
|
|||
return sParserService;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function that parses a sandbox attribute (of an <iframe> or a CSP
|
||||
* directive) and converts it to the set of flags used internally.
|
||||
*
|
||||
* @param aSandboxAttr the sandbox attribute
|
||||
* @return the set of flags (SANDBOXED_NONE if aSandboxAttr is
|
||||
* null)
|
||||
*/
|
||||
uint32_t
|
||||
nsContentUtils::ParseSandboxAttributeToFlags(const nsAttrValue* aSandboxAttr)
|
||||
{
|
||||
if (!aSandboxAttr) {
|
||||
return SANDBOXED_NONE;
|
||||
}
|
||||
|
||||
uint32_t out = SANDBOX_ALL_FLAGS;
|
||||
|
||||
#define SANDBOX_KEYWORD(string, atom, flags) \
|
||||
if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \
|
||||
out &= ~(flags); \
|
||||
}
|
||||
#include "IframeSandboxKeywordList.h"
|
||||
#undef SANDBOX_KEYWORD
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function that checks if a string matches a valid sandbox flag.
|
||||
*
|
||||
* @param aFlag the potential sandbox flag.
|
||||
* @return true if the flag is a sandbox flag.
|
||||
*/
|
||||
bool
|
||||
nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag)
|
||||
{
|
||||
#define SANDBOX_KEYWORD(string, atom, flags) \
|
||||
if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \
|
||||
return true; \
|
||||
}
|
||||
#include "IframeSandboxKeywordList.h"
|
||||
#undef SANDBOX_KEYWORD
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function that returns a string attribute corresponding to the
|
||||
* sandbox flags.
|
||||
*
|
||||
* @param aFlags the sandbox flags
|
||||
* @param aString the attribute corresponding to the flags (null if aFlags
|
||||
* is zero)
|
||||
*/
|
||||
void
|
||||
nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString)
|
||||
{
|
||||
if (!aFlags) {
|
||||
SetDOMStringToNull(aString);
|
||||
return;
|
||||
}
|
||||
|
||||
aString.Truncate();
|
||||
|
||||
#define SANDBOX_KEYWORD(string, atom, flags) \
|
||||
if (!(aFlags & (flags))) { \
|
||||
if (!aString.IsEmpty()) { \
|
||||
aString.Append(NS_LITERAL_STRING(" ")); \
|
||||
} \
|
||||
aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \
|
||||
}
|
||||
#include "IframeSandboxKeywordList.h"
|
||||
#undef SANDBOX_KEYWORD
|
||||
}
|
||||
|
||||
nsIBidiKeyboard*
|
||||
nsContentUtils::GetBidiKeyboard()
|
||||
{
|
||||
|
|
|
@ -917,6 +917,34 @@ public:
|
|||
const char* aKey,
|
||||
nsXPIDLString& aResult);
|
||||
|
||||
/**
|
||||
* A helper function that parses a sandbox attribute (of an <iframe> or a CSP
|
||||
* directive) and converts it to the set of flags used internally.
|
||||
*
|
||||
* @param aSandboxAttr the sandbox attribute
|
||||
* @return the set of flags (SANDBOXED_NONE if aSandboxAttr is
|
||||
* null)
|
||||
*/
|
||||
static uint32_t ParseSandboxAttributeToFlags(const nsAttrValue* aSandboxAttr);
|
||||
|
||||
/**
|
||||
* A helper function that checks if a string matches a valid sandbox flag.
|
||||
*
|
||||
* @param aFlag the potential sandbox flag.
|
||||
* @return true if the flag is a sandbox flag.
|
||||
*/
|
||||
static bool IsValidSandboxFlag(const nsAString& aFlag);
|
||||
|
||||
/**
|
||||
* A helper function that returns a string attribute corresponding to the
|
||||
* sandbox flags.
|
||||
*
|
||||
* @param aFlags the sandbox flags
|
||||
* @param aString the attribute corresponding to the flags (null if aFlags
|
||||
* is zero)
|
||||
*/
|
||||
static void SandboxFlagsToString(uint32_t aFlags, nsAString& aString);
|
||||
|
||||
/**
|
||||
* Helper function that generates a UUID.
|
||||
*/
|
||||
|
|
|
@ -3214,6 +3214,10 @@ PrepareForFullscreenChange(nsIPresShell* aPresShell, const nsSize& aSize,
|
|||
}
|
||||
if (nsRefreshDriver* rd = aPresShell->GetRefreshDriver()) {
|
||||
rd->SetIsResizeSuppressed();
|
||||
// Since we are suppressing the resize reflow which would originally
|
||||
// be triggered by view manager, we need to ensure that the refresh
|
||||
// driver actually schedules a flush, otherwise it may get stuck.
|
||||
rd->ScheduleViewManagerFlush();
|
||||
}
|
||||
if (!aSize.IsEmpty()) {
|
||||
if (nsViewManager* viewManager = aPresShell->GetViewManager()) {
|
||||
|
|
|
@ -1579,8 +1579,6 @@ nsDocument::~nsDocument()
|
|||
}
|
||||
Accumulate(Telemetry::MIXED_CONTENT_PAGE_LOAD, mixedContentLevel);
|
||||
|
||||
Accumulate(Telemetry::SCROLL_LINKED_EFFECT_FOUND, mHasScrollLinkedEffect);
|
||||
|
||||
// record mixed object subrequest telemetry
|
||||
if (mHasMixedContentObjectSubrequest) {
|
||||
/* mixed object subrequest loaded on page*/
|
||||
|
@ -2760,6 +2758,8 @@ nsDocument::ApplySettingsFromCSP(bool aSpeculative)
|
|||
nsresult
|
||||
nsDocument::InitCSP(nsIChannel* aChannel)
|
||||
{
|
||||
MOZ_ASSERT(!mScriptGlobalObject,
|
||||
"CSP must be initialized before mScriptGlobalObject is set!");
|
||||
if (!CSPService::sCSPEnabled) {
|
||||
MOZ_LOG(gCspPRLog, LogLevel::Debug,
|
||||
("CSP is disabled, skipping CSP init for document %p", this));
|
||||
|
@ -2792,7 +2792,7 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
|||
NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue);
|
||||
|
||||
// Figure out if we need to apply an app default CSP or a CSP from an app manifest
|
||||
nsIPrincipal* principal = NodePrincipal();
|
||||
nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
|
||||
|
||||
uint16_t appStatus = principal->GetAppStatus();
|
||||
bool applyAppDefaultCSP = false;
|
||||
|
@ -2941,6 +2941,24 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// ----- Enforce sandbox policy if supplied in CSP header
|
||||
// The document may already have some sandbox flags set (e.g. if the document
|
||||
// is an iframe with the sandbox attribute set). If we have a CSP sandbox
|
||||
// directive, intersect the CSP sandbox flags with the existing flags. This
|
||||
// corresponds to the _least_ permissive policy.
|
||||
uint32_t cspSandboxFlags = SANDBOXED_NONE;
|
||||
rv = csp->GetCSPSandboxFlags(&cspSandboxFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mSandboxFlags |= cspSandboxFlags;
|
||||
|
||||
if (cspSandboxFlags & SANDBOXED_ORIGIN) {
|
||||
// If the new CSP sandbox flags do not have the allow-same-origin flag
|
||||
// reset the document principal to a null principal
|
||||
principal = do_CreateInstance("@mozilla.org/nullprincipal;1");
|
||||
SetPrincipal(principal);
|
||||
}
|
||||
|
||||
// ----- Enforce frame-ancestor policy on any applied policies
|
||||
nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
|
||||
if (docShell) {
|
||||
|
@ -3672,6 +3690,12 @@ nsDocument::RemoveCharSetObserver(nsIObserver* aObserver)
|
|||
mCharSetObservers.RemoveElement(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::GetSandboxFlagsAsString(nsAString& aFlags)
|
||||
{
|
||||
nsContentUtils::SandboxFlagsToString(mSandboxFlags, aFlags);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::GetHeaderData(nsIAtom* aHeaderField, nsAString& aData) const
|
||||
{
|
||||
|
@ -4773,7 +4797,9 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
|
|||
}
|
||||
|
||||
MaybeRescheduleAnimationFrameNotifications();
|
||||
mRegistry = new Registry();
|
||||
if (Preferences::GetBool("dom.webcomponents.enabled")) {
|
||||
mRegistry = new Registry();
|
||||
}
|
||||
}
|
||||
|
||||
// Remember the pointer to our window (or lack there of), to avoid
|
||||
|
@ -5669,8 +5695,10 @@ nsDocument::CreateElement(const nsAString& aTagName,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (!aTagName.Equals(aTypeExtension)) {
|
||||
// Custom element type can not extend itself.
|
||||
if (!aTypeExtension.IsVoid() &&
|
||||
!aTagName.Equals(aTypeExtension)) {
|
||||
// do not process 'is' if it is null or the extended type is the same as
|
||||
// the localName
|
||||
SetupCustomElement(elem, GetDefaultNamespaceID(), &aTypeExtension);
|
||||
}
|
||||
|
||||
|
@ -5727,6 +5755,13 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (aTypeExtension.IsVoid() ||
|
||||
aQualifiedName.Equals(aTypeExtension)) {
|
||||
// do not process 'is' if it is null or the extended type is the same as
|
||||
// the localName
|
||||
return elem.forget();
|
||||
}
|
||||
|
||||
int32_t nameSpaceId = kNameSpaceID_Wildcard;
|
||||
if (!aNamespaceURI.EqualsLiteral("*")) {
|
||||
rv = nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
|
||||
|
@ -5736,10 +5771,7 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
|
|||
}
|
||||
}
|
||||
|
||||
if (!aQualifiedName.Equals(aTypeExtension)) {
|
||||
// A custom element type can not extend itself.
|
||||
SetupCustomElement(elem, nameSpaceId, &aTypeExtension);
|
||||
}
|
||||
SetupCustomElement(elem, nameSpaceId, &aTypeExtension);
|
||||
|
||||
return elem.forget();
|
||||
}
|
||||
|
@ -11652,7 +11684,7 @@ nsDocument::FullScreenStackPop()
|
|||
while (!mFullScreenStack.IsEmpty()) {
|
||||
Element* element = FullScreenStackTop();
|
||||
if (!element || !element->IsInUncomposedDoc() || element->OwnerDoc() != this) {
|
||||
NS_ASSERTION(!element->IsFullScreenAncestor(),
|
||||
NS_ASSERTION(!element->State().HasState(NS_EVENT_STATE_FULL_SCREEN),
|
||||
"Should have already removed full-screen styles");
|
||||
uint32_t last = mFullScreenStack.Length() - 1;
|
||||
mFullScreenStack.RemoveElementAt(last);
|
||||
|
@ -12214,7 +12246,7 @@ nsDocument::GetFullscreenElement()
|
|||
{
|
||||
Element* element = FullScreenStackTop();
|
||||
NS_ASSERTION(!element ||
|
||||
element->IsFullScreenAncestor(),
|
||||
element->State().HasState(NS_EVENT_STATE_FULL_SCREEN),
|
||||
"Fullscreen element should have fullscreen styles applied");
|
||||
return element;
|
||||
}
|
||||
|
|
|
@ -696,6 +696,11 @@ public:
|
|||
return mSandboxFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string representation of sandbox flags (null if no flags are set)
|
||||
*/
|
||||
void GetSandboxFlagsAsString(nsAString& aFlags);
|
||||
|
||||
/**
|
||||
* Set the sandbox flags for this document.
|
||||
* @see nsSandboxFlags.h for the possible flags
|
||||
|
|
|
@ -721,7 +721,8 @@ nsObjectLoadingContent::nsObjectLoadingContent()
|
|||
, mActivated(false)
|
||||
, mIsStopping(false)
|
||||
, mIsLoading(false)
|
||||
, mScriptRequested(false) {}
|
||||
, mScriptRequested(false)
|
||||
, mRewrittenYoutubeEmbed(false) {}
|
||||
|
||||
nsObjectLoadingContent::~nsObjectLoadingContent()
|
||||
{
|
||||
|
@ -1843,6 +1844,7 @@ nsObjectLoadingContent::UpdateObjectParameters(bool aJavaURI)
|
|||
NS_NOTREACHED("Unrecognized plugin-loading tag");
|
||||
}
|
||||
|
||||
mRewrittenYoutubeEmbed = false;
|
||||
// Note that the baseURI changing could affect the newURI, even if uriStr did
|
||||
// not change.
|
||||
if (!uriStr.IsEmpty()) {
|
||||
|
@ -1856,6 +1858,7 @@ nsObjectLoadingContent::UpdateObjectParameters(bool aJavaURI)
|
|||
getter_AddRefs(rewrittenURI));
|
||||
if (rewrittenURI) {
|
||||
newURI = rewrittenURI;
|
||||
mRewrittenYoutubeEmbed = true;
|
||||
newMime = NS_LITERAL_CSTRING("text/html");
|
||||
}
|
||||
|
||||
|
|
|
@ -250,6 +250,11 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
return runID;
|
||||
}
|
||||
|
||||
bool IsRewrittenYoutubeEmbed() const
|
||||
{
|
||||
return mRewrittenYoutubeEmbed;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Begins loading the object when called
|
||||
|
@ -628,7 +633,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
FallbackType mFallbackType : 8;
|
||||
|
||||
uint32_t mRunID;
|
||||
bool mHasRunID;
|
||||
bool mHasRunID : 1;
|
||||
|
||||
// If true, we have opened a channel as the listener and it has reached
|
||||
// OnStartRequest. Does not get set for channels that are passed directly to
|
||||
|
@ -658,6 +663,12 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
|||
// whether content js has tried to access the plugin script object.
|
||||
bool mScriptRequested : 1;
|
||||
|
||||
// True if object represents an object/embed tag pointing to a flash embed
|
||||
// for a youtube video. When possible (see IsRewritableYoutubeEmbed function
|
||||
// comments for details), we change these to try to load HTML5 versions of
|
||||
// videos.
|
||||
bool mRewrittenYoutubeEmbed : 1;
|
||||
|
||||
nsWeakFrame mPrintFrame;
|
||||
|
||||
RefPtr<nsPluginInstanceOwner> mInstanceOwner;
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "nsIWeakReference.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -66,7 +68,8 @@ NS_INTERFACE_MAP_END
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsPluginArray,
|
||||
mWindow,
|
||||
mPlugins)
|
||||
mPlugins,
|
||||
mCTPPlugins)
|
||||
|
||||
static void
|
||||
GetPluginMimeTypes(const nsTArray<RefPtr<nsPluginElement> >& aPlugins,
|
||||
|
@ -146,6 +149,7 @@ nsPluginArray::Refresh(bool aReloadDocuments)
|
|||
}
|
||||
|
||||
mPlugins.Clear();
|
||||
mCTPPlugins.Clear();
|
||||
|
||||
nsCOMPtr<nsIDOMNavigator> navigator = mWindow->GetNavigator();
|
||||
|
||||
|
@ -221,6 +225,13 @@ nsPluginArray::NamedGetter(const nsAString& aName, bool &aFound)
|
|||
|
||||
nsPluginElement* plugin = FindPlugin(mPlugins, aName);
|
||||
aFound = (plugin != nullptr);
|
||||
if (!aFound) {
|
||||
nsPluginElement* hiddenPlugin = FindPlugin(mCTPPlugins, aName);
|
||||
if (hiddenPlugin) {
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->NotifyObservers(hiddenPlugin->PluginTag(), "Plugin::HiddenPluginTouched", nsString(aName).get());
|
||||
}
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
|
||||
|
@ -282,7 +293,7 @@ operator<(const RefPtr<nsPluginElement>& lhs,
|
|||
void
|
||||
nsPluginArray::EnsurePlugins()
|
||||
{
|
||||
if (!mPlugins.IsEmpty()) {
|
||||
if (!mPlugins.IsEmpty() || !mCTPPlugins.IsEmpty()) {
|
||||
// We already have an array of plugin elements.
|
||||
return;
|
||||
}
|
||||
|
@ -299,7 +310,31 @@ nsPluginArray::EnsurePlugins()
|
|||
// need to wrap each of these with a nsPluginElement, which is
|
||||
// scriptable.
|
||||
for (uint32_t i = 0; i < pluginTags.Length(); ++i) {
|
||||
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
|
||||
nsCOMPtr<nsPluginTag> pluginTag = do_QueryInterface(pluginTags[i]);
|
||||
if (!pluginTag) {
|
||||
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
|
||||
} else if (pluginTag->IsActive()) {
|
||||
uint32_t permission = nsIPermissionManager::ALLOW_ACTION;
|
||||
if (pluginTag->IsClicktoplay()) {
|
||||
nsCString name;
|
||||
pluginTag->GetName(name);
|
||||
if (NS_LITERAL_CSTRING("Shockwave Flash").Equals(name)) {
|
||||
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
|
||||
nsCString permString;
|
||||
nsresult rv = pluginHost->GetPermissionStringForTag(pluginTag, 0, permString);
|
||||
if (rv == NS_OK) {
|
||||
nsIPrincipal* principal = mWindow->GetExtantDoc()->NodePrincipal();
|
||||
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
||||
permMgr->TestPermissionFromPrincipal(principal, permString.get(), &permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (permission == nsIPermissionManager::ALLOW_ACTION) {
|
||||
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
|
||||
} else {
|
||||
mCTPPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Alphabetize the enumeration order of non-hidden plugins to reduce
|
||||
|
|
|
@ -60,6 +60,10 @@ private:
|
|||
|
||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||
nsTArray<RefPtr<nsPluginElement> > mPlugins;
|
||||
/* A separate list of click-to-play plugins that we don't tell content
|
||||
* about but keep track of so we can still prompt the user to click to play.
|
||||
*/
|
||||
nsTArray<RefPtr<nsPluginElement> > mCTPPlugins;
|
||||
};
|
||||
|
||||
class nsPluginElement final : public nsISupports,
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
#ifndef nsSandboxFlags_h___
|
||||
#define nsSandboxFlags_h___
|
||||
|
||||
/**
|
||||
* This constant denotes the lack of a sandbox attribute/directive.
|
||||
*/
|
||||
const unsigned long SANDBOXED_NONE = 0x0;
|
||||
|
||||
/**
|
||||
* This flag prevents content from navigating browsing contexts other than
|
||||
* itself, browsing contexts nested inside it, the top-level browsing context
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1240471
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1240471</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
let SimpleTest = {
|
||||
finish: function() {
|
||||
parent.postMessage(JSON.stringify({fn: "finish"}), "*");
|
||||
}
|
||||
};
|
||||
["ok", "is", "info"].forEach(fn => {
|
||||
self[fn] = function (...args) {
|
||||
parent.postMessage(JSON.stringify({fn: fn, args: args}), "*");
|
||||
}
|
||||
});
|
||||
"use strict";
|
||||
function onLoad() {
|
||||
let youtube_changed_url_query = "https://mochitest.youtube.com/embed/Xm5i5kbIXzc?start=10&end=20";
|
||||
|
||||
function testEmbed(embed, expected_url, expected_fullscreen) {
|
||||
ok (!!embed, "Embed node exists");
|
||||
// getSVGDocument will return HTMLDocument if the content is HTML
|
||||
let doc = embed.getSVGDocument();
|
||||
// doc must be unprivileged because privileged doc will always be
|
||||
// allowed to use fullscreen.
|
||||
is (doc.fullscreenEnabled, expected_fullscreen,
|
||||
"fullscreen should be " + (expected_fullscreen ? "enabled" : "disabled"));
|
||||
embed = SpecialPowers.wrap(embed);
|
||||
is (embed.srcURI.spec, expected_url, "Should have src uri of " + expected_url);
|
||||
}
|
||||
info("Running youtube rewrite query test");
|
||||
testEmbed(document.getElementById("testembed-correct"), youtube_changed_url_query, false);
|
||||
testEmbed(document.getElementById("testembed-correct-fs"), youtube_changed_url_query, true);
|
||||
testEmbed(document.getElementById("testembed-wrong"), youtube_changed_url_query, false);
|
||||
testEmbed(document.getElementById("testembed-whywouldyouevendothat"), youtube_changed_url_query, true);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="onLoad()">
|
||||
<embed id="testembed-correct"
|
||||
src="https://mochitest.youtube.com/v/Xm5i5kbIXzc?start=10&end=20"
|
||||
type="application/x-shockwave-flash"
|
||||
allowscriptaccess="always"></embed>
|
||||
<embed id="testembed-correct-fs"
|
||||
src="https://mochitest.youtube.com/v/Xm5i5kbIXzc?start=10&end=20"
|
||||
type="application/x-shockwave-flash"
|
||||
allowfullscreen
|
||||
allowscriptaccess="always"></embed>
|
||||
<embed id="testembed-wrong"
|
||||
src="https://mochitest.youtube.com/v/Xm5i5kbIXzc&start=10&end=20"
|
||||
type="application/x-shockwave-flash"
|
||||
allowscriptaccess="always"></embed>
|
||||
<embed id="testembed-whywouldyouevendothat"
|
||||
src="https://mochitest.youtube.com/v/Xm5i5kbIXzc&start=10?end=20"
|
||||
type="application/x-shockwave-flash"
|
||||
allowfullscreen
|
||||
allowscriptaccess="always"></embed>
|
||||
</body>
|
||||
</html>
|
|
@ -189,6 +189,7 @@ support-files =
|
|||
file_xhtmlserializer_2_enthtml.xhtml
|
||||
file_xhtmlserializer_2_entw3c.xhtml
|
||||
file_xhtmlserializer_2_latin1.xhtml
|
||||
file_youtube_flash_embed.html
|
||||
fileapi_chromeScript.js
|
||||
fileutils.js
|
||||
forRemoval.resource
|
||||
|
|
|
@ -10,35 +10,23 @@
|
|||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
"use strict";
|
||||
function onLoad () {
|
||||
let youtube_changed_url_query = "https://mochitest.youtube.com/embed/Xm5i5kbIXzc?start=10&end=20";
|
||||
|
||||
function testEmbed(embed, expected_url) {
|
||||
ok (embed, "Embed node exists");
|
||||
embed = SpecialPowers.wrap(embed);
|
||||
is (embed.srcURI.spec, expected_url, "Should have src uri of " + expected_url);
|
||||
let path = location.pathname.substring(0, location.pathname.lastIndexOf('/')) + '/file_youtube_flash_embed.html';
|
||||
onmessage = function(e) {
|
||||
let msg = JSON.parse(e.data);
|
||||
if (msg.fn == "finish") {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
info("Running youtube rewrite query test");
|
||||
testEmbed(document.getElementById("testembed-correct"), youtube_changed_url_query);
|
||||
testEmbed(document.getElementById("testembed-wrong"), youtube_changed_url_query);
|
||||
testEmbed(document.getElementById("testembed-whywouldyouevendothat"), youtube_changed_url_query);
|
||||
SimpleTest.finish();
|
||||
self[msg.fn].apply(null, msg.args);
|
||||
}
|
||||
function onLoad() {
|
||||
// The test file must be loaded into youtube.com domain
|
||||
// because it needs unprivileged access to fullscreenEnabled.
|
||||
ifr.src = "https://mochitest.youtube.com" + path;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="onLoad()">
|
||||
<embed id="testembed-correct"
|
||||
src="https://mochitest.youtube.com/v/Xm5i5kbIXzc?start=10&end=20"
|
||||
type="application/x-shockwave-flash"
|
||||
allowscriptaccess="always"></embed>
|
||||
<embed id="testembed-wrong"
|
||||
src="https://mochitest.youtube.com/v/Xm5i5kbIXzc&start=10&end=20"
|
||||
type="application/x-shockwave-flash"
|
||||
allowscriptaccess="always"></embed>
|
||||
<embed id="testembed-whywouldyouevendothat"
|
||||
src="https://mochitest.youtube.com/v/Xm5i5kbIXzc&start=10?end=20"
|
||||
type="application/x-shockwave-flash"
|
||||
allowscriptaccess="always"></embed>
|
||||
<iframe id="ifr" allowfullscreen></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -241,12 +241,12 @@ IsNotDateOrRegExp(JSContext* cx, JS::Handle<JSObject*> obj,
|
|||
{
|
||||
MOZ_ASSERT(obj);
|
||||
|
||||
js::ESClassValue cls;
|
||||
js::ESClass cls;
|
||||
if (!js::GetBuiltinClass(cx, obj, &cls)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*notDateOrRegExp = cls != js::ESClass_Date && cls != js::ESClass_RegExp;
|
||||
*notDateOrRegExp = cls != js::ESClass::Date && cls != js::ESClass::RegExp;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -249,15 +249,7 @@ class TestWebIDLCodegenManager(unittest.TestCase):
|
|||
args = self._get_manager_args()
|
||||
m1 = WebIDLCodegenManager(**args)
|
||||
with MockedOpen({fake_path: '# Original content'}):
|
||||
old_exists = os.path.exists
|
||||
try:
|
||||
def exists(p):
|
||||
if p == fake_path:
|
||||
return True
|
||||
return old_exists(p)
|
||||
|
||||
os.path.exists = exists
|
||||
|
||||
result = m1.generate_build_files()
|
||||
l = len(result.inputs)
|
||||
|
||||
|
@ -271,7 +263,6 @@ class TestWebIDLCodegenManager(unittest.TestCase):
|
|||
result = m2.generate_build_files()
|
||||
self.assertEqual(len(result.inputs), 0)
|
||||
finally:
|
||||
os.path.exists = old_exists
|
||||
del sys.modules['mozwebidlcodegen.fakemodule']
|
||||
|
||||
def test_copy_input(self):
|
||||
|
|
|
@ -55,12 +55,6 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
namespace workers {
|
||||
extern bool IsCurrentThreadRunningChromeWorker();
|
||||
} // namespace workers
|
||||
} // namespace dom
|
||||
|
||||
using namespace dom;
|
||||
using namespace hal;
|
||||
|
||||
|
@ -1344,24 +1338,6 @@ EventListenerManager::Disconnect()
|
|||
RemoveAllListeners();
|
||||
}
|
||||
|
||||
static EventListenerFlags
|
||||
GetEventListenerFlagsFromOptions(const EventListenerOptions& aOptions,
|
||||
bool aIsMainThread)
|
||||
{
|
||||
EventListenerFlags flags;
|
||||
flags.mCapture = aOptions.mCapture;
|
||||
if (aOptions.mMozSystemGroup) {
|
||||
if (aIsMainThread) {
|
||||
JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
||||
MOZ_ASSERT(cx, "Not being called from JS?");
|
||||
flags.mInSystemGroup = IsChromeOrXBL(cx, nullptr);
|
||||
} else {
|
||||
flags.mInSystemGroup = workers::IsCurrentThreadRunningChromeWorker();
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
void
|
||||
EventListenerManager::AddEventListener(
|
||||
const nsAString& aType,
|
||||
|
@ -1387,7 +1363,8 @@ EventListenerManager::AddEventListener(
|
|||
flags.mCapture = aOptions.GetAsBoolean();
|
||||
} else {
|
||||
const auto& options = aOptions.GetAsAddEventListenerOptions();
|
||||
flags = GetEventListenerFlagsFromOptions(options, mIsMainThreadELM);
|
||||
flags.mCapture = options.mCapture;
|
||||
flags.mInSystemGroup = options.mMozSystemGroup;
|
||||
flags.mPassive = options.mPassive;
|
||||
}
|
||||
flags.mAllowUntrustedEvents = aWantsUntrusted;
|
||||
|
@ -1416,7 +1393,8 @@ EventListenerManager::RemoveEventListener(
|
|||
flags.mCapture = aOptions.GetAsBoolean();
|
||||
} else {
|
||||
const auto& options = aOptions.GetAsEventListenerOptions();
|
||||
flags = GetEventListenerFlagsFromOptions(options, mIsMainThreadELM);
|
||||
flags.mCapture = options.mCapture;
|
||||
flags.mInSystemGroup = options.mMozSystemGroup;
|
||||
}
|
||||
RemoveEventListenerByType(aListenerHolder, aType, flags);
|
||||
}
|
||||
|
|
|
@ -4817,26 +4817,11 @@ static nsIContent* FindCommonAncestor(nsIContent *aNode1, nsIContent *aNode2)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static Element*
|
||||
GetParentElement(Element* aElement)
|
||||
{
|
||||
nsIContent* p = aElement->GetParent();
|
||||
return (p && p->IsElement()) ? p->AsElement() : nullptr;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
EventStateManager::SetFullScreenState(Element* aElement, bool aIsFullScreen)
|
||||
{
|
||||
DoStateChange(aElement, NS_EVENT_STATE_FULL_SCREEN, aIsFullScreen);
|
||||
Element* ancestor = aElement;
|
||||
while ((ancestor = GetParentElement(ancestor))) {
|
||||
DoStateChange(ancestor, NS_EVENT_STATE_FULL_SCREEN_ANCESTOR, aIsFullScreen);
|
||||
if (ancestor->State().HasState(NS_EVENT_STATE_FULL_SCREEN)) {
|
||||
// If we meet another fullscreen element, stop here.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -262,8 +262,8 @@ private:
|
|||
// Content is the full screen element, or a frame containing the
|
||||
// current full-screen element.
|
||||
#define NS_EVENT_STATE_FULL_SCREEN NS_DEFINE_EVENT_STATE_MACRO(33)
|
||||
// Content is an ancestor of the DOM full-screen element.
|
||||
#define NS_EVENT_STATE_FULL_SCREEN_ANCESTOR NS_DEFINE_EVENT_STATE_MACRO(34)
|
||||
// This bit is currently free.
|
||||
// #define NS_EVENT_STATE_?????????? NS_DEFINE_EVENT_STATE_MACRO(34)
|
||||
// Handler for click to play plugin
|
||||
#define NS_EVENT_STATE_TYPE_CLICK_TO_PLAY NS_DEFINE_EVENT_STATE_MACRO(35)
|
||||
// Content is in the optimum region.
|
||||
|
@ -299,8 +299,7 @@ private:
|
|||
#define ESM_MANAGED_STATES (NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS | \
|
||||
NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER | \
|
||||
NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \
|
||||
NS_EVENT_STATE_FULL_SCREEN | NS_EVENT_STATE_FULL_SCREEN_ANCESTOR | \
|
||||
NS_EVENT_STATE_UNRESOLVED)
|
||||
NS_EVENT_STATE_FULL_SCREEN | NS_EVENT_STATE_UNRESOLVED)
|
||||
|
||||
#define INTRINSIC_STATES (~ESM_MANAGED_STATES)
|
||||
|
||||
|
|
|
@ -57,7 +57,8 @@ HttpServer::Init(int32_t aPort, bool aHttps, HttpServerListener* aListener)
|
|||
if (mHttps) {
|
||||
nsCOMPtr<nsILocalCertService> lcs =
|
||||
do_CreateInstance("@mozilla.org/security/local-cert-service;1");
|
||||
nsresult rv = lcs->GetOrCreateCert(NS_LITERAL_CSTRING("flyweb"), this);
|
||||
nsresult rv = lcs->GetOrCreateCert(NS_LITERAL_CSTRING("flyweb"), this,
|
||||
nsILocalCertService::KEY_TYPE_EC);
|
||||
if (NS_FAILED(rv)) {
|
||||
NotifyStarted(rv);
|
||||
}
|
||||
|
|
|
@ -4,56 +4,6 @@
|
|||
# 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/.
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Gamepad.h',
|
||||
'GamepadButton.h',
|
||||
'GamepadManager.h',
|
||||
'GamepadMonitoring.h',
|
||||
'GamepadPlatformService.h',
|
||||
'GamepadServiceTest.h',
|
||||
'ipc/GamepadEventChannelChild.h',
|
||||
'ipc/GamepadEventChannelParent.h',
|
||||
'ipc/GamepadTestChannelChild.h',
|
||||
'ipc/GamepadTestChannelParent.h'
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES = [
|
||||
'Gamepad.cpp',
|
||||
'GamepadButton.cpp',
|
||||
'GamepadManager.cpp',
|
||||
'GamepadMonitoring.cpp',
|
||||
'GamepadPlatformService.cpp',
|
||||
'GamepadServiceTest.cpp',
|
||||
'ipc/GamepadEventChannelChild.cpp',
|
||||
'ipc/GamepadEventChannelParent.cpp',
|
||||
'ipc/GamepadTestChannelChild.cpp',
|
||||
'ipc/GamepadTestChannelParent.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_GAMEPAD_BACKEND'] == 'stub':
|
||||
UNIFIED_SOURCES += [
|
||||
'fallback/FallbackGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'cocoa':
|
||||
UNIFIED_SOURCES += [
|
||||
'cocoa/CocoaGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'windows':
|
||||
UNIFIED_SOURCES += [
|
||||
'windows/WindowsGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'linux':
|
||||
UNIFIED_SOURCES += [
|
||||
'linux/LinuxGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'android':
|
||||
UNIFIED_SOURCES += [
|
||||
'android/AndroidGamepad.cpp'
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'ipc',
|
||||
]
|
||||
|
||||
IPDL_SOURCES += [
|
||||
'ipc/GamepadEventTypes.ipdlh',
|
||||
|
@ -61,14 +11,66 @@ IPDL_SOURCES += [
|
|||
'ipc/PGamepadTestChannel.ipdl'
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
if CONFIG['MOZ_GAMEPAD']:
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Gamepad.h',
|
||||
'GamepadButton.h',
|
||||
'GamepadManager.h',
|
||||
'GamepadMonitoring.h',
|
||||
'GamepadPlatformService.h',
|
||||
'GamepadServiceTest.h',
|
||||
'ipc/GamepadEventChannelChild.h',
|
||||
'ipc/GamepadEventChannelParent.h',
|
||||
'ipc/GamepadTestChannelChild.h',
|
||||
'ipc/GamepadTestChannelParent.h'
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
]
|
||||
UNIFIED_SOURCES = [
|
||||
'Gamepad.cpp',
|
||||
'GamepadButton.cpp',
|
||||
'GamepadManager.cpp',
|
||||
'GamepadMonitoring.cpp',
|
||||
'GamepadPlatformService.cpp',
|
||||
'GamepadServiceTest.cpp',
|
||||
'ipc/GamepadEventChannelChild.cpp',
|
||||
'ipc/GamepadEventChannelParent.cpp',
|
||||
'ipc/GamepadTestChannelChild.cpp',
|
||||
'ipc/GamepadTestChannelParent.cpp'
|
||||
]
|
||||
|
||||
CFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
if CONFIG['MOZ_GAMEPAD_BACKEND'] == 'stub':
|
||||
UNIFIED_SOURCES += [
|
||||
'fallback/FallbackGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'cocoa':
|
||||
UNIFIED_SOURCES += [
|
||||
'cocoa/CocoaGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'windows':
|
||||
UNIFIED_SOURCES += [
|
||||
'windows/WindowsGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'linux':
|
||||
UNIFIED_SOURCES += [
|
||||
'linux/LinuxGamepad.cpp'
|
||||
]
|
||||
elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'android':
|
||||
UNIFIED_SOURCES += [
|
||||
'android/AndroidGamepad.cpp'
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'ipc',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
]
|
||||
|
||||
CFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['GLIB_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
|
|
|
@ -242,17 +242,10 @@ HTMLIFrameElement::GetSandboxFlags()
|
|||
const nsAttrValue* sandboxAttr = GetParsedAttr(nsGkAtoms::sandbox);
|
||||
// No sandbox attribute, no sandbox flags.
|
||||
if (!sandboxAttr) {
|
||||
return 0;
|
||||
return SANDBOXED_NONE;
|
||||
}
|
||||
|
||||
// Start off by setting all the restriction flags.
|
||||
uint32_t out = SANDBOX_ALL_FLAGS;
|
||||
|
||||
// Macro for updating the flag according to the keywords
|
||||
#define SANDBOX_KEYWORD(string, atom, flags) \
|
||||
if (sandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { out &= ~(flags); }
|
||||
#include "IframeSandboxKeywordList.h"
|
||||
#undef SANDBOX_KEYWORD
|
||||
uint32_t out = nsContentUtils::ParseSandboxAttributeToFlags(sandboxAttr);
|
||||
|
||||
if (GetParsedAttr(nsGkAtoms::allowfullscreen) ||
|
||||
GetParsedAttr(nsGkAtoms::mozallowfullscreen)) {
|
||||
|
|
|
@ -3165,7 +3165,13 @@ HTMLInputElement::GetDisplayFileName(nsAString& aValue) const
|
|||
nsXPIDLString value;
|
||||
|
||||
if (mFilesOrDirectories.IsEmpty()) {
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
|
||||
if ((Preferences::GetBool("dom.input.dirpicker", false) &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::directory)) ||
|
||||
(Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory))) {
|
||||
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
||||
"NoDirSelected", value);
|
||||
} else if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
|
||||
nsContentUtils::GetLocalizedString(nsContentUtils::eFORMS_PROPERTIES,
|
||||
"NoFilesSelected", value);
|
||||
} else {
|
||||
|
@ -4405,12 +4411,10 @@ HTMLInputElement::MaybeInitPickers(EventChainPostVisitor& aVisitor)
|
|||
if (target &&
|
||||
target->GetParent() == this &&
|
||||
target->IsRootOfNativeAnonymousSubtree() &&
|
||||
(target->HasAttr(kNameSpaceID_None, nsGkAtoms::directory) ||
|
||||
target->HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory))) {
|
||||
MOZ_ASSERT(Preferences::GetBool("dom.input.dirpicker", false) ||
|
||||
Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false),
|
||||
"No API or UI should have been exposed to allow this code to "
|
||||
"be reached");
|
||||
((Preferences::GetBool("dom.input.dirpicker", false) &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::directory)) ||
|
||||
(Preferences::GetBool("dom.webkitBlink.dirPicker.enabled", false) &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::webkitdirectory)))) {
|
||||
type = FILE_PICKER_DIRECTORY;
|
||||
}
|
||||
return InitFilePicker(type);
|
||||
|
|
|
@ -304,7 +304,7 @@ public:
|
|||
private:
|
||||
RefPtr<HTMLMediaElement> mElement;
|
||||
nsCOMPtr<nsIStreamListener> mNextListener;
|
||||
uint32_t mLoadID;
|
||||
const uint32_t mLoadID;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(HTMLMediaElement::MediaLoadListener, nsIRequestObserver,
|
||||
|
@ -313,7 +313,8 @@ NS_IMPL_ISUPPORTS(HTMLMediaElement::MediaLoadListener, nsIRequestObserver,
|
|||
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::MediaLoadListener::Observe(nsISupports* aSubject,
|
||||
const char* aTopic, const char16_t* aData)
|
||||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
nsContentUtils::UnregisterShutdownObserver(this);
|
||||
|
||||
|
@ -322,21 +323,9 @@ HTMLMediaElement::MediaLoadListener::Observe(nsISupports* aSubject,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void HTMLMediaElement::ReportLoadError(const char* aMsg,
|
||||
const char16_t** aParams,
|
||||
uint32_t aParamCount)
|
||||
{
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("Media"),
|
||||
OwnerDoc(),
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
aMsg,
|
||||
aParams,
|
||||
aParamCount);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext)
|
||||
{
|
||||
nsContentUtils::UnregisterShutdownObserver(this);
|
||||
|
||||
|
@ -394,14 +383,12 @@ NS_IMETHODIMP HTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest* aR
|
|||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
if (channel &&
|
||||
element &&
|
||||
NS_SUCCEEDED(rv = element->InitializeDecoderForChannel(channel, getter_AddRefs(mNextListener))) &&
|
||||
mNextListener) {
|
||||
rv = mNextListener->OnStartRequest(aRequest, aContext);
|
||||
} else {
|
||||
// If InitializeDecoderForChannel() returned an error, fire a network
|
||||
// error.
|
||||
if (NS_FAILED(rv) && !mNextListener && element) {
|
||||
// If InitializeDecoderForChannel() returned an error, fire a network error.
|
||||
if (NS_FAILED(rv) && !mNextListener) {
|
||||
// Load failed, attempt to load the next candidate resource. If there
|
||||
// are none, this will trigger a MEDIA_ERR_SRC_NOT_SUPPORTED error.
|
||||
element->NotifyLoadError();
|
||||
|
@ -415,8 +402,10 @@ NS_IMETHODIMP HTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest* aR
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::MediaLoadListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
|
||||
nsresult aStatus)
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::MediaLoadListener::OnStopRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus)
|
||||
{
|
||||
if (mNextListener) {
|
||||
return mNextListener->OnStopRequest(aRequest, aContext, aStatus);
|
||||
|
@ -438,27 +427,210 @@ HTMLMediaElement::MediaLoadListener::OnDataAvailable(nsIRequest* aRequest,
|
|||
return mNextListener->OnDataAvailable(aRequest, aContext, aStream, aOffset, aCount);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::MediaLoadListener::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
||||
nsIChannel* aNewChannel,
|
||||
uint32_t aFlags,
|
||||
nsIAsyncVerifyRedirectCallback* cb)
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::MediaLoadListener::AsyncOnChannelRedirect(nsIChannel* aOldChannel,
|
||||
nsIChannel* aNewChannel,
|
||||
uint32_t aFlags,
|
||||
nsIAsyncVerifyRedirectCallback* cb)
|
||||
{
|
||||
// TODO is this really correct?? See bug #579329.
|
||||
if (mElement)
|
||||
if (mElement) {
|
||||
mElement->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
|
||||
}
|
||||
nsCOMPtr<nsIChannelEventSink> sink = do_QueryInterface(mNextListener);
|
||||
if (sink)
|
||||
if (sink) {
|
||||
return sink->AsyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags, cb);
|
||||
|
||||
}
|
||||
cb->OnRedirectVerifyCallback(NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP HTMLMediaElement::MediaLoadListener::GetInterface(const nsIID & aIID, void **aResult)
|
||||
NS_IMETHODIMP
|
||||
HTMLMediaElement::MediaLoadListener::GetInterface(const nsIID& aIID,
|
||||
void** aResult)
|
||||
{
|
||||
return QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
void HTMLMediaElement::ReportLoadError(const char* aMsg,
|
||||
const char16_t** aParams,
|
||||
uint32_t aParamCount)
|
||||
{
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("Media"),
|
||||
OwnerDoc(),
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
aMsg,
|
||||
aParams,
|
||||
aParamCount);
|
||||
}
|
||||
|
||||
class HTMLMediaElement::ChannelLoader final {
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(ChannelLoader);
|
||||
|
||||
void LoadInternal(HTMLMediaElement* aElement)
|
||||
{
|
||||
if (mCancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// determine what security checks need to be performed in AsyncOpen2().
|
||||
nsSecurityFlags securityFlags = aElement->ShouldCheckAllowOrigin()
|
||||
? nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS :
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
|
||||
|
||||
if (aElement->GetCORSMode() == CORS_USE_CREDENTIALS) {
|
||||
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aElement->IsAnyOfHTMLElements(nsGkAtoms::audio, nsGkAtoms::video));
|
||||
nsContentPolicyType contentPolicyType = aElement->IsHTMLElement(nsGkAtoms::audio)
|
||||
? nsIContentPolicy::TYPE_INTERNAL_AUDIO :
|
||||
nsIContentPolicy::TYPE_INTERNAL_VIDEO;
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = aElement->OwnerDoc()->GetDocShell();
|
||||
if (docShell) {
|
||||
nsDocShell* docShellPtr = nsDocShell::Cast(docShell);
|
||||
bool privateBrowsing;
|
||||
docShellPtr->GetUsePrivateBrowsing(&privateBrowsing);
|
||||
if (privateBrowsing) {
|
||||
securityFlags |= nsILoadInfo::SEC_FORCE_PRIVATE_BROWSING;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = aElement->GetDocumentLoadGroup();
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
aElement->mLoadingSrc,
|
||||
static_cast<Element*>(aElement),
|
||||
securityFlags,
|
||||
contentPolicyType,
|
||||
loadGroup,
|
||||
nullptr, // aCallbacks
|
||||
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
|
||||
nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE |
|
||||
nsIChannel::LOAD_CLASSIFY_URI |
|
||||
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// Notify load error so the element will try next resource candidate.
|
||||
aElement->NotifyLoadError();
|
||||
return;
|
||||
}
|
||||
|
||||
// This is a workaround and it will be fix in bug 1264230.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
||||
if (loadInfo) {
|
||||
NeckoOriginAttributes originAttrs;
|
||||
NS_GetOriginAttributes(channel, originAttrs);
|
||||
loadInfo->SetOriginAttributes(originAttrs);
|
||||
}
|
||||
|
||||
// The listener holds a strong reference to us. This creates a
|
||||
// reference cycle, once we've set mChannel, which is manually broken
|
||||
// in the listener's OnStartRequest method after it is finished with
|
||||
// the element. The cycle will also be broken if we get a shutdown
|
||||
// notification before OnStartRequest fires. Necko guarantees that
|
||||
// OnStartRequest will eventually fire if we don't shut down first.
|
||||
RefPtr<MediaLoadListener> loadListener = new MediaLoadListener(aElement);
|
||||
|
||||
channel->SetNotificationCallbacks(loadListener);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(channel);
|
||||
if (hc) {
|
||||
// Use a byte range request from the start of the resource.
|
||||
// This enables us to detect if the stream supports byte range
|
||||
// requests, and therefore seeking, early.
|
||||
hc->SetRequestHeader(NS_LITERAL_CSTRING("Range"),
|
||||
NS_LITERAL_CSTRING("bytes=0-"),
|
||||
false);
|
||||
aElement->SetRequestHeaders(hc);
|
||||
}
|
||||
|
||||
rv = channel->AsyncOpen2(loadListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Notify load error so the element will try next resource candidate.
|
||||
aElement->NotifyLoadError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Else the channel must be open and starting to download. If it encounters
|
||||
// a non-catastrophic failure, it will set a new task to continue loading
|
||||
// another candidate. It's safe to set it as mChannel now.
|
||||
mChannel = channel;
|
||||
|
||||
// loadListener will be unregistered either on shutdown or when
|
||||
// OnStartRequest for the channel we just opened fires.
|
||||
nsContentUtils::RegisterShutdownObserver(loadListener);
|
||||
}
|
||||
|
||||
nsresult Load(HTMLMediaElement* aElement)
|
||||
{
|
||||
// Per bug 1235183 comment 8, we can't spin the event loop from stable
|
||||
// state. Defer NS_NewChannel() to a new regular runnable.
|
||||
return NS_DispatchToMainThread(NewRunnableMethod<HTMLMediaElement*>(
|
||||
this, &ChannelLoader::LoadInternal, aElement));
|
||||
}
|
||||
|
||||
void Cancel()
|
||||
{
|
||||
mCancelled = true;
|
||||
if (mChannel) {
|
||||
mChannel->Cancel(NS_BINDING_ABORTED);
|
||||
mChannel = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Done() {
|
||||
MOZ_ASSERT(mChannel);
|
||||
// Decoder successfully created, the decoder now owns the MediaResource
|
||||
// which owns the channel.
|
||||
mChannel = nullptr;
|
||||
}
|
||||
|
||||
nsresult Redirect(nsIChannel* aChannel,
|
||||
nsIChannel* aNewChannel,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
NS_ASSERTION(aChannel == mChannel, "Channels should match!");
|
||||
mChannel = aNewChannel;
|
||||
|
||||
// Handle forwarding of Range header so that the intial detection
|
||||
// of seeking support (via result code 206) works across redirects.
|
||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aChannel);
|
||||
NS_ENSURE_STATE(http);
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(rangeHdr, "Range");
|
||||
|
||||
nsAutoCString rangeVal;
|
||||
if (NS_SUCCEEDED(http->GetRequestHeader(rangeHdr, rangeVal))) {
|
||||
NS_ENSURE_STATE(!rangeVal.IsEmpty());
|
||||
|
||||
http = do_QueryInterface(aNewChannel);
|
||||
NS_ENSURE_STATE(http);
|
||||
|
||||
nsresult rv = http->SetRequestHeader(rangeHdr, rangeVal, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~ChannelLoader()
|
||||
{
|
||||
MOZ_ASSERT(!mChannel);
|
||||
}
|
||||
// Holds a reference to the first channel we open to the media resource.
|
||||
// Once the decoder is created, control over the channel passes to the
|
||||
// decoder, and we null out this reference. We must store this in case
|
||||
// we need to cancel the channel before control of it passes to the decoder.
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
|
||||
bool mCancelled = false;
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
|
||||
NS_IMPL_RELEASE_INHERITED(HTMLMediaElement, nsGenericHTMLElement)
|
||||
|
||||
|
@ -672,28 +844,8 @@ HTMLMediaElement::OnChannelRedirect(nsIChannel* aChannel,
|
|||
nsIChannel* aNewChannel,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
NS_ASSERTION(aChannel == mChannel, "Channels should match!");
|
||||
mChannel = aNewChannel;
|
||||
|
||||
// Handle forwarding of Range header so that the intial detection
|
||||
// of seeking support (via result code 206) works across redirects.
|
||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aChannel);
|
||||
NS_ENSURE_STATE(http);
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(rangeHdr, "Range");
|
||||
|
||||
nsAutoCString rangeVal;
|
||||
if (NS_SUCCEEDED(http->GetRequestHeader(rangeHdr, rangeVal))) {
|
||||
NS_ENSURE_STATE(!rangeVal.IsEmpty());
|
||||
|
||||
http = do_QueryInterface(aNewChannel);
|
||||
NS_ENSURE_STATE(http);
|
||||
|
||||
nsresult rv = http->SetRequestHeader(rangeHdr, rangeVal, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
MOZ_ASSERT(mChannelLoader);
|
||||
return mChannelLoader->Redirect(aChannel, aNewChannel, aFlags);
|
||||
}
|
||||
|
||||
void HTMLMediaElement::ShutdownDecoder()
|
||||
|
@ -721,6 +873,11 @@ void HTMLMediaElement::AbortExistingLoads()
|
|||
// with a different load ID to silently be cancelled.
|
||||
mCurrentLoadID++;
|
||||
|
||||
if (mChannelLoader) {
|
||||
mChannelLoader->Cancel();
|
||||
mChannelLoader = nullptr;
|
||||
}
|
||||
|
||||
bool fireTimeUpdate = false;
|
||||
|
||||
// When aborting the existing loads, empty the objects in audio track list and
|
||||
|
@ -1250,9 +1407,9 @@ nsresult HTMLMediaElement::LoadResource()
|
|||
NS_ASSERTION(mDelayingLoadEvent,
|
||||
"Should delay load event (if in document) during load");
|
||||
|
||||
if (mChannel) {
|
||||
mChannel->Cancel(NS_BINDING_ABORTED);
|
||||
mChannel = nullptr;
|
||||
if (mChannelLoader) {
|
||||
mChannelLoader->Cancel();
|
||||
mChannelLoader = nullptr;
|
||||
}
|
||||
|
||||
// Check if media is allowed for the docshell.
|
||||
|
@ -1308,87 +1465,12 @@ nsresult HTMLMediaElement::LoadResource()
|
|||
return FinishDecoderSetup(decoder, resource, nullptr);
|
||||
}
|
||||
|
||||
// determine what security checks need to be performed in AsyncOpen2().
|
||||
nsSecurityFlags securityFlags =
|
||||
ShouldCheckAllowOrigin() ? nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS :
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
|
||||
|
||||
if (GetCORSMode() == CORS_USE_CREDENTIALS) {
|
||||
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
|
||||
RefPtr<ChannelLoader> loader = new ChannelLoader;
|
||||
nsresult rv = loader->Load(this);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mChannelLoader = loader.forget();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(IsAnyOfHTMLElements(nsGkAtoms::audio, nsGkAtoms::video));
|
||||
nsContentPolicyType contentPolicyType = IsHTMLElement(nsGkAtoms::audio) ?
|
||||
nsIContentPolicy::TYPE_INTERNAL_AUDIO : nsIContentPolicy::TYPE_INTERNAL_VIDEO;
|
||||
|
||||
nsDocShell* docShellPtr;
|
||||
if (docShell) {
|
||||
docShellPtr = nsDocShell::Cast(docShell);
|
||||
bool privateBrowsing;
|
||||
docShellPtr->GetUsePrivateBrowsing(&privateBrowsing);
|
||||
if (privateBrowsing) {
|
||||
securityFlags |= nsILoadInfo::SEC_FORCE_PRIVATE_BROWSING;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
mLoadingSrc,
|
||||
static_cast<Element*>(this),
|
||||
securityFlags,
|
||||
contentPolicyType,
|
||||
loadGroup,
|
||||
nullptr, // aCallbacks
|
||||
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
|
||||
nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE |
|
||||
nsIChannel::LOAD_CLASSIFY_URI |
|
||||
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// This is a workaround and it will be fix in bug 1264230.
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
||||
if (loadInfo) {
|
||||
NeckoOriginAttributes originAttrs;
|
||||
NS_GetOriginAttributes(channel, originAttrs);
|
||||
loadInfo->SetOriginAttributes(originAttrs);
|
||||
}
|
||||
|
||||
// The listener holds a strong reference to us. This creates a
|
||||
// reference cycle, once we've set mChannel, which is manually broken
|
||||
// in the listener's OnStartRequest method after it is finished with
|
||||
// the element. The cycle will also be broken if we get a shutdown
|
||||
// notification before OnStartRequest fires. Necko guarantees that
|
||||
// OnStartRequest will eventually fire if we don't shut down first.
|
||||
RefPtr<MediaLoadListener> loadListener = new MediaLoadListener(this);
|
||||
|
||||
channel->SetNotificationCallbacks(loadListener);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(channel);
|
||||
if (hc) {
|
||||
// Use a byte range request from the start of the resource.
|
||||
// This enables us to detect if the stream supports byte range
|
||||
// requests, and therefore seeking, early.
|
||||
hc->SetRequestHeader(NS_LITERAL_CSTRING("Range"),
|
||||
NS_LITERAL_CSTRING("bytes=0-"),
|
||||
false);
|
||||
|
||||
SetRequestHeaders(hc);
|
||||
}
|
||||
|
||||
rv = channel->AsyncOpen2(loadListener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Else the channel must be open and starting to download. If it encounters
|
||||
// a non-catastrophic failure, it will set a new task to continue loading
|
||||
// another candidate. It's safe to set it as mChannel now.
|
||||
mChannel = channel;
|
||||
|
||||
// loadListener will be unregistered either on shutdown or when
|
||||
// OnStartRequest for the channel we just opened fires.
|
||||
nsContentUtils::RegisterShutdownObserver(loadListener);
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult HTMLMediaElement::LoadWithChannel(nsIChannel* aChannel,
|
||||
|
@ -2400,8 +2482,8 @@ HTMLMediaElement::~HTMLMediaElement()
|
|||
NS_ASSERTION(MediaElementTableCount(this, mLoadingSrc) == 0,
|
||||
"Destroyed media element should no longer be in element table");
|
||||
|
||||
if (mChannel) {
|
||||
mChannel->Cancel(NS_BINDING_ABORTED);
|
||||
if (mChannelLoader) {
|
||||
mChannelLoader->Cancel();
|
||||
}
|
||||
|
||||
WakeLockRelease();
|
||||
|
@ -3056,8 +3138,10 @@ nsresult HTMLMediaElement::InitializeDecoderForChannel(nsIChannel* aChannel,
|
|||
if (!resource)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// stream successfully created, the stream now owns the channel.
|
||||
mChannel = nullptr;
|
||||
if (mChannelLoader) {
|
||||
mChannelLoader->Done();
|
||||
mChannelLoader = nullptr;
|
||||
}
|
||||
|
||||
// We postpone the |FinishDecoderSetup| function call until we get
|
||||
// |OnConnected| signal from MediaStreamController which is held by
|
||||
|
@ -3121,13 +3205,20 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
|
|||
|
||||
#ifdef MOZ_EME
|
||||
if (mMediaKeys) {
|
||||
mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy());
|
||||
if (mMediaKeys->GetCDMProxy()) {
|
||||
mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy());
|
||||
} else {
|
||||
// CDM must have crashed.
|
||||
ShutdownDecoder();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Decoder successfully created, the decoder now owns the MediaResource
|
||||
// which owns the channel.
|
||||
mChannel = nullptr;
|
||||
if (mChannelLoader) {
|
||||
mChannelLoader->Done();
|
||||
mChannelLoader = nullptr;
|
||||
}
|
||||
|
||||
AddMediaElementToURITable();
|
||||
|
||||
|
@ -5411,6 +5502,12 @@ HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
|
|||
|
||||
// 5.3. If mediaKeys is not null, run the following steps:
|
||||
if (aMediaKeys) {
|
||||
if (!aMediaKeys->GetCDMProxy()) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||
NS_LITERAL_CSTRING("CDM crashed before binding MediaKeys object to HTMLMediaElement"));
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
// 5.3.1 Associate the CDM instance represented by mediaKeys with the
|
||||
// media element for decrypting media data.
|
||||
if (NS_FAILED(aMediaKeys->Bind(this))) {
|
||||
|
|
|
@ -732,6 +732,7 @@ public:
|
|||
protected:
|
||||
virtual ~HTMLMediaElement();
|
||||
|
||||
class ChannelLoader;
|
||||
class MediaLoadListener;
|
||||
class MediaStreamTracksAvailableCallback;
|
||||
class MediaStreamTrackListener;
|
||||
|
@ -1255,11 +1256,7 @@ protected:
|
|||
// that resolved to a MediaSource.
|
||||
RefPtr<MediaSource> mMediaSource;
|
||||
|
||||
// Holds a reference to the first channel we open to the media resource.
|
||||
// Once the decoder is created, control over the channel passes to the
|
||||
// decoder, and we null out this reference. We must store this in case
|
||||
// we need to cancel the channel before control of it passes to the decoder.
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
RefPtr<ChannelLoader> mChannelLoader;
|
||||
|
||||
// Error attribute
|
||||
RefPtr<MediaError> mError;
|
||||
|
|
|
@ -155,12 +155,6 @@ function enter4(event) {
|
|||
is(event.target, document, "Event target should be full-screen document #5");
|
||||
is(document.fullscreenElement, inDocElement, "FSE should be inDocElement.");
|
||||
|
||||
var n = container;
|
||||
do {
|
||||
ok(n.matches(":-moz-full-screen-ancestor"), "Ancestor " + n + " should match :-moz-full-screen-ancestor")
|
||||
n = n.parentNode;
|
||||
} while (n && n.matches);
|
||||
|
||||
// Remove full-screen ancestor element from document, verify it stops being reported as current FSE.
|
||||
addFullscreenChangeContinuation("exit", exit_to_arg_test_1);
|
||||
container.parentNode.removeChild(container);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 671389</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
I am
|
||||
<ul>
|
||||
<li>sandboxed but with "allow-forms", "allow-pointer-lock", "allow-popups", "allow-same-origin", "allow-scripts", and "allow-top-navigation", </li>
|
||||
<li>sandboxed but with "allow-same-origin", "allow-scripts", </li>
|
||||
<li>sandboxed, or </li>
|
||||
<li>not sandboxed.</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
|
@ -98,6 +98,7 @@ support-files =
|
|||
file_iframe_sandbox_c_if6.html
|
||||
file_iframe_sandbox_c_if7.html
|
||||
file_iframe_sandbox_c_if8.html
|
||||
file_iframe_sandbox_c_if9.html
|
||||
file_iframe_sandbox_close.html
|
||||
file_iframe_sandbox_d_if1.html
|
||||
file_iframe_sandbox_d_if10.html
|
||||
|
|
|
@ -41,7 +41,7 @@ function ok_wrapper(result, desc) {
|
|||
passedTests++;
|
||||
}
|
||||
|
||||
if (completedTests == 27) {
|
||||
if (completedTests == 33) {
|
||||
is(passedTests, completedTests, "There are " + completedTests + " general tests that should pass");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -180,6 +180,14 @@ function doTest() {
|
|||
// This is done via file_iframe_sandbox_c_if4.html which is sandboxed with "allow-scripts" and "allow-same-origin"
|
||||
// the window it attempts to open calls window.opener.ok(false, ...) and file_iframe_c_if4.html has an ok()
|
||||
// function that calls window.parent.ok_wrapper.
|
||||
|
||||
// passes twice if good
|
||||
// 29-32) Test that sandboxFlagsAsString returns the set flags.
|
||||
// see if_14 and if_15
|
||||
|
||||
// passes once if good
|
||||
// 33) Test that sandboxFlagsAsString returns null if iframe does not have sandbox flag set.
|
||||
// see if_16
|
||||
}
|
||||
|
||||
addLoadEvent(doTest);
|
||||
|
@ -212,6 +220,36 @@ function do_if_10() {
|
|||
var if_10 = document.getElementById('if_10');
|
||||
if_10.src = 'javascript:"<html><script>window.parent.ok_wrapper(true, \'an iframe sandboxed with allow-scripts should execute script in a javascript URL in a newly set src attribute\');<\/script><\/html>"';
|
||||
}
|
||||
|
||||
function eqFlags(a, b) {
|
||||
// both a and b should be either null or have the array same flags
|
||||
if (a === null && b === null) { return true; }
|
||||
if (a === null || b === null) { return false; }
|
||||
if (a.length !== b.length) { return false; }
|
||||
var a_sorted = a.sort();
|
||||
var b_sorted = b.sort();
|
||||
for (var i in a_sorted) {
|
||||
if (a_sorted[i] !== b_sorted[i]) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getSandboxFlags(doc) {
|
||||
var flags = doc.sandboxFlagsAsString;
|
||||
if (flags === null) { return null; }
|
||||
return flags? flags.split(" "):[];
|
||||
}
|
||||
|
||||
function test_sandboxFlagsAsString(name, expected) {
|
||||
var ifr = document.getElementById(name);
|
||||
try {
|
||||
var flags = getSandboxFlags(SpecialPowers.wrap(ifr).contentDocument);
|
||||
ok_wrapper(eqFlags(flags, expected), name + ' expected: "' + expected + '", got: "' + flags + '"');
|
||||
} catch (e) {
|
||||
ok_wrapper(false, name + ' expected "' + expected + ', but failed with ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs
|
||||
|
@ -234,6 +272,10 @@ function do_if_10() {
|
|||
<iframe sandbox="allow-same-origin allow-scripts" onload='start_if_10()' id='if_10' src="about:blank" height="10" width="10"></iframe>
|
||||
<iframe sandbox="allow-scripts" id='if_11' src="file_iframe_sandbox_c_if7.html" height="10" width="10"></iframe>
|
||||
<iframe sandbox="allow-same-origin allow-scripts" id='if_12' src="file_iframe_sandbox_c_if8.html" height="10" width="10"></iframe>
|
||||
<iframe sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation " id='if_13' src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_13",["allow-forms", "allow-pointer-lock", "allow-popups", "allow-same-origin", "allow-scripts", "allow-top-navigation"])'></iframe>
|
||||
<iframe sandbox="	allow-same-origin	allow-scripts	" id="if_14" src="file_iframe_sandbox_c_if6.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_14",["allow-same-origin","allow-scripts"])'></iframe>
|
||||
<iframe sandbox="" id="if_15" src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_15",[])'></iframe>
|
||||
<iframe id="if_16" src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_16",null)'></iframe>
|
||||
<input type='button' id="a_button" onclick='do_if_9()'>
|
||||
<input type='button' id="a_button2" onclick='do_if_10()'>
|
||||
</div>
|
||||
|
|
|
@ -111,11 +111,11 @@ IDBKeyRange::FromJSVal(JSContext* aCx,
|
|||
JS::Rooted<JSObject*> obj(aCx, aVal.isObject() ? &aVal.toObject() : nullptr);
|
||||
bool isValidKey = aVal.isPrimitive();
|
||||
if (!isValidKey) {
|
||||
js::ESClassValue cls;
|
||||
js::ESClass cls;
|
||||
if (!js::GetBuiltinClass(aCx, obj, &cls)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
isValidKey = cls == js::ESClass_Array || cls == js::ESClass_Date;
|
||||
isValidKey = cls == js::ESClass::Array || cls == js::ESClass::Date;
|
||||
}
|
||||
if (isValidKey) {
|
||||
// A valid key returns an 'only' IDBKeyRange.
|
||||
|
|
|
@ -232,12 +232,12 @@ Key::EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
|
|||
if (aVal.isObject()) {
|
||||
JS::Rooted<JSObject*> obj(aCx, &aVal.toObject());
|
||||
|
||||
js::ESClassValue cls;
|
||||
js::ESClass cls;
|
||||
if (!js::GetBuiltinClass(aCx, obj, &cls)) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
if (cls == js::ESClass_Array) {
|
||||
if (cls == js::ESClass::Array) {
|
||||
aTypeOffset += eMaxType;
|
||||
|
||||
if (aTypeOffset == eMaxType * kMaxArrayCollapse) {
|
||||
|
@ -275,7 +275,7 @@ Key::EncodeJSValInternal(JSContext* aCx, JS::Handle<JS::Value> aVal,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (cls == js::ESClass_Date) {
|
||||
if (cls == js::ESClass::Date) {
|
||||
bool valid;
|
||||
if (!js::DateIsValid(aCx, obj, &valid)) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
|
|
|
@ -60,6 +60,7 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
const unsigned short CHILD_SRC_DIRECTIVE = 18;
|
||||
const unsigned short BLOCK_ALL_MIXED_CONTENT = 19;
|
||||
const unsigned short REQUIRE_SRI_FOR = 20;
|
||||
const unsigned short SANDBOX_DIRECTIVE = 21;
|
||||
|
||||
/**
|
||||
* Accessor method for a read-only string version of the policy at a given
|
||||
|
@ -157,6 +158,17 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
*/
|
||||
boolean getAllowsEval(out boolean shouldReportViolations);
|
||||
|
||||
/**
|
||||
* Delegate method called by the service when the protected document is loaded.
|
||||
* Returns the union of all the sandbox flags contained in CSP policies. This is the most
|
||||
* restrictive interpretation of flags set in multiple policies.
|
||||
* See nsSandboxFlags.h for the possible flags.
|
||||
*
|
||||
* @return
|
||||
* sandbox flags or SANDBOXED_NONE if no sandbox directive exists
|
||||
*/
|
||||
uint32_t getCSPSandboxFlags();
|
||||
|
||||
/**
|
||||
* For each violated policy (of type violationType), log policy violation on
|
||||
* the Error Console and send a report to report-uris present in the violated
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
Reset=Reset
|
||||
Submit=Submit Query
|
||||
Browse=Browse…
|
||||
ChooseFiles=Choose files…
|
||||
ChooseDirs=Choose folder…
|
||||
FileUpload=File Upload
|
||||
# LOCALIZATION NOTE (IsIndexPromptWithSpace): The last character of the string
|
||||
# should be a space (U+0020) in most locales. The prompt is followed by an
|
||||
|
@ -25,6 +23,10 @@ NoFileSelected=No file selected.
|
|||
# LOCALIZATION NOTE (NoFilesSelected): this string is shown on a
|
||||
# <input type='file' multiple> when there is no file selected yet.
|
||||
NoFilesSelected=No files selected.
|
||||
# LOCALIZATION NOTE (NoDirSelected): this string is shown on a
|
||||
# <input type='file' directory/webkitdirectory> when there is no directory
|
||||
# selected yet.
|
||||
NoDirSelected=No directory selected.
|
||||
# LOCALIZATION NOTE (XFilesSelected): this string is shown on a
|
||||
# <input type='file' multiple> when there are more than one selected file.
|
||||
# %S will be a number greater or equal to 2.
|
||||
|
|
|
@ -74,6 +74,9 @@ blockAllMixedContent = Blocking insecure request ‘%1$S’.
|
|||
# LOCALIZATION NOTE (ignoringDirectiveWithNoValues):
|
||||
# %1$S is the name of a CSP directive that requires additional values (e.g., 'require-sri-for')
|
||||
ignoringDirectiveWithNoValues = Ignoring ‘%1$S’ since it does not contain any parameters.
|
||||
# LOCALIZATION NOTE (ignoringReportOnlyDirective):
|
||||
# %1$S is the directive that is ignored in report-only mode.
|
||||
ignoringReportOnlyDirective = Ignoring sandbox directive when delivered in a report-only policy ‘%1$S’
|
||||
|
||||
# CSP Errors:
|
||||
# LOCALIZATION NOTE (couldntParseInvalidSource):
|
||||
|
@ -94,3 +97,6 @@ duplicateDirective = Duplicate %1$S directives detected. All but the first inst
|
|||
# LOCALIZATION NOTE (deprecatedDirective):
|
||||
# %1$S is the name of the deprecated directive, %2$S is the name of the replacement.
|
||||
deprecatedDirective = Directive ‘%1$S’ has been deprecated. Please use directive ‘%2$S’ instead.
|
||||
# LOCALIZATION NOTE (couldntParseInvalidSandboxFlag):
|
||||
# %1$S is the option that could not be understood
|
||||
couldntParseInvalidSandboxFlag = Couldn’t parse invalid sandbox flag ‘%1$S’
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//Used by JSHint:
|
||||
/*global Cu, BrowserTestUtils, ok, add_task, PromiseMessage, gBrowser */
|
||||
/*global Cu, BrowserTestUtils, ok, add_task, gBrowser */
|
||||
"use strict";
|
||||
const { PromiseMessage } = Cu.import("resource://gre/modules/PromiseMessage.jsm", {});
|
||||
const testPath = "/browser/dom/manifest/test/file_reg_install_event.html";
|
||||
|
@ -7,21 +7,35 @@ const defaultURL = new URL("http://example.org/browser/dom/manifest/test/file_te
|
|||
const testURL = new URL(defaultURL);
|
||||
testURL.searchParams.append("file", testPath);
|
||||
|
||||
// Enable window.oninstall, so we can fire events at it.
|
||||
function enableOnInstallPref() {
|
||||
const ops = {
|
||||
"set": [
|
||||
["dom.manifest.oninstall", true],
|
||||
],
|
||||
};
|
||||
return SpecialPowers.pushPrefEnv(ops);
|
||||
}
|
||||
|
||||
// Send a message for the even to be fired.
|
||||
// This cause file_reg_install_event.html to be dynamically change.
|
||||
function* theTest(aBrowser) {
|
||||
aBrowser.allowEvents = true;
|
||||
// Resolves when we get a custom event with the correct name
|
||||
const responsePromise = new Promise((resolve) => {
|
||||
aBrowser.contentDocument.addEventListener("dom.manifest.oninstall", resolve);
|
||||
});
|
||||
const mm = aBrowser.messageManager;
|
||||
const msgKey = "DOM:Manifest:FireInstallEvent";
|
||||
const initialText = aBrowser.contentWindowAsCPOW.document.body.innerHTML.trim()
|
||||
is(initialText, '<h1 id="output">waiting for event</h1>', "should be waiting for event");
|
||||
const { data: { success } } = yield PromiseMessage.send(mm, msgKey);
|
||||
ok(success, "message sent and received successfully.");
|
||||
const eventText = aBrowser.contentWindowAsCPOW.document.body.innerHTML.trim();
|
||||
is(eventText, '<h1 id="output">event received!</h1>', "text of the page should have changed.");
|
||||
};
|
||||
const { detail: { result } } = yield responsePromise;
|
||||
ok(result, "the page sent us an acknowledgment as a custom event");
|
||||
}
|
||||
|
||||
// Open a tab and run the test
|
||||
add_task(function*() {
|
||||
yield enableOnInstallPref();
|
||||
let tabOptions = {
|
||||
gBrowser: gBrowser,
|
||||
url: testURL.href,
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
<meta charset=utf-8>
|
||||
<script>
|
||||
window.addEventListener("install", (ev) => {
|
||||
"use strict";
|
||||
window.addEventListener("install", () => {
|
||||
document
|
||||
.querySelector("#output")
|
||||
.innerHTML = "event received!"
|
||||
.innerHTML = "event received!";
|
||||
// Send a custom event back to the browser
|
||||
// to acknowledge that we got this
|
||||
const detail = { result: true }
|
||||
const ev = new CustomEvent("dom.manifest.oninstall", { detail });
|
||||
document.dispatchEvent(ev);
|
||||
});
|
||||
</script>
|
||||
<link rel="manifest" href="file_manifest.json">
|
||||
<h1 id=output>waiting for event</h1>
|
||||
|
|
|
@ -3,42 +3,96 @@
|
|||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1265279
|
||||
-->
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1265279 - Web Manifest: Implement window.oninstall</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
|
||||
<script>
|
||||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
is(window.hasOwnProperty("oninstall"), true, "window has own oninstall property");
|
||||
is(window.oninstall, null, "window install is initially set to null");
|
||||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
const finish = SimpleTest.finish.bind(SimpleTest);
|
||||
enableOnInstallPref()
|
||||
.then(createIframe)
|
||||
.then(checkImplementation)
|
||||
.then(checkOnInstallEventFires)
|
||||
.then(checkAddEventListenerFires)
|
||||
.then(finish)
|
||||
.catch(err => {
|
||||
dump(`${err}: ${err.stack}`);
|
||||
finish();
|
||||
});
|
||||
|
||||
// Check that enumerable, configurable, and has a getter and setter
|
||||
const objDescriptor = Object.getOwnPropertyDescriptor(window, "oninstall");
|
||||
is(objDescriptor.enumerable, true, "is enumerable");
|
||||
is(objDescriptor.configurable, true, "is configurable");
|
||||
is(objDescriptor.hasOwnProperty("get"), true, "has getter");
|
||||
is(objDescriptor.hasOwnProperty("set"), true, "has setter");
|
||||
function enableOnInstallPref() {
|
||||
const ops = {
|
||||
"set": [
|
||||
["dom.manifest.oninstall", true],
|
||||
],
|
||||
};
|
||||
return SpecialPowers.pushPrefEnv(ops);
|
||||
}
|
||||
|
||||
// Test is we receive the event on window.install
|
||||
const customEv = new CustomEvent("install");
|
||||
window.oninstall = function handler(ev){
|
||||
window.oninstall = null;
|
||||
is(ev, customEv, "The events should be the same");
|
||||
testAddEventListener();
|
||||
};
|
||||
window.dispatchEvent(customEv);
|
||||
// WebIDL conditional annotations for an interface are evaluate once per
|
||||
// global, so we need to create an iframe to see the effects of calling
|
||||
// enableOnInstallPref().
|
||||
function createIframe() {
|
||||
return new Promise((resolve) => {
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.src = "about:blank";
|
||||
iframe.onload = () => resolve(iframe.contentWindow);
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}
|
||||
|
||||
// Test that it works with .addEventListener("install", f);
|
||||
function testAddEventListener(){
|
||||
const customEv2 = new CustomEvent("install");
|
||||
window.addEventListener("install", function handler2(ev2) {
|
||||
window.removeEventListener("install", handler2);
|
||||
is(ev2, customEv2, "The events should be the same");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
window.dispatchEvent(customEv2);
|
||||
}
|
||||
// Check that the WebIDL is as expected.
|
||||
function checkImplementation(ifrWindow) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const hasOnInstallProp = ifrWindow.hasOwnProperty("oninstall");
|
||||
ok(hasOnInstallProp, "window has own oninstall property");
|
||||
|
||||
// no point in continuing
|
||||
if (!hasOnInstallProp) {
|
||||
const err = new Error("No 'oninstall' IDL attribute. Aborting early.");
|
||||
return reject(err);
|
||||
}
|
||||
is(ifrWindow.oninstall, null, "window install is initially set to null");
|
||||
|
||||
// Check that enumerable, configurable, and has a getter and setter.
|
||||
const objDescriptor = Object.getOwnPropertyDescriptor(window, "oninstall");
|
||||
ok(objDescriptor.enumerable, "is enumerable");
|
||||
ok(objDescriptor.configurable, "is configurable");
|
||||
ok(objDescriptor.hasOwnProperty("get"), "has getter");
|
||||
ok(objDescriptor.hasOwnProperty("set"), "has setter");
|
||||
resolve(ifrWindow);
|
||||
});
|
||||
}
|
||||
|
||||
// Checks that .oninstall receives an event.
|
||||
function checkOnInstallEventFires(ifrWindow) {
|
||||
const customEv = new CustomEvent("install");
|
||||
return new Promise((resolve) => {
|
||||
// Test is we receive the event on `oninstall`
|
||||
ifrWindow.oninstall = ev => {
|
||||
ifrWindow.oninstall = null;
|
||||
is(ev, customEv, "The events should be the same event object");
|
||||
resolve(ifrWindow);
|
||||
};
|
||||
ifrWindow.dispatchEvent(customEv);
|
||||
});
|
||||
}
|
||||
|
||||
// Checks that .addEventListener("install") receives an event.
|
||||
function checkAddEventListenerFires(ifrWindow) {
|
||||
const customEv = new CustomEvent("install");
|
||||
return new Promise((resolve) => {
|
||||
ifrWindow.addEventListener("install", function handler(ev) {
|
||||
ifrWindow.removeEventListener("install", handler);
|
||||
is(ev, customEv, "The events should be the same");
|
||||
resolve(ifrWindow);
|
||||
});
|
||||
ifrWindow.dispatchEvent(customEv);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
|
@ -1713,6 +1713,7 @@ void
|
|||
MediaDecoder::SetCDMProxy(CDMProxy* aProxy)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aProxy);
|
||||
|
||||
mCDMProxyPromiseHolder.ResolveIfExists(aProxy, __func__);
|
||||
}
|
||||
|
|
|
@ -93,7 +93,8 @@ MP4Decoder::CanHandleMediaType(const nsACString& aMIMETypeExcludingCodecs,
|
|||
// the web, as opposed to what we use internally (i.e. what our demuxers
|
||||
// etc output).
|
||||
const bool isMP4Audio = aMIMETypeExcludingCodecs.EqualsASCII("audio/mp4") ||
|
||||
aMIMETypeExcludingCodecs.EqualsASCII("audio/x-m4a");
|
||||
aMIMETypeExcludingCodecs.EqualsASCII("audio/x-m4a") ||
|
||||
aMIMETypeExcludingCodecs.EqualsASCII("audio/opus");
|
||||
const bool isMP4Video =
|
||||
// On B2G, treat 3GPP as MP4 when Gonk PDM is available.
|
||||
#ifdef MOZ_GONK_MEDIACODEC
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AgnosticDecoderModule.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "OpusDecoder.h"
|
||||
#include "VorbisDecoder.h"
|
||||
#include "VPXDecoder.h"
|
||||
|
@ -16,10 +17,14 @@ bool
|
|||
AgnosticDecoderModule::SupportsMimeType(const nsACString& aMimeType,
|
||||
DecoderDoctorDiagnostics* aDiagnostics) const
|
||||
{
|
||||
return VPXDecoder::IsVPX(aMimeType) ||
|
||||
bool supports =
|
||||
VPXDecoder::IsVPX(aMimeType) ||
|
||||
OpusDataDecoder::IsOpus(aMimeType) ||
|
||||
VorbisDataDecoder::IsVorbis(aMimeType) ||
|
||||
WaveDataDecoder::IsWave(aMimeType);
|
||||
MOZ_LOG(sPDMLog, LogLevel::Debug, ("Agnostic decoder %s requested type",
|
||||
supports ? "supports" : "rejects"));
|
||||
return supports;
|
||||
}
|
||||
|
||||
already_AddRefed<MediaDataDecoder>
|
||||
|
|
|
@ -47,18 +47,28 @@ OpusDataDecoder::Shutdown()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
OpusDataDecoder::AppendCodecDelay(MediaByteBuffer* config, uint64_t codecDelayUS)
|
||||
{
|
||||
uint8_t buffer[sizeof(uint64_t)];
|
||||
BigEndian::writeUint64(buffer, codecDelayUS);
|
||||
config->AppendElements(buffer, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::InitPromise>
|
||||
OpusDataDecoder::Init()
|
||||
{
|
||||
size_t length = mInfo.mCodecSpecificConfig->Length();
|
||||
uint8_t *p = mInfo.mCodecSpecificConfig->Elements();
|
||||
if (length < sizeof(uint64_t)) {
|
||||
OPUS_DEBUG("CodecSpecificConfig too short to read codecDelay!");
|
||||
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
|
||||
}
|
||||
int64_t codecDelay = BigEndian::readUint64(p);
|
||||
length -= sizeof(uint64_t);
|
||||
p += sizeof(uint64_t);
|
||||
if (NS_FAILED(DecodeHeader(p, length))) {
|
||||
OPUS_DEBUG("Error decoding header!");
|
||||
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
|
||||
}
|
||||
|
||||
|
@ -348,7 +358,9 @@ bool
|
|||
OpusDataDecoder::IsOpus(const nsACString& aMimeType)
|
||||
{
|
||||
return aMimeType.EqualsLiteral("audio/webm; codecs=opus") ||
|
||||
aMimeType.EqualsLiteral("audio/ogg; codecs=opus");
|
||||
aMimeType.EqualsLiteral("audio/ogg; codecs=opus") ||
|
||||
aMimeType.EqualsLiteral("audio/mp4; codecs=opus") ||
|
||||
aMimeType.EqualsLiteral("audio/opus");
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -33,6 +33,13 @@ public:
|
|||
// Return true if mimetype is Opus
|
||||
static bool IsOpus(const nsACString& aMimeType);
|
||||
|
||||
// Pack pre-skip/CodecDelay, given in microseconds, into a
|
||||
// MediaByteBuffer. The decoder expects this value to come
|
||||
// from the container (if any) and to precede the OpusHead
|
||||
// block in the CodecSpecificConfig buffer to verify the
|
||||
// values match.
|
||||
static void AppendCodecDelay(MediaByteBuffer* config, uint64_t codecDelayUS);
|
||||
|
||||
private:
|
||||
enum DecodeError {
|
||||
DECODE_SUCCESS,
|
||||
|
|
|
@ -22,8 +22,8 @@ already_AddRefed<MediaDataDecoder>
|
|||
GonkDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams)
|
||||
{
|
||||
RefPtr<MediaDataDecoder> decoder =
|
||||
new GonkMediaDataDecoder(new GonkVideoDecoderManager(aImageContainer, aConfig),
|
||||
aCallback);
|
||||
new GonkMediaDataDecoder(new GonkVideoDecoderManager(aParams.mImageContainer, aParams.VideoConfig()),
|
||||
aParams.mCallback);
|
||||
return decoder.forget();
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,8 @@ already_AddRefed<MediaDataDecoder>
|
|||
GonkDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams)
|
||||
{
|
||||
RefPtr<MediaDataDecoder> decoder =
|
||||
new GonkMediaDataDecoder(new GonkAudioDecoderManager(aConfig),
|
||||
aCallback);
|
||||
new GonkMediaDataDecoder(new GonkAudioDecoderManager(aParams.AudioConfig()),
|
||||
aParams.mCallback);
|
||||
return decoder.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "MediaDecoderStateMachine.h"
|
||||
#include "AbstractMediaDecoder.h"
|
||||
#include "MediaResource.h"
|
||||
#include "OpusDecoder.h"
|
||||
#include "WebMDemuxer.h"
|
||||
#include "WebMBufferedParser.h"
|
||||
#include "gfx2DGlue.h"
|
||||
|
@ -396,15 +397,13 @@ WebMDemuxer::ReadMetadata()
|
|||
|
||||
mAudioTrack = track;
|
||||
mHasAudio = true;
|
||||
mCodecDelay = media::TimeUnit::FromNanoseconds(params.codec_delay).ToMicroseconds();
|
||||
mAudioCodec = nestegg_track_codec_id(context, track);
|
||||
if (mAudioCodec == NESTEGG_CODEC_VORBIS) {
|
||||
mInfo.mAudio.mMimeType = "audio/webm; codecs=vorbis";
|
||||
} else if (mAudioCodec == NESTEGG_CODEC_OPUS) {
|
||||
mInfo.mAudio.mMimeType = "audio/webm; codecs=opus";
|
||||
uint8_t c[sizeof(uint64_t)];
|
||||
BigEndian::writeUint64(&c[0], mCodecDelay);
|
||||
mInfo.mAudio.mCodecSpecificConfig->AppendElements(&c[0], sizeof(uint64_t));
|
||||
OpusDataDecoder::AppendCodecDelay(mInfo.mAudio.mCodecSpecificConfig,
|
||||
media::TimeUnit::FromNanoseconds(params.codec_delay).ToMicroseconds());
|
||||
}
|
||||
mSeekPreroll = params.seek_preroll;
|
||||
mInfo.mAudio.mRate = params.rate;
|
||||
|
|
|
@ -213,9 +213,6 @@ private:
|
|||
uint32_t mVideoTrack;
|
||||
uint32_t mAudioTrack;
|
||||
|
||||
// Number of microseconds that must be discarded from the start of the Stream.
|
||||
uint64_t mCodecDelay;
|
||||
|
||||
// Nanoseconds to discard after seeking.
|
||||
uint64_t mSeekPreroll;
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ DIRS += [
|
|||
'filesystem',
|
||||
'flyweb',
|
||||
'fmradio',
|
||||
'gamepad',
|
||||
'geolocation',
|
||||
'html',
|
||||
'icc',
|
||||
|
@ -135,9 +136,6 @@ if CONFIG['MOZ_B2G_RIL']:
|
|||
if CONFIG['MOZ_PAY']:
|
||||
DIRS += ['payment']
|
||||
|
||||
if CONFIG['MOZ_GAMEPAD']:
|
||||
DIRS += ['gamepad']
|
||||
|
||||
if CONFIG['MOZ_NFC']:
|
||||
DIRS += ['nfc']
|
||||
|
||||
|
|
|
@ -99,6 +99,18 @@ interface nsIPluginHost : nsISupports
|
|||
ACString getPermissionStringForType(in AUTF8String mimeType,
|
||||
[optional] in uint32_t excludeFlags);
|
||||
|
||||
/**
|
||||
* Get the "permission string" for the plugin. This is a string that can be
|
||||
* passed to the permission manager to see whether the plugin is allowed to
|
||||
* run, for example. This will typically be based on the plugin's "nice name"
|
||||
* and its blocklist state.
|
||||
*
|
||||
* @tag The tage we're interested in
|
||||
* @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE.
|
||||
*/
|
||||
ACString getPermissionStringForTag(in nsIPluginTag tag,
|
||||
[optional] in uint32_t excludeFlags);
|
||||
|
||||
/**
|
||||
* Get the nsIPluginTag for this MIME type. This method works with both
|
||||
* enabled and disabled/blocklisted plugins, but an enabled plugin will
|
||||
|
|
|
@ -1110,11 +1110,19 @@ nsPluginHost::GetPermissionStringForType(const nsACString &aMimeType,
|
|||
nsresult rv = GetPluginTagForType(aMimeType, aExcludeFlags,
|
||||
getter_AddRefs(tag));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(tag, NS_ERROR_FAILURE);
|
||||
return GetPermissionStringForTag(tag, aExcludeFlags, aPermissionString);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginHost::GetPermissionStringForTag(nsIPluginTag* aTag,
|
||||
uint32_t aExcludeFlags,
|
||||
nsACString &aPermissionString)
|
||||
{
|
||||
NS_ENSURE_TRUE(aTag, NS_ERROR_FAILURE);
|
||||
|
||||
aPermissionString.Truncate();
|
||||
uint32_t blocklistState;
|
||||
rv = tag->GetBlocklistState(&blocklistState);
|
||||
nsresult rv = aTag->GetBlocklistState(&blocklistState);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (blocklistState == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE ||
|
||||
|
@ -1126,7 +1134,7 @@ nsPluginHost::GetPermissionStringForType(const nsACString &aMimeType,
|
|||
}
|
||||
|
||||
nsCString niceName;
|
||||
rv = tag->GetNiceName(niceName);
|
||||
rv = aTag->GetNiceName(niceName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(!niceName.IsEmpty(), NS_ERROR_FAILURE);
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ nsPluginTag::~nsPluginTag()
|
|||
NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsPluginTag, nsIPluginTag, nsIInternalPluginTag)
|
||||
NS_IMPL_ISUPPORTS(nsPluginTag, nsPluginTag, nsIInternalPluginTag, nsIPluginTag)
|
||||
|
||||
void nsPluginTag::InitMime(const char* const* aMimeTypes,
|
||||
const char* const* aMimeDescriptions,
|
||||
|
|
|
@ -30,6 +30,9 @@ struct FakePluginTagInit;
|
|||
{ 0xe8fdd227, 0x27da, 0x46ee, \
|
||||
{ 0xbe, 0xf3, 0x1a, 0xef, 0x5a, 0x8f, 0xc5, 0xb4 } }
|
||||
|
||||
#define NS_PLUGINTAG_IID \
|
||||
{ 0xcce2e8b9, 0x9702, 0x4d4b, \
|
||||
{ 0xbe, 0xa4, 0x7c, 0x1e, 0x13, 0x1f, 0xaf, 0x78 } }
|
||||
class nsIInternalPluginTag : public nsIPluginTag
|
||||
{
|
||||
public:
|
||||
|
@ -90,6 +93,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIInternalPluginTag, NS_IINTERNALPLUGINTAG_IID)
|
|||
class nsPluginTag final : public nsIInternalPluginTag
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PLUGINTAG_IID)
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPLUGINTAG
|
||||
|
||||
|
@ -192,6 +197,7 @@ private:
|
|||
|
||||
static uint32_t sNextId;
|
||||
};
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsPluginTag, NS_PLUGINTAG_IID)
|
||||
|
||||
// A class representing "fake" plugin tags; that is plugin tags not
|
||||
// corresponding to actual NPAPI plugins. In practice these are all
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "mozilla/dom/CSPDictionariesBinding.h"
|
||||
#include "mozilla/net/ReferrerPolicy.h"
|
||||
#include "nsINetworkInterceptController.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -1323,6 +1324,45 @@ nsCSPContext::ToJSON(nsAString& outCSPinJSON)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSPContext::GetCSPSandboxFlags(uint32_t* aOutSandboxFlags)
|
||||
{
|
||||
if (!aOutSandboxFlags) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
*aOutSandboxFlags = SANDBOXED_NONE;
|
||||
|
||||
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
|
||||
uint32_t flags = mPolicies[i]->getSandboxFlags();
|
||||
|
||||
// current policy doesn't have sandbox flag, check next policy
|
||||
if (!flags) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// current policy has sandbox flags, if the policy is in enforcement-mode
|
||||
// (i.e. not report-only) set these flags and check for policies with more
|
||||
// restrictions
|
||||
if (!mPolicies[i]->getReportOnlyFlag()) {
|
||||
*aOutSandboxFlags |= flags;
|
||||
} else {
|
||||
// sandbox directive is ignored in report-only mode, warn about it and
|
||||
// continue the loop checking for an enforcement policy.
|
||||
nsAutoString policy;
|
||||
mPolicies[i]->toString(policy);
|
||||
|
||||
CSPCONTEXTLOG(("nsCSPContext::GetCSPSandboxFlags, report only policy, ignoring sandbox in: %s",
|
||||
policy.get()));
|
||||
|
||||
const char16_t* params[] = { policy.get() };
|
||||
logToConsole(MOZ_UTF16("ignoringReportOnlyDirective"), params, ArrayLength(params),
|
||||
EmptyString(), EmptyString(), 0, 0, nsIScriptError::warningFlag);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* ========== CSPViolationReportListener implementation ========== */
|
||||
|
||||
NS_IMPL_ISUPPORTS(CSPViolationReportListener, nsIStreamListener, nsIRequestObserver, nsISupports);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCSPParser.h"
|
||||
#include "nsCSPUtils.h"
|
||||
#include "nsIConsoleService.h"
|
||||
|
@ -993,6 +994,41 @@ nsCSPParser::reportURIList(nsTArray<nsCSPBaseSrc*>& outSrcs)
|
|||
}
|
||||
}
|
||||
|
||||
/* Helper function for parsing sandbox flags. This function solely concatenates
|
||||
* all the source list tokens (the sandbox flags) so the attribute parser
|
||||
* (nsContentUtils::ParseSandboxAttributeToFlags) can parse them.
|
||||
*/
|
||||
void
|
||||
nsCSPParser::sandboxFlagList(nsTArray<nsCSPBaseSrc*>& outSrcs)
|
||||
{
|
||||
nsAutoString flags;
|
||||
|
||||
// remember, srcs start at index 1
|
||||
for (uint32_t i = 1; i < mCurDir.Length(); i++) {
|
||||
mCurToken = mCurDir[i];
|
||||
|
||||
CSPPARSERLOG(("nsCSPParser::sandboxFlagList, mCurToken: %s, mCurValue: %s",
|
||||
NS_ConvertUTF16toUTF8(mCurToken).get(),
|
||||
NS_ConvertUTF16toUTF8(mCurValue).get()));
|
||||
|
||||
if (!nsContentUtils::IsValidSandboxFlag(mCurToken)) {
|
||||
const char16_t* params[] = { mCurToken.get() };
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag,
|
||||
"couldntParseInvalidSandboxFlag",
|
||||
params, ArrayLength(params));
|
||||
continue;
|
||||
}
|
||||
|
||||
flags.Append(mCurToken);
|
||||
if (i != mCurDir.Length() - 1) {
|
||||
flags.AppendASCII(" ");
|
||||
}
|
||||
}
|
||||
|
||||
nsCSPSandboxFlags* sandboxFlags = new nsCSPSandboxFlags(flags);
|
||||
outSrcs.AppendElement(sandboxFlags);
|
||||
}
|
||||
|
||||
// directive-value = *( WSP / <VCHAR except ";" and ","> )
|
||||
void
|
||||
nsCSPParser::directiveValue(nsTArray<nsCSPBaseSrc*>& outSrcs)
|
||||
|
@ -1014,6 +1050,13 @@ nsCSPParser::directiveValue(nsTArray<nsCSPBaseSrc*>& outSrcs)
|
|||
return;
|
||||
}
|
||||
|
||||
// For the sandbox flag the source list is a list of flags, so we're special
|
||||
// casing this directive
|
||||
if (CSP_IsDirective(mCurDir[0], nsIContentSecurityPolicy::SANDBOX_DIRECTIVE)) {
|
||||
sandboxFlagList(outSrcs);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise just forward to sourceList
|
||||
sourceList(outSrcs);
|
||||
}
|
||||
|
@ -1061,7 +1104,8 @@ nsCSPParser::directiveName()
|
|||
// http://www.w3.org/TR/CSP11/#delivery-html-meta-element
|
||||
if (mDeliveredViaMetaTag &&
|
||||
((CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::REPORT_URI_DIRECTIVE)) ||
|
||||
(CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE)))) {
|
||||
(CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::FRAME_ANCESTORS_DIRECTIVE)) ||
|
||||
(CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::SANDBOX_DIRECTIVE)))) {
|
||||
// log to the console to indicate that meta CSP is ignoring the directive
|
||||
const char16_t* params[] = { mCurToken.get() };
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag,
|
||||
|
|
|
@ -137,14 +137,15 @@ class nsCSPParser {
|
|||
bool port();
|
||||
bool path(nsCSPHostSrc* aCspHost);
|
||||
|
||||
bool subHost(); // helper function to parse subDomains
|
||||
bool atValidUnreservedChar(); // helper function to parse unreserved
|
||||
bool atValidSubDelimChar(); // helper function to parse sub-delims
|
||||
bool atValidPctEncodedChar(); // helper function to parse pct-encoded
|
||||
bool subPath(nsCSPHostSrc* aCspHost); // helper function to parse paths
|
||||
void reportURIList(nsTArray<nsCSPBaseSrc*>& outSrcs); // helper function to parse report-uris
|
||||
void percentDecodeStr(const nsAString& aEncStr, // helper function to percent-decode
|
||||
bool subHost(); // helper function to parse subDomains
|
||||
bool atValidUnreservedChar(); // helper function to parse unreserved
|
||||
bool atValidSubDelimChar(); // helper function to parse sub-delims
|
||||
bool atValidPctEncodedChar(); // helper function to parse pct-encoded
|
||||
bool subPath(nsCSPHostSrc* aCspHost); // helper function to parse paths
|
||||
void reportURIList(nsTArray<nsCSPBaseSrc*>& outSrcs); // helper function to parse report-uris
|
||||
void percentDecodeStr(const nsAString& aEncStr, // helper function to percent-decode
|
||||
nsAString& outDecStr);
|
||||
void sandboxFlagList(nsTArray<nsCSPBaseSrc*>& outSrcs); // helper function to parse sandbox flags
|
||||
|
||||
inline bool atEnd()
|
||||
{
|
||||
|
|
|
@ -4,6 +4,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/. */
|
||||
|
||||
#include "nsAttrValue.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCSPUtils.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsIConsoleService.h"
|
||||
|
@ -13,6 +15,7 @@
|
|||
#include "nsIStringBundle.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
|
||||
static mozilla::LogModule*
|
||||
GetCspUtilsLog()
|
||||
|
@ -792,6 +795,29 @@ nsCSPReportURI::toString(nsAString& outStr) const
|
|||
outStr.AppendASCII(spec.get());
|
||||
}
|
||||
|
||||
/* ===== nsCSPSandboxFlags ===================== */
|
||||
|
||||
nsCSPSandboxFlags::nsCSPSandboxFlags(const nsAString& aFlags)
|
||||
: mFlags(aFlags)
|
||||
{
|
||||
}
|
||||
|
||||
nsCSPSandboxFlags::~nsCSPSandboxFlags()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
nsCSPSandboxFlags::visit(nsCSPSrcVisitor* aVisitor) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsCSPSandboxFlags::toString(nsAString& outStr) const
|
||||
{
|
||||
outStr.Append(mFlags);
|
||||
}
|
||||
|
||||
/* ===== nsCSPDirective ====================== */
|
||||
|
||||
nsCSPDirective::nsCSPDirective(CSPDirective aDirective)
|
||||
|
@ -953,6 +979,11 @@ nsCSPDirective::toDomCSPStruct(mozilla::dom::CSP& outCSP) const
|
|||
outCSP.mChild_src.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
case nsIContentSecurityPolicy::SANDBOX_DIRECTIVE:
|
||||
outCSP.mSandbox.Construct();
|
||||
outCSP.mSandbox.Value() = mozilla::Move(srcs);
|
||||
return;
|
||||
|
||||
// REFERRER_DIRECTIVE and REQUIRE_SRI_FOR are handled in nsCSPPolicy::toDomCSPStruct()
|
||||
|
||||
default:
|
||||
|
@ -1344,6 +1375,33 @@ nsCSPPolicy::getDirectiveAsString(CSPDirective aDir, nsAString& outDirective) co
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function that returns the underlying bit representation of sandbox
|
||||
* flags. The function returns SANDBOXED_NONE if there are no sandbox
|
||||
* directives.
|
||||
*/
|
||||
uint32_t
|
||||
nsCSPPolicy::getSandboxFlags() const
|
||||
{
|
||||
for (uint32_t i = 0; i < mDirectives.Length(); i++) {
|
||||
if (mDirectives[i]->equals(nsIContentSecurityPolicy::SANDBOX_DIRECTIVE)) {
|
||||
nsAutoString flags;
|
||||
mDirectives[i]->toString(flags);
|
||||
|
||||
if (flags.IsEmpty()) {
|
||||
return SANDBOX_ALL_FLAGS;
|
||||
}
|
||||
|
||||
nsAttrValue attr;
|
||||
attr.ParseAtomArray(flags);
|
||||
|
||||
return nsContentUtils::ParseSandboxAttributeToFlags(&attr);
|
||||
}
|
||||
}
|
||||
|
||||
return SANDBOXED_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
nsCSPPolicy::getReportURIs(nsTArray<nsString>& outReportURIs) const
|
||||
{
|
||||
|
|
|
@ -92,8 +92,8 @@ static const char* CSPStrDirectives[] = {
|
|||
"upgrade-insecure-requests", // UPGRADE_IF_INSECURE_DIRECTIVE
|
||||
"child-src", // CHILD_SRC_DIRECTIVE
|
||||
"block-all-mixed-content", // BLOCK_ALL_MIXED_CONTENT
|
||||
"require-sri-for" // REQUIRE_SRI_FOR
|
||||
|
||||
"require-sri-for", // REQUIRE_SRI_FOR
|
||||
"sandbox" // SANDBOX_DIRECTIVE
|
||||
};
|
||||
|
||||
inline const char* CSP_CSPDirectiveToString(CSPDirective aDir)
|
||||
|
@ -334,6 +334,20 @@ class nsCSPReportURI : public nsCSPBaseSrc {
|
|||
nsCOMPtr<nsIURI> mReportURI;
|
||||
};
|
||||
|
||||
/* =============== nsCSPSandboxFlags ================== */
|
||||
|
||||
class nsCSPSandboxFlags : public nsCSPBaseSrc {
|
||||
public:
|
||||
explicit nsCSPSandboxFlags(const nsAString& aFlags);
|
||||
virtual ~nsCSPSandboxFlags();
|
||||
|
||||
bool visit(nsCSPSrcVisitor* aVisitor) const;
|
||||
void toString(nsAString& outStr) const;
|
||||
|
||||
private:
|
||||
nsString mFlags;
|
||||
};
|
||||
|
||||
/* =============== nsCSPSrcVisitor ================== */
|
||||
|
||||
class nsCSPSrcVisitor {
|
||||
|
@ -558,6 +572,8 @@ class nsCSPPolicy {
|
|||
|
||||
void getDirectiveAsString(CSPDirective aDir, nsAString& outDirective) const;
|
||||
|
||||
uint32_t getSandboxFlags() const;
|
||||
|
||||
bool requireSRIForType(nsContentPolicyType aContentType);
|
||||
|
||||
inline uint32_t getNumDirectives() const
|
||||
|
|
|
@ -175,6 +175,13 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
|
|||
nsCString mimeTypeGuess;
|
||||
nsCOMPtr<nsINode> requestingContext = nullptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
// Don't enforce TYPE_DOCUMENT assertions for loads
|
||||
// initiated by javascript tests.
|
||||
bool skipContentTypeCheck = false;
|
||||
skipContentTypeCheck = Preferences::GetBool("network.loadinfo.skip_type_assertion");
|
||||
#endif
|
||||
|
||||
switch(contentPolicyType) {
|
||||
case nsIContentPolicy::TYPE_OTHER: {
|
||||
mimeTypeGuess = EmptyCString();
|
||||
|
@ -207,7 +214,7 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
|
|||
}
|
||||
|
||||
case nsIContentPolicy::TYPE_DOCUMENT: {
|
||||
MOZ_ASSERT(false, "contentPolicyType not supported yet");
|
||||
MOZ_ASSERT(skipContentTypeCheck || false, "contentPolicyType not supported yet");
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<script type="text/javascript">
|
||||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
function doStuff() {
|
||||
var beforePrincipal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
document.open();
|
||||
document.write("rewritten sandboxed document");
|
||||
document.close();
|
||||
var afterPrincipal = SpecialPowers.wrap(document).nodePrincipal;
|
||||
ok(beforePrincipal.equals(afterPrincipal),
|
||||
"document.write() does not change underlying principal");
|
||||
}
|
||||
</script>
|
||||
<body onLoad='doStuff();'>
|
||||
sandboxed with allow-scripts
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- sandbox="allow-same-origin" -->
|
||||
<!-- Content-Security-Policy: default-src 'self' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img1_bad&type=img/png"> </img>
|
||||
|
||||
<!-- these should load ok -->
|
||||
<img src="/tests/dom/security/test/csp/file_CSP.sjs?testid=img1a_good&type=img/png" />
|
||||
<!-- should not execute script -->
|
||||
<script src='/tests/dom/security/test/csp/file_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- Content-Security-Policy: default-src 'none'; sandbox -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img10_bad&type=img/png"> </img>
|
||||
<img src="/tests/dom/security/test/csp/file_CSP.sjs?testid=img10a_bad&type=img/png" />
|
||||
<script src='/tests/dom/security/test/csp/file_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<script type="text/javascript">
|
||||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
|
||||
function doStuff() {
|
||||
ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts");
|
||||
}
|
||||
</script>
|
||||
<script src='file_sandbox_fail.js'></script>
|
||||
<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
|
||||
I am sandboxed but with only inline "allow-scripts"
|
||||
|
||||
<!-- Content-Security-Policy: default-src 'none'; script-src 'unsafe-inline'; sandbox allow-scripts -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="/tests/dom/security/test/csp/file_CSP.sjs?testid=img11_bad&type=img/png" />
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img11a_bad&type=img/png"> </img>
|
||||
<script src='/tests/dom/security/test/csp/file_CSP.sjs?testid=script11_bad&type=text/javascript'></script>
|
||||
<script src='http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=script11a_bad&type=text/javascript'></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<script type="text/javascript">
|
||||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
|
||||
function doStuff() {
|
||||
ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts");
|
||||
|
||||
document.getElementById('a_form').submit();
|
||||
|
||||
// trigger the javascript: url test
|
||||
sendMouseEvent({type:'click'}, 'a_link');
|
||||
}
|
||||
</script>
|
||||
<script src='file_sandbox_pass.js'></script>
|
||||
<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
|
||||
I am sandboxed but with "allow-same-origin" and allow-scripts"
|
||||
|
||||
|
||||
<!-- Content-Security-Policy: sandbox allow-same-origin allow-scripts; default-src 'self' 'unsafe-inline'; -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img12_bad&type=img/png"> </img>
|
||||
<script src='http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=script12_bad&type=text/javascript'></script>
|
||||
|
||||
<form method="get" action="/tests/content/html/content/test/file_iframe_sandbox_form_fail.html" id="a_form">
|
||||
First name: <input type="text" name="firstname">
|
||||
Last name: <input type="text" name="lastname">
|
||||
<input type="submit" onclick="doSubmit()" id="a_button">
|
||||
</form>
|
||||
|
||||
<a href = 'javascript:ok(true, "documents sandboxed with allow-scripts should be able to run script from javascript: URLs");' id='a_link'>click me</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- sandbox -->
|
||||
<!-- Content-Security-Policy: default-src 'self' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img2_bad&type=img/png"> </img>
|
||||
|
||||
<!-- these should load ok -->
|
||||
<img src="/tests/dom/security/test/csp/file_CSP.sjs?testid=img2a_good&type=img/png" />
|
||||
<!-- should not execute script -->
|
||||
<script src='/tests/dom/security/test/csp/file_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- sandbox="allow-same-origin" -->
|
||||
<!-- Content-Security-Policy: default-src 'none' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img3_bad&type=img/png"> </img>
|
||||
<img src="/tests/dom/security/test/csp/file_CSP.sjs?testid=img3a_bad&type=img/png" />
|
||||
<script src='/tests/dom/security/test/csp/file_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- sandbox -->
|
||||
<!-- Content-Security-Policy: default-src 'none' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/base/test/csp/file_CSP.sjs?testid=img4_bad&type=img/png"> </img>
|
||||
<img src="/tests/dom/base/test/csp/file_CSP.sjs?testid=img4a_bad&type=img/png" />
|
||||
<script src='/tests/dom/base/test/csp/file_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<script type="text/javascript">
|
||||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
|
||||
function doStuff() {
|
||||
ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts");
|
||||
}
|
||||
</script>
|
||||
<script src='file_sandbox_fail.js'></script>
|
||||
<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
|
||||
I am sandboxed but with only inline "allow-scripts"
|
||||
|
||||
<!-- sandbox="allow-scripts" -->
|
||||
<!-- Content-Security-Policy: default-src 'none'; script-src 'unsafe-inline' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="/tests/dom/security/test/csp/file_CSP.sjs?testid=img5_bad&type=img/png" />
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img5a_bad&type=img/png"> </img>
|
||||
<script src='/tests/dom/security/test/csp/file_CSP.sjs?testid=script5_bad&type=text/javascript'></script>
|
||||
<script src='http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=script5a_bad&type=text/javascript'></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<script type="text/javascript">
|
||||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
|
||||
function doStuff() {
|
||||
ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts");
|
||||
|
||||
document.getElementById('a_form').submit();
|
||||
|
||||
// trigger the javascript: url test
|
||||
sendMouseEvent({type:'click'}, 'a_link');
|
||||
}
|
||||
</script>
|
||||
<script src='file_sandbox_pass.js'></script>
|
||||
<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
|
||||
I am sandboxed but with "allow-same-origin" and allow-scripts"
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img6_bad&type=img/png"> </img>
|
||||
<script src='http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=script6_bad&type=text/javascript'></script>
|
||||
|
||||
<form method="get" action="/tests/content/html/content/test/file_iframe_sandbox_form_fail.html" id="a_form">
|
||||
First name: <input type="text" name="firstname">
|
||||
Last name: <input type="text" name="lastname">
|
||||
<input type="submit" onclick="doSubmit()" id="a_button">
|
||||
</form>
|
||||
|
||||
<a href = 'javascript:ok(true, "documents sandboxed with allow-scripts should be able to run script from javascript: URLs");' id='a_link'>click me</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- Content-Security-Policy: default-src 'self'; sandbox allow-same-origin -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img7_bad&type=img/png"> </img>
|
||||
|
||||
<!-- these should load ok -->
|
||||
<img src="/tests/dom/security/test/csp/file_CSP.sjs?testid=img7a_good&type=img/png" />
|
||||
<!-- should not execute script -->
|
||||
<script src='/tests/dom/security/test/csp/file_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- Content-Security-Policy: sandbox; default-src 'self' -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img8_bad&type=img/png"> </img>
|
||||
|
||||
<!-- these should load ok -->
|
||||
<img src="/tests/dom/security/test/csp/file_CSP.sjs?testid=img8a_good&type=img/png" />
|
||||
<!-- should not execute script -->
|
||||
<script src='/tests/dom/security/test/csp/file_sandbox_fail.js'></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head> <meta charset="utf-8"> </head>
|
||||
<body>
|
||||
<!-- Content-Security-Policy: default-src 'none'; sandbox allow-same-origin -->
|
||||
|
||||
<!-- these should be stopped by CSP -->
|
||||
<img src="http://example.org/tests/dom/security/test/csp/file_CSP.sjs?testid=img9_bad&type=img/png"> </img>
|
||||
<img src="/tests/dom/security/test/csp/file_CSP.sjs?testid=img9a_bad&type=img/png" />
|
||||
|
||||
<script src='/tests/dom/security/test/csp/file_sandbox_fail.js'></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,4 @@
|
|||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
ok(false, "documents sandboxed with allow-scripts should NOT be able to run <script src=...>");
|
|
@ -0,0 +1,4 @@
|
|||
function ok(result, desc) {
|
||||
window.parent.postMessage({ok: result, desc: desc}, "*");
|
||||
}
|
||||
ok(true, "documents sandboxed with allow-scripts should be able to run <script src=...>");
|
|
@ -39,6 +39,11 @@ function handleRequest(request, response) {
|
|||
response.setHeader("Content-Security-Policy", query.get("csp"), false);
|
||||
}
|
||||
|
||||
// Deliver the CSP report-only policy encoded in the URI
|
||||
if(query.has("cspRO")){
|
||||
response.setHeader("Content-Security-Policy-Report-Only", query.get("cspRO"), false);
|
||||
}
|
||||
|
||||
// Deliver the CORS header in the URL
|
||||
if(query.has("cors")){
|
||||
response.setHeader("Access-Control-Allow-Origin", query.get("cors"), false);
|
||||
|
@ -46,5 +51,7 @@ function handleRequest(request, response) {
|
|||
|
||||
// Send HTML to test allowed/blocked behaviors
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
response.write(loadHTMLFromFile(query.get("file")));
|
||||
if(query.has("file")){
|
||||
response.write(loadHTMLFromFile(query.get("file")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,6 +163,22 @@ support-files =
|
|||
!/image/test/mochitest/blue.png
|
||||
file_meta_whitespace_skipping.html
|
||||
file_ping.html
|
||||
test_iframe_sandbox_top_1.html^headers^
|
||||
file_iframe_sandbox_document_write.html
|
||||
file_sandbox_pass.js
|
||||
file_sandbox_fail.js
|
||||
file_sandbox_1.html
|
||||
file_sandbox_2.html
|
||||
file_sandbox_3.html
|
||||
file_sandbox_4.html
|
||||
file_sandbox_5.html
|
||||
file_sandbox_6.html
|
||||
file_sandbox_7.html
|
||||
file_sandbox_8.html
|
||||
file_sandbox_9.html
|
||||
file_sandbox_10.html
|
||||
file_sandbox_11.html
|
||||
file_sandbox_12.html
|
||||
|
||||
[test_base-uri.html]
|
||||
[test_blob_data_schemes.html]
|
||||
|
@ -249,4 +265,7 @@ tags = mcb
|
|||
tags = mcb
|
||||
[test_form_action_blocks_url.html]
|
||||
[test_meta_whitespace_skipping.html]
|
||||
[test_iframe_sandbox.html]
|
||||
[test_iframe_sandbox_top_1.html]
|
||||
[test_sandbox.html]
|
||||
[test_ping.html]
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=671389
|
||||
Bug 671389 - Implement CSP sandbox directive
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests for Bug 671389</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Check if two sandbox flags are the same, ignoring case-sensitivity.
|
||||
// getSandboxFlags returns a list of sandbox flags (if any) or
|
||||
// null if the flag is not set.
|
||||
// This function checks if two flags are the same, i.e., they're
|
||||
// either not set or have the same flags.
|
||||
function eqFlags(a, b) {
|
||||
if (a === null && b === null) { return true; }
|
||||
if (a === null || b === null) { return false; }
|
||||
if (a.length !== b.length) { return false; }
|
||||
var a_sorted = a.map(function(e) { return e.toLowerCase(); }).sort();
|
||||
var b_sorted = b.map(function(e) { return e.toLowerCase(); }).sort();
|
||||
for (var i in a_sorted) {
|
||||
if (a_sorted[i] !== b_sorted[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the sandbox flags of document doc.
|
||||
// If the flag is not set sandboxFlagsAsString returns null,
|
||||
// this function also returns null.
|
||||
// If the flag is set it may have some flags; in this case
|
||||
// this function returns the (potentially empty) list of flags.
|
||||
function getSandboxFlags(doc) {
|
||||
var flags = doc.sandboxFlagsAsString;
|
||||
if (flags === null) { return null; }
|
||||
return flags? flags.split(" "):[];
|
||||
}
|
||||
|
||||
// Constructor for a CSP sandbox flags test. The constructor
|
||||
// expectes a description 'desc' and set of options 'opts':
|
||||
// - sandboxAttribute: [null] or string corresponding to the iframe sandbox attributes
|
||||
// - csp: [null] or string corresponding to the CSP sandbox flags
|
||||
// - cspReportOnly: [null] or string corresponding to the CSP report-only sandbox flags
|
||||
// - file: [null] or string corresponding to file the server should serve
|
||||
// Above, we use [brackets] to denote default values.
|
||||
function CSPFlagsTest(desc, opts) {
|
||||
function ifundef(x, v) {
|
||||
return (x !== undefined) ? x : v;
|
||||
}
|
||||
|
||||
function intersect(as, bs) { // Intersect two csp attributes:
|
||||
as = as === null ? null
|
||||
: as.split(' ').filter(function(x) { return !!x; });
|
||||
bs = bs === null ? null
|
||||
: bs.split(' ').filter(function(x) { return !!x; });
|
||||
|
||||
if (as === null) { return bs; }
|
||||
if (bs === null) { return as; }
|
||||
|
||||
var cs = [];
|
||||
as.forEach(function(a) {
|
||||
if (a && bs.indexOf(a) != -1)
|
||||
cs.push(a);
|
||||
});
|
||||
return cs;
|
||||
}
|
||||
|
||||
this.desc = desc || "Untitled test";
|
||||
this.attr = ifundef(opts.sandboxAttribute, null);
|
||||
this.csp = ifundef(opts.csp, null);
|
||||
this.cspRO = ifundef(opts.cspReportOnly, null);
|
||||
this.file = ifundef(opts.file, null);
|
||||
this.expected = intersect(this.attr, this.csp);
|
||||
}
|
||||
|
||||
// Return function that checks that the actual flags are the same as the
|
||||
// expected flags
|
||||
CSPFlagsTest.prototype.checkFlags = function(iframe) {
|
||||
var this_ = this;
|
||||
return function() {
|
||||
try {
|
||||
var actual = getSandboxFlags(SpecialPowers.wrap(iframe).contentDocument);
|
||||
ok(eqFlags(actual, this_.expected),
|
||||
this_.desc, 'expected: "' + this_.expected + '", got: "' + actual + '"');
|
||||
} catch (e) {
|
||||
ok(false, this_.desc, 'expected: "' + this_.expected + '", failed with: "' + e + '"');
|
||||
}
|
||||
runNextTest();
|
||||
};
|
||||
};
|
||||
|
||||
// Set the iframe src and sandbox attribute
|
||||
CSPFlagsTest.prototype.runTest = function () {
|
||||
var iframe = document.createElement('iframe');
|
||||
document.getElementById("content").appendChild(iframe);
|
||||
iframe.onload = this.checkFlags(iframe);
|
||||
|
||||
// set sandbox attribute
|
||||
if (this.attr === null) {
|
||||
iframe.removeAttribute('sandbox');
|
||||
} else {
|
||||
iframe.sandbox = this.attr;
|
||||
}
|
||||
|
||||
// set query string
|
||||
var src = 'http://mochi.test:8888/tests/dom/security/test/csp/file_testserver.sjs';
|
||||
|
||||
var delim = '?';
|
||||
|
||||
if (this.csp !== null) {
|
||||
src += delim + 'csp=' + escape('sandbox ' + this.csp);
|
||||
delim = '&';
|
||||
}
|
||||
|
||||
if (this.cspRO !== null) {
|
||||
src += delim + 'cspRO=' + escape('sandbox ' + this.cspRO);
|
||||
delim = '&';
|
||||
}
|
||||
|
||||
if (this.file !== null) {
|
||||
src += delim + 'file=' + escape(this.file);
|
||||
delim = '&';
|
||||
}
|
||||
|
||||
iframe.src = src;
|
||||
iframe.width = iframe.height = 10;
|
||||
|
||||
}
|
||||
|
||||
testCases = [
|
||||
{
|
||||
desc: "Test 1: Header should not override attribute",
|
||||
sandboxAttribute: "",
|
||||
csp: "allow-forms aLLOw-POinter-lock alLOW-popups aLLOW-SAME-ORIGin ALLOW-SCRIPTS allow-top-navigation"
|
||||
},
|
||||
{
|
||||
desc: "Test 2: Attribute should not override header",
|
||||
sandboxAttribute: "sandbox allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation",
|
||||
csp: ""
|
||||
},
|
||||
{
|
||||
desc: "Test 3: Header and attribute intersect",
|
||||
sandboxAttribute: "allow-same-origin allow-scripts",
|
||||
csp: "allow-forms allow-same-origin allow-scripts"
|
||||
},
|
||||
{
|
||||
desc: "Test 4: CSP sandbox sets the right flags (pt 1)",
|
||||
csp: "alLOW-FORms ALLOW-pointer-lock allow-popups allow-same-origin allow-scripts ALLOW-TOP-NAVIGation"
|
||||
},
|
||||
{
|
||||
desc: "Test 5: CSP sandbox sets the right flags (pt 2)",
|
||||
csp: "allow-same-origin allow-TOP-navigation"
|
||||
},
|
||||
{
|
||||
desc: "Test 6: CSP sandbox sets the right flags (pt 3)",
|
||||
csp: "allow-FORMS ALLOW-scripts"
|
||||
},
|
||||
{
|
||||
desc: "Test 7: CSP sandbox sets the right flags (pt 4)",
|
||||
csp: ""
|
||||
},
|
||||
{
|
||||
desc: "Test 8: CSP sandbox sets the right flags (pt 5)",
|
||||
csp: null
|
||||
},
|
||||
{
|
||||
desc: "Test 9: Read-only header should not override attribute",
|
||||
sandboxAttribute: "",
|
||||
cspReportOnly: "allow-forms ALLOW-pointer-lock allow-POPUPS allow-same-origin ALLOW-scripts allow-top-NAVIGATION"
|
||||
},
|
||||
{
|
||||
desc: "Test 10: Read-only header should not override CSP header",
|
||||
csp: "allow-forms allow-scripts",
|
||||
cspReportOnly: "allow-forms aLlOw-PoInTeR-lOcK aLLow-pOPupS aLLoW-SaME-oRIgIN alLow-scripts allow-tOp-navigation"
|
||||
},
|
||||
{
|
||||
desc: "Test 11: Read-only header should not override attribute or CSP header",
|
||||
sandboxAttribute: "allow-same-origin allow-scripts",
|
||||
csp: "allow-forms allow-same-origin allow-scripts",
|
||||
cspReportOnly: "allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation"
|
||||
},
|
||||
{
|
||||
desc: "Test 12: CSP sandbox not affected by document.write()",
|
||||
csp: "allow-scripts",
|
||||
file: 'tests/dom/security/test/csp/file_iframe_sandbox_document_write.html'
|
||||
},
|
||||
].map(function(t) { return (new CSPFlagsTest(t.desc,t)); });
|
||||
|
||||
|
||||
var testCaseIndex = 0;
|
||||
|
||||
// Track ok messages from iframes
|
||||
var childMessages = 0;
|
||||
var totalChildMessages = 1;
|
||||
|
||||
|
||||
// Check to see if we ran all the tests and received all messges
|
||||
// from child iframes. If so, finish.
|
||||
function tryFinish() {
|
||||
if (testCaseIndex === testCases.length && childMessages === totalChildMessages){
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
|
||||
tryFinish();
|
||||
|
||||
if (testCaseIndex < testCases.length) {
|
||||
testCases[testCaseIndex].runTest();
|
||||
testCaseIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
function receiveMessage(event) {
|
||||
ok(event.data.ok, event.data.desc);
|
||||
childMessages++;
|
||||
tryFinish();
|
||||
}
|
||||
|
||||
window.addEventListener("message", receiveMessage, false);
|
||||
|
||||
addLoadEvent(runNextTest);
|
||||
</script>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=671389">Mozilla Bug 671389</a> - Implement CSP sandbox directive
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,80 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=671389
|
||||
Bug 671389 - Implement CSP sandbox directive
|
||||
|
||||
Tests CSP sandbox attribute on top-level page.
|
||||
|
||||
Minimal flags: allow-same-origin allow-scripts:
|
||||
Since we need to load the SimpleTest files, we have to set the
|
||||
allow-same-origin flag. Additionally, we set the allow-scripts flag
|
||||
since we need JS to check the flags.
|
||||
|
||||
Though not necessary, for this test we also set the allow-forms flag.
|
||||
We may later wish to extend the testing suite with sandbox_csp_top_*
|
||||
tests that set different permutations of the flags.
|
||||
|
||||
CSP header: Content-Security-Policy: sandbox allow-forms allow-scripts allow-same-origin
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests for Bug 671389</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Check if two sandbox flags are the same.
|
||||
// getSandboxFlags returns a list of sandbox flags (if any) or
|
||||
// null if the flag is not set.
|
||||
// This function checks if two flags are the same, i.e., they're
|
||||
// either not set or have the same flags.
|
||||
function eqFlags(a, b) {
|
||||
if (a === null && b === null) { return true; }
|
||||
if (a === null || b === null) { return false; }
|
||||
if (a.length !== b.length) { return false; }
|
||||
var a_sorted = a.sort();
|
||||
var b_sorted = b.sort();
|
||||
for (var i in a_sorted) {
|
||||
if (a_sorted[i] !== b_sorted[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the sandbox flags of document doc.
|
||||
// If the flag is not set sandboxFlagsAsString returns null,
|
||||
// this function also returns null.
|
||||
// If the flag is set it may have some flags; in this case
|
||||
// this function returns the (potentially empty) list of flags.
|
||||
function getSandboxFlags(doc) {
|
||||
var flags = doc.sandboxFlagsAsString;
|
||||
if (flags === null) { return null; }
|
||||
return flags? flags.split(" "):[];
|
||||
}
|
||||
|
||||
function checkFlags(expected) {
|
||||
try {
|
||||
var flags = getSandboxFlags(SpecialPowers.wrap(document));
|
||||
ok(eqFlags(flags, expected), name + ' expected: "' + expected + '", got: "' + flags + '"');
|
||||
} catch (e) {
|
||||
ok(false, name + ' expected "' + expected + ', but failed with ' + e);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<body onLoad='checkFlags(["allow-forms", "allow-scripts", "allow-same-origin"]);'>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=671389">Mozilla Bug 671389</a> - Implement CSP sandbox directive
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
I am a top-level page sandboxed with "allow-scripts allow-forms
|
||||
allow-same-origin".
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
Content-Security-Policy: sAnDbOx aLLow-FOrms aLlOw-ScRiPtS ALLOW-same-origin
|
|
@ -67,7 +67,7 @@ var tests = [
|
|||
},
|
||||
{
|
||||
policy1: "default-src 'unsafe-inline' 'sha256-uJXAPKP5NZxnVMZMUkDofh6a9P3UMRc1CRTevVPS/rI=' 'nonce-FooNonce' ",
|
||||
policy2: "sandbox allow-forms",
|
||||
policy2: "sandbox allow-scripts allow-same-origin",
|
||||
description: "unsafe-inline should *not* be ignored within default-src even if hash or nonce is specified",
|
||||
file: "file_ignore_unsafe_inline.html",
|
||||
result: "abcd",
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tests for bugs 886164 and 671389</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
</div>
|
||||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var testCases = [
|
||||
{
|
||||
// Test 1: don't load image from non-same-origin; allow loading
|
||||
// images from same-same origin
|
||||
sandboxAttribute: "allow-same-origin",
|
||||
csp: "default-src 'self'",
|
||||
file: "file_sandbox_1.html",
|
||||
results: { img1a_good: -1, img1_bad: -1 }
|
||||
// fails if scripts execute
|
||||
},
|
||||
{
|
||||
// Test 2: don't load image from non-same-origin; allow loading
|
||||
// images from same-same origin, even without allow-same-origin
|
||||
// flag
|
||||
sandboxAttribute: "",
|
||||
csp: "default-src 'self'",
|
||||
file: "file_sandbox_2.html",
|
||||
results: { img2_bad: -1, img2a_good: -1 }
|
||||
// fails if scripts execute
|
||||
},
|
||||
{
|
||||
// Test 3: disallow loading images from any host, even with
|
||||
// allow-same-origin flag set
|
||||
sandboxAttribute: "allow-same-origin",
|
||||
csp: "default-src 'none'",
|
||||
file: "file_sandbox_3.html",
|
||||
results: { img3_bad: -1, img3a_bad: -1 },
|
||||
// fails if scripts execute
|
||||
},
|
||||
{
|
||||
// Test 4: disallow loading images from any host
|
||||
sandboxAttribute: "",
|
||||
csp: "default-src 'none'",
|
||||
file: "file_sandbox_4.html",
|
||||
results: { img4_bad: -1, img4a_bad: -1 }
|
||||
// fails if scripts execute
|
||||
},
|
||||
{
|
||||
// Test 5: disallow loading images or scripts, allow inline scripts
|
||||
sandboxAttribute: "allow-scripts",
|
||||
csp: "default-src 'none'; script-src 'unsafe-inline';",
|
||||
file: "file_sandbox_5.html",
|
||||
results: { img5_bad: -1, img5a_bad: -1, script5_bad: -1, script5a_bad: -1 },
|
||||
nrOKmessages: 2 // sends 2 ok message
|
||||
// fails if scripts execute
|
||||
},
|
||||
{
|
||||
// Test 6: disallow non-same-origin images, allow inline and same origin scripts
|
||||
sandboxAttribute: "allow-same-origin allow-scripts",
|
||||
csp: "default-src 'self' 'unsafe-inline';",
|
||||
file: "file_sandbox_6.html",
|
||||
results: { img6_bad: -1, script6_bad: -1 },
|
||||
nrOKmessages: 4 // sends 4 ok message
|
||||
// fails if forms are not disallowed
|
||||
},
|
||||
{
|
||||
// Test 7: same as Test 1
|
||||
csp: "default-src 'self'; sandbox allow-same-origin",
|
||||
file: "file_sandbox_7.html",
|
||||
results: { img7a_good: -1, img7_bad: -1 }
|
||||
},
|
||||
{
|
||||
// Test 8: same as Test 2
|
||||
csp: "sandbox allow-same-origin; default-src 'self'",
|
||||
file: "file_sandbox_8.html",
|
||||
results: { img8_bad: -1, img8a_good: -1 }
|
||||
},
|
||||
{
|
||||
// Test 9: same as Test 3
|
||||
csp: "default-src 'none'; sandbox allow-same-origin",
|
||||
file: "file_sandbox_9.html",
|
||||
results: { img9_bad: -1, img9a_bad: -1 }
|
||||
},
|
||||
{
|
||||
// Test 10: same as Test 4
|
||||
csp: "default-src 'none'; sandbox allow-same-origin",
|
||||
file: "file_sandbox_10.html",
|
||||
results: { img10_bad: -1, img10a_bad: -1 }
|
||||
},
|
||||
{
|
||||
// Test 11: same as Test 5
|
||||
csp: "default-src 'none'; script-src 'unsafe-inline'; sandbox allow-scripts allow-same-origin",
|
||||
file: "file_sandbox_11.html",
|
||||
results: { img11_bad: -1, img11a_bad: -1, script11_bad: -1, script11a_bad: -1 },
|
||||
nrOKmessages: 2 // sends 2 ok message
|
||||
},
|
||||
{
|
||||
// Test 12: same as Test 6
|
||||
csp: "sandbox allow-same-origin allow-scripts; default-src 'self' 'unsafe-inline';",
|
||||
file: "file_sandbox_12.html",
|
||||
results: { img12_bad: -1, script12_bad: -1 },
|
||||
nrOKmessages: 4 // sends 4 ok message
|
||||
},
|
||||
];
|
||||
|
||||
// a postMessage handler that is used by sandboxed iframes without
|
||||
// 'allow-same-origin' to communicate pass/fail back to this main page.
|
||||
// it expects to be called with an object like:
|
||||
// { ok: true/false,
|
||||
// desc: <description of the test> which it then forwards to ok() }
|
||||
window.addEventListener("message", receiveMessage, false);
|
||||
|
||||
function receiveMessage(event) {
|
||||
ok_wrapper(event.data.ok, event.data.desc);
|
||||
}
|
||||
|
||||
var completedTests = 0;
|
||||
var passedTests = 0;
|
||||
|
||||
var totalTests = (function() {
|
||||
var nrCSPloadTests = 0;
|
||||
for(var i = 0; i < testCases.length; i++) {
|
||||
nrCSPloadTests += Object.keys(testCases[i].results).length;
|
||||
if (testCases[i].nrOKmessages) {
|
||||
// + number of expected postMessages from iframe
|
||||
nrCSPloadTests += testCases[i].nrOKmessages;
|
||||
}
|
||||
}
|
||||
return nrCSPloadTests;
|
||||
})();
|
||||
|
||||
function ok_wrapper(result, desc) {
|
||||
ok(result, desc);
|
||||
|
||||
completedTests++;
|
||||
|
||||
if (result) {
|
||||
passedTests++;
|
||||
}
|
||||
|
||||
if (completedTests === totalTests) {
|
||||
window.examiner.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
// Set the iframe src and sandbox attribute
|
||||
function runTest(test) {
|
||||
var iframe = document.createElement('iframe');
|
||||
|
||||
document.getElementById('content').appendChild(iframe);
|
||||
|
||||
// set sandbox attribute
|
||||
if (test.sandboxAttribute !== undefined) {
|
||||
iframe.sandbox = test.sandboxAttribute;
|
||||
}
|
||||
|
||||
// set query string
|
||||
var src = 'file_testserver.sjs';
|
||||
// path where the files are
|
||||
var path = '/tests/dom/security/test/csp/';
|
||||
|
||||
src += '?file=' + escape(path+test.file);
|
||||
|
||||
if (test.csp !== undefined) {
|
||||
src += '&csp=' + escape(test.csp);
|
||||
}
|
||||
|
||||
iframe.src = src;
|
||||
iframe.width = iframe.height = 10;
|
||||
}
|
||||
|
||||
// Examiner related
|
||||
|
||||
// This is used to watch the blocked data bounce off CSP and allowed data
|
||||
// get sent out to the wire.
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
SpecialPowers.addObserver(this, "specialpowers-http-notify-request", false);
|
||||
}
|
||||
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
var testpat = new RegExp("testid=([a-z0-9_]+)");
|
||||
|
||||
//_good things better be allowed!
|
||||
//_bad things better be stopped!
|
||||
|
||||
if (topic === "specialpowers-http-notify-request") {
|
||||
//these things were allowed by CSP
|
||||
var uri = data;
|
||||
if (!testpat.test(uri)) return;
|
||||
var testid = testpat.exec(uri)[1];
|
||||
|
||||
if(/_good/.test(testid)) {
|
||||
ok_wrapper(true, uri + " is allowed by csp");
|
||||
} else {
|
||||
ok_wrapper(false, uri + " should not be allowed by csp");
|
||||
}
|
||||
}
|
||||
|
||||
if(topic === "csp-on-violate-policy") {
|
||||
//these were blocked... record that they were blocked
|
||||
var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
|
||||
if (!testpat.test(asciiSpec)) return;
|
||||
var testid = testpat.exec(asciiSpec)[1];
|
||||
if(/_bad/.test(testid)) {
|
||||
ok_wrapper(true, asciiSpec + " was blocked by \"" + data + "\"");
|
||||
} else {
|
||||
ok_wrapper(false, asciiSpec + " should have been blocked by \"" + data + "\"");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// must eventually call this to remove the listener,
|
||||
// or mochitests might get borked.
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
|
||||
}
|
||||
}
|
||||
|
||||
window.examiner = new examiner();
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
(function() { // Run tests:
|
||||
for(var i = 0; i < testCases.length; i++) {
|
||||
runTest(testCases[i]);
|
||||
}
|
||||
})();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -93,7 +93,7 @@ function run_next_test() {
|
|||
return;
|
||||
}
|
||||
channel = setupChannel(curTest.contentType);
|
||||
channel.asyncOpen(new ChannelListener(), null);
|
||||
channel.asyncOpen2(new ChannelListener());
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
|
|
|
@ -5,6 +5,7 @@ support-files =
|
|||
[test_bug900724.html]
|
||||
[test_bug1017896.html]
|
||||
[test_bug1176757.html]
|
||||
[test_bug1276240.html]
|
||||
[test_content_element.html]
|
||||
[test_custom_element_adopt_callbacks.html]
|
||||
[test_custom_element_callback_innerhtml.html]
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1276240</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1276240">Mozilla Bug 1276240</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 1276240 **/
|
||||
// when passing null for the second argument, it would be ignored
|
||||
|
||||
function test() {
|
||||
var e = document.createElement("p", null);
|
||||
is(e.getAttribute("is"), null);
|
||||
|
||||
e = document.createElement("p", undefined);
|
||||
is(e.getAttribute("is"), null);
|
||||
|
||||
e = document.createElementNS("http://www.w3.org/1999/xhtml", "p", null);
|
||||
is(e.getAttribute("is"), null);
|
||||
|
||||
e = document.createElementNS("http://www.w3.org/1999/xhtml", "p", undefined);
|
||||
is(e.getAttribute("is"), null);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
test();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
// test with webcomponents enabled
|
||||
test();
|
||||
|
||||
// test with webcomponents disabled
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ 'set': [["dom.webcomponents.enabled", false]]}, runTest);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче