mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
commit
b4e6d275b7
@ -116,16 +116,9 @@ devtools/server/tests/browser/**
|
||||
!devtools/server/tests/browser/browser_webextension_inspected_window.js
|
||||
devtools/server/tests/mochitest/**
|
||||
devtools/server/tests/unit/**
|
||||
devtools/shared/apps/**
|
||||
devtools/shared/gcli/**
|
||||
!devtools/shared/gcli/templater.js
|
||||
devtools/shared/heapsnapshot/**
|
||||
devtools/shared/transport/**
|
||||
!devtools/shared/transport/transport.js
|
||||
!devtools/shared/transport/websocket-transport.js
|
||||
devtools/shared/transport/tests/unit/**
|
||||
devtools/shared/webconsole/test/**
|
||||
devtools/shared/worker/**
|
||||
!devtools/shared/worker/worker.js
|
||||
|
||||
# Ignore devtools pre-processed files
|
||||
devtools/client/framework/toolbox-process-window.js
|
||||
@ -136,7 +129,7 @@ devtools/client/preferences/**
|
||||
# Ignore devtools third-party libs
|
||||
devtools/shared/jsbeautify/*
|
||||
devtools/shared/acorn/*
|
||||
devtools/client/sourceeditor/tern/*
|
||||
devtools/shared/gcli/source/*
|
||||
devtools/shared/node-properties/*
|
||||
devtools/shared/pretty-fast/*
|
||||
devtools/shared/sourcemap/*
|
||||
@ -147,6 +140,7 @@ devtools/client/shared/demangle.js
|
||||
devtools/client/shared/vendor/*
|
||||
devtools/client/sourceeditor/codemirror/*.js
|
||||
devtools/client/sourceeditor/codemirror/**/*.js
|
||||
devtools/client/sourceeditor/tern/*
|
||||
devtools/client/sourceeditor/test/cm_mode_ruby.js
|
||||
devtools/client/sourceeditor/test/codemirror/*
|
||||
devtools/client/inspector/markup/test/lib_*
|
||||
|
@ -13,6 +13,10 @@
|
||||
"type": "string",
|
||||
"pattern": "^\\s*(Alt|Ctrl|Command|MacCtrl)\\s*\\+\\s*(Shift\\s*\\+\\s*)?([A-Z0-9]|Comma|Period|Home|End|PageUp|PageDown|Space|Insert|Delete|Up|Down|Left|Right)\\s*$"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^\\s*((Alt|Ctrl|Command|MacCtrl)\\s*\\+\\s*)?(Shift\\s*\\+\\s*)?(F[1-9]|F1[0-2])\\s*$"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^(MediaNextTrack|MediaPlayPause|MediaPrevTrack|MediaStop)$"
|
||||
|
@ -98,6 +98,25 @@ add_task(function* test_user_defined_commands() {
|
||||
shiftKey: true,
|
||||
},
|
||||
},
|
||||
// Function keys
|
||||
{
|
||||
name: "function-keys-Alt+Shift+F3",
|
||||
shortcut: "Alt+Shift+F3",
|
||||
key: "VK_F3",
|
||||
modifiers: {
|
||||
altKey: true,
|
||||
shiftKey: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "function-keys-F2",
|
||||
shortcut: "F2",
|
||||
key: "VK_F2",
|
||||
modifiers: {
|
||||
altKey: false,
|
||||
shiftKey: false,
|
||||
},
|
||||
},
|
||||
// Misc Shortcuts
|
||||
{
|
||||
name: "valid-command-with-unrecognized-property-name",
|
||||
|
@ -15,7 +15,8 @@ add_task(function* test_manifest_commands() {
|
||||
|
||||
let expectedError = (
|
||||
String.raw`commands.toggle-feature.suggested_key.default: Value must either: ` +
|
||||
String.raw`match the pattern /^\s*(Alt|Ctrl|Command|MacCtrl)\s*\+\s*(Shift\s*\+\s*)?([A-Z0-9]|Comma|Period|Home|End|PageUp|PageDown|Space|Insert|Delete|Up|Down|Left|Right)\s*$/, or ` +
|
||||
String.raw`match the pattern /^\s*(Alt|Ctrl|Command|MacCtrl)\s*\+\s*(Shift\s*\+\s*)?([A-Z0-9]|Comma|Period|Home|End|PageUp|PageDown|Space|Insert|Delete|Up|Down|Left|Right)\s*$/, ` +
|
||||
String.raw`match the pattern /^\s*((Alt|Ctrl|Command|MacCtrl)\s*\+\s*)?(Shift\s*\+\s*)?(F[1-9]|F1[0-2])\s*$/, or ` +
|
||||
String.raw`match the pattern /^(MediaNextTrack|MediaPlayPause|MediaPrevTrack|MediaStop)$/`
|
||||
);
|
||||
|
||||
|
@ -264,7 +264,7 @@ FeedConverter.prototype = {
|
||||
}
|
||||
|
||||
chromeChannel.loadGroup = this._request.loadGroup;
|
||||
chromeChannel.asyncOpen(this._listener, null);
|
||||
chromeChannel.asyncOpen2(this._listener);
|
||||
} finally {
|
||||
this._releaseHandles();
|
||||
}
|
||||
|
@ -67,11 +67,10 @@ def do_import_clang_tidy(source_dir):
|
||||
do_import(clang_plugin_path, clang_tidy_path)
|
||||
|
||||
|
||||
def build_package(package_build_dir, run_cmake, cmake_args):
|
||||
def build_package(package_build_dir, cmake_args):
|
||||
if not os.path.exists(package_build_dir):
|
||||
os.mkdir(package_build_dir)
|
||||
if run_cmake:
|
||||
run_in(package_build_dir, ["cmake"] + cmake_args)
|
||||
run_in(package_build_dir, ["cmake"] + cmake_args)
|
||||
run_in(package_build_dir, ["ninja", "install"])
|
||||
|
||||
|
||||
@ -158,6 +157,7 @@ def svn_co(source_dir, url, directory, revision):
|
||||
|
||||
def svn_update(directory, revision):
|
||||
run_in(directory, ["svn", "update", "-q", "-r", revision])
|
||||
run_in(directory, ["svn", "revert", "-q", "-R", revision])
|
||||
|
||||
|
||||
def get_platform():
|
||||
@ -198,9 +198,11 @@ def build_one_stage(cc, cxx, src_dir, stage_dir, build_libcxx,
|
||||
build_dir = stage_dir + "/build"
|
||||
inst_dir = stage_dir + "/clang"
|
||||
|
||||
run_cmake = True
|
||||
if os.path.exists(build_dir + "/build.ninja"):
|
||||
run_cmake = False
|
||||
# If CMake has already been run, it may have been run with different
|
||||
# arguments, so we need to re-run it. Make sure the cached copy of the
|
||||
# previous CMake run is cleared before running it again.
|
||||
if os.path.exists(build_dir + "/CMakeCache.txt"):
|
||||
os.path.remove(build_dir + "/CMakeCache.txt")
|
||||
|
||||
# cmake doesn't deal well with backslashes in paths.
|
||||
def slashify_path(path):
|
||||
@ -222,7 +224,7 @@ def build_one_stage(cc, cxx, src_dir, stage_dir, build_libcxx,
|
||||
src_dir];
|
||||
if is_windows():
|
||||
cmake_args.insert(-1, "-DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON")
|
||||
build_package(build_dir, run_cmake, cmake_args)
|
||||
build_package(build_dir, cmake_args)
|
||||
|
||||
if is_linux():
|
||||
install_libgcc(gcc_dir, inst_dir)
|
||||
@ -350,25 +352,34 @@ if __name__ == "__main__":
|
||||
|
||||
if not os.path.exists(source_dir):
|
||||
os.makedirs(source_dir)
|
||||
svn_co(source_dir, llvm_repo, llvm_source_dir, llvm_revision)
|
||||
svn_co(source_dir, clang_repo, clang_source_dir, llvm_revision)
|
||||
svn_co(source_dir, compiler_repo, compiler_rt_source_dir, llvm_revision)
|
||||
svn_co(source_dir, libcxx_repo, libcxx_source_dir, llvm_revision)
|
||||
if libcxxabi_repo:
|
||||
svn_co(source_dir, libcxxabi_repo, libcxxabi_source_dir, llvm_revision)
|
||||
if extra_repo:
|
||||
svn_co(source_dir, extra_repo, extra_source_dir, llvm_revision)
|
||||
for p in config.get("patches", {}).get(get_platform(), []):
|
||||
patch(p, source_dir)
|
||||
else:
|
||||
if os.path.exists(llvm_source_dir):
|
||||
svn_update(llvm_source_dir, llvm_revision)
|
||||
else:
|
||||
svn_co(source_dir, llvm_repo, llvm_source_dir, llvm_revision)
|
||||
if os.path.exists(clang_source_dir):
|
||||
svn_update(clang_source_dir, llvm_revision)
|
||||
else:
|
||||
svn_co(source_dir, clang_repo, clang_source_dir, llvm_revision)
|
||||
if os.path.exists(compiler_rt_source_dir):
|
||||
svn_update(compiler_rt_source_dir, llvm_revision)
|
||||
else:
|
||||
svn_co(source_dir, compiler_repo, compiler_rt_source_dir, llvm_revision)
|
||||
if os.path.exists(libcxx_source_dir):
|
||||
svn_update(libcxx_source_dir, llvm_revision)
|
||||
if libcxxabi_repo:
|
||||
else:
|
||||
svn_co(source_dir, libcxx_repo, libcxx_source_dir, llvm_revision)
|
||||
if libcxxabi_repo:
|
||||
if os.path.exists(libcxxabi_source_dir):
|
||||
svn_update(libcxxabi_source_dir, llvm_revision)
|
||||
if extra_repo:
|
||||
else:
|
||||
svn_co(source_dir, libcxxabi_repo, libcxxabi_source_dir, llvm_revision)
|
||||
if extra_repo:
|
||||
if os.path.exists(extra_source_dir):
|
||||
svn_update(extra_source_dir, llvm_revision)
|
||||
else:
|
||||
svn_co(source_dir, extra_repo, extra_source_dir, llvm_revision)
|
||||
for p in config.get("patches", {}).get(get_platform(), []):
|
||||
patch(p, source_dir)
|
||||
|
||||
symlinks = [(source_dir + "/clang",
|
||||
llvm_source_dir + "/tools/clang"),
|
||||
|
16
build/build-clang/clang-tidy-win32.json
Normal file
16
build/build-clang/clang-tidy-win32.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"llvm_revision": "290055",
|
||||
"stages": "1",
|
||||
"build_libcxx": false,
|
||||
"build_type": "Release",
|
||||
"assertions": false,
|
||||
"import_clang_tidy": true,
|
||||
"llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk",
|
||||
"clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
|
||||
"extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/trunk",
|
||||
"compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk",
|
||||
"libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
|
||||
"python_path": "c:/mozilla-build/python/python.exe",
|
||||
"cc": "cl.exe",
|
||||
"cxx": "cl.exe"
|
||||
}
|
16
build/build-clang/clang-tidy-win64.json
Normal file
16
build/build-clang/clang-tidy-win64.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"llvm_revision": "290055",
|
||||
"stages": "1",
|
||||
"build_libcxx": false,
|
||||
"build_type": "Release",
|
||||
"assertions": false,
|
||||
"import_clang_tidy": true,
|
||||
"llvm_repo": "https://llvm.org/svn/llvm-project/llvm/trunk",
|
||||
"clang_repo": "https://llvm.org/svn/llvm-project/cfe/trunk",
|
||||
"extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/trunk",
|
||||
"compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/trunk",
|
||||
"libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/trunk",
|
||||
"python_path": "c:/mozilla-build/python/python.exe",
|
||||
"cc": "cl.exe",
|
||||
"cxx": "cl.exe"
|
||||
}
|
@ -163,6 +163,7 @@ class ClassInfoData
|
||||
public:
|
||||
ClassInfoData(nsIClassInfo *aClassInfo, const char *aName)
|
||||
: mClassInfo(aClassInfo),
|
||||
mFlags(0),
|
||||
mName(const_cast<char *>(aName)),
|
||||
mDidGetFlags(false),
|
||||
mMustFreeName(false)
|
||||
|
@ -273,7 +273,7 @@ module.exports = {
|
||||
// Disallow declaring the same variable more than once (we use let anyway).
|
||||
"no-redeclare": "error",
|
||||
// Disallow multiple spaces in a regular expression literal.
|
||||
"no-regex-spaces": "error",
|
||||
"no-regex-spaces": "off",
|
||||
// Allow reserved words being used as object literal keys.
|
||||
"no-reserved-keys": "off",
|
||||
// Don't restrict usage of specified node modules (not a node environment).
|
||||
|
@ -37,7 +37,6 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsJSInspector)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsJSInspector)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSInspector)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSInspector)
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
Components.utils.import("resource://devtools/shared/event-emitter.js");
|
||||
|
||||
/* exported EXPORTED_SYMBOLS */
|
||||
|
||||
const EXPORTED_SYMBOLS = ["Devices"];
|
||||
|
||||
var addonInstalled = false;
|
||||
|
@ -37,8 +37,7 @@ function addDirToZip(writer, dir, basePath) {
|
||||
|
||||
if (file.isHidden() ||
|
||||
file.isSpecial() ||
|
||||
file.equals(writer.file))
|
||||
{
|
||||
file.equals(writer.file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -62,12 +61,15 @@ function addDirToZip(writer, dir, basePath) {
|
||||
*/
|
||||
function getResultText(code) {
|
||||
let regexp =
|
||||
/^\[Exception... "(.*)" nsresult: "0x[0-9a-fA-F]* \((.*)\)" location: ".*" data: .*\]$/;
|
||||
let ex = Cc["@mozilla.org/js/xpc/Exception;1"].
|
||||
createInstance(Ci.nsIXPCException);
|
||||
/^\[Exception... "(.*)" nsresult: "0x[0-9a-fA-F]* \((.*)\)" location: ".*" data: .*\]$/; // eslint-disable-line
|
||||
let ex = Cc["@mozilla.org/js/xpc/Exception;1"]
|
||||
.createInstance(Ci.nsIXPCException);
|
||||
ex.initialize(null, code, null, null, null, null);
|
||||
let [, message, name] = regexp.exec(ex.toString());
|
||||
return { name: name, message: message };
|
||||
return {
|
||||
name,
|
||||
message
|
||||
};
|
||||
}
|
||||
|
||||
function zipDirectory(zipFile, dirToArchive) {
|
||||
@ -75,7 +77,7 @@ function zipDirectory(zipFile, dirToArchive) {
|
||||
let writer = Cc["@mozilla.org/zipwriter;1"].createInstance(Ci.nsIZipWriter);
|
||||
writer.open(zipFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
|
||||
|
||||
this.addDirToZip(writer, dirToArchive, "");
|
||||
addDirToZip(writer, dirToArchive, "");
|
||||
|
||||
writer.processQueue({
|
||||
onStartRequest: function onStartRequest(request, context) {},
|
||||
@ -83,8 +85,7 @@ function zipDirectory(zipFile, dirToArchive) {
|
||||
if (status == Cr.NS_OK) {
|
||||
writer.close();
|
||||
deferred.resolve(zipFile);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let { name, message } = getResultText(status);
|
||||
deferred.reject(name + ": " + message);
|
||||
}
|
||||
@ -97,9 +98,8 @@ function zipDirectory(zipFile, dirToArchive) {
|
||||
function uploadPackage(client, webappsActor, packageFile, progressCallback) {
|
||||
if (client.traits.bulk) {
|
||||
return uploadPackageBulk(client, webappsActor, packageFile, progressCallback);
|
||||
} else {
|
||||
return uploadPackageJSON(client, webappsActor, packageFile, progressCallback);
|
||||
}
|
||||
return uploadPackageJSON(client, webappsActor, packageFile, progressCallback);
|
||||
}
|
||||
|
||||
function uploadPackageJSON(client, webappsActor, packageFile, progressCallback) {
|
||||
@ -125,48 +125,45 @@ function uploadPackageJSON(client, webappsActor, packageFile, progressCallback)
|
||||
|
||||
function openFile(actor) {
|
||||
let openedFile;
|
||||
OS.File.open(packageFile.path)
|
||||
.then(file => {
|
||||
openedFile = file;
|
||||
return openedFile.stat();
|
||||
})
|
||||
.then(fileInfo => {
|
||||
fileSize = fileInfo.size;
|
||||
emitProgress();
|
||||
uploadChunk(actor, openedFile);
|
||||
});
|
||||
OS.File.open(packageFile.path).then(file => {
|
||||
openedFile = file;
|
||||
return openedFile.stat();
|
||||
}).then(fileInfo => {
|
||||
fileSize = fileInfo.size;
|
||||
emitProgress();
|
||||
uploadChunk(actor, openedFile);
|
||||
});
|
||||
}
|
||||
function uploadChunk(actor, file) {
|
||||
file.read(CHUNK_SIZE)
|
||||
.then(function (bytes) {
|
||||
bytesRead += bytes.length;
|
||||
emitProgress();
|
||||
// To work around the fact that JSON.stringify translates the typed
|
||||
// array to object, we are encoding the typed array here into a string
|
||||
let chunk = String.fromCharCode.apply(null, bytes);
|
||||
file.read(CHUNK_SIZE).then(function (bytes) {
|
||||
bytesRead += bytes.length;
|
||||
emitProgress();
|
||||
// To work around the fact that JSON.stringify translates the typed
|
||||
// array to object, we are encoding the typed array here into a string
|
||||
let chunk = String.fromCharCode.apply(null, bytes);
|
||||
|
||||
let request = {
|
||||
to: actor,
|
||||
type: "chunk",
|
||||
chunk: chunk
|
||||
};
|
||||
client.request(request, (res) => {
|
||||
if (bytes.length == CHUNK_SIZE) {
|
||||
uploadChunk(actor, file);
|
||||
} else {
|
||||
file.close().then(function () {
|
||||
endsUpload(actor);
|
||||
});
|
||||
}
|
||||
let chunkRequest = {
|
||||
to: actor,
|
||||
type: "chunk",
|
||||
chunk,
|
||||
};
|
||||
client.request(chunkRequest, (res) => {
|
||||
if (bytes.length == CHUNK_SIZE) {
|
||||
uploadChunk(actor, file);
|
||||
} else {
|
||||
file.close().then(function () {
|
||||
endsUpload(actor);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
function endsUpload(actor) {
|
||||
let request = {
|
||||
let doneRequest = {
|
||||
to: actor,
|
||||
type: "done"
|
||||
};
|
||||
client.request(request, (res) => {
|
||||
client.request(doneRequest, (res) => {
|
||||
deferred.resolve(actor);
|
||||
});
|
||||
}
|
||||
@ -190,13 +187,13 @@ function uploadPackageBulk(client, webappsActor, packageFile, progressCallback)
|
||||
let fileSize = packageFile.fileSize;
|
||||
console.log("File size: " + fileSize);
|
||||
|
||||
let request = client.startBulkRequest({
|
||||
let streamRequest = client.startBulkRequest({
|
||||
actor: actor,
|
||||
type: "stream",
|
||||
length: fileSize
|
||||
});
|
||||
|
||||
request.on("bulk-send-ready", ({copyFrom}) => {
|
||||
streamRequest.on("bulk-send-ready", ({copyFrom}) => {
|
||||
NetUtil.asyncFetch({
|
||||
uri: NetUtil.newURI(packageFile),
|
||||
loadUsingSystemPrincipal: true
|
||||
@ -245,36 +242,37 @@ function installPackaged(client, webappsActor, packagePath, appId, progressCallb
|
||||
packagePromise = promise.resolve(file);
|
||||
}
|
||||
packagePromise.then((zipFile) => {
|
||||
uploadPackage(client, webappsActor, zipFile, progressCallback)
|
||||
.then((fileActor) => {
|
||||
let request = {
|
||||
to: webappsActor,
|
||||
type: "install",
|
||||
appId: appId,
|
||||
upload: fileActor
|
||||
};
|
||||
client.request(request, (res) => {
|
||||
// If the install method immediatly fails,
|
||||
// reject immediatly the installPackaged promise.
|
||||
// Otherwise, wait for webappsEvent for completion
|
||||
if (res.error) {
|
||||
deferred.reject(res);
|
||||
}
|
||||
if ("error" in res)
|
||||
deferred.reject({error: res.error, message: res.message});
|
||||
else
|
||||
deferred.resolve({appId: res.appId});
|
||||
});
|
||||
// Ensure deleting the temporary package file, but only if that a temporary
|
||||
// package created when we pass a directory as `packagePath`
|
||||
if (zipFile != file)
|
||||
zipFile.remove(false);
|
||||
// In case of success or error, ensure deleting the temporary package file
|
||||
// also created on the device, but only once install request is done
|
||||
deferred.promise.then(
|
||||
() => removeServerTemporaryFile(client, fileActor),
|
||||
() => removeServerTemporaryFile(client, fileActor));
|
||||
});
|
||||
uploadPackage(client, webappsActor, zipFile, progressCallback).then((fileActor) => {
|
||||
let request = {
|
||||
to: webappsActor,
|
||||
type: "install",
|
||||
appId: appId,
|
||||
upload: fileActor
|
||||
};
|
||||
client.request(request, (res) => {
|
||||
// If the install method immediatly fails,
|
||||
// reject immediatly the installPackaged promise.
|
||||
// Otherwise, wait for webappsEvent for completion
|
||||
if (res.error) {
|
||||
deferred.reject(res);
|
||||
}
|
||||
if ("error" in res) {
|
||||
deferred.reject({error: res.error, message: res.message});
|
||||
} else {
|
||||
deferred.resolve({appId: res.appId});
|
||||
}
|
||||
});
|
||||
// Ensure deleting the temporary package file, but only if that a temporary
|
||||
// package created when we pass a directory as `packagePath`
|
||||
if (zipFile != file) {
|
||||
zipFile.remove(false);
|
||||
}
|
||||
// In case of success or error, ensure deleting the temporary package file
|
||||
// also created on the device, but only once install request is done
|
||||
deferred.promise.then(
|
||||
() => removeServerTemporaryFile(client, fileActor),
|
||||
() => removeServerTemporaryFile(client, fileActor));
|
||||
});
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
@ -293,10 +291,11 @@ function installHosted(client, webappsActor, appId, metadata, manifest) {
|
||||
if (res.error) {
|
||||
deferred.reject(res);
|
||||
}
|
||||
if ("error" in res)
|
||||
if ("error" in res) {
|
||||
deferred.reject({error: res.error, message: res.message});
|
||||
else
|
||||
} else {
|
||||
deferred.resolve({appId: res.appId});
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
@ -307,8 +306,9 @@ function getTargetForApp(client, webappsActor, manifestURL) {
|
||||
// of the same app in order to show only one toolbox per app and
|
||||
// avoid re-creating lot of objects twice.
|
||||
let existingTarget = appTargets.get(manifestURL);
|
||||
if (existingTarget)
|
||||
if (existingTarget) {
|
||||
return promise.resolve(existingTarget);
|
||||
}
|
||||
|
||||
let deferred = defer();
|
||||
let request = {
|
||||
@ -343,23 +343,22 @@ function getTargetForApp(client, webappsActor, manifestURL) {
|
||||
exports.getTargetForApp = getTargetForApp;
|
||||
|
||||
function reloadApp(client, webappsActor, manifestURL) {
|
||||
return getTargetForApp(client,
|
||||
webappsActor,
|
||||
manifestURL).
|
||||
then((target) => {
|
||||
// Request the ContentActor to reload the app
|
||||
let request = {
|
||||
to: target.form.actor,
|
||||
type: "reload",
|
||||
options: {
|
||||
force: true
|
||||
},
|
||||
manifestURL: manifestURL
|
||||
};
|
||||
return client.request(request);
|
||||
}, () => {
|
||||
throw new Error("Not running");
|
||||
});
|
||||
return getTargetForApp(
|
||||
client, webappsActor, manifestURL
|
||||
).then((target) => {
|
||||
// Request the ContentActor to reload the app
|
||||
let request = {
|
||||
to: target.form.actor,
|
||||
type: "reload",
|
||||
options: {
|
||||
force: true
|
||||
},
|
||||
manifestURL,
|
||||
};
|
||||
return client.request(request);
|
||||
}, () => {
|
||||
throw new Error("Not running");
|
||||
});
|
||||
}
|
||||
exports.reloadApp = reloadApp;
|
||||
|
||||
@ -423,25 +422,26 @@ App.prototype = {
|
||||
type: "getAppActor",
|
||||
manifestURL: this.manifest.manifestURL
|
||||
};
|
||||
return this.client.request(request)
|
||||
.then(res => {
|
||||
return this._form = res.actor;
|
||||
});
|
||||
return this.client.request(request).then(res => {
|
||||
this._form = res.actor;
|
||||
return this._form;
|
||||
});
|
||||
},
|
||||
|
||||
getTarget: function () {
|
||||
if (this._target) {
|
||||
return promise.resolve(this._target);
|
||||
}
|
||||
return this.getForm().
|
||||
then((form) => getTarget(this.client, form)).
|
||||
then((target) => {
|
||||
target.on("close", () => {
|
||||
delete this._form;
|
||||
delete this._target;
|
||||
});
|
||||
return this._target = target;
|
||||
return this.getForm().then(
|
||||
(form) => getTarget(this.client, form)
|
||||
).then((target) => {
|
||||
target.on("close", () => {
|
||||
delete this._form;
|
||||
delete this._target;
|
||||
});
|
||||
this._target = target;
|
||||
return this._target;
|
||||
});
|
||||
},
|
||||
|
||||
launch: function () {
|
||||
@ -487,7 +487,6 @@ App.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* `AppActorFront` is a client for the webapps actor.
|
||||
*/
|
||||
@ -537,23 +536,21 @@ AppActorFront.prototype = {
|
||||
let app = this._apps ? this._apps.get(manifestURL) : null;
|
||||
if (app) {
|
||||
return promise.resolve(app);
|
||||
} else {
|
||||
let request = {
|
||||
to: this.actor,
|
||||
type: "getApp",
|
||||
manifestURL: manifestURL
|
||||
};
|
||||
return this.client.request(request)
|
||||
.then(res => {
|
||||
let app = new App(this.client, this.actor, res.app);
|
||||
if (this._apps) {
|
||||
this._apps.set(manifestURL, app);
|
||||
}
|
||||
return app;
|
||||
}, e => {
|
||||
console.error("Unable to retrieve app", manifestURL, e);
|
||||
});
|
||||
}
|
||||
let request = {
|
||||
to: this.actor,
|
||||
type: "getApp",
|
||||
manifestURL,
|
||||
};
|
||||
return this.client.request(request).then(res => {
|
||||
app = new App(this.client, this.actor, res.app);
|
||||
if (this._apps) {
|
||||
this._apps.set(manifestURL, app);
|
||||
}
|
||||
return app;
|
||||
}, e => {
|
||||
console.error("Unable to retrieve app", manifestURL, e);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@ -583,47 +580,42 @@ AppActorFront.prototype = {
|
||||
to: this.actor,
|
||||
type: "getAll"
|
||||
};
|
||||
return this._loadingPromise = this.client.request(request)
|
||||
.then(res => {
|
||||
delete this._loadingPromise;
|
||||
this._apps = new Map();
|
||||
for (let a of res.apps) {
|
||||
let app = new App(this.client, this.actor, a);
|
||||
this._apps.set(a.manifestURL, app);
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
// Then retrieve all running apps in order to flag them as running
|
||||
let request = {
|
||||
to: this.actor,
|
||||
type: "listRunningApps"
|
||||
};
|
||||
return this.client.request(request)
|
||||
.then(res => res.apps);
|
||||
})
|
||||
.then(apps => {
|
||||
let promises = apps.map(manifestURL => {
|
||||
// _getApp creates `App` instance and register it to AppActorFront
|
||||
return this._getApp(manifestURL)
|
||||
.then(app => {
|
||||
app.running = true;
|
||||
// Fake appOpen event for all already opened
|
||||
this._notifyListeners("appOpen", app);
|
||||
});
|
||||
this._loadingPromise = this.client.request(request).then(res => {
|
||||
delete this._loadingPromise;
|
||||
this._apps = new Map();
|
||||
for (let a of res.apps) {
|
||||
let app = new App(this.client, this.actor, a);
|
||||
this._apps.set(a.manifestURL, app);
|
||||
}
|
||||
}).then(() => {
|
||||
// Then retrieve all running apps in order to flag them as running
|
||||
let listRequest = {
|
||||
to: this.actor,
|
||||
type: "listRunningApps"
|
||||
};
|
||||
return this.client.request(listRequest).then(res => res.apps);
|
||||
}).then(apps => {
|
||||
let promises = apps.map(manifestURL => {
|
||||
// _getApp creates `App` instance and register it to AppActorFront
|
||||
return this._getApp(manifestURL).then(app => {
|
||||
app.running = true;
|
||||
// Fake appOpen event for all already opened
|
||||
this._notifyListeners("appOpen", app);
|
||||
});
|
||||
return promise.all(promises);
|
||||
})
|
||||
.then(() => {
|
||||
// Finally ask to receive all app events
|
||||
return this._listenAppEvents(listener);
|
||||
});
|
||||
return promise.all(promises);
|
||||
}).then(() => {
|
||||
// Finally ask to receive all app events
|
||||
return this._listenAppEvents(listener);
|
||||
});
|
||||
return this._loadingPromise;
|
||||
},
|
||||
|
||||
fetchIcons: function () {
|
||||
// On demand, retrieve apps icons in order to be able
|
||||
// to synchronously retrieve it on `App` objects
|
||||
let promises = [];
|
||||
for (let [manifestURL, app] of this._apps) {
|
||||
for (let [, app] of this._apps) {
|
||||
promises.push(app.getIcon());
|
||||
}
|
||||
|
||||
@ -708,16 +700,15 @@ AppActorFront.prototype = {
|
||||
to: this.actor,
|
||||
type: "listRunningApps"
|
||||
};
|
||||
this.client.request(request)
|
||||
.then(res => {
|
||||
if (res.apps.indexOf(manifestURL) !== -1) {
|
||||
app.running = true;
|
||||
this._notifyListeners("appInstall", app);
|
||||
this._notifyListeners("appOpen", app);
|
||||
} else {
|
||||
this._notifyListeners("appInstall", app);
|
||||
}
|
||||
});
|
||||
this.client.request(request).then(res => {
|
||||
if (res.apps.indexOf(manifestURL) !== -1) {
|
||||
app.running = true;
|
||||
this._notifyListeners("appInstall", app);
|
||||
this._notifyListeners("appOpen", app);
|
||||
} else {
|
||||
this._notifyListeners("appInstall", app);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "appUninstall":
|
||||
// Fake a appClose event if we didn't got one before uninstall
|
||||
@ -796,22 +787,19 @@ AppActorFront.prototype = {
|
||||
}
|
||||
}
|
||||
};
|
||||
this._listenAppEvents(listener)
|
||||
// Execute the request
|
||||
.then(request)
|
||||
.then(response => {
|
||||
finalAppId = response.appId;
|
||||
manifestURL = response.manifestURL;
|
||||
// Execute the request
|
||||
this._listenAppEvents(listener).then(request).then(response => {
|
||||
finalAppId = response.appId;
|
||||
manifestURL = response.manifestURL;
|
||||
|
||||
// Resolves immediately if the appInstall event
|
||||
// was dispatched during the request.
|
||||
if (manifestURL in installs) {
|
||||
resolve(installs[manifestURL]);
|
||||
}
|
||||
}, deferred.reject);
|
||||
// Resolves immediately if the appInstall event
|
||||
// was dispatched during the request.
|
||||
if (manifestURL in installs) {
|
||||
resolve(installs[manifestURL]);
|
||||
}
|
||||
}, deferred.reject);
|
||||
|
||||
return deferred.promise;
|
||||
|
||||
},
|
||||
|
||||
/*
|
||||
@ -826,12 +814,12 @@ AppActorFront.prototype = {
|
||||
let manifestURL = metadata.manifestURL ||
|
||||
metadata.origin + "/manifest.webapp";
|
||||
let request = () => {
|
||||
return installHosted(this.client, this.actor, appId, metadata,
|
||||
manifest)
|
||||
.then(response => ({
|
||||
appId: response.appId,
|
||||
manifestURL: manifestURL
|
||||
}));
|
||||
return installHosted(
|
||||
this.client, this.actor, appId, metadata, manifest
|
||||
).then(response => ({
|
||||
appId: response.appId,
|
||||
manifestURL: manifestURL
|
||||
}));
|
||||
};
|
||||
return this._install(request);
|
||||
}
|
||||
|
@ -15,8 +15,7 @@ function getAddonManager() {
|
||||
AddonManager: require("resource://gre/modules/AddonManager.jsm").AddonManager,
|
||||
addonManagerActive: true
|
||||
};
|
||||
}
|
||||
catch (ex) {
|
||||
} catch (ex) {
|
||||
// Fake up an AddonManager just enough to let the file load
|
||||
return {
|
||||
AddonManager: {
|
||||
@ -28,21 +27,15 @@ function getAddonManager() {
|
||||
}
|
||||
}
|
||||
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const { AddonManager, addonManagerActive } = getAddonManager();
|
||||
const l10n = require("gcli/l10n");
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://branding/locale/brand.properties")
|
||||
.GetStringFromName("brandShortName");
|
||||
|
||||
/**
|
||||
* Takes a function that uses a callback as its last parameter, and returns a
|
||||
* new function that returns a promise instead.
|
||||
* This should probably live in async-util
|
||||
*/
|
||||
const promiseify = function(scope, functionWithLastParamCallback) {
|
||||
const promiseify = function (scope, functionWithLastParamCallback) {
|
||||
return (...args) => {
|
||||
return new Promise(resolve => {
|
||||
args.push((...results) => {
|
||||
@ -50,7 +43,7 @@ const promiseify = function(scope, functionWithLastParamCallback) {
|
||||
});
|
||||
functionWithLastParamCallback.apply(scope, args);
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Convert callback based functions to promise based ones
|
||||
@ -65,7 +58,7 @@ function pendingOperations(addon) {
|
||||
"PENDING_ENABLE", "PENDING_DISABLE", "PENDING_UNINSTALL",
|
||||
"PENDING_INSTALL", "PENDING_UPGRADE"
|
||||
];
|
||||
return allOperations.reduce(function(operations, opName) {
|
||||
return allOperations.reduce(function (operations, opName) {
|
||||
return addon.pendingOperations & AddonManager[opName] ?
|
||||
operations.concat(opName) :
|
||||
operations;
|
||||
@ -79,15 +72,19 @@ var items = [
|
||||
parent: "selection",
|
||||
stringifyProperty: "name",
|
||||
cacheable: true,
|
||||
constructor: function() {
|
||||
constructor: function () {
|
||||
// Tell GCLI to clear the cache of addons when one is added or removed
|
||||
let listener = {
|
||||
onInstalled: addon => { this.clearCache(); },
|
||||
onUninstalled: addon => { this.clearCache(); },
|
||||
onInstalled: addon => {
|
||||
this.clearCache();
|
||||
},
|
||||
onUninstalled: addon => {
|
||||
this.clearCache();
|
||||
},
|
||||
};
|
||||
AddonManager.addAddonListener(listener);
|
||||
},
|
||||
lookup: function() {
|
||||
lookup: function () {
|
||||
return getAllAddons().then(addons => {
|
||||
return addons.map(addon => {
|
||||
let name = addon.name + " " + addon.version;
|
||||
@ -114,10 +111,10 @@ var items = [
|
||||
defaultValue: "all",
|
||||
description: l10n.lookup("addonListTypeDesc")
|
||||
}],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let types = (args.type === "all") ? null : [ args.type ];
|
||||
return getAddonsByTypes(types).then(addons => {
|
||||
addons = addons.map(function(addon) {
|
||||
addons = addons.map(function (addon) {
|
||||
return {
|
||||
name: addon.name,
|
||||
version: addon.version,
|
||||
@ -133,7 +130,7 @@ var items = [
|
||||
item: "converter",
|
||||
from: "addonsInfo",
|
||||
to: "view",
|
||||
exec: function(addonsInfo, context) {
|
||||
exec: function (addonsInfo, context) {
|
||||
if (!addonsInfo.addons.length) {
|
||||
return context.createView({
|
||||
html: "<p>${message}</p>",
|
||||
@ -167,7 +164,7 @@ var items = [
|
||||
function arrangeAddons(addons) {
|
||||
let enabledAddons = [];
|
||||
let disabledAddons = [];
|
||||
addons.forEach(function(addon) {
|
||||
addons.forEach(function (addon) {
|
||||
if (addon.isActive) {
|
||||
enabledAddons.push(addon);
|
||||
} else {
|
||||
@ -208,7 +205,7 @@ var items = [
|
||||
"</table>",
|
||||
data: {
|
||||
header: header,
|
||||
addons: arrangeAddons(addonsInfo.addons).map(function(addon) {
|
||||
addons: arrangeAddons(addonsInfo.addons).map(function (addon) {
|
||||
return {
|
||||
name: addon.name,
|
||||
label: addon.name.replace(/\s/g, "_") +
|
||||
@ -220,7 +217,7 @@ var items = [
|
||||
+ addon.pendingOperations.map(lookupOperation).join(", ")
|
||||
+ ")") :
|
||||
"",
|
||||
toggleActionName: isActiveForToggle(addon) ? "disable": "enable",
|
||||
toggleActionName: isActiveForToggle(addon) ? "disable" : "enable",
|
||||
toggleActionMessage: isActiveForToggle(addon) ?
|
||||
l10n.lookup("addonListOutDisable") :
|
||||
l10n.lookup("addonListOutEnable")
|
||||
@ -244,7 +241,7 @@ var items = [
|
||||
description: l10n.lookup("addonNameDesc")
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let name = (args.addon.name + " " + args.addon.version).trim();
|
||||
if (args.addon.userDisabled) {
|
||||
args.addon.userDisabled = false;
|
||||
@ -266,7 +263,7 @@ var items = [
|
||||
description: l10n.lookup("addonNameDesc")
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
// If the addon is not disabled or is set to "click to play" then
|
||||
// disable it. Otherwise display the message "Add-on is already
|
||||
// disabled."
|
||||
@ -292,7 +289,7 @@ var items = [
|
||||
description: l10n.lookup("addonNameDesc")
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let name = (args.addon.name + " " + args.addon.version).trim();
|
||||
if (args.addon.type !== "plugin") {
|
||||
return l10n.lookupFormat("addonCantCtp", [ name ]);
|
||||
|
@ -32,7 +32,7 @@ exports.items = [
|
||||
}
|
||||
]
|
||||
}],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let utils;
|
||||
let deferred = context.defer();
|
||||
|
||||
@ -42,7 +42,7 @@ exports.items = [
|
||||
utils = new AppCacheUtils(context.environment.document);
|
||||
}
|
||||
|
||||
utils.validateManifest().then(function(errors) {
|
||||
utils.validateManifest().then(function (errors) {
|
||||
deferred.resolve([errors, utils.manifestURI || "-"]);
|
||||
});
|
||||
|
||||
@ -53,7 +53,7 @@ exports.items = [
|
||||
item: "converter",
|
||||
from: "appcacheerrors",
|
||||
to: "view",
|
||||
exec: function([errors, manifestURI], context) {
|
||||
exec: function ([errors, manifestURI], context) {
|
||||
if (errors.length == 0) {
|
||||
return context.createView({
|
||||
html: "<span>" + l10n.lookup("appCacheValidatedSuccessfully") + "</span>"
|
||||
@ -81,7 +81,7 @@ exports.items = [
|
||||
name: "appcache clear",
|
||||
description: l10n.lookup("appCacheClearDesc"),
|
||||
manual: l10n.lookup("appCacheClearManual"),
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let utils = new AppCacheUtils(args.uri);
|
||||
utils.clearAll();
|
||||
|
||||
@ -106,7 +106,7 @@ exports.items = [
|
||||
},
|
||||
]
|
||||
}],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let utils = new AppCacheUtils();
|
||||
return utils.listEntries(args.search);
|
||||
}
|
||||
@ -115,7 +115,7 @@ exports.items = [
|
||||
item: "converter",
|
||||
from: "appcacheentries",
|
||||
to: "view",
|
||||
exec: function(entries, context) {
|
||||
exec: function (entries, context) {
|
||||
return context.createView({
|
||||
html: "" +
|
||||
"<ul class='gcli-appcache-list'>" +
|
||||
@ -178,7 +178,7 @@ exports.items = [
|
||||
defaultValue: null,
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let utils = new AppCacheUtils();
|
||||
return utils.viewEntry(args.key);
|
||||
}
|
||||
|
@ -27,11 +27,11 @@ exports.items = [
|
||||
name: "calllog start",
|
||||
description: l10n.lookup("calllogStartDesc"),
|
||||
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let contentWindow = context.environment.window;
|
||||
|
||||
let dbg = new Debugger(contentWindow);
|
||||
dbg.onEnterFrame = function(frame) {
|
||||
dbg.onEnterFrame = function (frame) {
|
||||
// BUG 773652 - Make the output from the GCLI calllog command nicer
|
||||
contentWindow.console.log("Method call: " + this.callDescription(frame));
|
||||
}.bind(this);
|
||||
@ -45,12 +45,11 @@ exports.items = [
|
||||
return l10n.lookup("calllogStartReply");
|
||||
},
|
||||
|
||||
callDescription: function(frame) {
|
||||
callDescription: function (frame) {
|
||||
let name = "<anonymous>";
|
||||
if (frame.callee.name) {
|
||||
name = frame.callee.name;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let desc = frame.callee.getOwnPropertyDescriptor("displayName");
|
||||
if (desc && desc.value && typeof desc.value == "string") {
|
||||
name = desc.value;
|
||||
@ -61,7 +60,7 @@ exports.items = [
|
||||
return name + "(" + args + ")";
|
||||
},
|
||||
|
||||
valueToString: function(value) {
|
||||
valueToString: function (value) {
|
||||
if (typeof value !== "object" || value === null) {
|
||||
return uneval(value);
|
||||
}
|
||||
@ -74,7 +73,7 @@ exports.items = [
|
||||
name: "calllog stop",
|
||||
description: l10n.lookup("calllogStopDesc"),
|
||||
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let numDebuggers = debuggers.length;
|
||||
if (numDebuggers == 0) {
|
||||
return l10n.lookup("calllogStopNoLogging");
|
||||
@ -111,7 +110,7 @@ exports.items = [
|
||||
manual: l10n.lookup("calllogChromeSourceTypeManual"),
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let globalObj;
|
||||
let contentWindow = context.environment.window;
|
||||
|
||||
@ -136,17 +135,16 @@ exports.items = [
|
||||
}
|
||||
} else {
|
||||
let chromeWin = context.environment.chromeDocument.defaultView;
|
||||
let sandbox = new Cu.Sandbox(chromeWin,
|
||||
{
|
||||
sandboxPrototype: chromeWin,
|
||||
wantXrays: false,
|
||||
sandboxName: "gcli-cmd-calllog-chrome"
|
||||
});
|
||||
let sandbox = new Cu.Sandbox(chromeWin, {
|
||||
sandboxPrototype: chromeWin,
|
||||
wantXrays: false,
|
||||
sandboxName: "gcli-cmd-calllog-chrome"
|
||||
});
|
||||
let returnVal;
|
||||
try {
|
||||
returnVal = Cu.evalInSandbox(args.source, sandbox, "ECMAv5");
|
||||
sandboxes.push(sandbox);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
// We need to save the message before cleaning up else e contains a dead
|
||||
// object.
|
||||
let msg = l10n.lookup("callLogChromeEvalException") + ": " + e;
|
||||
@ -164,7 +162,7 @@ exports.items = [
|
||||
let dbg = new Debugger(globalObj);
|
||||
chromeDebuggers.push(dbg);
|
||||
|
||||
dbg.onEnterFrame = function(frame) {
|
||||
dbg.onEnterFrame = function (frame) {
|
||||
// BUG 773652 - Make the output from the GCLI calllog command nicer
|
||||
contentWindow.console.log(l10n.lookup("callLogChromeMethodCall") +
|
||||
": " + this.callDescription(frame));
|
||||
@ -177,13 +175,14 @@ exports.items = [
|
||||
return l10n.lookup("calllogChromeStartReply");
|
||||
},
|
||||
|
||||
valueToString: function(value) {
|
||||
if (typeof value !== "object" || value === null)
|
||||
valueToString: function (value) {
|
||||
if (typeof value !== "object" || value === null) {
|
||||
return uneval(value);
|
||||
}
|
||||
return "[object " + value.class + "]";
|
||||
},
|
||||
|
||||
callDescription: function(frame) {
|
||||
callDescription: function (frame) {
|
||||
let name = frame.callee.name || l10n.lookup("callLogChromeAnonFunction");
|
||||
let args = frame.arguments.map(this.valueToString).join(", ");
|
||||
return name + "(" + args + ")";
|
||||
@ -197,7 +196,7 @@ exports.items = [
|
||||
get hidden() {
|
||||
return gcli.hiddenByChromePref();
|
||||
},
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let numDebuggers = chromeDebuggers.length;
|
||||
if (numDebuggers == 0) {
|
||||
return l10n.lookup("calllogChromeStopNoLogging");
|
||||
|
@ -5,18 +5,19 @@
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const { OS, TextDecoder } = Cu.import("resource://gre/modules/osfile.jsm", {});
|
||||
const { Task } = require("devtools/shared/task");
|
||||
|
||||
const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
|
||||
const { TextEncoder, TextDecoder } = Cu.import('resource://gre/modules/commonjs/toolkit/loader.js', {});
|
||||
const gcli = require("gcli/index");
|
||||
const l10n = require("gcli/l10n");
|
||||
|
||||
loader.lazyGetter(this, "prefBranch", function() {
|
||||
let prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
|
||||
loader.lazyGetter(this, "prefBranch", function () {
|
||||
let prefService = Cc["@mozilla.org/preferences-service;1"]
|
||||
.getService(Ci.nsIPrefService);
|
||||
return prefService.getBranch(null).QueryInterface(Ci.nsIPrefBranch2);
|
||||
});
|
||||
|
||||
loader.lazyGetter(this, "supportsString", function() {
|
||||
loader.lazyGetter(this, "supportsString", function () {
|
||||
return Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
|
||||
});
|
||||
|
||||
@ -66,30 +67,32 @@ function loadItemsFromMozDir() {
|
||||
|
||||
// We need to return (a promise of) an array of items from the *.mozcmd
|
||||
// files in dirName (which we can assume to be a valid directory now)
|
||||
return statPromise.then(() => {
|
||||
return Task.async(function* () {
|
||||
yield statPromise;
|
||||
let itemPromises = [];
|
||||
|
||||
let iterator = new OS.File.DirectoryIterator(dirName);
|
||||
let iterPromise = iterator.forEach(entry => {
|
||||
if (entry.name.match(/.*\.mozcmd$/) && !entry.isDir) {
|
||||
itemPromises.push(loadCommandFile(entry));
|
||||
}
|
||||
});
|
||||
|
||||
return iterPromise.then(() => {
|
||||
iterator.close();
|
||||
return Promise.all(itemPromises).then((itemsArray) => {
|
||||
return itemsArray.reduce((prev, curr) => {
|
||||
return prev.concat(curr);
|
||||
}, []);
|
||||
try {
|
||||
yield iterator.forEach(entry => {
|
||||
if (entry.name.match(/.*\.mozcmd$/) && !entry.isDir) {
|
||||
itemPromises.push(loadCommandFile(entry));
|
||||
}
|
||||
});
|
||||
}, reason => { iterator.close(); throw reason; });
|
||||
iterator.close();
|
||||
let itemsArray = yield Promise.all(itemPromises);
|
||||
return itemsArray.reduce((prev, curr) => {
|
||||
return prev.concat(curr);
|
||||
}, []);
|
||||
} catch (e) {
|
||||
iterator.close();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exports.mozDirLoader = function(name) {
|
||||
exports.mozDirLoader = function (name) {
|
||||
return loadItemsFromMozDir().then(items => {
|
||||
return { items: items };
|
||||
return { items };
|
||||
});
|
||||
};
|
||||
|
||||
@ -100,10 +103,10 @@ exports.mozDirLoader = function(name) {
|
||||
*/
|
||||
function loadCommandFile(entry) {
|
||||
let readPromise = OS.File.read(entry.path);
|
||||
return readPromise = readPromise.then(array => {
|
||||
readPromise = readPromise.then(array => {
|
||||
let decoder = new TextDecoder();
|
||||
let source = decoder.decode(array);
|
||||
var principal = Cc["@mozilla.org/systemprincipal;1"]
|
||||
let principal = Cc["@mozilla.org/systemprincipal;1"]
|
||||
.createInstance(Ci.nsIPrincipal);
|
||||
|
||||
let sandbox = new Cu.Sandbox(principal, {
|
||||
@ -113,11 +116,12 @@ function loadCommandFile(entry) {
|
||||
|
||||
if (!Array.isArray(data)) {
|
||||
console.error("Command file '" + entry.name + "' does not have top level array.");
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
return readPromise;
|
||||
}
|
||||
|
||||
exports.items = [
|
||||
@ -136,7 +140,7 @@ exports.items = [
|
||||
get hidden() {
|
||||
return !prefBranch.prefHasUserValue(PREF_DIR);
|
||||
},
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
gcli.load();
|
||||
|
||||
let dirName = prefBranch.getComplexValue(PREF_DIR,
|
||||
@ -164,9 +168,10 @@ exports.items = [
|
||||
],
|
||||
returnType: "string",
|
||||
get hidden() {
|
||||
return true; // !prefBranch.prefHasUserValue(PREF_DIR);
|
||||
// !prefBranch.prefHasUserValue(PREF_DIR);
|
||||
return true;
|
||||
},
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
supportsString.data = args.directory;
|
||||
prefBranch.setComplexValue(PREF_DIR, Ci.nsISupportsString, supportsString);
|
||||
|
||||
|
@ -24,7 +24,7 @@ const { Ci, Cc } = require("chrome");
|
||||
const l10n = require("gcli/l10n");
|
||||
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "cookieMgr", function() {
|
||||
XPCOMUtils.defineLazyGetter(this, "cookieMgr", function () {
|
||||
return Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
|
||||
});
|
||||
|
||||
@ -52,9 +52,9 @@ function translateExpires(expires) {
|
||||
return l10n.lookup("cookieListOutSession");
|
||||
}
|
||||
|
||||
let expires_msec = expires * 1000;
|
||||
let expiresMsec = expires * 1000;
|
||||
|
||||
return (new Date(expires_msec)).toLocaleString();
|
||||
return (new Date(expiresMsec)).toLocaleString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,17 +86,16 @@ exports.items = [
|
||||
description: l10n.lookup("cookieListDesc"),
|
||||
manual: l10n.lookup("cookieListManual"),
|
||||
returnType: "cookies",
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
if (context.environment.target.isRemote) {
|
||||
throw new Error("The cookie gcli commands only work in a local tab, " +
|
||||
"see bug 1221488");
|
||||
}
|
||||
let host = new URL(context.environment.target.url).host;
|
||||
let contentWindow = context.environment.window;
|
||||
let contentWindow = context.environment.window;
|
||||
host = sanitizeHost(host);
|
||||
let enm = cookieMgr.getCookiesFromHost(host, contentWindow.document.
|
||||
nodePrincipal.
|
||||
originAttributes);
|
||||
let { originAttributes } = contentWindow.document.nodePrincipal;
|
||||
let enm = cookieMgr.getCookiesFromHost(host, originAttributes);
|
||||
|
||||
let cookies = [];
|
||||
while (enm.hasMoreElements()) {
|
||||
@ -131,17 +130,16 @@ exports.items = [
|
||||
description: l10n.lookup("cookieRemoveKeyDesc"),
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
if (context.environment.target.isRemote) {
|
||||
throw new Error("The cookie gcli commands only work in a local tab, " +
|
||||
"see bug 1221488");
|
||||
}
|
||||
let host = new URL(context.environment.target.url).host;
|
||||
let contentWindow = context.environment.window;
|
||||
let contentWindow = context.environment.window;
|
||||
host = sanitizeHost(host);
|
||||
let enm = cookieMgr.getCookiesFromHost(host, contentWindow.document.
|
||||
nodePrincipal.
|
||||
originAttributes);
|
||||
let { originAttributes } = contentWindow.document.nodePrincipal;
|
||||
let enm = cookieMgr.getCookiesFromHost(host, originAttributes);
|
||||
|
||||
while (enm.hasMoreElements()) {
|
||||
let cookie = enm.getNext().QueryInterface(Ci.nsICookie);
|
||||
@ -158,7 +156,7 @@ exports.items = [
|
||||
item: "converter",
|
||||
from: "cookies",
|
||||
to: "view",
|
||||
exec: function(cookies, context) {
|
||||
exec: function (cookies, context) {
|
||||
if (cookies.length == 0) {
|
||||
let host = new URL(context.environment.target.url).host;
|
||||
host = sanitizeHost(host);
|
||||
@ -275,7 +273,7 @@ exports.items = [
|
||||
]
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
if (context.environment.target.isRemote) {
|
||||
throw new Error("The cookie gcli commands only work in a local tab, " +
|
||||
"see bug 1221488");
|
||||
@ -283,7 +281,7 @@ exports.items = [
|
||||
let host = new URL(context.environment.target.url).host;
|
||||
host = sanitizeHost(host);
|
||||
let time = Date.parse(args.expires) / 1000;
|
||||
let contentWindow = context.environment.window;
|
||||
let contentWindow = context.environment.window;
|
||||
cookieMgr.add(args.domain ? "." + args.domain : host,
|
||||
args.path ? args.path : "/",
|
||||
args.name,
|
||||
@ -292,9 +290,7 @@ exports.items = [
|
||||
args.httpOnly,
|
||||
args.session,
|
||||
time,
|
||||
contentWindow.document.
|
||||
nodePrincipal.
|
||||
originAttributes);
|
||||
contentWindow.document.nodePrincipal.originAttributes);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -4,8 +4,6 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci } = require("chrome");
|
||||
|
||||
const domtemplate = require("gcli/util/domtemplate");
|
||||
const csscoverage = require("devtools/shared/fronts/csscoverage");
|
||||
const l10n = csscoverage.l10n;
|
||||
@ -37,7 +35,7 @@ exports.items = [
|
||||
manual: l10n.lookup("csscoverageStartNoReloadManual")
|
||||
}
|
||||
],
|
||||
exec: function*(args, context) {
|
||||
exec: function* (args, context) {
|
||||
let usage = yield csscoverage.getUsage(context.environment.target);
|
||||
if (usage == null) {
|
||||
throw new Error(l10n.lookup("csscoverageNoRemoteError"));
|
||||
@ -52,7 +50,7 @@ exports.items = [
|
||||
name: "csscoverage stop",
|
||||
hidden: true,
|
||||
description: l10n.lookup("csscoverageStopDesc2"),
|
||||
exec: function*(args, context) {
|
||||
exec: function* (args, context) {
|
||||
let target = context.environment.target;
|
||||
let usage = yield csscoverage.getUsage(target);
|
||||
if (usage == null) {
|
||||
@ -68,7 +66,7 @@ exports.items = [
|
||||
name: "csscoverage oneshot",
|
||||
hidden: true,
|
||||
description: l10n.lookup("csscoverageOneShotDesc2"),
|
||||
exec: function*(args, context) {
|
||||
exec: function* (args, context) {
|
||||
let target = context.environment.target;
|
||||
let usage = yield csscoverage.getUsage(target);
|
||||
if (usage == null) {
|
||||
@ -85,25 +83,27 @@ exports.items = [
|
||||
hidden: true,
|
||||
description: l10n.lookup("csscoverageToggleDesc2"),
|
||||
state: {
|
||||
isChecked: function(target) {
|
||||
isChecked: function (target) {
|
||||
return csscoverage.getUsage(target).then(usage => {
|
||||
return usage.isRunning();
|
||||
});
|
||||
},
|
||||
onChange: function(target, handler) {
|
||||
onChange: function (target, handler) {
|
||||
csscoverage.getUsage(target).then(usage => {
|
||||
this.handler = ev => { handler("state-change", ev); };
|
||||
this.handler = ev => {
|
||||
handler("state-change", ev);
|
||||
};
|
||||
usage.on("state-change", this.handler);
|
||||
});
|
||||
},
|
||||
offChange: function(target, handler) {
|
||||
offChange: function (target, handler) {
|
||||
csscoverage.getUsage(target).then(usage => {
|
||||
usage.off("state-change", this.handler);
|
||||
this.handler = undefined;
|
||||
});
|
||||
},
|
||||
},
|
||||
exec: function*(args, context) {
|
||||
exec: function* (args, context) {
|
||||
let target = context.environment.target;
|
||||
let usage = yield csscoverage.getUsage(target);
|
||||
if (usage == null) {
|
||||
@ -120,7 +120,7 @@ exports.items = [
|
||||
name: "csscoverage report",
|
||||
hidden: true,
|
||||
description: l10n.lookup("csscoverageReportDesc2"),
|
||||
exec: function*(args, context) {
|
||||
exec: function* (args, context) {
|
||||
let usage = yield csscoverage.getUsage(context.environment.target);
|
||||
if (usage == null) {
|
||||
throw new Error(l10n.lookup("csscoverageNoRemoteError"));
|
||||
@ -137,7 +137,7 @@ exports.items = [
|
||||
item: "converter",
|
||||
from: "csscoveragePageReport",
|
||||
to: "dom",
|
||||
exec: function*(csscoveragePageReport, context) {
|
||||
exec: function* (csscoveragePageReport, context) {
|
||||
let target = context.environment.target;
|
||||
|
||||
let toolbox = yield gDevTools.showToolbox(target, "styleeditor");
|
||||
@ -185,7 +185,8 @@ exports.items = [
|
||||
// Create a new chart.
|
||||
let container = host.querySelector(".csscoverage-report-chart");
|
||||
let chart = Chart.PieTable(panel._panelDoc, {
|
||||
diameter: 200, // px
|
||||
// px
|
||||
diameter: 200,
|
||||
title: "CSS Usage",
|
||||
data: [
|
||||
{ size: data.summary.preload, label: "Used Preload" },
|
||||
|
@ -4,25 +4,24 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu, CC } = require("chrome");
|
||||
const { Cc, Ci, CC } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const l10n = require("gcli/l10n");
|
||||
const dirService = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties);
|
||||
|
||||
function showFolder(aPath) {
|
||||
let nsLocalFile = CC("@mozilla.org/file/local;1", "nsILocalFile",
|
||||
function showFolder(path) {
|
||||
let NSLocalFile = CC("@mozilla.org/file/local;1", "nsILocalFile",
|
||||
"initWithPath");
|
||||
|
||||
try {
|
||||
let file = new nsLocalFile(aPath);
|
||||
let file = new NSLocalFile(path);
|
||||
|
||||
if (file.exists()) {
|
||||
file.reveal();
|
||||
return l10n.lookupFormat("folderOpenDirResult", [aPath]);
|
||||
} else {
|
||||
return l10n.lookup("folderInvalidPath");
|
||||
return l10n.lookupFormat("folderOpenDirResult", [path]);
|
||||
}
|
||||
return l10n.lookup("folderInvalidPath");
|
||||
} catch (e) {
|
||||
return l10n.lookup("folderInvalidPath");
|
||||
}
|
||||
@ -47,7 +46,7 @@ exports.items = [
|
||||
}
|
||||
],
|
||||
returnType: "string",
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let dirName = args.path;
|
||||
|
||||
// replaces ~ with the home directory path in unix and windows
|
||||
@ -67,7 +66,7 @@ exports.items = [
|
||||
name: "folder openprofile",
|
||||
description: l10n.lookup("folderOpenProfileDesc"),
|
||||
returnType: "string",
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
// Get the profile directory.
|
||||
let currProfD = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
let profileDir = currProfD.path;
|
||||
|
@ -103,7 +103,7 @@ exports.items = [
|
||||
]
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
// Remove all existing highlighters unless told otherwise
|
||||
if (!args.keep) {
|
||||
unhighlightAll();
|
||||
|
@ -107,7 +107,7 @@ try {
|
||||
/**
|
||||
* Add modules to a system for use in a content process (but don't call load)
|
||||
*/
|
||||
exports.addAllItemsByModule = function(system) {
|
||||
exports.addAllItemsByModule = function (system) {
|
||||
system.addItemsByModule(exports.baseModules, { delayedLoad: true });
|
||||
system.addItemsByModule(exports.devtoolsModules, { delayedLoad: true });
|
||||
system.addItemsByModule(exports.devtoolsToolModules, { delayedLoad: true });
|
||||
@ -133,7 +133,7 @@ var customProperties = [ "buttonId", "buttonClass", "tooltipText" ];
|
||||
* Create a system which connects to a GCLI in a remote target
|
||||
* @return Promise<System> for the given target
|
||||
*/
|
||||
exports.getSystem = function(target) {
|
||||
exports.getSystem = function (target) {
|
||||
const existingLinks = linksForTarget.get(target);
|
||||
if (existingLinks != null) {
|
||||
existingLinks.refs++;
|
||||
@ -164,7 +164,7 @@ exports.getSystem = function(target) {
|
||||
* Someone that called getSystem doesn't need it any more, so decrement the
|
||||
* count of users of the system for that target, and destroy if needed
|
||||
*/
|
||||
exports.releaseSystem = function(target) {
|
||||
exports.releaseSystem = function (target) {
|
||||
const links = linksForTarget.get(target);
|
||||
if (links == null) {
|
||||
throw new Error("releaseSystem called for unknown target");
|
||||
|
@ -53,7 +53,7 @@ exports.items = [
|
||||
},
|
||||
description: l10n.lookup("injectLibraryDesc")
|
||||
}],
|
||||
exec: function*(args, context) {
|
||||
exec: function* (args, context) {
|
||||
let document = context.environment.document;
|
||||
let library = args.library;
|
||||
let name = (library.type === "selection") ?
|
||||
@ -68,7 +68,7 @@ exports.items = [
|
||||
try {
|
||||
// Check if URI is valid
|
||||
Services.io.newURI(src, null, null);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
return l10n.lookupFormat("injectFailed", [name]);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const { Cc } = require("chrome");
|
||||
const l10n = require("gcli/l10n");
|
||||
const XMLHttpRequest = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"];
|
||||
|
||||
@ -19,7 +19,7 @@ exports.items = [
|
||||
runAt: "client",
|
||||
name: "jsb",
|
||||
description: l10n.lookup("jsbDesc"),
|
||||
returnValue:"string",
|
||||
returnValue: "string",
|
||||
params: [
|
||||
{
|
||||
name: "url",
|
||||
@ -91,7 +91,8 @@ exports.items = [
|
||||
]
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
/* eslint-disable camelcase */
|
||||
let opts = {
|
||||
indent_size: args.indentSize,
|
||||
indent_char: args.indentChar,
|
||||
@ -103,12 +104,12 @@ exports.items = [
|
||||
space_before_conditional: !args.noSpaceBeforeConditional,
|
||||
unescape_strings: args.unescapeStrings
|
||||
};
|
||||
|
||||
/* eslint-enable camelcase */
|
||||
let xhr = new XMLHttpRequest();
|
||||
|
||||
let deferred = context.defer();
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status == 200 || xhr.status == 0) {
|
||||
let result = beautify.js(xhr.responseText, opts);
|
||||
@ -120,12 +121,12 @@ exports.items = [
|
||||
deferred.reject("Unable to load page to beautify: " + args.url + " " +
|
||||
xhr.status + " " + xhr.statusText);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
try {
|
||||
xhr.open("GET", args.url, true);
|
||||
xhr.send(null);
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
return l10n.lookup("jsbInvalidURL");
|
||||
}
|
||||
return deferred.promise;
|
||||
|
@ -69,7 +69,7 @@ exports.items = [
|
||||
},
|
||||
],
|
||||
exec: function (args, context) {
|
||||
var listener = debuggerServer.createListener();
|
||||
let listener = debuggerServer.createListener();
|
||||
if (!listener) {
|
||||
throw new Error(l10n.lookup("listenDisabledOutput"));
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ exports.items = [{
|
||||
defaultValue: null,
|
||||
description: l10n.lookup("mdnCssProp")
|
||||
}],
|
||||
exec: function(args) {
|
||||
exec: function (args) {
|
||||
if (!MdnDocsWidget) {
|
||||
return null;
|
||||
}
|
||||
@ -47,7 +47,7 @@ exports.items = [{
|
||||
item: "converter",
|
||||
from: "cssPropertyOutput",
|
||||
to: "dom",
|
||||
exec: function(result, context) {
|
||||
exec: function (result, context) {
|
||||
let propertyName = result.property;
|
||||
|
||||
let document = context.document;
|
||||
|
@ -40,7 +40,7 @@ exports.items = [
|
||||
onChange: (target, handler) => eventEmitter.on("changed", handler),
|
||||
offChange: (target, handler) => eventEmitter.off("changed", handler)
|
||||
},
|
||||
exec: function*(args, context) {
|
||||
exec: function* (args, context) {
|
||||
let { target } = context.environment;
|
||||
|
||||
// Pipe the call to the server command.
|
||||
@ -73,7 +73,7 @@ exports.items = [
|
||||
runAt: "server",
|
||||
hidden: true,
|
||||
returnType: "highlighterVisibility",
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let env = context.environment;
|
||||
let { document } = env;
|
||||
let id = getOuterId(env.window);
|
||||
@ -99,8 +99,8 @@ exports.items = [
|
||||
// window is refreshed or closed with the measuring tool shown.
|
||||
events.once(highlighter, "destroy", () => {
|
||||
if (highlighters.has(document)) {
|
||||
let { environment } = highlighters.get(document);
|
||||
environment.destroy();
|
||||
let { environment: toDestroy } = highlighters.get(document);
|
||||
toDestroy.destroy();
|
||||
highlighters.delete(document);
|
||||
}
|
||||
});
|
||||
|
@ -38,7 +38,7 @@ exports.items = [
|
||||
}
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let contentViewer = getContentViewer(context);
|
||||
contentViewer.emulateMedium(args.type);
|
||||
}
|
||||
@ -48,7 +48,7 @@ exports.items = [
|
||||
runAt: "server",
|
||||
name: "media reset",
|
||||
description: l10n.lookup("mediaResetDesc"),
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let contentViewer = getContentViewer(context);
|
||||
contentViewer.stopEmulatingMedium();
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const l10n = require("gcli/l10n");
|
||||
|
||||
exports.items = [
|
||||
@ -37,7 +37,7 @@ exports.items = [
|
||||
name: "selector",
|
||||
type: "string",
|
||||
description: l10n.lookup("pagemodReplaceSelectorDesc"),
|
||||
defaultValue: "*:not(script):not(style):not(embed):not(object):not(frame):not(iframe):not(frameset)",
|
||||
defaultValue: "*:not(script):not(style):not(embed):not(object):not(frame):not(iframe):not(frameset)", // eslint-disable-line
|
||||
},
|
||||
{
|
||||
name: "root",
|
||||
@ -63,10 +63,10 @@ exports.items = [
|
||||
},
|
||||
],
|
||||
// Make a given string safe to use in a regular expression.
|
||||
escapeRegex: function(aString) {
|
||||
return aString.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
escapeRegex: function (string) {
|
||||
return string.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
},
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let searchTextNodes = !args.attrOnly;
|
||||
let searchAttributes = !args.contentOnly;
|
||||
let regexOptions = args.ignoreCase ? "ig" : "g";
|
||||
@ -117,8 +117,7 @@ exports.items = [
|
||||
}
|
||||
|
||||
return l10n.lookupFormat("pagemodReplaceResult",
|
||||
[elements.length, replacedTextNodes,
|
||||
replacedAttributes]);
|
||||
[elements.length, replacedTextNodes, replacedAttributes]);
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -153,7 +152,7 @@ exports.items = [
|
||||
description: l10n.lookup("pagemodRemoveElementIfEmptyOnlyDesc"),
|
||||
},
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let root = args.root || context.environment.document;
|
||||
let elements = Array.prototype.slice.call(root.querySelectorAll(args.search));
|
||||
|
||||
@ -207,7 +206,7 @@ exports.items = [
|
||||
description: l10n.lookup("pagemodRemoveAttributeIgnoreCaseDesc"),
|
||||
},
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let root = args.root || context.environment.document;
|
||||
let regexOptions = args.ignoreCase ? "ig" : "g";
|
||||
let attributeRegex = new RegExp(args.searchAttributes, regexOptions);
|
||||
@ -221,7 +220,7 @@ exports.items = [
|
||||
continue;
|
||||
}
|
||||
|
||||
var attrs = Array.prototype.slice.call(element.attributes);
|
||||
let attrs = Array.prototype.slice.call(element.attributes);
|
||||
for (let y = 0; y < attrs.length; y++) {
|
||||
let attr = attrs[y];
|
||||
if (attributeRegex.test(attr.name)) {
|
||||
@ -255,7 +254,7 @@ exports.items = [
|
||||
defaultValue: "window"
|
||||
}
|
||||
],
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let html = context.environment.document.documentElement.outerHTML;
|
||||
if (args.destination === "stdout") {
|
||||
return html;
|
||||
@ -265,12 +264,12 @@ exports.items = [
|
||||
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]
|
||||
.getService(Ci.nsIClipboardHelper);
|
||||
clipboard.copyString(url);
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
|
||||
let url = "data:text/plain;charset=utf8," + encodeURIComponent(html);
|
||||
context.environment.window.open(url);
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -12,7 +12,7 @@ var telemetry;
|
||||
try {
|
||||
const Telemetry = require("devtools/client/shared/telemetry");
|
||||
telemetry = new Telemetry();
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
// DevTools Telemetry module only available in Firefox
|
||||
}
|
||||
|
||||
@ -115,7 +115,7 @@ exports.items = [
|
||||
}
|
||||
]
|
||||
}],
|
||||
exec: function*(args, context) {
|
||||
exec: function* (args, context) {
|
||||
if (!args.chrome) {
|
||||
const output = yield context.updateExec("paintflashing_server --state on");
|
||||
|
||||
@ -144,7 +144,7 @@ exports.items = [
|
||||
}
|
||||
]
|
||||
}],
|
||||
exec: function*(args, context) {
|
||||
exec: function* (args, context) {
|
||||
if (!args.chrome) {
|
||||
const output = yield context.updateExec("paintflashing_server --state off");
|
||||
|
||||
@ -169,7 +169,7 @@ exports.items = [
|
||||
tooltipText: l10n.lookup("paintflashingTooltip"),
|
||||
description: l10n.lookup("paintflashingToggleDesc"),
|
||||
manual: l10n.lookup("paintflashingManual"),
|
||||
exec: function*(args, context) {
|
||||
exec: function* (args, context) {
|
||||
const output = yield context.updateExec("paintflashing_server --state toggle");
|
||||
|
||||
onPaintFlashingChanged(context.environment.target, output.data);
|
||||
@ -190,7 +190,7 @@ exports.items = [
|
||||
},
|
||||
],
|
||||
returnType: "paintFlashingState",
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let { window } = context.environment;
|
||||
let id = getOuterId(window);
|
||||
let flashing = setPaintFlashing(window, args.state);
|
||||
|
@ -1,24 +1,24 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const l10n = require("gcli/l10n");
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
item: "command",
|
||||
runAt: "server",
|
||||
name: "qsa",
|
||||
description: l10n.lookup("qsaDesc"),
|
||||
params: [{
|
||||
name: "query",
|
||||
type: "nodelist",
|
||||
description: l10n.lookup("qsaQueryDesc")
|
||||
}],
|
||||
exec: function(args, context) {
|
||||
return args.query.length;
|
||||
}
|
||||
}
|
||||
];
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const l10n = require("gcli/l10n");
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
item: "command",
|
||||
runAt: "server",
|
||||
name: "qsa",
|
||||
description: l10n.lookup("qsaDesc"),
|
||||
params: [{
|
||||
name: "query",
|
||||
type: "nodelist",
|
||||
description: l10n.lookup("qsaQueryDesc")
|
||||
}],
|
||||
exec: function (args, context) {
|
||||
return args.query.length;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const l10n = require("gcli/l10n");
|
||||
const Services = require("Services");
|
||||
|
||||
|
@ -39,7 +39,7 @@ exports.items = [
|
||||
onChange: (target, handler) => eventEmitter.on("changed", handler),
|
||||
offChange: (target, handler) => eventEmitter.off("changed", handler)
|
||||
},
|
||||
exec: function*(args, context) {
|
||||
exec: function* (args, context) {
|
||||
let { target } = context.environment;
|
||||
|
||||
// Pipe the call to the server command.
|
||||
@ -71,7 +71,7 @@ exports.items = [
|
||||
runAt: "server",
|
||||
hidden: true,
|
||||
returnType: "highlighterVisibility",
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let env = context.environment;
|
||||
let { document } = env;
|
||||
let id = getOuterId(env.window);
|
||||
@ -97,8 +97,8 @@ exports.items = [
|
||||
// window is refreshed or closed with the rulers shown.
|
||||
events.once(highlighter, "destroy", () => {
|
||||
if (highlighters.has(document)) {
|
||||
let { environment } = highlighters.get(document);
|
||||
environment.destroy();
|
||||
let { environment: toDestroy } = highlighters.get(document);
|
||||
toDestroy.destroy();
|
||||
highlighters.delete(document);
|
||||
}
|
||||
});
|
||||
|
@ -9,7 +9,6 @@ const l10n = require("gcli/l10n");
|
||||
const Services = require("Services");
|
||||
const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
|
||||
const { getRect } = require("devtools/shared/layout/utils");
|
||||
const promise = require("promise");
|
||||
const defer = require("devtools/shared/defer");
|
||||
const { Task } = require("devtools/shared/task");
|
||||
|
||||
@ -19,11 +18,6 @@ loader.lazyImporter(this, "FileUtils", "resource://gre/modules/FileUtils.jsm");
|
||||
loader.lazyImporter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
const BRAND_SHORT_NAME = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://branding/locale/brand.properties")
|
||||
.GetStringFromName("brandShortName");
|
||||
|
||||
// String used as an indication to generate default file name in the following
|
||||
// format: "Screen Shot yyyy-mm-dd at HH.MM.SS.png"
|
||||
const FILENAME_DEFAULT_VALUE = " ";
|
||||
@ -128,7 +122,7 @@ exports.items = [
|
||||
item: "converter",
|
||||
from: "imageSummary",
|
||||
to: "dom",
|
||||
exec: function(imageSummary, context) {
|
||||
exec: function (imageSummary, context) {
|
||||
const document = context.document;
|
||||
const root = document.createElement("div");
|
||||
|
||||
@ -142,7 +136,8 @@ exports.items = [
|
||||
// Add the thumbnail image
|
||||
if (imageSummary.data != null) {
|
||||
const image = context.document.createElement("div");
|
||||
const previewHeight = parseInt(256 * imageSummary.height / imageSummary.width);
|
||||
const previewHeight = parseInt(256 * imageSummary.height / imageSummary.width,
|
||||
10);
|
||||
const style = "" +
|
||||
"width: 256px;" +
|
||||
"height: " + previewHeight + "px;" +
|
||||
@ -240,9 +235,7 @@ function captureScreenshot(args, document) {
|
||||
}, args.delay * 1000);
|
||||
});
|
||||
}
|
||||
else {
|
||||
return createScreenshotData(document, args);
|
||||
}
|
||||
return createScreenshotData(document, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -260,8 +253,8 @@ function saveScreenshot(args, context, reply) {
|
||||
|
||||
return Promise.all([
|
||||
args.clipboard ? saveToClipboard(context, reply) : SKIP,
|
||||
args.imgur ? uploadToImgur(reply) : SKIP,
|
||||
fileNeeded ? saveToFile(context, reply) : SKIP,
|
||||
args.imgur ? uploadToImgur(reply) : SKIP,
|
||||
fileNeeded ? saveToFile(context, reply) : SKIP,
|
||||
]).then(() => reply);
|
||||
}
|
||||
|
||||
@ -283,15 +276,13 @@ function createScreenshotData(document, args) {
|
||||
if (args.fullpage) {
|
||||
// Bug 961832: GCLI screenshot shows fixed position element in wrong
|
||||
// position if we don't scroll to top
|
||||
window.scrollTo(0,0);
|
||||
window.scrollTo(0, 0);
|
||||
width = window.innerWidth + window.scrollMaxX - window.scrollMinX;
|
||||
height = window.innerHeight + window.scrollMaxY - window.scrollMinY;
|
||||
filename = filename.replace(".png", "-fullpage.png");
|
||||
}
|
||||
else if (args.selector) {
|
||||
} else if (args.selector) {
|
||||
({ top, left, width, height } = getRect(window, args.selector, window));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
left = window.scrollX;
|
||||
top = window.scrollY;
|
||||
width = window.innerWidth;
|
||||
@ -347,7 +338,7 @@ function getFilename(defaultName) {
|
||||
const date = new Date();
|
||||
let dateString = date.getFullYear() + "-" + (date.getMonth() + 1) +
|
||||
"-" + date.getDate();
|
||||
dateString = dateString.split("-").map(function(part) {
|
||||
dateString = dateString.split("-").map(function (part) {
|
||||
if (part.length == 1) {
|
||||
part = "0" + part;
|
||||
}
|
||||
@ -399,8 +390,7 @@ function saveToClipboard(context, reply) {
|
||||
clip.setData(trans, null, Ci.nsIClipboard.kGlobalClipboard);
|
||||
|
||||
reply.destinations.push(l10n.lookup("screenshotCopied"));
|
||||
}
|
||||
catch (ex) {
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
reply.destinations.push(l10n.lookup("screenshotErrorCopying"));
|
||||
}
|
||||
@ -422,14 +412,15 @@ function uploadToImgur(reply) {
|
||||
fd.append("title", reply.filename);
|
||||
|
||||
const postURL = Services.prefs.getCharPref("devtools.gcli.imgurUploadURL");
|
||||
const clientID = "Client-ID " + Services.prefs.getCharPref("devtools.gcli.imgurClientID");
|
||||
const clientID = "Client-ID " +
|
||||
Services.prefs.getCharPref("devtools.gcli.imgurClientID");
|
||||
|
||||
xhr.open("POST", postURL);
|
||||
xhr.setRequestHeader("Authorization", clientID);
|
||||
xhr.send(fd);
|
||||
xhr.responseType = "json";
|
||||
|
||||
xhr.onreadystatechange = function() {
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status == 200) {
|
||||
reply.href = xhr.response.data.link;
|
||||
@ -477,7 +468,7 @@ function DownloadListener(win, transfer) {
|
||||
}
|
||||
|
||||
DownloadListener.prototype = {
|
||||
QueryInterface: function(iid) {
|
||||
QueryInterface: function (iid) {
|
||||
if (iid.equals(Ci.nsIInterfaceRequestor) ||
|
||||
iid.equals(Ci.nsIWebProgressListener) ||
|
||||
iid.equals(Ci.nsIWebProgressListener2) ||
|
||||
@ -487,7 +478,7 @@ DownloadListener.prototype = {
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
getInterface: function(iid) {
|
||||
getInterface: function (iid) {
|
||||
if (iid.equals(Ci.nsIAuthPrompt) ||
|
||||
iid.equals(Ci.nsIAuthPrompt2)) {
|
||||
let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
@ -498,7 +489,7 @@ DownloadListener.prototype = {
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
onStateChange: function(webProgress, request, state, status) {
|
||||
onStateChange: function (webProgress, request, state, status) {
|
||||
// Check if the download has completed
|
||||
if ((state & Ci.nsIWebProgressListener.STATE_STOP) &&
|
||||
(state & Ci.nsIWebProgressListener.STATE_IS_NETWORK)) {
|
||||
@ -517,7 +508,7 @@ DownloadListener.prototype = {
|
||||
* Save the screenshot data to disk, returning a promise which is resolved on
|
||||
* completion.
|
||||
*/
|
||||
var saveToFile = Task.async(function*(context, reply) {
|
||||
var saveToFile = Task.async(function* (context, reply) {
|
||||
let document = context.environment.chromeDocument;
|
||||
let window = context.environment.chromeWindow;
|
||||
|
||||
|
@ -13,17 +13,15 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu, CC } = require("chrome");
|
||||
const { Ci } = require("chrome");
|
||||
const l10n = require("gcli/l10n");
|
||||
const CSP = Cc["@mozilla.org/cspcontext;1"].getService(Ci.nsIContentSecurityPolicy);
|
||||
|
||||
const GOOD_IMG_SRC = "chrome://browser/content/gcli_sec_good.svg";
|
||||
const MOD_IMG_SRC = "chrome://browser/content/gcli_sec_moderate.svg";
|
||||
const BAD_IMG_SRC = "chrome://browser/content/gcli_sec_bad.svg";
|
||||
|
||||
|
||||
// special handling within policy
|
||||
const POLICY_REPORT_ONLY = "report-only"
|
||||
const POLICY_REPORT_ONLY = "report-only";
|
||||
|
||||
// special handling of directives
|
||||
const DIR_UPGRADE_INSECURE = "upgrade-insecure-requests";
|
||||
@ -42,7 +40,11 @@ const CONTENT_SECURITY_POLICY_REPORT_ONLY_MSG = l10n.lookup("securityCSPROHeader
|
||||
const NEXT_URI_HEADER = l10n.lookup("securityReferrerNextURI");
|
||||
const CALCULATED_REFERRER_HEADER = l10n.lookup("securityReferrerCalculatedReferrer");
|
||||
/* The official names from the W3C Referrer Policy Draft http://www.w3.org/TR/referrer-policy/ */
|
||||
const REFERRER_POLICY_NAMES = [ "None When Downgrade (default)", "None", "Origin Only", "Origin When Cross-Origin", "Unsafe URL" ];
|
||||
const REFERRER_POLICY_NAMES = [
|
||||
"None When Downgrade (default)",
|
||||
"None", "Origin Only",
|
||||
"Origin When Cross-Origin", "Unsafe URL"
|
||||
];
|
||||
|
||||
exports.items = [
|
||||
{
|
||||
@ -59,24 +61,23 @@ exports.items = [
|
||||
description: l10n.lookup("securityCSPDesc"),
|
||||
manual: l10n.lookup("securityCSPManual"),
|
||||
returnType: "securityCSPInfo",
|
||||
exec: function(args, context) {
|
||||
exec: function (args, context) {
|
||||
let cspJSON = context.environment.document.nodePrincipal.cspJSON;
|
||||
let cspOBJ = JSON.parse(cspJSON);
|
||||
|
||||
var cspJSON = context.environment.document.nodePrincipal.cspJSON;
|
||||
var cspOBJ = JSON.parse(cspJSON);
|
||||
let outPolicies = [];
|
||||
|
||||
var outPolicies = [];
|
||||
|
||||
var policies = cspOBJ["csp-policies"];
|
||||
let policies = cspOBJ["csp-policies"];
|
||||
|
||||
// loop over all the different policies
|
||||
for (var csp in policies) {
|
||||
var curPolicy = policies[csp];
|
||||
for (let csp in policies) {
|
||||
let curPolicy = policies[csp];
|
||||
|
||||
// loop over all the directive-values within that policy
|
||||
var outDirectives = [];
|
||||
var outHeader = CONTENT_SECURITY_POLICY_MSG;
|
||||
for (var dir in curPolicy) {
|
||||
var curDir = curPolicy[dir];
|
||||
let outDirectives = [];
|
||||
let outHeader = CONTENT_SECURITY_POLICY_MSG;
|
||||
for (let dir in curPolicy) {
|
||||
let curDir = curPolicy[dir];
|
||||
|
||||
// when iterating properties within the obj we might also
|
||||
// encounter the 'report-only' flag, which is not a csp directive.
|
||||
@ -88,7 +89,7 @@ exports.items = [
|
||||
}
|
||||
|
||||
// loop over all the directive-sources within that directive
|
||||
var outSrcs = [];
|
||||
let outSrcs = [];
|
||||
|
||||
// special case handling for the directives
|
||||
// upgrade-insecure-requests and block-all-mixed-content
|
||||
@ -97,17 +98,19 @@ exports.items = [
|
||||
dir === DIR_BLOCK_ALL_MIXED_CONTENT) {
|
||||
outSrcs.push({
|
||||
icon: GOOD_IMG_SRC,
|
||||
src: "", // no src
|
||||
desc: "" // no description
|
||||
// no src
|
||||
src: "",
|
||||
// no description
|
||||
desc: ""
|
||||
});
|
||||
}
|
||||
|
||||
for (var src in curDir) {
|
||||
var curSrc = curDir[src];
|
||||
for (let src in curDir) {
|
||||
let curSrc = curDir[src];
|
||||
|
||||
// the default icon and descritpion of the directive-src
|
||||
var outIcon = GOOD_IMG_SRC;
|
||||
var outDesc = "";
|
||||
let outIcon = GOOD_IMG_SRC;
|
||||
let outDesc = "";
|
||||
|
||||
if (curSrc.indexOf("*") > -1) {
|
||||
outIcon = MOD_IMG_SRC;
|
||||
@ -142,8 +145,8 @@ exports.items = [
|
||||
item: "converter",
|
||||
from: "securityCSPInfo",
|
||||
to: "view",
|
||||
exec: function(cspInfo, context) {
|
||||
var url = context.environment.target.url;
|
||||
exec: function (cspInfo, context) {
|
||||
const url = context.environment.target.url;
|
||||
|
||||
if (cspInfo.length == 0) {
|
||||
return context.createView({
|
||||
@ -156,6 +159,7 @@ exports.items = [
|
||||
"</table>"});
|
||||
}
|
||||
|
||||
/* eslint-disable max-len */
|
||||
return context.createView({
|
||||
html:
|
||||
"<table class='gcli-csp-detail' cellspacing='10' valign='top'>" +
|
||||
@ -181,10 +185,11 @@ exports.items = [
|
||||
" </td>" +
|
||||
" </tr>" +
|
||||
"</table>",
|
||||
data: {
|
||||
cspinfo: cspInfo,
|
||||
}
|
||||
});
|
||||
data: {
|
||||
cspinfo: cspInfo,
|
||||
}
|
||||
});
|
||||
/* eslint-enable max-len */
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -195,17 +200,17 @@ exports.items = [
|
||||
description: l10n.lookup("securityReferrerPolicyDesc"),
|
||||
manual: l10n.lookup("securityReferrerPolicyManual"),
|
||||
returnType: "securityReferrerPolicyInfo",
|
||||
exec: function(args, context) {
|
||||
var doc = context.environment.document;
|
||||
exec: function (args, context) {
|
||||
let doc = context.environment.document;
|
||||
|
||||
var referrerPolicy = doc.referrerPolicy;
|
||||
let { referrerPolicy } = doc;
|
||||
|
||||
var pageURI = doc.documentURIObject;
|
||||
var sameDomainReferrer = "";
|
||||
var otherDomainReferrer = "";
|
||||
var downgradeReferrer = "";
|
||||
var otherDowngradeReferrer = "";
|
||||
var origin = pageURI.prePath;
|
||||
let pageURI = doc.documentURIObject;
|
||||
let sameDomainReferrer = "";
|
||||
let otherDomainReferrer = "";
|
||||
let downgradeReferrer = "";
|
||||
let otherDowngradeReferrer = "";
|
||||
let origin = pageURI.prePath;
|
||||
|
||||
switch (referrerPolicy) {
|
||||
case Ci.nsIHttpChannel.REFERRER_POLICY_NO_REFERRER:
|
||||
@ -255,28 +260,28 @@ exports.items = [
|
||||
break;
|
||||
}
|
||||
|
||||
var sameDomainUri = origin + "/*";
|
||||
let sameDomainUri = origin + "/*";
|
||||
|
||||
var referrerUrls = [
|
||||
let referrerUrls = [
|
||||
// add the referrer uri 'referrer' we would send when visiting 'uri'
|
||||
{
|
||||
uri: pageURI.scheme+'://example.com/',
|
||||
uri: pageURI.scheme + "://example.com/",
|
||||
referrer: otherDomainReferrer,
|
||||
description: l10n.lookup('securityReferrerPolicyOtherDomain')},
|
||||
description: l10n.lookup("securityReferrerPolicyOtherDomain")},
|
||||
{
|
||||
uri: sameDomainUri,
|
||||
referrer: sameDomainReferrer,
|
||||
description: l10n.lookup('securityReferrerPolicySameDomain')}
|
||||
description: l10n.lookup("securityReferrerPolicySameDomain")}
|
||||
];
|
||||
|
||||
if (pageURI.schemeIs('https')) {
|
||||
if (pageURI.schemeIs("https")) {
|
||||
// add the referrer we would send on downgrading http->https
|
||||
if (sameDomainReferrer != downgradeReferrer) {
|
||||
referrerUrls.push({
|
||||
uri: "http://"+pageURI.hostPort+"/*",
|
||||
uri: "http://" + pageURI.hostPort + "/*",
|
||||
referrer: downgradeReferrer,
|
||||
description:
|
||||
l10n.lookup('securityReferrerPolicySameDomainDowngrade')
|
||||
l10n.lookup("securityReferrerPolicySameDomainDowngrade")
|
||||
});
|
||||
}
|
||||
if (otherDomainReferrer != otherDowngradeReferrer) {
|
||||
@ -284,7 +289,7 @@ exports.items = [
|
||||
uri: "http://example.com/",
|
||||
referrer: otherDowngradeReferrer,
|
||||
description:
|
||||
l10n.lookup('securityReferrerPolicyOtherDomainDowngrade')
|
||||
l10n.lookup("securityReferrerPolicyOtherDomainDowngrade")
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -294,16 +299,16 @@ exports.items = [
|
||||
[pageURI.spec]),
|
||||
policyName: REFERRER_POLICY_NAMES[referrerPolicy],
|
||||
urls: referrerUrls
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
item: "converter",
|
||||
from: "securityReferrerPolicyInfo",
|
||||
to: "view",
|
||||
exec: function(referrerPolicyInfo, context) {
|
||||
exec: function (referrerPolicyInfo, context) {
|
||||
return context.createView({
|
||||
html:
|
||||
html:
|
||||
"<div class='gcli-referrer-policy'>" +
|
||||
" <strong> ${rpi.header} </strong> <br />" +
|
||||
" ${rpi.policyName} <br />" +
|
||||
@ -319,10 +324,10 @@ exports.items = [
|
||||
" </tr>" +
|
||||
" </table>" +
|
||||
"</div>",
|
||||
data: {
|
||||
rpi: referrerPolicyInfo,
|
||||
}
|
||||
});
|
||||
}
|
||||
data: {
|
||||
rpi: referrerPolicyInfo,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -24,12 +24,11 @@
|
||||
* Called to clean up at the end of use
|
||||
*/
|
||||
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const { Cc, Ci } = require("chrome");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const { dumpn, dumpv } = DevToolsUtils;
|
||||
const flags = require("devtools/shared/flags");
|
||||
const StreamUtils = require("devtools/shared/transport/stream-utils");
|
||||
const promise = require("promise");
|
||||
const defer = require("devtools/shared/defer");
|
||||
|
||||
DevToolsUtils.defineLazyGetter(this, "unicodeConverter", () => {
|
||||
@ -136,7 +135,9 @@ Object.defineProperty(JSONPacket.prototype, "object", {
|
||||
/**
|
||||
* Gets the object (not the serialized string) being read or written.
|
||||
*/
|
||||
get: function () { return this._object; },
|
||||
get: function () {
|
||||
return this._object;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the object to be sent when write() is called.
|
||||
@ -200,7 +201,9 @@ JSONPacket.prototype.write = function (stream) {
|
||||
};
|
||||
|
||||
Object.defineProperty(JSONPacket.prototype, "done", {
|
||||
get: function () { return this._done; }
|
||||
get: function () {
|
||||
return this._done;
|
||||
}
|
||||
});
|
||||
|
||||
JSONPacket.prototype.toString = function () {
|
||||
@ -369,10 +372,11 @@ Object.defineProperty(BulkPacket.prototype, "header", {
|
||||
});
|
||||
|
||||
Object.defineProperty(BulkPacket.prototype, "done", {
|
||||
get: function () { return this._done; },
|
||||
get: function () {
|
||||
return this._done;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
BulkPacket.prototype.toString = function () {
|
||||
return "Bulk: " + JSON.stringify(this.header, null, 2);
|
||||
};
|
||||
@ -408,7 +412,9 @@ RawPacket.prototype.write = function (stream) {
|
||||
};
|
||||
|
||||
Object.defineProperty(RawPacket.prototype, "done", {
|
||||
get: function () { return this._done; }
|
||||
get: function () {
|
||||
return this._done;
|
||||
}
|
||||
});
|
||||
|
||||
exports.RawPacket = RawPacket;
|
||||
|
@ -4,12 +4,11 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const { Ci, Cc, Cu, Cr, CC } = require("chrome");
|
||||
const { Ci, Cc, Cr, CC } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const { dumpv } = DevToolsUtils;
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const promise = require("promise");
|
||||
const defer = require("devtools/shared/defer");
|
||||
|
||||
DevToolsUtils.defineLazyGetter(this, "IOUtil", () => {
|
||||
@ -70,8 +69,8 @@ function StreamCopier(input, output, length) {
|
||||
if (IOUtil.outputStreamIsBuffered(output)) {
|
||||
this.output = output;
|
||||
} else {
|
||||
this.output = Cc["@mozilla.org/network/buffered-output-stream;1"].
|
||||
createInstance(Ci.nsIBufferedOutputStream);
|
||||
this.output = Cc["@mozilla.org/network/buffered-output-stream;1"]
|
||||
.createInstance(Ci.nsIBufferedOutputStream);
|
||||
this.output.init(output, BUFFER_SIZE);
|
||||
}
|
||||
this._length = length;
|
||||
@ -124,9 +123,8 @@ StreamCopier.prototype = {
|
||||
this._debug("Waiting for output stream");
|
||||
this.baseAsyncOutput.asyncWait(this, 0, 0, Services.tm.currentThread);
|
||||
return;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
this._amountLeft -= bytesCopied;
|
||||
@ -162,9 +160,8 @@ StreamCopier.prototype = {
|
||||
this._debug("Waiting for output stream");
|
||||
this.baseAsyncOutput.asyncWait(this, 0, 0, Services.tm.currentThread);
|
||||
return;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
this._deferred.resolve();
|
||||
},
|
||||
|
@ -1,9 +1,12 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
(function (root, factory) {
|
||||
"use strict";
|
||||
|
||||
/* eslint-env amd */
|
||||
|
||||
"use strict";
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define(factory);
|
||||
} else if (typeof exports === "object") {
|
||||
@ -12,8 +15,6 @@
|
||||
root.workerHelper = factory();
|
||||
}
|
||||
}(this, function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* This file is to only be included by ChromeWorkers. This exposes
|
||||
* a `createTask` function to workers to register tasks for communication
|
||||
@ -81,23 +82,20 @@
|
||||
}
|
||||
|
||||
try {
|
||||
let results;
|
||||
handleResponse(taskFn(data));
|
||||
} catch (e) {
|
||||
handleError(e);
|
||||
} catch (ex) {
|
||||
handleError(ex);
|
||||
}
|
||||
|
||||
function handleResponse(response) {
|
||||
// If a promise
|
||||
if (response && typeof response.then === "function") {
|
||||
response.then(val => self.postMessage({ id, response: val }), handleError);
|
||||
}
|
||||
// If an error object
|
||||
else if (response instanceof Error) {
|
||||
} else if (response instanceof Error) {
|
||||
// If an error object
|
||||
handleError(response);
|
||||
}
|
||||
// If anything else
|
||||
else {
|
||||
} else {
|
||||
// If anything else
|
||||
self.postMessage({ id, response });
|
||||
}
|
||||
}
|
||||
@ -106,21 +104,23 @@
|
||||
try {
|
||||
// First, try and structured clone the error across directly.
|
||||
self.postMessage({ id, error });
|
||||
} catch (_) {
|
||||
} catch (x) {
|
||||
// We could not clone whatever error value was given. Do our best to
|
||||
// stringify it.
|
||||
let errorString = `Error while performing task "${task}": `;
|
||||
|
||||
try {
|
||||
errorString += error.toString();
|
||||
} catch (_) {
|
||||
} catch (ex) {
|
||||
errorString += "<could not stringify error>";
|
||||
}
|
||||
|
||||
if ("stack" in error) {
|
||||
try {
|
||||
errorString += "\n" + error.stack;
|
||||
} catch (_) { }
|
||||
} catch (err) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
self.postMessage({ id, error: errorString });
|
||||
@ -130,4 +130,4 @@
|
||||
}
|
||||
|
||||
return { createTask: createTask };
|
||||
}.bind(this)));
|
||||
}));
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
/* global worker */
|
||||
|
||||
// A CommonJS module loader that is designed to run inside a worker debugger.
|
||||
// We can't simply use the SDK module loader, because it relies heavily on
|
||||
// Components, which isn't available in workers.
|
||||
@ -60,7 +62,7 @@ function normalizeId(id) {
|
||||
// An id consists of an optional root and a path. A root consists of either
|
||||
// a scheme name followed by 2 or 3 slashes, or a single slash. Slashes in the
|
||||
// root are not used as separators, so only normalize the path.
|
||||
let [_, root, path] = id.match(/^(\w+:\/\/\/?|\/)?(.*)/);
|
||||
let [, root, path] = id.match(/^(\w+:\/\/\/?|\/)?(.*)/);
|
||||
|
||||
let stack = [];
|
||||
path.split("/").forEach(function (component) {
|
||||
@ -75,12 +77,10 @@ function normalizeId(id) {
|
||||
} else {
|
||||
stack.push("..");
|
||||
}
|
||||
} else if (stack[stack.length - 1] == "..") {
|
||||
stack.push("..");
|
||||
} else {
|
||||
if (stack[stack.length - 1] == "..") {
|
||||
stack.push("..");
|
||||
} else {
|
||||
stack.pop();
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -336,7 +336,8 @@ var loader = {
|
||||
Object.defineProperty(object, name, {
|
||||
get: function () {
|
||||
delete object[name];
|
||||
return object[name] = lambda.apply(object);
|
||||
object[name] = lambda.apply(object);
|
||||
return object[name];
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
@ -361,6 +362,7 @@ var loader = {
|
||||
// object to implement them. On worker threads, we use the APIs provided by
|
||||
// the worker debugger.
|
||||
|
||||
/* eslint-disable no-shadow */
|
||||
var {
|
||||
Debugger,
|
||||
URL,
|
||||
@ -372,13 +374,12 @@ var {
|
||||
setImmediate,
|
||||
xpcInspector,
|
||||
} = (function () {
|
||||
if (typeof Components === "object") { // Main thread
|
||||
// Main thread
|
||||
if (typeof Components === "object") {
|
||||
let {
|
||||
Constructor: CC,
|
||||
classes: Cc,
|
||||
manager: Cm,
|
||||
interfaces: Ci,
|
||||
results: Cr,
|
||||
utils: Cu
|
||||
} = Components;
|
||||
|
||||
@ -406,8 +407,8 @@ var {
|
||||
|
||||
let rpc = undefined;
|
||||
|
||||
let subScriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
|
||||
getService(Ci.mozIJSSubScriptLoader);
|
||||
let subScriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader);
|
||||
|
||||
let loadSubScript = function (url, sandbox) {
|
||||
subScriptLoader.loadSubScript(url, sandbox, "UTF-8");
|
||||
@ -421,8 +422,8 @@ var {
|
||||
Timer.setTimeout(callback, 0);
|
||||
};
|
||||
|
||||
let xpcInspector = Cc["@mozilla.org/jsinspector;1"].
|
||||
getService(Ci.nsIJSInspector);
|
||||
let xpcInspector = Cc["@mozilla.org/jsinspector;1"]
|
||||
.getService(Ci.nsIJSInspector);
|
||||
|
||||
return {
|
||||
Debugger,
|
||||
@ -435,46 +436,47 @@ var {
|
||||
setImmediate,
|
||||
xpcInspector
|
||||
};
|
||||
} else { // Worker thread
|
||||
let requestors = [];
|
||||
|
||||
let scope = this;
|
||||
|
||||
let xpcInspector = {
|
||||
get eventLoopNestLevel() {
|
||||
return requestors.length;
|
||||
},
|
||||
|
||||
get lastNestRequestor() {
|
||||
return requestors.length === 0 ? null : requestors[requestors.length - 1];
|
||||
},
|
||||
|
||||
enterNestedEventLoop: function (requestor) {
|
||||
requestors.push(requestor);
|
||||
scope.enterEventLoop();
|
||||
return requestors.length;
|
||||
},
|
||||
|
||||
exitNestedEventLoop: function () {
|
||||
requestors.pop();
|
||||
scope.leaveEventLoop();
|
||||
return requestors.length;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
Debugger: this.Debugger,
|
||||
URL: this.URL,
|
||||
createSandbox: this.createSandbox,
|
||||
dump: this.dump,
|
||||
rpc: this.rpc,
|
||||
loadSubScript: this.loadSubScript,
|
||||
reportError: this.reportError,
|
||||
setImmediate: this.setImmediate,
|
||||
xpcInspector: xpcInspector
|
||||
};
|
||||
}
|
||||
// Worker thread
|
||||
let requestors = [];
|
||||
|
||||
let scope = this;
|
||||
|
||||
let xpcInspector = {
|
||||
get eventLoopNestLevel() {
|
||||
return requestors.length;
|
||||
},
|
||||
|
||||
get lastNestRequestor() {
|
||||
return requestors.length === 0 ? null : requestors[requestors.length - 1];
|
||||
},
|
||||
|
||||
enterNestedEventLoop: function (requestor) {
|
||||
requestors.push(requestor);
|
||||
scope.enterEventLoop();
|
||||
return requestors.length;
|
||||
},
|
||||
|
||||
exitNestedEventLoop: function () {
|
||||
requestors.pop();
|
||||
scope.leaveEventLoop();
|
||||
return requestors.length;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
Debugger: this.Debugger,
|
||||
URL: this.URL,
|
||||
createSandbox: this.createSandbox,
|
||||
dump: this.dump,
|
||||
rpc: this.rpc,
|
||||
loadSubScript: this.loadSubScript,
|
||||
reportError: this.reportError,
|
||||
setImmediate: this.setImmediate,
|
||||
xpcInspector: xpcInspector
|
||||
};
|
||||
}).call(this);
|
||||
/* eslint-enable no-shadow */
|
||||
|
||||
// Create the default instance of the worker loader, using the APIs we defined
|
||||
// above.
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that the devtools/shared/worker communicates properly
|
||||
// as both CommonJS module and as a JSM.
|
||||
|
||||
@ -37,7 +39,7 @@ function* testWorker(context, workerFactory) {
|
||||
ok(results.plottedData.length,
|
||||
`worker should have returned an object with array properties in ${context}`);
|
||||
|
||||
let fn = workerify(function (x) { return x * x; });
|
||||
let fn = workerify(x => x * x);
|
||||
is((yield fn(5)), 25, `workerify works in ${context}`);
|
||||
fn.destroy();
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests errors are handled properly by the DevToolsWorker.
|
||||
|
||||
const { DevToolsWorker } = require("devtools/shared/worker/worker");
|
||||
@ -9,7 +11,7 @@ const WORKER_URL =
|
||||
|
||||
add_task(function* () {
|
||||
try {
|
||||
let workerNotFound = new DevToolsWorker("resource://i/dont/exist.js");
|
||||
new DevToolsWorker("resource://i/dont/exist.js");
|
||||
ok(false, "Creating a DevToolsWorker with an invalid URL throws");
|
||||
} catch (e) {
|
||||
ok(true, "Creating a DevToolsWorker with an invalid URL throws");
|
||||
@ -19,14 +21,16 @@ add_task(function* () {
|
||||
try {
|
||||
// plotTimestampsGraph requires timestamp, interval an duration props on the object
|
||||
// passed in so there should be an error thrown in the worker
|
||||
let results = yield worker.performTask("plotTimestampsGraph", {});
|
||||
ok(false, "DevToolsWorker returns a rejected promise when an error occurs in the worker");
|
||||
yield worker.performTask("plotTimestampsGraph", {});
|
||||
ok(false,
|
||||
"DevToolsWorker returns a rejected promise when an error occurs in the worker");
|
||||
} catch (e) {
|
||||
ok(true, "DevToolsWorker returns a rejected promise when an error occurs in the worker");
|
||||
ok(true,
|
||||
"DevToolsWorker returns a rejected promise when an error occurs in the worker");
|
||||
}
|
||||
|
||||
try {
|
||||
let results = yield worker.performTask("not a real task");
|
||||
yield worker.performTask("not a real task");
|
||||
ok(false, "DevToolsWorker returns a rejected promise when task does not exist");
|
||||
} catch (e) {
|
||||
ok(true, "DevToolsWorker returns a rejected promise when task does not exist");
|
||||
@ -34,7 +38,7 @@ add_task(function* () {
|
||||
|
||||
worker.destroy();
|
||||
try {
|
||||
let results = yield worker.performTask("plotTimestampsGraph", {
|
||||
yield worker.performTask("plotTimestampsGraph", {
|
||||
timestamps: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||
interval: 1,
|
||||
duration: 1
|
||||
|
@ -1,12 +1,14 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that the devtools/shared/worker can handle:
|
||||
// returned primitives (or promise or Error)
|
||||
//
|
||||
// And tests `workerify` by doing so.
|
||||
|
||||
const { DevToolsWorker, workerify } = require("devtools/shared/worker/worker");
|
||||
const { workerify } = require("devtools/shared/worker/worker");
|
||||
function square(x) {
|
||||
return x * x;
|
||||
}
|
||||
|
@ -68,7 +68,6 @@
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsQueryObject.h"
|
||||
@ -1633,7 +1632,7 @@ nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
|
||||
uri,
|
||||
aStream,
|
||||
triggeringPrincipal,
|
||||
nsILoadInfo::SEC_NORMAL,
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
aContentType,
|
||||
aContentCharset);
|
||||
@ -9866,23 +9865,6 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
#endif
|
||||
}
|
||||
|
||||
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(contentType,
|
||||
aURI,
|
||||
aTriggeringPrincipal,
|
||||
requestingContext,
|
||||
EmptyCString(), // mime guess
|
||||
nullptr, // extra
|
||||
&shouldLoad);
|
||||
|
||||
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
|
||||
if (NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) {
|
||||
return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
|
||||
}
|
||||
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
|
||||
// If HSTS priming was set by nsMixedContentBlocker::ShouldLoad, and we
|
||||
// would block due to mixed content, go ahead and block here. If we try to
|
||||
// proceed with priming, we will error out later on.
|
||||
@ -10881,7 +10863,8 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||
}
|
||||
|
||||
nsLoadFlags loadFlags = mDefaultLoadFlags;
|
||||
nsSecurityFlags securityFlags = nsILoadInfo::SEC_NORMAL;
|
||||
nsSecurityFlags securityFlags =
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
|
||||
|
||||
if (aFirstParty) {
|
||||
// tag first party URL loads
|
||||
@ -13804,7 +13787,8 @@ public:
|
||||
nsIInputStream* aPostDataStream,
|
||||
nsIInputStream* aHeadersDataStream,
|
||||
bool aNoOpenerImplied,
|
||||
bool aIsTrusted);
|
||||
bool aIsTrusted,
|
||||
nsIPrincipal* aTriggeringPrincipal);
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
@ -13821,7 +13805,7 @@ public:
|
||||
mTargetSpec.get(), mFileName,
|
||||
mPostDataStream, mHeadersDataStream,
|
||||
mNoOpenerImplied,
|
||||
nullptr, nullptr);
|
||||
nullptr, nullptr, mTriggeringPrincipal);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -13837,6 +13821,7 @@ private:
|
||||
PopupControlState mPopupState;
|
||||
bool mNoOpenerImplied;
|
||||
bool mIsTrusted;
|
||||
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
|
||||
};
|
||||
|
||||
OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
|
||||
@ -13847,7 +13832,8 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
|
||||
nsIInputStream* aPostDataStream,
|
||||
nsIInputStream* aHeadersDataStream,
|
||||
bool aNoOpenerImplied,
|
||||
bool aIsTrusted)
|
||||
bool aIsTrusted,
|
||||
nsIPrincipal* aTriggeringPrincipal)
|
||||
: mHandler(aHandler)
|
||||
, mURI(aURI)
|
||||
, mTargetSpec(aTargetSpec)
|
||||
@ -13858,6 +13844,7 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
|
||||
, mPopupState(mHandler->mScriptGlobal->GetPopupControlState())
|
||||
, mNoOpenerImplied(aNoOpenerImplied)
|
||||
, mIsTrusted(aIsTrusted)
|
||||
, mTriggeringPrincipal(aTriggeringPrincipal)
|
||||
{
|
||||
}
|
||||
|
||||
@ -13868,7 +13855,8 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
|
||||
const nsAString& aFileName,
|
||||
nsIInputStream* aPostDataStream,
|
||||
nsIInputStream* aHeadersDataStream,
|
||||
bool aIsTrusted)
|
||||
bool aIsTrusted,
|
||||
nsIPrincipal* aTriggeringPrincipal)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "wrong thread");
|
||||
|
||||
@ -13912,7 +13900,7 @@ nsDocShell::OnLinkClick(nsIContent* aContent,
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new OnLinkClickEvent(this, aContent, aURI, target.get(), aFileName,
|
||||
aPostDataStream, aHeadersDataStream, noOpenerImplied,
|
||||
aIsTrusted);
|
||||
aIsTrusted, aTriggeringPrincipal);
|
||||
return NS_DispatchToCurrentThread(ev);
|
||||
}
|
||||
|
||||
@ -13925,7 +13913,8 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
||||
nsIInputStream* aHeadersDataStream,
|
||||
bool aNoOpenerImplied,
|
||||
nsIDocShell** aDocShell,
|
||||
nsIRequest** aRequest)
|
||||
nsIRequest** aRequest,
|
||||
nsIPrincipal* aTriggeringPrincipal)
|
||||
{
|
||||
// Initialize the DocShell / Request
|
||||
if (aDocShell) {
|
||||
@ -14051,13 +14040,18 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// if the triggeringPrincipal is not passed explicitly, then we
|
||||
// fall back to using doc->NodePrincipal() as the triggeringPrincipal.
|
||||
nsCOMPtr<nsIPrincipal> triggeringPrincipal =
|
||||
aTriggeringPrincipal ? aTriggeringPrincipal
|
||||
: aContent->NodePrincipal();
|
||||
|
||||
nsresult rv = InternalLoad(clonedURI, // New URI
|
||||
nullptr, // Original URI
|
||||
false, // LoadReplace
|
||||
referer, // Referer URI
|
||||
refererPolicy, // Referer policy
|
||||
aContent->NodePrincipal(), // Triggering is our node's
|
||||
// principal
|
||||
triggeringPrincipal,
|
||||
aContent->NodePrincipal(),
|
||||
flags,
|
||||
target, // Window target
|
||||
@ -14739,44 +14733,31 @@ nsDocShell::GetCommandManager()
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetIsProcessLocked(bool* aIsLocked)
|
||||
nsDocShell::GetIsOnlyToplevelInTabGroup(bool* aResult)
|
||||
{
|
||||
MOZ_ASSERT(aIsLocked);
|
||||
*aIsLocked = GetProcessLockReason() != PROCESS_LOCK_NONE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetProcessLockReason(uint32_t* aReason)
|
||||
{
|
||||
MOZ_ASSERT(aReason);
|
||||
MOZ_ASSERT(aResult);
|
||||
|
||||
nsPIDOMWindowOuter* outer = GetWindow();
|
||||
MOZ_ASSERT(outer);
|
||||
|
||||
// Check if we are a toplevel window
|
||||
// If we are not toplevel then we are not the only toplevel window in the tab
|
||||
// group.
|
||||
if (outer->GetScriptableParentOrNull()) {
|
||||
*aReason = PROCESS_LOCK_IFRAME;
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we have any other toplevel windows in our tab group, then we cannot
|
||||
// perform the navigation.
|
||||
// If we have any other toplevel windows in our tab group, then we are not the
|
||||
// only toplevel window in the tab group.
|
||||
nsTArray<nsPIDOMWindowOuter*> toplevelWindows =
|
||||
outer->TabGroup()->GetTopLevelWindows();
|
||||
if (toplevelWindows.Length() > 1) {
|
||||
*aReason = PROCESS_LOCK_RELATED_CONTEXTS;
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
MOZ_ASSERT(toplevelWindows.Length() == 1);
|
||||
MOZ_ASSERT(toplevelWindows[0] == outer);
|
||||
|
||||
// If we aren't in a content process, we cannot perform a cross-process load.
|
||||
if (!XRE_IsContentProcess()) {
|
||||
*aReason = PROCESS_LOCK_NON_CONTENT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aReason = PROCESS_LOCK_NONE;
|
||||
*aResult = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -200,7 +200,8 @@ public:
|
||||
const nsAString& aFileName,
|
||||
nsIInputStream* aPostDataStream,
|
||||
nsIInputStream* aHeadersDataStream,
|
||||
bool aIsTrusted) override;
|
||||
bool aIsTrusted,
|
||||
nsIPrincipal* aTriggeringPrincipal) override;
|
||||
NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
|
||||
nsIURI* aURI,
|
||||
const char16_t* aTargetSpec,
|
||||
@ -209,7 +210,8 @@ public:
|
||||
nsIInputStream* aHeadersDataStream = 0,
|
||||
bool aNoOpenerImplied = false,
|
||||
nsIDocShell** aDocShell = 0,
|
||||
nsIRequest** aRequest = 0) override;
|
||||
nsIRequest** aRequest = 0,
|
||||
nsIPrincipal* aTriggeringPrincipal = nullptr) override;
|
||||
NS_IMETHOD OnOverLink(nsIContent* aContent,
|
||||
nsIURI* aURI,
|
||||
const char16_t* aTargetSpec) override;
|
||||
|
@ -1112,38 +1112,16 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
const unsigned long TOUCHEVENTS_OVERRIDE_NONE = 2;
|
||||
|
||||
/**
|
||||
* A DocShell is locked to the current process if it would be
|
||||
* content-observable for a process switch to occur before performing a
|
||||
* navigation load. It is important to ensure that a DocShell is not process
|
||||
* locked before performing process changing loads.
|
||||
*/
|
||||
[infallible] readonly attribute boolean isProcessLocked;
|
||||
/**
|
||||
* Return PROCESS_LOCK_NONE if docShell is not locked to current process,
|
||||
* otherwise return the reason why process is locked.
|
||||
*/
|
||||
[infallible] readonly attribute unsigned long processLockReason;
|
||||
/**
|
||||
* The DocShell is not locked to the current process, and a navigation may
|
||||
* proceed in a new process.
|
||||
*/
|
||||
const unsigned long PROCESS_LOCK_NONE = 0;
|
||||
/**
|
||||
* The DocShell is locked to the current process because it is not a
|
||||
* toplevel browsing context.
|
||||
*/
|
||||
const unsigned long PROCESS_LOCK_IFRAME = 1;
|
||||
/**
|
||||
* The DocShell is locked to the current process because there exist other
|
||||
* related browsing contexts which may be holding a reference.
|
||||
*/
|
||||
const unsigned long PROCESS_LOCK_RELATED_CONTEXTS = 2;
|
||||
/**
|
||||
* The DocShell is locked to the current process because the current
|
||||
* process is not a content process.
|
||||
* This value is `true` if its corresponding unit of related browsing contexts
|
||||
* (TabGroup) contains only 1 toplevel window, and that window is the outer
|
||||
* window corresponding to this docshell.
|
||||
*
|
||||
* NOTE: Some loads may not consider this a hard process lock, and may wish to
|
||||
* ignore this reason.
|
||||
* The value is `false` otherwise. This is the case if the docshell is an
|
||||
* iframe, has window.opener set, or another window with window.opener
|
||||
* referring to this window exists.
|
||||
*
|
||||
* If this value is `false`, it would be web content visible for a load
|
||||
* occuring in this docshell to be performed within a different docshell.
|
||||
*/
|
||||
const unsigned long PROCESS_LOCK_NON_CONTENT = 3;
|
||||
[infallible] readonly attribute boolean isOnlyToplevelInTabGroup;
|
||||
};
|
||||
|
@ -37,6 +37,8 @@ public:
|
||||
* @param aFileName non-null when the link should be downloaded as the given file
|
||||
* @param aHeadersDataStream ???
|
||||
* @param aIsTrusted false if the triggerer is an untrusted DOM event.
|
||||
* @param aTriggeringPrincipal, if not passed explicitly we fall back to
|
||||
* the document's principal.
|
||||
*/
|
||||
NS_IMETHOD OnLinkClick(nsIContent* aContent,
|
||||
nsIURI* aURI,
|
||||
@ -44,7 +46,8 @@ public:
|
||||
const nsAString& aFileName,
|
||||
nsIInputStream* aPostDataStream,
|
||||
nsIInputStream* aHeadersDataStream,
|
||||
bool aIsTrusted) = 0;
|
||||
bool aIsTrusted,
|
||||
nsIPrincipal* aTriggeringPrincipal) = 0;
|
||||
|
||||
/**
|
||||
* Process a click on a link.
|
||||
@ -62,6 +65,8 @@ public:
|
||||
* @param aNoOpenerImplied if the link implies "noopener"
|
||||
* @param aDocShell (out-param) the DocShell that the request was opened on
|
||||
* @param aRequest the request that was opened
|
||||
* @param aTriggeringPrincipal, if not passed explicitly we fall back to
|
||||
* the document's principal.
|
||||
*/
|
||||
NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
|
||||
nsIURI* aURI,
|
||||
@ -71,7 +76,8 @@ public:
|
||||
nsIInputStream* aHeadersDataStream = 0,
|
||||
bool aNoOpenerImplied = false,
|
||||
nsIDocShell** aDocShell = 0,
|
||||
nsIRequest** aRequest = 0) = 0;
|
||||
nsIRequest** aRequest = 0,
|
||||
nsIPrincipal* aTriggeringPrincipal = nullptr) = 0;
|
||||
|
||||
/**
|
||||
* Process a mouse-over a link.
|
||||
|
@ -29,7 +29,23 @@ var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
// We need to wait for the hidden window to load, but can't access
|
||||
// an event target for a regular event listener.
|
||||
var hidden = mainWindow.Services.appShell.hiddenPrivateDOMWindow;
|
||||
mainWindow.PrivateBrowsingUtils.whenHiddenPrivateWindowReady(function(hidden) {
|
||||
|
||||
function isNotLoaded() {
|
||||
return ["complete", "interactive"].indexOf(hidden.document.readyState) == -1;
|
||||
}
|
||||
if (isNotLoaded()) {
|
||||
setTimeout(function poll() {
|
||||
if (isNotLoaded()) {
|
||||
setTimeout(poll, 100);
|
||||
return;
|
||||
}
|
||||
onHiddenPrivateWindowReady();
|
||||
}, 4);
|
||||
} else {
|
||||
onHiddenPrivateWindowReady();
|
||||
}
|
||||
|
||||
function onHiddenPrivateWindowReady() {
|
||||
var iframe = hidden.document.createElement('iframe');
|
||||
iframe.src = 'generic.html';
|
||||
hidden.document.body.appendChild(iframe);
|
||||
@ -40,7 +56,7 @@ mainWindow.PrivateBrowsingUtils.whenHiddenPrivateWindowReady(function(hidden) {
|
||||
win.close();
|
||||
win = null;
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
function observer(aSubject, aTopic, aData) {
|
||||
is(aTopic, "last-pb-context-exited", "Unexpected observer topic");
|
||||
|
@ -23,7 +23,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AnimationEffectReadOnly)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument, mTiming, mAnimation)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(AnimationEffectReadOnly)
|
||||
|
@ -21,7 +21,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AnimationTimeline)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow, mAnimations)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(AnimationTimeline)
|
||||
|
@ -59,8 +59,6 @@ Attr::Attr(nsDOMAttributeMap *aAttrMap,
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Attr)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Attr)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
|
||||
if (!nsINode::Traverse(tmp, cb)) {
|
||||
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
|
||||
}
|
||||
|
@ -139,7 +139,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementRegistry)
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWhenDefinedPromiseMap)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CustomElementRegistry)
|
||||
|
@ -165,7 +165,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(Exception)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Exception)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mData)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Exception)
|
||||
|
@ -51,7 +51,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMIntersectionObserver)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMIntersectionObserver)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
|
||||
|
@ -84,7 +84,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FormData)
|
||||
"mFormData[i].GetAsBlob()", 0);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(FormData)
|
||||
|
@ -1904,10 +1904,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(FragmentOrElement, tmp->mRefCnt.get())
|
||||
}
|
||||
|
||||
// Always need to traverse script objects, so do that before we check
|
||||
// if we're uncollectable.
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
|
||||
if (!nsINode::Traverse(tmp, cb)) {
|
||||
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
|
||||
}
|
||||
|
@ -79,7 +79,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Location)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInnerWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Location)
|
||||
|
@ -217,7 +217,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresentation)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Navigator)
|
||||
|
@ -26,7 +26,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Pose)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Pose)
|
||||
|
@ -52,7 +52,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ProcessGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal)
|
||||
tmp->TraverseHostObjectURIs(cb);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ProcessGlobal)
|
||||
|
@ -54,7 +54,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsBaseContentList)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBaseContentList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElements)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsBaseContentList)
|
||||
|
||||
|
@ -5133,7 +5133,7 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
|
||||
|
||||
handler->OnLinkClick(aContent, aLinkURI,
|
||||
fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(),
|
||||
fileName, nullptr, nullptr, aIsTrusted);
|
||||
fileName, nullptr, nullptr, aIsTrusted, aContent->NodePrincipal());
|
||||
}
|
||||
}
|
||||
|
||||
@ -9702,39 +9702,28 @@ nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel)
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIDocShell* docShell = outer->GetDocShell();
|
||||
nsIDocument* doc = outer->GetExtantDoc();
|
||||
|
||||
// If the docshell is not allowed to change process, report an error based on
|
||||
// the reason
|
||||
const char* errorName = nullptr;
|
||||
switch (docShell->GetProcessLockReason()) {
|
||||
case nsIDocShell::PROCESS_LOCK_NON_CONTENT:
|
||||
errorName = "LargeAllocationNonE10S";
|
||||
break;
|
||||
case nsIDocShell::PROCESS_LOCK_IFRAME:
|
||||
errorName = "LargeAllocationIFrame";
|
||||
break;
|
||||
case nsIDocShell::PROCESS_LOCK_RELATED_CONTEXTS:
|
||||
errorName = "LargeAllocationRelatedBrowsingContexts";
|
||||
break;
|
||||
case nsIDocShell::PROCESS_LOCK_NONE:
|
||||
// Don't print a warning, we're allowed to change processes!
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Should be unreachable!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errorName) {
|
||||
if (!XRE_IsContentProcess()) {
|
||||
if (doc) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DOM"),
|
||||
doc,
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
errorName);
|
||||
"LargeAllocationNonE10S");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIDocShell* docShell = outer->GetDocShell();
|
||||
if (!docShell->GetIsOnlyToplevelInTabGroup()) {
|
||||
if (doc) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DOM"),
|
||||
doc,
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"LargeAllocationRelatedBrowsingContexts");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMAttributeMap)
|
||||
for (auto iter = tmp->mAttributeCache.Iter(); !iter.Done(); iter.Next()) {
|
||||
cb.NoteXPCOMChild(static_cast<nsINode*>(iter.Data().get()));
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
@ -506,7 +506,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMMutationObserver)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMMutationObserver)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReceivers)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFirstPendingMutation)
|
||||
|
@ -1634,10 +1634,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsDocument, tmp->mRefCnt.get())
|
||||
}
|
||||
|
||||
// Always need to traverse script objects, so do that before we check
|
||||
// if we're uncollectable.
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
|
||||
if (!nsINode::Traverse(tmp, cb)) {
|
||||
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
|
||||
}
|
||||
@ -2964,11 +2960,16 @@ nsIDocument::PrerenderHref(nsIURI* aHref)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adopting an out-of-process prerendered document is conceptually similar to
|
||||
// switching dochshell's process, since it's the same browsing context from
|
||||
// other browsing contexts' perspective. If we're locked in current process,
|
||||
// we can not prerender out-of-process.
|
||||
if (docShell->GetIsProcessLocked()) {
|
||||
// We currently do not support prerendering in documents loaded within the
|
||||
// chrome process.
|
||||
if (!XRE_IsContentProcess()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adopting an prerendered document is similar to performing a load within a
|
||||
// different docshell, as the prerendering must have occurred in a different
|
||||
// docshell.
|
||||
if (!docShell->GetIsOnlyToplevelInTabGroup()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager)
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildManagers)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsFrameMessageManager)
|
||||
|
@ -98,10 +98,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGenericDOMDataNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGenericDOMDataNode, tmp->mRefCnt.get())
|
||||
}
|
||||
|
||||
// Always need to traverse script objects, so do that before we check
|
||||
// if we're uncollectable.
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
|
||||
if (!nsINode::Traverse(tmp, cb)) {
|
||||
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
|
||||
}
|
||||
|
@ -1992,8 +1992,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMozSelfSupport)
|
||||
|
||||
tmp->TraverseHostObjectURIs(cb);
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
||||
|
@ -626,7 +626,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSContext)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSContext)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobalObjectRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSContext)
|
||||
@ -2737,7 +2736,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSArgArray)
|
||||
tmp->ReleaseJSObjects();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSArgArray)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSArgArray)
|
||||
|
@ -150,7 +150,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSScriptTimeoutHandler)
|
||||
|
||||
if (tmp->mFunction) {
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFunction)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
@ -353,7 +353,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsRange)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelection)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsRange)
|
||||
|
@ -346,7 +346,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsModuleScript)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsModuleScript)
|
||||
|
@ -133,7 +133,7 @@ nsWrapperCache::CheckCCWrapperTraversal(void* aScriptObjectHolder,
|
||||
// see through the COM layer, so we use a suppression to help it.
|
||||
JS::AutoSuppressGCAnalysis suppress;
|
||||
|
||||
aTracer->Traverse(aScriptObjectHolder, callback);
|
||||
aTracer->TraverseNativeAndJS(aScriptObjectHolder, callback);
|
||||
MOZ_ASSERT(callback.mFound,
|
||||
"Cycle collection participant didn't traverse to preserved "
|
||||
"wrapper! This will probably crash.");
|
||||
|
@ -331,8 +331,7 @@ private:
|
||||
* causes between the native object and the JS object, so it is important that
|
||||
* any native object that supports preserving of its wrapper
|
||||
* traces/traverses/unlinks the cached JS object (see
|
||||
* NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER,
|
||||
* NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS and
|
||||
* NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER and
|
||||
* NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER).
|
||||
*/
|
||||
enum { WRAPPER_BIT_PRESERVED = 1 << 0 };
|
||||
@ -383,7 +382,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
|
||||
|
||||
@ -395,7 +393,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(__VA_ARGS__) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
|
||||
|
||||
|
@ -39,7 +39,6 @@ var policy = {
|
||||
{
|
||||
// Remember last content type seen for the test url
|
||||
if (contentLocation.spec.endsWith(urlSuffix)) {
|
||||
assert.ok(frame === browserElement, "correct <browser> element");
|
||||
sendAsyncMessage("shouldLoad", {contentType: contentType, isTopLevel: isTopLevel});
|
||||
return Ci.nsIContentPolicy.REJECT_REQUEST;
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CallbackObject)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncumbentGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncumbentGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackObject)
|
||||
|
@ -14985,7 +14985,6 @@ class CGJSImplClass(CGBindingImplClass):
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(${ifaceName})
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImpl)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(${ifaceName})
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(${ifaceName})
|
||||
|
@ -305,7 +305,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(JSStackFrame)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCaller)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAsyncCaller)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(JSStackFrame)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mStack)
|
||||
|
@ -29,8 +29,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SimpleGlobalObject)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(SimpleGlobalObject)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
tmp->TraverseHostObjectURIs(cb);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
@ -1010,7 +1010,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CanvasRenderingContext2D)
|
||||
ImplCycleCollectionTraverse(cb, info.mElement, "Hit region fallback element");
|
||||
}
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(CanvasRenderingContext2D)
|
||||
|
@ -29,7 +29,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ImageData)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ImageData)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ImageData)
|
||||
|
@ -654,6 +654,17 @@ WebGLProgram::GetAttribLocation(const nsAString& userName_wide) const
|
||||
return GLint(info->mLoc);
|
||||
}
|
||||
|
||||
static GLint
|
||||
GetFragDataByUserName(const WebGLProgram* prog,
|
||||
const nsCString& userName)
|
||||
{
|
||||
nsCString mappedName;
|
||||
if (!prog->LinkInfo()->MapFragDataName(userName, &mappedName))
|
||||
return -1;
|
||||
|
||||
return prog->mContext->gl->fGetFragDataLocation(prog->mGLName, mappedName.BeginReading());
|
||||
}
|
||||
|
||||
GLint
|
||||
WebGLProgram::GetFragDataLocation(const nsAString& userName_wide) const
|
||||
{
|
||||
@ -665,14 +676,30 @@ WebGLProgram::GetFragDataLocation(const nsAString& userName_wide) const
|
||||
return -1;
|
||||
}
|
||||
|
||||
const NS_LossyConvertUTF16toASCII userName(userName_wide);
|
||||
nsCString mappedName;
|
||||
if (!LinkInfo()->MapFragDataName(userName, &mappedName))
|
||||
return -1;
|
||||
|
||||
gl::GLContext* gl = mContext->GL();
|
||||
const auto& gl = mContext->gl;
|
||||
gl->MakeCurrent();
|
||||
return gl->fGetFragDataLocation(mGLName, mappedName.BeginReading());
|
||||
|
||||
const NS_LossyConvertUTF16toASCII userName(userName_wide);
|
||||
#ifdef XP_MACOSX
|
||||
if (gl->WorkAroundDriverBugs()) {
|
||||
// OSX doesn't return locs for indexed names, just the base names.
|
||||
// Indicated by failure in: conformance2/programs/gl-get-frag-data-location.html
|
||||
bool isArray;
|
||||
size_t arrayIndex;
|
||||
nsCString baseUserName;
|
||||
if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
|
||||
return -1;
|
||||
|
||||
if (arrayIndex >= mContext->mImplMaxDrawBuffers)
|
||||
return -1;
|
||||
|
||||
const auto baseLoc = GetFragDataByUserName(this, baseUserName);
|
||||
const auto loc = baseLoc + GLint(arrayIndex);
|
||||
return loc;
|
||||
}
|
||||
#endif
|
||||
return GetFragDataByUserName(this, userName);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -158,19 +158,24 @@ WebGLShader::~WebGLShader()
|
||||
void
|
||||
WebGLShader::ShaderSource(const nsAString& source)
|
||||
{
|
||||
StripComments stripComments(source);
|
||||
const nsAString& cleanSource = Substring(stripComments.result().Elements(),
|
||||
stripComments.length());
|
||||
if (!ValidateGLSLString(cleanSource, mContext, "shaderSource"))
|
||||
const char funcName[] = "shaderSource";
|
||||
nsString sourceWithoutComments;
|
||||
if (!TruncateComments(source, &sourceWithoutComments)) {
|
||||
mContext->ErrorOutOfMemory("%s: Failed to alloc for empting comment contents.",
|
||||
funcName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ValidateGLSLPreprocString(mContext, funcName, sourceWithoutComments))
|
||||
return;
|
||||
|
||||
// We checked that the source stripped of comments is in the
|
||||
// 7-bit ASCII range, so we can skip the NS_IsAscii() check.
|
||||
const NS_LossyConvertUTF16toASCII sourceCString(cleanSource);
|
||||
const NS_LossyConvertUTF16toASCII cleanSource(sourceWithoutComments);
|
||||
|
||||
if (mContext->gl->WorkAroundDriverBugs()) {
|
||||
const size_t maxSourceLength = 0x3ffff;
|
||||
if (sourceCString.Length() > maxSourceLength) {
|
||||
if (cleanSource.Length() > maxSourceLength) {
|
||||
mContext->ErrorInvalidValue("shaderSource: Source has more than %d"
|
||||
" characters. (Driver workaround)",
|
||||
maxSourceLength);
|
||||
@ -185,20 +190,28 @@ WebGLShader::ShaderSource(const nsAString& source)
|
||||
// Wow - Roll Your Own Foreach-Lines because printf_stderr has a hard-coded
|
||||
// internal size, so long strings are truncated.
|
||||
|
||||
int32_t start = 0;
|
||||
int32_t end = sourceCString.Find("\n", false, start, -1);
|
||||
while (end > -1) {
|
||||
const nsCString line(sourceCString.BeginReading() + start, end - start);
|
||||
printf_stderr("%s\n", line.BeginReading());
|
||||
start = end + 1;
|
||||
end = sourceCString.Find("\n", false, start, -1);
|
||||
const size_t maxChunkSize = 1024-1; // -1 for null-term.
|
||||
const UniqueBuffer buf(moz_xmalloc(maxChunkSize+1)); // +1 for null-term
|
||||
const auto bufBegin = (char*)buf.get();
|
||||
|
||||
size_t chunkStart = 0;
|
||||
while (chunkStart != cleanSource.Length()) {
|
||||
const auto chunkEnd = std::min(chunkStart + maxChunkSize,
|
||||
size_t(cleanSource.Length()));
|
||||
const auto chunkSize = chunkEnd - chunkStart;
|
||||
|
||||
memcpy(bufBegin, cleanSource.BeginReading() + chunkStart, chunkSize);
|
||||
bufBegin[chunkSize + 1] = '\0';
|
||||
|
||||
printf_stderr("%s", bufBegin);
|
||||
chunkStart += chunkSize;
|
||||
}
|
||||
|
||||
printf_stderr("////////////////////////////////////////\n");
|
||||
}
|
||||
|
||||
mSource = source;
|
||||
mCleanSource = sourceCString;
|
||||
mCleanSource = cleanSource;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -5,130 +5,192 @@
|
||||
|
||||
#include "WebGLValidateStrings.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "WebGLContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
// The following code was taken from the WebKit WebGL implementation,
|
||||
// which can be found here:
|
||||
// http://trac.webkit.org/browser/trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp?rev=93625#L121
|
||||
// Note that some modifications were done to adapt it to Mozilla.
|
||||
/****** BEGIN CODE TAKEN FROM WEBKIT ******/
|
||||
bool IsValidGLSLCharacter(char16_t c)
|
||||
{
|
||||
// Printing characters are valid except " $ ` @ \ ' DEL.
|
||||
if (c >= 32 && c <= 126 &&
|
||||
c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Horizontal tab, line feed, vertical tab, form feed, carriage return
|
||||
// are also valid.
|
||||
if (c >= 9 && c <= 13) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void StripComments::process(char16_t c)
|
||||
{
|
||||
if (isNewline(c)) {
|
||||
// No matter what state we are in, pass through newlines
|
||||
// so we preserve line numbers.
|
||||
emit(c);
|
||||
|
||||
if (m_parseState != InMultiLineComment)
|
||||
m_parseState = BeginningOfLine;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
char16_t temp = 0;
|
||||
switch (m_parseState) {
|
||||
case BeginningOfLine:
|
||||
// If it's an ASCII space.
|
||||
if (c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9))) {
|
||||
emit(c);
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '#') {
|
||||
m_parseState = InPreprocessorDirective;
|
||||
emit(c);
|
||||
break;
|
||||
}
|
||||
|
||||
// Transition to normal state and re-handle character.
|
||||
m_parseState = MiddleOfLine;
|
||||
process(c);
|
||||
break;
|
||||
|
||||
case MiddleOfLine:
|
||||
if (c == '/' && peek(temp)) {
|
||||
if (temp == '/') {
|
||||
m_parseState = InSingleLineComment;
|
||||
emit(' ');
|
||||
advance();
|
||||
break;
|
||||
}
|
||||
|
||||
if (temp == '*') {
|
||||
m_parseState = InMultiLineComment;
|
||||
// Emit the comment start in case the user has
|
||||
// an unclosed comment and we want to later
|
||||
// signal an error.
|
||||
emit('/');
|
||||
emit('*');
|
||||
advance();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
emit(c);
|
||||
break;
|
||||
|
||||
case InPreprocessorDirective:
|
||||
// No matter what the character is, just pass it
|
||||
// through. Do not parse comments in this state. This
|
||||
// might not be the right thing to do long term, but it
|
||||
// should handle the #error preprocessor directive.
|
||||
emit(c);
|
||||
break;
|
||||
|
||||
case InSingleLineComment:
|
||||
// The newline code at the top of this function takes care
|
||||
// of resetting our state when we get out of the
|
||||
// single-line comment. Swallow all other characters.
|
||||
break;
|
||||
|
||||
case InMultiLineComment:
|
||||
if (c == '*' && peek(temp) && temp == '/') {
|
||||
emit('*');
|
||||
emit('/');
|
||||
m_parseState = MiddleOfLine;
|
||||
advance();
|
||||
break;
|
||||
}
|
||||
|
||||
// Swallow all other characters. Unclear whether we may
|
||||
// want or need to just emit a space per character to try
|
||||
// to preserve column numbers for debugging purposes.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****** END CODE TAKEN FROM WEBKIT ******/
|
||||
|
||||
bool
|
||||
ValidateGLSLString(const nsAString& string, WebGLContext* webgl, const char* funcName)
|
||||
TruncateComments(const nsAString& src, nsAString* const out)
|
||||
{
|
||||
const size_t dstByteCount = src.Length() * sizeof(src[0]);
|
||||
const UniqueBuffer dst(malloc(dstByteCount));
|
||||
if (!dst)
|
||||
return false;
|
||||
|
||||
auto srcItr = src.BeginReading();
|
||||
const auto srcEnd = src.EndReading();
|
||||
const auto dstBegin = (decltype(src[0])*)dst.get();
|
||||
auto dstItr = dstBegin;
|
||||
|
||||
const auto fnEmitUntil = [&](const decltype(srcItr)& nextSrcItr) {
|
||||
while (srcItr != nextSrcItr) {
|
||||
*dstItr = *srcItr;
|
||||
++srcItr;
|
||||
++dstItr;
|
||||
}
|
||||
};
|
||||
|
||||
const auto fnFindSoonestOf = [&](const nsString* needles, size_t needleCount,
|
||||
size_t* const out_foundId)
|
||||
{
|
||||
auto foundItr = srcItr;
|
||||
while (foundItr != srcEnd) {
|
||||
const auto haystack = Substring(foundItr, srcEnd);
|
||||
for (size_t i = 0; i < needleCount; i++) {
|
||||
if (StringBeginsWith(haystack, needles[i])) {
|
||||
*out_foundId = i;
|
||||
return foundItr;
|
||||
}
|
||||
}
|
||||
++foundItr;
|
||||
}
|
||||
*out_foundId = needleCount;
|
||||
return foundItr;
|
||||
};
|
||||
|
||||
////
|
||||
|
||||
const nsString commentBeginnings[] = { NS_LITERAL_STRING("//"),
|
||||
NS_LITERAL_STRING("/*"),
|
||||
nsString() }; // Final empty string for "found
|
||||
// nothing".
|
||||
const nsString lineCommentEndings[] = { NS_LITERAL_STRING("\\\n"),
|
||||
NS_LITERAL_STRING("\n"),
|
||||
nsString() };
|
||||
const nsString blockCommentEndings[] = { NS_LITERAL_STRING("\n"),
|
||||
NS_LITERAL_STRING("*/"),
|
||||
nsString() };
|
||||
|
||||
while (srcItr != srcEnd) {
|
||||
size_t foundId;
|
||||
fnEmitUntil( fnFindSoonestOf(commentBeginnings, 2, &foundId) );
|
||||
fnEmitUntil(srcItr + commentBeginnings[foundId].Length()); // Final empty string
|
||||
// allows us to skip
|
||||
// forward here
|
||||
// unconditionally.
|
||||
switch (foundId) {
|
||||
case 0: // line comment
|
||||
while (true) {
|
||||
size_t endId;
|
||||
srcItr = fnFindSoonestOf(lineCommentEndings, 2, &endId);
|
||||
fnEmitUntil(srcItr + lineCommentEndings[endId].Length());
|
||||
if (endId == 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // block comment
|
||||
while (true) {
|
||||
size_t endId;
|
||||
srcItr = fnFindSoonestOf(blockCommentEndings, 2, &endId);
|
||||
fnEmitUntil(srcItr + blockCommentEndings[endId].Length());
|
||||
if (endId == 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default: // not found
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT((dstBegin+1) - dstBegin == 1);
|
||||
const uint32_t dstCharLen = dstItr - dstBegin;
|
||||
if (!out->Assign(dstBegin, dstCharLen, mozilla::fallible))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool
|
||||
IsValidGLSLChar(char16_t c)
|
||||
{
|
||||
if (('a' <= c && c <= 'z') ||
|
||||
('A' <= c && c <= 'Z') ||
|
||||
('0' <= c && c <= '9'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\v':
|
||||
case '\f':
|
||||
case '\r':
|
||||
case '\n':
|
||||
case '_':
|
||||
case '.':
|
||||
case '+':
|
||||
case '-':
|
||||
case '/':
|
||||
case '*':
|
||||
case '%':
|
||||
case '<':
|
||||
case '>':
|
||||
case '[':
|
||||
case ']':
|
||||
case '(':
|
||||
case ')':
|
||||
case '{':
|
||||
case '}':
|
||||
case '^':
|
||||
case '|':
|
||||
case '&':
|
||||
case '~':
|
||||
case '=':
|
||||
case '!':
|
||||
case ':':
|
||||
case ';':
|
||||
case ',':
|
||||
case '?':
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
IsValidGLSLPreprocChar(char16_t c)
|
||||
{
|
||||
if (IsValidGLSLChar(c))
|
||||
return true;
|
||||
|
||||
switch (c) {
|
||||
case '\\':
|
||||
case '#':
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
bool
|
||||
ValidateGLSLPreprocString(WebGLContext* webgl, const char* funcName,
|
||||
const nsAString& string)
|
||||
{
|
||||
for (size_t i = 0; i < string.Length(); ++i) {
|
||||
if (!IsValidGLSLCharacter(string.CharAt(i))) {
|
||||
webgl->ErrorInvalidValue("%s: String contains the illegal character '%d'",
|
||||
funcName, string.CharAt(i));
|
||||
return false;
|
||||
const auto& cur = string[i];
|
||||
|
||||
if (!IsValidGLSLPreprocChar(cur)) {
|
||||
webgl->ErrorInvalidValue("%s: String contains the illegal character 0x%x.",
|
||||
funcName, cur);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cur == '\\' && !webgl->IsWebGL2()) {
|
||||
// Todo: Backslash is technically still invalid in WebGLSL 1 under even under
|
||||
// WebGL 2.
|
||||
webgl->ErrorInvalidValue("%s: Backslash is not valid in WebGL 1.", funcName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,14 +205,20 @@ ValidateGLSLVariableName(const nsAString& name, WebGLContext* webgl, const char*
|
||||
|
||||
const uint32_t maxSize = webgl->IsWebGL2() ? 1024 : 256;
|
||||
if (name.Length() > maxSize) {
|
||||
webgl->ErrorInvalidValue("%s: Identifier is %d characters long, exceeds the"
|
||||
" maximum allowed length of %d characters.",
|
||||
webgl->ErrorInvalidValue("%s: Identifier is %u characters long, exceeds the"
|
||||
" maximum allowed length of %u characters.",
|
||||
funcName, name.Length(), maxSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateGLSLString(name, webgl, funcName))
|
||||
return false;
|
||||
for (size_t i = 0; i < name.Length(); ++i) {
|
||||
const auto& cur = name[i];
|
||||
if (!IsValidGLSLChar(cur)) {
|
||||
webgl->ErrorInvalidValue("%s: String contains the illegal character 0x%x'.",
|
||||
funcName, cur);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsString prefix1 = NS_LITERAL_STRING("webgl_");
|
||||
nsString prefix2 = NS_LITERAL_STRING("_webgl_");
|
||||
|
@ -28,128 +28,19 @@
|
||||
#define WEBGL_VALIDATE_STRINGS_H_
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class WebGLContext;
|
||||
|
||||
// The following code was taken from the WebKit WebGL implementation,
|
||||
// which can be found here:
|
||||
// http://trac.webkit.org/browser/trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp?rev=93625#L121
|
||||
// Note that some modifications were done to adapt it to Mozilla.
|
||||
/****** BEGIN CODE TAKEN FROM WEBKIT ******/
|
||||
// Strips comments from shader text. This allows non-ASCII characters
|
||||
// to be used in comments without potentially breaking OpenGL
|
||||
// implementations not expecting characters outside the GLSL ES set.
|
||||
class StripComments {
|
||||
public:
|
||||
explicit StripComments(const nsAString& str)
|
||||
: m_parseState(BeginningOfLine)
|
||||
, m_end(str.EndReading())
|
||||
, m_current(str.BeginReading())
|
||||
, m_position(0)
|
||||
{
|
||||
m_result.SetLength(str.Length());
|
||||
parse();
|
||||
}
|
||||
|
||||
const nsTArray<char16_t>& result()
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
size_t length()
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
private:
|
||||
bool hasMoreCharacters()
|
||||
{
|
||||
return (m_current < m_end);
|
||||
}
|
||||
|
||||
void parse()
|
||||
{
|
||||
while (hasMoreCharacters()) {
|
||||
process(current());
|
||||
// process() might advance the position.
|
||||
if (hasMoreCharacters())
|
||||
advance();
|
||||
}
|
||||
}
|
||||
|
||||
void process(char16_t);
|
||||
|
||||
bool peek(char16_t& character)
|
||||
{
|
||||
if (m_current + 1 >= m_end)
|
||||
return false;
|
||||
character = *(m_current + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
char16_t current()
|
||||
{
|
||||
//ASSERT(m_position < m_length);
|
||||
return *m_current;
|
||||
}
|
||||
|
||||
void advance()
|
||||
{
|
||||
++m_current;
|
||||
}
|
||||
|
||||
bool isNewline(char16_t character)
|
||||
{
|
||||
// Don't attempt to canonicalize newline related characters.
|
||||
return (character == '\n' || character == '\r');
|
||||
}
|
||||
|
||||
void emit(char16_t character)
|
||||
{
|
||||
m_result[m_position++] = character;
|
||||
}
|
||||
|
||||
enum ParseState {
|
||||
// Have not seen an ASCII non-whitespace character yet on
|
||||
// this line. Possible that we might see a preprocessor
|
||||
// directive.
|
||||
BeginningOfLine,
|
||||
|
||||
// Have seen at least one ASCII non-whitespace character
|
||||
// on this line.
|
||||
MiddleOfLine,
|
||||
|
||||
// Handling a preprocessor directive. Passes through all
|
||||
// characters up to the end of the line. Disables comment
|
||||
// processing.
|
||||
InPreprocessorDirective,
|
||||
|
||||
// Handling a single-line comment. The comment text is
|
||||
// replaced with a single space.
|
||||
InSingleLineComment,
|
||||
|
||||
// Handling a multi-line comment. Newlines are passed
|
||||
// through to preserve line numbers.
|
||||
InMultiLineComment
|
||||
};
|
||||
|
||||
ParseState m_parseState;
|
||||
const char16_t* m_end;
|
||||
const char16_t* m_current;
|
||||
size_t m_position;
|
||||
nsTArray<char16_t> m_result;
|
||||
};
|
||||
|
||||
/****** END CODE TAKEN FROM WEBKIT ******/
|
||||
|
||||
bool ValidateGLSLString(const nsAString& string, WebGLContext* webgl,
|
||||
const char* funcName);
|
||||
|
||||
bool ValidateGLSLVariableName(const nsAString& name, WebGLContext* webgl,
|
||||
const char* funcName);
|
||||
bool
|
||||
TruncateComments(const nsAString& src, nsAString* const out);
|
||||
bool
|
||||
ValidateGLSLPreprocString(WebGLContext* webgl, const char* funcName,
|
||||
const nsAString& string);
|
||||
bool
|
||||
ValidateGLSLVariableName(const nsAString& name, WebGLContext* webgl,
|
||||
const char* funcName);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -36,7 +36,7 @@ shader-with-clipvertex.vert.html
|
||||
--min-version 1.0.2 shader-with-conditional-scoping-negative.html
|
||||
shader-with-default-precision.frag.html
|
||||
shader-with-default-precision.vert.html
|
||||
shader-with-define-line-continuation.frag.html
|
||||
--max-version 1.9.9 shader-with-define-line-continuation.frag.html
|
||||
shader-with-dfdx-no-ext.frag.html
|
||||
shader-with-dfdx.frag.html
|
||||
--min-version 1.0.2 shader-with-do-loop.html
|
||||
|
@ -44,6 +44,7 @@ description("Test for invalid passed parameters");
|
||||
|
||||
var wtu = WebGLTestUtils;
|
||||
var context = wtu.create3DContext();
|
||||
var contextVersion = wtu.getDefault3DContextVersion();
|
||||
|
||||
debug("");
|
||||
debug("Test createShader()");
|
||||
@ -110,7 +111,7 @@ function generateShaderSource(opt_invalidIdentifierChar, opt_invalidCommentChar)
|
||||
+ "varying float " + validAttribName + ";\n"
|
||||
+ "void main() {\n"
|
||||
+ validAttribName + " = " + validUniformName + ";\n"
|
||||
+ "gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }\n";
|
||||
+ "gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }\n"
|
||||
+ "//.+-/*%<>[](){}^|&~=!:;,?# " + invalidCommentString;
|
||||
}
|
||||
var vShader = context.createShader(context.VERTEX_SHADER);
|
||||
@ -143,6 +144,9 @@ shouldBe("context.getError()", "context.NO_ERROR");
|
||||
debug("");
|
||||
debug("Test shaderSource() with invalid characters");
|
||||
for (var i = 0; i < invalidSet.length; ++i) {
|
||||
// Backslash as line-continuation is allowed in WebGL 2.0.
|
||||
if (contextVersion > 1 && invalidSet[i] == '\\')
|
||||
continue;
|
||||
var validShaderSource = generateShaderSource(undefined, invalidSet[i]);
|
||||
context.shaderSource(vShader, validShaderSource);
|
||||
shouldBe("context.getError()", "context.NO_ERROR");
|
||||
|
@ -5102,8 +5102,6 @@ skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.
|
||||
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
[generated/test_2_conformance__glsl__misc__shader-with-default-precision.vert.html]
|
||||
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
[generated/test_2_conformance__glsl__misc__shader-with-define-line-continuation.frag.html]
|
||||
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
[generated/test_2_conformance__glsl__misc__shader-with-dfdx-no-ext.frag.html]
|
||||
skip-if = (os == 'android' || os == 'linux' || (os == 'win' && os_version == '5.1'))
|
||||
[generated/test_2_conformance__glsl__misc__shader-with-dfdx.frag.html]
|
||||
|
@ -771,7 +771,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Console)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsoleEventNotifier)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Console)
|
||||
|
@ -43,7 +43,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(DOMEventTargetHelper, tmp->mRefCnt.get())
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
@ -57,7 +57,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DataTransfer)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mItems)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragTarget)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragImage)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(DataTransfer)
|
||||
|
||||
|
@ -230,7 +230,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Event)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExplicitOriginalTarget)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
||||
|
@ -63,7 +63,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(JSEventHandler)
|
||||
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(JSEventHandler, tmp->mRefCnt.get())
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mTypedHandler.Ptr())
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(JSEventHandler)
|
||||
|
@ -136,7 +136,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Blob)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Blob)
|
||||
|
@ -53,7 +53,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Directory)
|
||||
tmp->mFileSystem->Traverse(cb);
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Directory)
|
||||
|
@ -35,7 +35,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(GamepadServiceTest)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(GamepadServiceTest,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
@ -134,7 +134,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HTMLFormControlsCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(HTMLFormControlsCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNameLookupTable)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(HTMLFormControlsCollection)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
|
@ -1927,6 +1927,22 @@ HTMLInputElement::ConvertStringToNumber(nsAString& aValue,
|
||||
aResultValue = Decimal::fromDouble(days * kMsPerDay);
|
||||
return true;
|
||||
}
|
||||
case NS_FORM_INPUT_DATETIME_LOCAL:
|
||||
{
|
||||
uint32_t year, month, day, timeInMs;
|
||||
if (!ParseDateTimeLocal(aValue, &year, &month, &day, &timeInMs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::ClippedTime time = JS::TimeClip(JS::MakeDate(year, month - 1, day,
|
||||
timeInMs));
|
||||
if (!time.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aResultValue = Decimal::fromDouble(time.toDouble());
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unrecognized input type");
|
||||
return false;
|
||||
@ -2102,21 +2118,17 @@ HTMLInputElement::ConvertNumberToString(Decimal aValue,
|
||||
}
|
||||
case NS_FORM_INPUT_TIME:
|
||||
{
|
||||
aValue = aValue.floor();
|
||||
// Per spec, we need to truncate |aValue| and we should only represent
|
||||
// times inside a day [00:00, 24:00[, which means that we should do a
|
||||
// modulo on |aValue| using the number of milliseconds in a day (86400000).
|
||||
uint32_t value = NS_floorModulo(aValue.floor(), Decimal(86400000)).toDouble();
|
||||
uint32_t value =
|
||||
NS_floorModulo(aValue, Decimal::fromDouble(kMsPerDay)).toDouble();
|
||||
|
||||
uint16_t milliseconds = value % 1000;
|
||||
value /= 1000;
|
||||
|
||||
uint8_t seconds = value % 60;
|
||||
value /= 60;
|
||||
|
||||
uint8_t minutes = value % 60;
|
||||
value /= 60;
|
||||
|
||||
uint8_t hours = value;
|
||||
uint16_t milliseconds, seconds, minutes, hours;
|
||||
if (!GetTimeFromMs(value, &hours, &minutes, &seconds, &milliseconds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (milliseconds != 0) {
|
||||
aResultString.AppendPrintf("%02d:%02d:%02d.%03d",
|
||||
@ -2184,6 +2196,42 @@ HTMLInputElement::ConvertNumberToString(Decimal aValue,
|
||||
}
|
||||
|
||||
aResultString.AppendPrintf("%04.0f-W%02d", year, week);
|
||||
return true;
|
||||
}
|
||||
case NS_FORM_INPUT_DATETIME_LOCAL:
|
||||
{
|
||||
aValue = aValue.floor();
|
||||
|
||||
uint32_t timeValue =
|
||||
NS_floorModulo(aValue, Decimal::fromDouble(kMsPerDay)).toDouble();
|
||||
|
||||
uint16_t milliseconds, seconds, minutes, hours;
|
||||
if (!GetTimeFromMs(timeValue,
|
||||
&hours, &minutes, &seconds, &milliseconds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double year = JS::YearFromTime(aValue.toDouble());
|
||||
double month = JS::MonthFromTime(aValue.toDouble());
|
||||
double day = JS::DayFromTime(aValue.toDouble());
|
||||
|
||||
if (IsNaN(year) || IsNaN(month) || IsNaN(day)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (milliseconds != 0) {
|
||||
aResultString.AppendPrintf("%04.0f-%02.0f-%02.0fT%02d:%02d:%02d.%03d",
|
||||
year, month + 1, day, hours, minutes,
|
||||
seconds, milliseconds);
|
||||
} else if (seconds != 0) {
|
||||
aResultString.AppendPrintf("%04.0f-%02.0f-%02.0fT%02d:%02d:%02d",
|
||||
year, month + 1, day, hours, minutes,
|
||||
seconds);
|
||||
} else {
|
||||
aResultString.AppendPrintf("%04.0f-%02.0f-%02.0fT%02d:%02d",
|
||||
year, month + 1, day, hours, minutes);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
@ -2196,8 +2244,7 @@ HTMLInputElement::ConvertNumberToString(Decimal aValue,
|
||||
Nullable<Date>
|
||||
HTMLInputElement::GetValueAsDate(ErrorResult& aRv)
|
||||
{
|
||||
// TODO: this is temporary until bug 888331 is fixed.
|
||||
if (!IsDateTimeInputType(mType) || mType == NS_FORM_INPUT_DATETIME_LOCAL) {
|
||||
if (!IsDateTimeInputType(mType)) {
|
||||
return Nullable<Date>();
|
||||
}
|
||||
|
||||
@ -2255,6 +2302,19 @@ HTMLInputElement::GetValueAsDate(ErrorResult& aRv)
|
||||
|
||||
return Nullable<Date>(Date(time));
|
||||
}
|
||||
case NS_FORM_INPUT_DATETIME_LOCAL:
|
||||
{
|
||||
uint32_t year, month, day, timeInMs;
|
||||
nsAutoString value;
|
||||
GetNonFileValueInternal(value);
|
||||
if (!ParseDateTimeLocal(value, &year, &month, &day, &timeInMs)) {
|
||||
return Nullable<Date>();
|
||||
}
|
||||
|
||||
JS::ClippedTime time = JS::TimeClip(JS::MakeDate(year, month - 1, day,
|
||||
timeInMs));
|
||||
return Nullable<Date>(Date(time));
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false, "Unrecognized input type");
|
||||
@ -2265,8 +2325,7 @@ HTMLInputElement::GetValueAsDate(ErrorResult& aRv)
|
||||
void
|
||||
HTMLInputElement::SetValueAsDate(Nullable<Date> aDate, ErrorResult& aRv)
|
||||
{
|
||||
// TODO: this is temporary until bug 888331 is fixed.
|
||||
if (!IsDateTimeInputType(mType) || mType == NS_FORM_INPUT_DATETIME_LOCAL) {
|
||||
if (!IsDateTimeInputType(mType)) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
@ -5351,6 +5410,29 @@ HTMLInputElement::MaximumWeekInYear(uint32_t aYear) const
|
||||
kMaximumWeekInYear : kMaximumWeekInYear - 1;
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLInputElement::GetTimeFromMs(double aValue, uint16_t* aHours,
|
||||
uint16_t* aMinutes, uint16_t* aSeconds,
|
||||
uint16_t* aMilliseconds) const {
|
||||
MOZ_ASSERT(aValue >= 0 && aValue < kMsPerDay,
|
||||
"aValue must be milliseconds within a day!");
|
||||
|
||||
uint32_t value = floor(aValue);
|
||||
|
||||
*aMilliseconds = value % 1000;
|
||||
value /= 1000;
|
||||
|
||||
*aSeconds = value % 60;
|
||||
value /= 60;
|
||||
|
||||
*aMinutes = value % 60;
|
||||
value /= 60;
|
||||
|
||||
*aHours = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLInputElement::IsValidWeek(const nsAString& aValue) const
|
||||
{
|
||||
|
@ -1084,11 +1084,7 @@ protected:
|
||||
/**
|
||||
* Returns if valueAsNumber attribute applies for the current type.
|
||||
*/
|
||||
bool DoesValueAsNumberApply() const
|
||||
{
|
||||
// TODO: this is temporary until bug 888331 is fixed.
|
||||
return DoesMinMaxApply() && mType != NS_FORM_INPUT_DATETIME_LOCAL;
|
||||
}
|
||||
bool DoesValueAsNumberApply() const { return DoesMinMaxApply(); }
|
||||
|
||||
/**
|
||||
* Returns if autocomplete attribute applies for the current type.
|
||||
@ -1296,6 +1292,7 @@ protected:
|
||||
* https://html.spec.whatwg.org/multipage/infrastructure.html#valid-normalised-local-date-and-time-string
|
||||
*/
|
||||
void NormalizeDateTimeLocal(nsAString& aValue) const;
|
||||
|
||||
/**
|
||||
* This methods returns the number of days since epoch for a given year and
|
||||
* week.
|
||||
@ -1326,6 +1323,13 @@ protected:
|
||||
*/
|
||||
uint32_t MaximumWeekInYear(uint32_t aYear) const;
|
||||
|
||||
/**
|
||||
* This method converts aValue (milliseconds within a day) to hours, minutes,
|
||||
* seconds and milliseconds.
|
||||
*/
|
||||
bool GetTimeFromMs(double aValue, uint16_t* aHours, uint16_t* aMinutes,
|
||||
uint16_t* aSeconds, uint16_t* aMilliseconds) const;
|
||||
|
||||
/**
|
||||
* This methods returns true if it's a leap year.
|
||||
*/
|
||||
|
@ -19,7 +19,6 @@ using namespace mozilla::dom;
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMStringMap)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStringMap)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
|
@ -47,8 +47,7 @@ var validTypes =
|
||||
["color", false],
|
||||
["month", true],
|
||||
["week", true],
|
||||
// TODO: temporary set to false until bug 888331 is fixed.
|
||||
["datetime-local", false],
|
||||
["datetime-local", true],
|
||||
];
|
||||
|
||||
function checkAvailability()
|
||||
@ -622,6 +621,107 @@ function checkWeekSet()
|
||||
}
|
||||
}
|
||||
|
||||
function checkDatetimeLocalGet()
|
||||
{
|
||||
var validData =
|
||||
[
|
||||
// Simple cases.
|
||||
[ "2016-12-27T10:30", Date.UTC(2016, 11, 27, 10, 30, 0) ],
|
||||
[ "2016-12-27T10:30:40", Date.UTC(2016, 11, 27, 10, 30, 40) ],
|
||||
[ "2016-12-27T10:30:40.567", Date.UTC(2016, 11, 27, 10, 30, 40, 567) ],
|
||||
[ "1969-12-31T12:00:00", Date.UTC(1969, 11, 31, 12, 0, 0) ],
|
||||
[ "1970-01-01T00:00", 0 ],
|
||||
// Leap years.
|
||||
[ "1804-02-29 12:34", Date.UTC(1804, 1, 29, 12, 34, 0) ],
|
||||
[ "2016-02-29T12:34", Date.UTC(2016, 1, 29, 12, 34, 0) ],
|
||||
[ "2016-12-31T12:34:56", Date.UTC(2016, 11, 31, 12, 34, 56) ],
|
||||
[ "2016-01-01T12:34:56.789", Date.UTC(2016, 0, 1, 12, 34, 56, 789) ],
|
||||
[ "2017-01-01 12:34:56.789", Date.UTC(2017, 0, 1, 12, 34, 56, 789) ],
|
||||
// Maximum valid datetime-local (limited by the ecma date object range).
|
||||
[ "275760-09-13T00:00", 8640000000000000 ],
|
||||
// Minimum valid datetime-local (limited by the input element minimum valid value).
|
||||
[ "0001-01-01T00:00", -62135596800000 ],
|
||||
];
|
||||
|
||||
var invalidData =
|
||||
[
|
||||
[ "invaliddateime-local" ],
|
||||
[ "0000-01-01T00:00" ],
|
||||
[ "2016-12-25T00:00Z" ],
|
||||
[ "2015-02-29T12:34" ],
|
||||
[ "1-1-1T12:00" ],
|
||||
[ "" ],
|
||||
// This datetime-local is valid for the input element, but is out of the
|
||||
// date object range. In this case, on getting valueAsDate, a Date object
|
||||
// will be created, but it will have a NaN internal value, and will return
|
||||
// the string "Invalid Date".
|
||||
[ "275760-09-13T12:00", true ],
|
||||
];
|
||||
|
||||
element.type = "datetime-local";
|
||||
for (let data of validData) {
|
||||
element.value = data[0];
|
||||
is(element.valueAsDate.valueOf(), data[1],
|
||||
"valueAsDate should return the " +
|
||||
"valid date object representing this datetime-local");
|
||||
}
|
||||
|
||||
for (let data of invalidData) {
|
||||
element.value = data[0];
|
||||
if (data[1]) {
|
||||
is(String(element.valueAsDate), "Invalid Date",
|
||||
"valueAsDate should return an invalid Date object " +
|
||||
"when the element value is not a valid datetime-local");
|
||||
} else {
|
||||
is(element.valueAsDate, null,
|
||||
"valueAsDate should return null " +
|
||||
"when the element value is not a valid datetime-local");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkDatetimeLocalSet()
|
||||
{
|
||||
var testData =
|
||||
[
|
||||
// Simple cases.
|
||||
[ Date.UTC(2016, 11, 27, 10, 30, 0), "2016-12-27T10:30" ],
|
||||
[ Date.UTC(2016, 11, 27, 10, 30, 30), "2016-12-27T10:30:30" ],
|
||||
[ Date.UTC(1999, 11, 31, 23, 59, 59), "1999-12-31T23:59:59" ],
|
||||
[ Date.UTC(1999, 11, 31, 23, 59, 59, 999), "1999-12-31T23:59:59.999" ],
|
||||
[ Date.UTC(123456, 7, 8, 9, 10), "123456-08-08T09:10" ],
|
||||
[ 0, "1970-01-01T00:00" ],
|
||||
// Maximum valid datetime-local (limited by the ecma date object range).
|
||||
[ 8640000000000000, "275760-09-13T00:00" ],
|
||||
// Minimum valid datetime-local (limited by the input element minimum valid value).
|
||||
[ -62135596800000, "0001-01-01T00:00" ],
|
||||
// Leap years.
|
||||
[ Date.UTC(1804, 1, 29, 12, 34, 0), "1804-02-29T12:34" ],
|
||||
[ Date.UTC(2016, 1, 29, 12, 34, 0), "2016-02-29T12:34" ],
|
||||
[ Date.UTC(2016, 11, 31, 12, 34, 56), "2016-12-31T12:34:56" ],
|
||||
[ Date.UTC(2016, 0, 1, 12, 34, 56, 789), "2016-01-01T12:34:56.789" ],
|
||||
[ Date.UTC(2017, 0, 1, 12, 34, 56, 789), "2017-01-01T12:34:56.789" ],
|
||||
// "Values must be truncated to valid datetime-local"
|
||||
[ 123.123456789123, "1970-01-01T00:00:00.123" ],
|
||||
[ 1e-1, "1970-01-01T00:00" ],
|
||||
[ -1.1, "1969-12-31T23:59:59.999" ],
|
||||
[ -345600000, "1969-12-28T00:00" ],
|
||||
// Negative years, this is out of range for the input element,
|
||||
// the corresponding datetime-local string is the empty string
|
||||
[ -62135596800001, "" ],
|
||||
];
|
||||
|
||||
element.type = "datetime-local";
|
||||
for (let data of testData) {
|
||||
element.valueAsDate = new Date(data[0]);
|
||||
is(element.value, data[1], "valueAsDate should set the value to " +
|
||||
data[1]);
|
||||
element.valueAsDate = new testFrame.Date(data[0]);
|
||||
is(element.value, data[1], "valueAsDate with other-global date should " +
|
||||
"set the value to " + data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
checkAvailability();
|
||||
checkGarbageValues();
|
||||
checkWithBustedPrototype();
|
||||
@ -642,6 +742,10 @@ checkMonthSet();
|
||||
checkWeekGet();
|
||||
checkWeekSet();
|
||||
|
||||
// Test <input type='datetime-local'>.
|
||||
checkDatetimeLocalGet();
|
||||
checkDatetimeLocalSet();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user