merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-09-09 15:56:53 +02:00
Родитель 3920ed5c4e 4eec6b8e99
Коммит 81ce456a3a
321 изменённых файлов: 2663 добавлений и 2517 удалений

Просмотреть файл

@ -193,9 +193,9 @@ const LRESULT = ctypes.size_t;
const ULONG_PTR = ctypes.uintptr_t;
const PVOID = ctypes.voidptr_t;
const LPVOID = PVOID;
const LPCTSTR = ctypes.jschar.ptr;
const LPCWSTR = ctypes.jschar.ptr;
const LPTSTR = ctypes.jschar.ptr;
const LPCTSTR = ctypes.char16_t.ptr;
const LPCWSTR = ctypes.char16_t.ptr;
const LPTSTR = ctypes.char16_t.ptr;
const LPSTR = ctypes.char.ptr;
const LPCSTR = ctypes.char.ptr;
const LPBYTE = ctypes.char.ptr;
@ -707,8 +707,8 @@ function subprocess_win32(options) {
if(environment.length) {
//An environment block consists of
//a null-terminated block of null-terminated strings.
//Using CREATE_UNICODE_ENVIRONMENT so needs to be jschar
environment = ctypes.jschar.array()(environment.join('\0') + '\0');
//Using CREATE_UNICODE_ENVIRONMENT so needs to be char16_t
environment = ctypes.char16_t.array()(environment.join('\0') + '\0');
} else {
environment = null;
}

Просмотреть файл

@ -976,12 +976,12 @@ pref("apz.subframe.enabled", true);
// Overscroll-related settings
pref("apz.overscroll.enabled", true);
pref("apz.overscroll.fling_friction", "0.02");
pref("apz.overscroll.fling_friction", "0.05");
pref("apz.overscroll.fling_stopped_threshold", "0.4");
pref("apz.overscroll.stretch_factor", "0.5");
pref("apz.overscroll.snap_back.spring_stiffness", "0.6");
pref("apz.overscroll.snap_back.spring_stiffness", "0.05");
pref("apz.overscroll.snap_back.spring_friction", "0.1");
pref("apz.overscroll.snap_back.mass", "1200");
pref("apz.overscroll.snap_back.mass", "100");
// This preference allows FirefoxOS apps (and content, I think) to force
// the use of software (instead of hardware accelerated) 2D canvases by

Просмотреть файл

@ -1279,6 +1279,7 @@ pref("services.sync.prefs.sync.privacy.clearOnShutdown.siteSettings", true);
pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true);
pref("services.sync.prefs.sync.privacy.donottrackheader.value", true);
pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true);
pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true);
pref("services.sync.prefs.sync.security.OCSP.enabled", true);
pref("services.sync.prefs.sync.security.OCSP.require", true);
pref("services.sync.prefs.sync.security.default_personal_cert", true);

Просмотреть файл

@ -44,8 +44,11 @@ const gXPInstallObserver = {
} catch (e) {
browser = winOrBrowser;
}
if (!browser)
// Note that the above try/catch will pass through dead object proxies and
// other degenerate objects. Make sure the browser is bonafide.
if (!browser || gBrowser.browsers.indexOf(browser) == -1)
return;
const anchorID = "addons-notification-icon";
var messageString, action;
var brandShortName = brandBundle.getString("brandShortName");
@ -80,8 +83,16 @@ const gXPInstallObserver = {
action, null, options);
break;
case "addon-install-blocked":
let originatingHost;
try {
originatingHost = installInfo.originatingURI.host;
} catch (ex) {
// Need to deal with missing originatingURI and with about:/data: URIs more gracefully,
// see bug 1063418 - but for now, bail:
return;
}
messageString = gNavigatorBundle.getFormattedString("xpinstallPromptWarning",
[brandShortName, installInfo.originatingURI.host]);
[brandShortName, originatingHost]);
let secHistogram = Components.classes["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry).getHistogramById("SECURITY_UI");
action = {

Просмотреть файл

@ -2336,6 +2336,9 @@ let BrowserOnClick = {
let originalTarget = event.originalTarget;
let ownerDoc = originalTarget.ownerDocument;
if (!ownerDoc) {
return;
}
if (gMultiProcessBrowser &&
ownerDoc.documentURI.toLowerCase() == "about:newtab") {

Просмотреть файл

@ -370,6 +370,9 @@ let ClickEventHandler = {
let originalTarget = event.originalTarget;
let ownerDoc = originalTarget.ownerDocument;
if (!ownerDoc) {
return;
}
// Handle click events from about pages
if (ownerDoc.documentURI.startsWith("about:certerror")) {

Просмотреть файл

@ -143,6 +143,7 @@ add_task(function* formHistory() {
let deferred = Promise.defer();
Services.obs.addObserver(function onAdd(subj, topic, data) {
if (data == "formhistory-add") {
Services.obs.removeObserver(onAdd, "satchel-storage-changed");
executeSoon(() => deferred.resolve());
}
}, "satchel-storage-changed", false);
@ -167,8 +168,9 @@ add_task(function* formHistory() {
// Wait for Satchel.
deferred = Promise.defer();
Services.obs.addObserver(function onAdd(subj, topic, data) {
Services.obs.addObserver(function onRemove(subj, topic, data) {
if (data == "formhistory-remove") {
Services.obs.removeObserver(onRemove, "satchel-storage-changed");
executeSoon(() => deferred.resolve());
}
}, "satchel-storage-changed", false);

Просмотреть файл

@ -659,7 +659,7 @@ var gAdvancedPane = {
}
try {
const DRIVE_FIXED = 3;
const LPCWSTR = ctypes.jschar.ptr;
const LPCWSTR = ctypes.char16_t.ptr;
const UINT = ctypes.uint32_t;
let kernel32 = ctypes.open("kernel32");
let GetDriveType = kernel32.declare("GetDriveTypeW", ctypes.default_abi, UINT, LPCWSTR);

Просмотреть файл

@ -133,7 +133,9 @@ function windowLoad(event, win, dialog) {
return;
if (tests[currentTest].observances.length == 0) {
// Should fail here as we are not expecting a notification.
// Should fail here as we are not expecting a notification, but we don't.
// See bug 1063410.
return;
}
let permission = aSubject.QueryInterface(Ci.nsIPermission);

Просмотреть файл

@ -17,6 +17,10 @@ function notification(win, topic) {
}
let { notification, window } = expected.shift();
if (Cu.isDeadWrapper(window)) {
// Sometimes we end up with a nuked window reference here :-(
return;
}
is(topic, notification, "Saw the expected notification");
is(win, window, "Saw the expected window");
}

Просмотреть файл

@ -45,7 +45,7 @@ add_task(function* SetCurrentEngine() {
info("Test observed " + data);
if (data == "engine-current") {
ok(true, "Test observed engine-current");
Services.obs.removeObserver(obs, "browser-search-engine-modified", false);
Services.obs.removeObserver(obs, "browser-search-engine-modified");
deferred.resolve();
}
}, "browser-search-engine-modified", false);
@ -188,6 +188,7 @@ add_task(function* GetSuggestions_AddFormHistoryEntry_RemoveFormHistoryEntry() {
let deferred = Promise.defer();
Services.obs.addObserver(function onAdd(subj, topic, data) {
if (data == "formhistory-add") {
Services.obs.removeObserver(onAdd, "satchel-storage-changed");
executeSoon(() => deferred.resolve());
}
}, "satchel-storage-changed", false);
@ -224,6 +225,7 @@ add_task(function* GetSuggestions_AddFormHistoryEntry_RemoveFormHistoryEntry() {
deferred = Promise.defer();
Services.obs.addObserver(function onRemove(subj, topic, data) {
if (data == "formhistory-remove") {
Services.obs.removeObserver(onRemove, "satchel-storage-changed");
executeSoon(() => deferred.resolve());
}
}, "satchel-storage-changed", false);

Просмотреть файл

@ -255,7 +255,8 @@ function test_auth() {
let winObs = new WindowObserver(function(authWin) {
ok(authWin, "Authentication window opened");
ok(authWin.contentWindow.location);
// See bug 1063404.
// ok(authWin.location);
});
Services.ww.registerNotification(winObs);

Просмотреть файл

@ -33,6 +33,7 @@
#include "nsTextFormatter.h"
#include "nsIStringBundle.h"
#include "nsNetUtil.h"
#include "nsIEffectiveTLDService.h"
#include "nsIProperties.h"
#include "nsDirectoryServiceDefs.h"
#include "nsIFile.h"
@ -580,6 +581,35 @@ DenyAccessIfURIHasFlags(nsIURI* aURI, uint32_t aURIFlags)
return NS_OK;
}
static bool
EqualOrSubdomain(nsIURI* aProbeArg, nsIURI* aBase)
{
// Make a clone of the incoming URI, because we're going to mutate it.
nsCOMPtr<nsIURI> probe;
nsresult rv = aProbeArg->Clone(getter_AddRefs(probe));
NS_ENSURE_SUCCESS(rv, false);
nsCOMPtr<nsIEffectiveTLDService> tldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
NS_ENSURE_TRUE(tldService, false);
while (true) {
if (nsScriptSecurityManager::SecurityCompareURIs(probe, aBase)) {
return true;
}
nsAutoCString host, newHost;
nsresult rv = probe->GetHost(host);
NS_ENSURE_SUCCESS(rv, false);
rv = tldService->GetNextSubDomain(host, newHost);
if (rv == NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
return false;
}
NS_ENSURE_SUCCESS(rv, false);
rv = probe->SetHost(newHost);
NS_ENSURE_SUCCESS(rv, false);
}
}
NS_IMETHODIMP
nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
nsIURI *aTargetURI,
@ -796,7 +826,7 @@ nsScriptSecurityManager::CheckLoadURIWithPrincipal(nsIPrincipal* aPrincipal,
// Allow domains that were whitelisted in the prefs. In 99.9% of cases,
// this array is empty.
for (size_t i = 0; i < mFileURIWhitelist.Length(); ++i) {
if (SecurityCompareURIs(mFileURIWhitelist[i], sourceURI)) {
if (EqualOrSubdomain(sourceURI, mFileURIWhitelist[i])) {
return NS_OK;
}
}
@ -1433,7 +1463,7 @@ nsScriptSecurityManager::AddSitesToFileURIWhitelist(const nsCString& aSiteList)
if (NS_FAILED(sIOService->ExtractScheme(site, unused))) {
AddSitesToFileURIWhitelist(NS_LITERAL_CSTRING("http://") + site);
AddSitesToFileURIWhitelist(NS_LITERAL_CSTRING("https://") + site);
return;
continue;
}
// Convert it to a URI and add it to our list.

Просмотреть файл

@ -82,13 +82,18 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=995943
pushPrefs.bind(null, [['capability.policy.policynames', ',somepolicy, someotherpolicy, '],
['capability.policy.somepolicy.checkloaduri.enabled', 'allaccess'],
['capability.policy.someotherpolicy.checkloaduri.enabled', 'nope'],
['capability.policy.somepolicy.sites', ' http://example.org https://example.com test1.example.com'],
['capability.policy.somepolicy.sites', ' http://example.org test1.example.com https://test2.example.com '],
['capability.policy.someotherpolicy.sites', 'http://example.net ']]))
.then(checkLoadFileURI.bind(null, 'http://example.org', true))
.then(checkLoadFileURI.bind(null, 'http://example.com', false))
.then(checkLoadFileURI.bind(null, 'http://test2.example.com', false))
.then(checkLoadFileURI.bind(null, 'https://test2.example.com', true))
.then(checkLoadFileURI.bind(null, 'http://sub1.test2.example.com', false))
.then(checkLoadFileURI.bind(null, 'https://sub1.test2.example.com', true))
.then(checkLoadFileURI.bind(null, 'http://example.net', false))
.then(checkLoadFileURI.bind(null, 'http://test1.example.com', true))
.then(checkLoadFileURI.bind(null, 'https://test1.example.com', true))
.then(checkLoadFileURI.bind(null, 'http://sub1.test1.example.com', true))
.then(checkLoadFileURI.bind(null, 'https://sub1.test1.example.com', true))
.then(pushPrefs.bind(null, [['capability.policy.someotherpolicy.checkloaduri.enabled', 'allAccess']]))
.then(checkLoadFileURI.bind(null, 'http://example.net', true))
.then(popPrefs)

Просмотреть файл

@ -574,10 +574,6 @@ def tarjan(V, E):
def main():
# Suppress the build time check if MOZ_NO_BUILD_TIME_SM_CHECKS is set.
if "MOZ_NO_BUILD_TIME_SM_CHECKS" in os.environ:
sys.exit(0)
ok = check_style()
if ok:

Просмотреть файл

@ -6408,7 +6408,7 @@ nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
JS::Rooted<JSObject*> re(cx,
JS_NewUCRegExpObjectNoStatics(cx,
static_cast<jschar*>(aPattern.BeginWriting()),
static_cast<char16_t*>(aPattern.BeginWriting()),
aPattern.Length(), 0));
if (!re) {
JS_ClearPendingException(cx);
@ -6418,7 +6418,7 @@ nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
JS::Rooted<JS::Value> rval(cx, JS::NullValue());
size_t idx = 0;
if (!JS_ExecuteRegExpNoStatics(cx, re,
static_cast<jschar*>(aValue.BeginWriting()),
static_cast<char16_t*>(aValue.BeginWriting()),
aValue.Length(), &idx, true, &rval)) {
JS_ClearPendingException(cx);
return true;

Просмотреть файл

@ -512,7 +512,7 @@ nsFrameMessageManager::GetDelayedFrameScripts(JSContext* aCx, JS::MutableHandle<
}
static bool
JSONCreator(const jschar* aBuf, uint32_t aLen, void* aData)
JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData)
{
nsAString* result = static_cast<nsAString*>(aData);
result->Append(static_cast<const char16_t*>(aBuf),
@ -542,7 +542,7 @@ GetParamsForMessage(JSContext* aCx,
NS_ENSURE_TRUE(!json.IsEmpty(), false);
JS::Rooted<JS::Value> val(aCx, JS::NullValue());
NS_ENSURE_TRUE(JS_ParseJSON(aCx, static_cast<const jschar*>(json.get()),
NS_ENSURE_TRUE(JS_ParseJSON(aCx, static_cast<const char16_t*>(json.get()),
json.Length(), &val), false);
return WriteStructuredClone(aCx, val, aBuffer, aClosure);
@ -638,7 +638,7 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName,
}
JS::Rooted<JS::Value> ret(aCx);
if (!JS_ParseJSON(aCx, static_cast<const jschar*>(retval[i].get()),
if (!JS_ParseJSON(aCx, static_cast<const char16_t*>(retval[i].get()),
retval[i].Length(), &ret)) {
return NS_ERROR_UNEXPECTED;
}
@ -996,7 +996,7 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
}
JS::Rooted<JSString*> jsMessage(cx,
JS_NewUCStringCopyN(cx,
static_cast<const jschar*>(aMessage.BeginReading()),
static_cast<const char16_t*>(aMessage.BeginReading()),
aMessage.Length()));
NS_ENSURE_TRUE(jsMessage, NS_ERROR_OUT_OF_MEMORY);
JS::Rooted<JS::Value> syncv(cx, JS::BooleanValue(aIsSync));
@ -1489,7 +1489,7 @@ nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
nsCOMPtr<nsIInputStream> input;
channel->Open(getter_AddRefs(input));
nsString dataString;
jschar* dataStringBuf = nullptr;
char16_t* dataStringBuf = nullptr;
size_t dataStringLength = 0;
uint64_t avail64 = 0;
if (input && NS_SUCCEEDED(input->Available(&avail64)) && avail64) {

Просмотреть файл

@ -109,7 +109,7 @@ public:
bool mIsInline; // Is the script inline or loaded?
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
nsString mSourceMapURL; // Holds source map url for loaded scripts
jschar* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
char16_t* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
size_t mScriptTextLength; // use nsString so we can give ownership to jsapi.
uint32_t mJSVersion;
nsCOMPtr<nsIURI> mURI;
@ -898,7 +898,7 @@ nsScriptLoader::ProcessRequest(nsScriptLoadRequest* aRequest, void **aOffThreadT
NS_ENSURE_ARG(aRequest);
nsAutoString textData;
const jschar* scriptBuf = nullptr;
const char16_t* scriptBuf = nullptr;
size_t scriptLength = 0;
JS::SourceBufferHolder::Ownership giveScriptOwnership =
JS::SourceBufferHolder::NoOwnership;
@ -1278,7 +1278,7 @@ DetectByteOrderMark(const unsigned char* aBytes, int32_t aLen, nsCString& oChars
nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
uint32_t aLength, const nsAString& aHintCharset,
nsIDocument* aDocument,
jschar*& aBufOut, size_t& aLengthOut)
char16_t*& aBufOut, size_t& aLengthOut)
{
if (!aLength) {
aBufOut = nullptr;
@ -1335,7 +1335,7 @@ nsScriptLoader::ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
aLength, &unicodeLength);
NS_ENSURE_SUCCESS(rv, rv);
aBufOut = static_cast<jschar*>(js_malloc(unicodeLength * sizeof(jschar)));
aBufOut = static_cast<char16_t*>(js_malloc(unicodeLength * sizeof(char16_t)));
if (!aBufOut) {
aLengthOut = 0;
return NS_ERROR_OUT_OF_MEMORY;

Просмотреть файл

@ -170,17 +170,17 @@ public:
* attribute). May be the empty string.
* @param aDocument Document which the data is loaded for. Must not be
* null.
* @param aBufOut [out] jschar array allocated by ConvertToUTF16 and
* @param aBufOut [out] char16_t array allocated by ConvertToUTF16 and
* containing data converted to unicode. Caller must
* js_free() this data when no longer needed.
* @param aLengthOut [out] Length of array returned in aBufOut in number
* of jschars.
* of char16_t code units.
*/
static nsresult ConvertToUTF16(nsIChannel* aChannel, const uint8_t* aData,
uint32_t aLength,
const nsAString& aHintCharset,
nsIDocument* aDocument,
jschar*& aBufOut, size_t& aLengthOut);
char16_t*& aBufOut, size_t& aLengthOut);
/**
* Processes any pending requests that are ready for processing.

Просмотреть файл

@ -766,7 +766,7 @@ nsXMLHttpRequest::CreateResponseParsedJSON(JSContext* aCx)
// The Unicode converter has already zapped the BOM if there was one
JS::Rooted<JS::Value> value(aCx);
if (!JS_ParseJSON(aCx,
static_cast<const jschar*>(mResponseText.get()), mResponseText.Length(),
static_cast<const char16_t*>(mResponseText.get()), mResponseText.Length(),
&value)) {
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -36,7 +36,8 @@ function afterLoad() {
.getService(SpecialPowers.Ci.nsIProperties)
.get("TmpD", SpecialPowers.Ci.nsILocalFile);
file.append("345339_test.file");
file.createUnique(SpecialPowers.Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
// Only the file's path is used, so it doesn't need to be created.
// See also bug 1058977.
filePath = file.path;
SpecialPowers.wrap(iframeDoc).getElementById("file").value = filePath;

Просмотреть файл

@ -1,2 +1,5 @@
[DEFAULT]
support-files =
submit_invalid_file.sjs
[test_autocompleteinfo.html]
[test_submit_invalid_file.html]

Просмотреть файл

@ -1,7 +1,6 @@
[DEFAULT]
support-files =
save_restore_radio_groups.sjs
submit_invalid_file.sjs
test_input_number_data.js
[test_bug1039548.html]
@ -91,7 +90,6 @@ skip-if = e10s
[test_step_attribute.html]
skip-if = e10s
[test_stepup_stepdown.html]
[test_submit_invalid_file.html]
[test_textarea_attributes_reflection.html]
[test_validation.html]
skip-if = buildapp == 'b2g' || e10s # b2g(374 total, bug 901848, no keygen support) b2g-debug(374 total, bug 901848, no keygen support) b2g-desktop(374 total, bug 901848, no keygen support)

Просмотреть файл

@ -67,7 +67,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=722599
function testUserInput() {
//Simulating an OK click and with a file name return.
MockFilePicker.useAnyFile();
MockFilePicker.useBlobFile();
MockFilePicker.returnValue = MockFilePicker.returnOK;
var input = document.getElementById('fileInput');
input.focus();

Просмотреть файл

@ -59,7 +59,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
function testUserInput() {
// Simulating an OK click and with a file name return.
MockFilePicker.useAnyFile();
MockFilePicker.useBlobFile();
MockFilePicker.returnValue = MockFilePicker.returnOK;
var input = document.getElementById('fileInput');
input.focus();

Просмотреть файл

@ -179,17 +179,12 @@ for (var test of data) {
.getService(SpecialPowers.Ci.nsIProperties);
var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
file.append('635499_file');
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(SpecialPowers.Ci.nsIFileOutputStream);
outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write("foo", 3);
outStream.close();
// Only the file's path is used, so it doesn't need to be created.
// See also bug 1058977.
SpecialPowers.wrap(input).value = file.path;
checkValidity(input, true, apply, apply);
file.remove(false);
break;
case 'date':
input.max = '2012-06-27';

Просмотреть файл

@ -177,17 +177,12 @@ for (var test of data) {
.getService(SpecialPowers.Ci.nsIProperties);
var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
file.append('635499_file');
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(SpecialPowers.Ci.nsIFileOutputStream);
outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write("foo", 3);
outStream.close();
// Only the file's path is used, so it doesn't need to be created.
// See also bug 1058977.
SpecialPowers.wrap(input).value = file.path;
checkValidity(input, true, apply, apply);
file.remove(false);
break;
case 'date':
input.value = '2012-06-28';

Просмотреть файл

@ -308,22 +308,18 @@ function checkInputRequiredValidityForFile()
element.type = 'file'
document.forms[0].appendChild(element);
function createFileWithData(fileName, fileData) {
function createFile(fileName) {
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
.getService(SpecialPowers.Ci.nsIProperties);
var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
testFile.append(fileName);
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(SpecialPowers.Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write(fileData, fileData.length);
outStream.close();
// Only the file's path is used, so it doesn't need to be created.
// See also bug 1058977.
return testFile;
}
var file = createFileWithData("345822_file", "file content");
var file = createFile("345822_file");
SpecialPowers.wrap(element).value = "";
element.required = false;
@ -350,7 +346,6 @@ function checkInputRequiredValidityForFile()
element.required = true;
SpecialPowers.wrap(element).value = '';
file.remove(false);
document.forms[0].removeChild(element);
checkSufferingFromBeingMissing(element, true);
}

Просмотреть файл

@ -132,17 +132,12 @@ for (var test of data) {
.getService(SpecialPowers.Ci.nsIProperties);
var file = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
file.append('635499_file');
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(SpecialPowers.Ci.nsIFileOutputStream);
outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
0666, 0);
outStream.write("foo", 3);
outStream.close();
// Only the file's path is used, so it doesn't need to be created.
// See also bug 1058977.
SpecialPowers.wrap(input).value = file.path;
checkValidity(input, true, apply);
file.remove(false);
break;
case 'date':
// For date, the step is calulated on the timestamp since 1970-01-01

Просмотреть файл

@ -6,14 +6,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=702949
<head>
<meta charset="utf-8">
<title>Test invalid file submission</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=702949">Mozilla Bug 702949</a>
<p id="display"></p>
<div id="content" style="display: none">
<form action='submit_invalid_file.sjs' method='post' target='result'
<form action='http://mochi.test:8888/chrome/content/html/content/test/forms/submit_invalid_file.sjs' method='post' target='result'
enctype='multipart/form-data'>
<input type='file' name='file'>
</form>

Просмотреть файл

@ -60,7 +60,7 @@ SimpleTest.waitForFocus(function() {
b2.click();
// Now, we can launch tests when file picker isn't canceled.
MockFilePicker.useAnyFile();
MockFilePicker.useBlobFile();
MockFilePicker.returnValue = MockFilePicker.returnOK;
var b = document.getElementById('b');

Просмотреть файл

@ -30,7 +30,9 @@ class nsXPCClassInfo;
namespace mozilla {
class DOMLocalMediaStream;
class MediaStream;
class MediaEngineSource;
namespace dom {
class AudioNode;
@ -102,6 +104,8 @@ public:
virtual void StopTrack(TrackID aTrackID);
virtual DOMLocalMediaStream* AsDOMLocalMediaStream() { return nullptr; }
bool IsFinished();
/**
* Returns a principal indicating who may access this stream. The stream contents
@ -301,6 +305,8 @@ public:
virtual void Stop();
virtual MediaEngineSource* GetMediaEngine(TrackID aTrackID) { return nullptr; }
/**
* Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream.
*/

Просмотреть файл

@ -11,8 +11,10 @@
#include "mozilla/dom/ImageCaptureErrorEvent.h"
#include "mozilla/dom/ImageCaptureErrorEventBinding.h"
#include "mozilla/dom/VideoStreamTrack.h"
#include "nsDOMFile.h"
#include "nsIDocument.h"
#include "CaptureTask.h"
#include "MediaEngine.h"
namespace mozilla {
@ -77,6 +79,69 @@ ImageCapture::GetVideoStreamTrack() const
return mVideoStreamTrack;
}
nsresult
ImageCapture::TakePhotoByMediaEngine()
{
// Callback for TakPhoto(), it also monitor the principal. If principal
// changes, it returns PHOTO_ERROR with security error.
class TakePhotoCallback : public MediaEngineSource::PhotoCallback,
public DOMMediaStream::PrincipalChangeObserver
{
public:
TakePhotoCallback(DOMMediaStream* aStream, ImageCapture* aImageCapture)
: mStream(aStream)
, mImageCapture(aImageCapture)
, mPrincipalChanged(false)
{
MOZ_ASSERT(NS_IsMainThread());
mStream->AddPrincipalChangeObserver(this);
}
void PrincipalChanged(DOMMediaStream* aMediaStream) MOZ_OVERRIDE
{
mPrincipalChanged = true;
}
nsresult PhotoComplete(already_AddRefed<DOMFile> aBlob) MOZ_OVERRIDE
{
nsRefPtr<DOMFile> blob = aBlob;
if (mPrincipalChanged) {
return PhotoError(NS_ERROR_DOM_SECURITY_ERR);
}
return mImageCapture->PostBlobEvent(blob);
}
nsresult PhotoError(nsresult aRv) MOZ_OVERRIDE
{
return mImageCapture->PostErrorEvent(ImageCaptureError::PHOTO_ERROR, aRv);
}
protected:
~TakePhotoCallback()
{
MOZ_ASSERT(NS_IsMainThread());
mStream->RemovePrincipalChangeObserver(this);
}
nsRefPtr<DOMMediaStream> mStream;
nsRefPtr<ImageCapture> mImageCapture;
bool mPrincipalChanged;
};
nsRefPtr<DOMMediaStream> domStream = mVideoStreamTrack->GetStream();
DOMLocalMediaStream* domLocalStream = domStream->AsDOMLocalMediaStream();
if (domLocalStream) {
nsRefPtr<MediaEngineSource> mediaEngine =
domLocalStream->GetMediaEngine(mVideoStreamTrack->GetTrackID());
nsRefPtr<MediaEngineSource::PhotoCallback> callback =
new TakePhotoCallback(domStream, this);
return mediaEngine->TakePhoto(callback);
}
return NS_ERROR_NOT_IMPLEMENTED;
}
void
ImageCapture::TakePhoto(ErrorResult& aResult)
{
@ -90,12 +155,20 @@ ImageCapture::TakePhoto(ErrorResult& aResult)
return;
}
nsRefPtr<CaptureTask> task =
new CaptureTask(this, mVideoStreamTrack->GetTrackID());
// Try if MediaEngine supports taking photo.
nsresult rv = TakePhotoByMediaEngine();
// It adds itself into MediaStreamGraph, so ImageCapture doesn't need to hold the
// reference.
task->AttachStream();
// It falls back to MediaStreamGraph image capture if MediaEngine doesn't
// support TakePhoto().
if (rv == NS_ERROR_NOT_IMPLEMENTED) {
IC_LOG("MediaEngine doesn't support TakePhoto(), it falls back to MediaStreamGraph.");
nsRefPtr<CaptureTask> task =
new CaptureTask(this, mVideoStreamTrack->GetTrackID());
// It adds itself into MediaStreamGraph, so ImageCapture doesn't need to hold
// the reference.
task->AttachStream();
}
}
nsresult

Просмотреть файл

@ -41,6 +41,11 @@ class VideoStreamTrack;
* be sent back as a JPG format via Blob event.
*
* All the functions in ImageCapture are run in main thread.
*
* There are two ways to capture image, MediaEngineSource and MediaStreamGraph.
* When the implementation of MediaEngineSource supports TakePhoto() in platform
* like B2G, it uses the platform camera to grab image. Otherwise, it falls back
* to the MediaStreamGraph way.
*/
class ImageCapture MOZ_FINAL : public DOMEventTargetHelper
@ -86,6 +91,10 @@ public:
protected:
virtual ~ImageCapture();
// Capture image by MediaEngine. If it's not support taking photo, this function
// should return NS_ERROR_NOT_IMPLEMENTED.
nsresult TakePhotoByMediaEngine();
nsRefPtr<VideoStreamTrack> mVideoStreamTrack;
};

Просмотреть файл

@ -173,17 +173,8 @@ MediaSourceDecoder::SetMediaSourceDuration(double aDuration)
}
void
MediaSourceDecoder::WaitForData()
MediaSourceDecoder::NotifyTimeRangesChanged()
{
MSE_DEBUG("MediaSourceDecoder(%p)::WaitForData()", this);
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mon.Wait();
}
void
MediaSourceDecoder::NotifyGotData()
{
MSE_DEBUG("MediaSourceDecoder(%p)::NotifyGotData()", this);
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
mon.NotifyAll();
}

Просмотреть файл

@ -55,11 +55,9 @@ public:
void SetMediaSourceDuration(double aDuration);
// Provide a mechanism for MediaSourceReader to block waiting on data from a SourceBuffer.
void WaitForData();
// Called whenever a SourceBuffer has new data appended.
void NotifyGotData();
// Called whenever a TrackBuffer has new data appended or a new decoder
// initializes. Safe to call from any thread.
void NotifyTimeRangesChanged();
// Indicates the point in time at which the reader should consider
// registered TrackBuffers essential for initialization.

Просмотреть файл

@ -84,16 +84,15 @@ MediaSourceReader::RequestAudioData()
GetCallback()->OnDecodeError();
return;
}
if (SwitchAudioReader(double(mLastAudioTime) / USECS_PER_S)) {
MSE_DEBUGV("MediaSourceReader(%p)::RequestAudioData switching audio reader", this);
}
mAudioIsSeeking = false;
SwitchAudioReader(double(mLastAudioTime) / USECS_PER_S);
mAudioReader->RequestAudioData();
}
void
MediaSourceReader::OnAudioDecoded(AudioData* aSample)
{
MSE_DEBUGV("MediaSourceReader(%p)::OnAudioDecoded mTime=%lld mDuration=%lld d=%d",
MSE_DEBUGV("MediaSourceReader(%p)::OnAudioDecoded [mTime=%lld mDuration=%lld mDiscontinuity=%d]",
this, aSample->mTime, aSample->mDuration, aSample->mDiscontinuity);
if (mDropAudioBeforeThreshold) {
if (aSample->mTime < mTimeThreshold) {
@ -106,14 +105,12 @@ MediaSourceReader::OnAudioDecoded(AudioData* aSample)
mDropAudioBeforeThreshold = false;
}
// If we are seeking we need to make sure the first sample decoded after
// that seek has the mDiscontinuity field set to ensure the media decoder
// state machine picks up that the seek is complete.
if (mAudioIsSeeking) {
mAudioIsSeeking = false;
aSample->mDiscontinuity = true;
// Any OnAudioDecoded callbacks received while mAudioIsSeeking must be not
// update our last used timestamp, as these are emitted by the reader we're
// switching away from.
if (!mAudioIsSeeking) {
mLastAudioTime = aSample->mTime + aSample->mDuration;
}
mLastAudioTime = aSample->mTime + aSample->mDuration;
GetCallback()->OnAudioDecoded(aSample);
}
@ -148,16 +145,15 @@ MediaSourceReader::RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThres
mDropAudioBeforeThreshold = true;
mDropVideoBeforeThreshold = true;
}
if (SwitchVideoReader(double(mLastVideoTime) / USECS_PER_S)) {
MSE_DEBUGV("MediaSourceReader(%p)::RequestVideoData switching video reader", this);
}
mVideoIsSeeking = false;
SwitchVideoReader(double(mLastVideoTime) / USECS_PER_S);
mVideoReader->RequestVideoData(aSkipToNextKeyframe, aTimeThreshold);
}
void
MediaSourceReader::OnVideoDecoded(VideoData* aSample)
{
MSE_DEBUGV("MediaSourceReader(%p)::OnVideoDecoded mTime=%lld mDuration=%lld d=%d",
MSE_DEBUGV("MediaSourceReader(%p)::OnVideoDecoded [mTime=%lld mDuration=%lld mDiscontinuity=%d]",
this, aSample->mTime, aSample->mDuration, aSample->mDiscontinuity);
if (mDropVideoBeforeThreshold) {
if (aSample->mTime < mTimeThreshold) {
@ -170,14 +166,12 @@ MediaSourceReader::OnVideoDecoded(VideoData* aSample)
mDropVideoBeforeThreshold = false;
}
// If we are seeking we need to make sure the first sample decoded after
// that seek has the mDiscontinuity field set to ensure the media decoder
// state machine picks up that the seek is complete.
if (mVideoIsSeeking) {
mVideoIsSeeking = false;
aSample->mDiscontinuity = true;
// Any OnVideoDecoded callbacks received while mVideoIsSeeking must be not
// update our last used timestamp, as these are emitted by the reader we're
// switching away from.
if (!mVideoIsSeeking) {
mLastVideoTime = aSample->mTime + aSample->mDuration;
}
mLastVideoTime = aSample->mTime + aSample->mDuration;
GetCallback()->OnVideoDecoded(aSample);
}
@ -234,45 +228,90 @@ MediaSourceReader::BreakCycles()
}
bool
MediaSourceReader::SwitchAudioReader(double aTarget)
MediaSourceReader::CanSelectAudioReader(MediaDecoderReader* aNewReader)
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
// XXX: Can't handle adding an audio track after ReadMetadata yet.
if (!mAudioTrack) {
AudioInfo currentInfo = mAudioReader->GetMediaInfo().mAudio;
AudioInfo newInfo = aNewReader->GetMediaInfo().mAudio;
// TODO: We can't handle switching audio formats yet.
if (currentInfo.mRate != newInfo.mRate ||
currentInfo.mChannels != newInfo.mChannels) {
MSE_DEBUGV("MediaSourceReader(%p)::CanSelectAudioReader(%p) skip reader due to format mismatch",
this, aNewReader);
return false;
}
auto& decoders = mAudioTrack->Decoders();
for (uint32_t i = 0; i < decoders.Length(); ++i) {
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
decoders[i]->GetBuffered(ranges);
MediaDecoderReader* newReader = decoders[i]->GetReader();
MSE_DEBUGV("MediaDecoderReader(%p)::SwitchAudioReader(%f) audioReader=%p reader=%p ranges=%s",
this, aTarget, mAudioReader.get(), newReader, DumpTimeRanges(ranges).get());
if (aNewReader->AudioQueue().AtEndOfStream()) {
MSE_DEBUGV("MediaSourceReader(%p)::CanSelectAudioReader(%p) skip reader due to queue EOS",
this, aNewReader);
return false;
}
AudioInfo targetInfo = newReader->GetMediaInfo().mAudio;
AudioInfo currentInfo = mAudioReader->GetMediaInfo().mAudio;
return true;
}
// TODO: We can't handle switching audio formats yet.
if (currentInfo.mRate != targetInfo.mRate ||
currentInfo.mChannels != targetInfo.mChannels) {
bool
MediaSourceReader::CanSelectVideoReader(MediaDecoderReader* aNewReader)
{
if (aNewReader->VideoQueue().AtEndOfStream()) {
MSE_DEBUGV("MediaSourceReader(%p)::CanSelectVideoReader(%p) skip reader due to queue EOS",
this, aNewReader);
return false;
}
return true;
}
already_AddRefed<MediaDecoderReader>
MediaSourceReader::SelectReader(double aTarget,
bool (MediaSourceReader::*aCanSelectReader)(MediaDecoderReader*),
const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders)
{
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
// Consider decoders in order of newest to oldest, as a newer decoder
// providing a given buffered range is expected to replace an older one.
for (int32_t i = aTrackDecoders.Length() - 1; i >= 0; --i) {
nsRefPtr<MediaDecoderReader> newReader = aTrackDecoders[i]->GetReader();
// Check the track-type-specific aspects first, as it's assumed these
// are cheaper than a buffered range comparison, which seems worthwhile
// to avoid on any reader we'd subsequently reject.
if (!(this->*aCanSelectReader)(newReader)) {
continue;
}
if (ranges->Find(aTarget) != dom::TimeRanges::NoIndex) {
if (newReader->AudioQueue().AtEndOfStream()) {
continue;
}
if (mAudioReader) {
mAudioReader->SetIdle();
}
mAudioReader = newReader;
MSE_DEBUG("MediaDecoderReader(%p)::SwitchAudioReader(%f) switching to audio reader %p",
this, aTarget, mAudioReader.get());
return true;
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
aTrackDecoders[i]->GetBuffered(ranges);
if (ranges->Find(aTarget) == dom::TimeRanges::NoIndex) {
MSE_DEBUGV("MediaSourceReader(%p)::SelectReader(%f) newReader=%p target not in ranges=%s",
this, aTarget, newReader.get(), DumpTimeRanges(ranges).get());
continue;
}
return newReader.forget();
}
return nullptr;
}
bool
MediaSourceReader::SwitchAudioReader(double aTarget)
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
// XXX: Can't handle adding an audio track after ReadMetadata.
if (!mAudioTrack) {
return false;
}
nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget,
&MediaSourceReader::CanSelectAudioReader,
mAudioTrack->Decoders());
if (newReader && newReader != mAudioReader) {
mAudioReader->SetIdle();
mAudioReader = newReader;
MSE_DEBUGV("MediaSourceReader(%p)::SwitchAudioReader switched reader to %p", this, mAudioReader.get());
return true;
}
return false;
}
@ -280,33 +319,19 @@ bool
MediaSourceReader::SwitchVideoReader(double aTarget)
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
// XXX: Can't handle adding a video track after ReadMetadata yet.
// XXX: Can't handle adding a video track after ReadMetadata.
if (!mVideoTrack) {
return false;
}
auto& decoders = mVideoTrack->Decoders();
for (uint32_t i = 0; i < decoders.Length(); ++i) {
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
decoders[i]->GetBuffered(ranges);
MediaDecoderReader* newReader = decoders[i]->GetReader();
MSE_DEBUGV("MediaDecoderReader(%p)::SwitchVideoReader(%f) videoReader=%p reader=%p ranges=%s",
this, aTarget, mVideoReader.get(), newReader, DumpTimeRanges(ranges).get());
if (ranges->Find(aTarget) != dom::TimeRanges::NoIndex) {
if (newReader->VideoQueue().AtEndOfStream()) {
continue;
}
if (mVideoReader) {
mVideoReader->SetIdle();
}
mVideoReader = newReader;
MSE_DEBUG("MediaDecoderReader(%p)::SwitchVideoReader(%f) switching to video reader %p",
this, aTarget, mVideoReader.get());
return true;
}
nsRefPtr<MediaDecoderReader> newReader = SelectReader(aTarget,
&MediaSourceReader::CanSelectVideoReader,
mVideoTrack->Decoders());
if (newReader && newReader != mVideoReader) {
mVideoReader->SetIdle();
mVideoReader = newReader;
MSE_DEBUGV("MediaSourceReader(%p)::SwitchVideoReader switched reader to %p", this, mVideoReader.get());
return true;
}
return false;
}
@ -413,6 +438,21 @@ private:
nsRefPtr<AbstractMediaDecoder> mDecoder;
};
void
MediaSourceReader::WaitForTimeRange(double aTime)
{
MSE_DEBUG("MediaSourceReader(%p)::WaitForTimeRange(%f)", this, aTime);
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
// Loop until we have the requested time range in the active TrackBuffers.
// Ideally, this wait loop would use an async request and callback
// instead. Bug 1056441 covers that change.
while (!TrackBuffersContainTime(aTime) && !IsShutdown() && !IsEnded()) {
MSE_DEBUG("MediaSourceReader(%p)::WaitForTimeRange(%f) waiting", this, aTime);
mon.Wait();
}
}
bool
MediaSourceReader::TrackBuffersContainTime(double aTime)
{
@ -448,14 +488,7 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
NS_DispatchToMainThread(new ChangeToHaveMetadata(mDecoder));
}
// Loop until we have the requested time range in the source buffers.
// This is a workaround for our lack of async functionality in the
// MediaDecoderStateMachine. Bug 979104 implements what we need and
// we'll remove this for an async approach based on that in bug 1056441.
while (!TrackBuffersContainTime(target) && !IsShutdown() && !IsEnded()) {
MSE_DEBUG("MediaSourceReader(%p)::Seek waiting for target=%f", this, target);
static_cast<MediaSourceDecoder*>(mDecoder)->WaitForData();
}
WaitForTimeRange(target);
if (IsShutdown()) {
return NS_ERROR_FAILURE;
@ -463,8 +496,8 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
if (mAudioTrack) {
mAudioIsSeeking = true;
DebugOnly<bool> ok = SwitchAudioReader(target);
MOZ_ASSERT(ok && static_cast<SourceBufferDecoder*>(mAudioReader->GetDecoder())->ContainsTime(target));
SwitchAudioReader(target);
MOZ_ASSERT(static_cast<SourceBufferDecoder*>(mAudioReader->GetDecoder())->ContainsTime(target));
nsresult rv = mAudioReader->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
MSE_DEBUG("MediaSourceReader(%p)::Seek audio reader=%p rv=%x", this, mAudioReader.get(), rv);
if (NS_FAILED(rv)) {
@ -473,8 +506,8 @@ MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
}
if (mVideoTrack) {
mVideoIsSeeking = true;
DebugOnly<bool> ok = SwitchVideoReader(target);
MOZ_ASSERT(ok && static_cast<SourceBufferDecoder*>(mVideoReader->GetDecoder())->ContainsTime(target));
SwitchVideoReader(target);
MOZ_ASSERT(static_cast<SourceBufferDecoder*>(mVideoReader->GetDecoder())->ContainsTime(target));
nsresult rv = mVideoReader->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
MSE_DEBUG("MediaSourceReader(%p)::Seek video reader=%p rv=%x", this, mVideoReader.get(), rv);
if (NS_FAILED(rv)) {

Просмотреть файл

@ -105,6 +105,27 @@ private:
bool SwitchAudioReader(double aTarget);
bool SwitchVideoReader(double aTarget);
// Return a reader from the set available in aTrackDecoders that is considered
// usable by the aCanUserReader callback and has data available in the range
// requested by aTarget.
// aCanSelectReader is passed each reader available in aTrackDecoders and is
// expected to return true if the reader is considerable selectable.
already_AddRefed<MediaDecoderReader> SelectReader(double aTarget,
bool (MediaSourceReader::*aCanSelectReader)(MediaDecoderReader*),
const nsTArray<nsRefPtr<SourceBufferDecoder>>& aTrackDecoders);
// Passed to SelectReader to enforce any track format specific requirements.
// In the case of CanSelectAudioReader, verifies that aNewReader has a
// matching audio format to the existing reader, as format switching is not
// yet supported.
bool CanSelectAudioReader(MediaDecoderReader* aNewReader);
bool CanSelectVideoReader(MediaDecoderReader* aNewReader);
// Waits on the decoder monitor for aTime to become available in the active
// TrackBuffers. Used to block a Seek call until the necessary data has been
// provided to the relevant SourceBuffers.
void WaitForTimeRange(double aTime);
nsRefPtr<MediaDecoderReader> mAudioReader;
nsRefPtr<MediaDecoderReader> mVideoReader;

Просмотреть файл

@ -440,8 +440,13 @@ SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
return;
}
StartUpdating();
/// TODO: Run coded frame removal algorithm asynchronously (would call StopUpdating()).
StopUpdating();
/// TODO: Run coded frame removal algorithm.
// Run the final step of the coded frame removal algorithm asynchronously
// to ensure the SourceBuffer's updating flag transition behaves as
// required by the spec.
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating);
NS_DispatchToMainThread(event);
}
void
@ -561,7 +566,7 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
// TODO: Run coded frame eviction algorithm.
// TODO: Test buffer full flag.
StartUpdating();
// TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
// TODO: Run more of the buffer append algorithm asynchronously.
if (mParser->IsInitSegmentPresent(aData, aLength)) {
MSE_DEBUG("SourceBuffer(%p)::AppendData: New initialization segment.", this);
mMediaSource->QueueInitializationEvent();
@ -632,13 +637,16 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
// the current start point.
mMediaSource->NotifyEvicted(0.0, GetBufferedStart());
}
StopUpdating();
// Run the final step of the buffer append algorithm asynchronously to
// ensure the SourceBuffer's updating flag transition behaves as required
// by the spec.
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating);
NS_DispatchToMainThread(event);
// Schedule the state machine thread to ensure playback starts
// if required when data is appended.
mMediaSource->GetDecoder()->ScheduleStateMachineThread();
mMediaSource->GetDecoder()->NotifyGotData();
}
double

Просмотреть файл

@ -106,10 +106,13 @@ TrackBuffer::AppendData(const uint8_t* aData, uint32_t aLength)
}
SourceBufferResource* resource = mCurrentDecoder->GetResource();
int64_t appendOffset = resource->GetLength();
resource->AppendData(aData, aLength);
// XXX: For future reference: NDA call must run on the main thread.
mCurrentDecoder->NotifyDataArrived(reinterpret_cast<const char*>(aData),
aLength, resource->GetLength());
resource->AppendData(aData, aLength);
aLength, appendOffset);
mParentDecoder->NotifyTimeRangesChanged();
return true;
}
@ -245,6 +248,7 @@ TrackBuffer::RegisterDecoder(nsRefPtr<SourceBufferDecoder> aDecoder)
MSE_DEBUG("TrackBuffer(%p)::RegisterDecoder with mismatched audio/video tracks", this);
}
mInitializedDecoders.AppendElement(aDecoder);
mParentDecoder->NotifyTimeRangesChanged();
}
void

Просмотреть файл

@ -9,9 +9,7 @@ function fetchWithXHR(uri, onLoadFunction) {
xhr.open("GET", uri, true);
xhr.responseType = "blob";
xhr.addEventListener("load", function (e) {
if (xhr.status != 200) {
return;
}
is(xhr.status, 200, "fetchWithXHR load uri='" + uri + "' status=" + xhr.status);
var rdr = new FileReader();
rdr.addEventListener("load", function (e) {
onLoadFunction(e.target.result);

Просмотреть файл

@ -1,15 +1,13 @@
[DEFAULT]
skip-if = e10s
support-files = mediasource.js seek.webm seek.webm^headers^
[test_MediaSource.html]
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
[test_SplitAppend.html]
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
[test_SplitAppendDelay.html]
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
skip-if = e10s || buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
support-files =
mediasource.js
seek.webm seek.webm^headers^
seek_lowres.webm seek_lowres.webm^headers^
[test_BufferedSeek.html]
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
[test_FrameSelection.html]
[test_MediaSource.html]
[test_SplitAppendDelay.html]
[test_SplitAppend.html]

Двоичные данные
content/media/mediasource/test/seek_lowres.webm Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1 @@
Cache-Control: no-store

Просмотреть файл

@ -25,7 +25,9 @@ runWithMSE(function () {
fetchWithXHR("seek.webm", function (arrayBuffer) {
sb.appendBuffer(new Uint8Array(arrayBuffer));
ms.endOfStream();
sb.addEventListener("updateend", function () {
ms.endOfStream()
});
});
var target = 2;

Просмотреть файл

@ -0,0 +1,79 @@
<!DOCTYPE HTML>
<html>
<head>
<title>MSE: verify correct frames selected for given position</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mediasource.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
runWithMSE(function () {
var ms = new MediaSource();
var v = document.createElement("video");
v.preload = "auto";
v.src = URL.createObjectURL(ms);
document.body.appendChild(v);
ms.addEventListener("sourceopen", function () {
var sb = ms.addSourceBuffer("video/webm");
fetchWithXHR("seek.webm", function (arrayBuffer) {
// Append entire file covering range [0, 4].
sb.appendBuffer(new Uint8Array(arrayBuffer));
});
var targets = [{ currentTime: 3, videoWidth: 160, videoHeight: 120 },
{ currentTime: 2, videoWidth: 160, videoHeight: 120 },
{ currentTime: 0, videoWidth: 320, videoHeight: 240 }];
var target;
v.addEventListener("loadedmetadata", function () {
is(v.currentTime, 0, "currentTime has incorrect initial value");
is(v.videoWidth, 320, "videoWidth has incorrect initial value");
is(v.videoHeight, 240, "videoHeight has incorrect initial value");
fetchWithXHR("seek_lowres.webm", function (arrayBuffer) {
// Append initialization segment.
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 438));
var first = true;
sb.addEventListener("updateend", function () {
if (first) {
// Append media segment covering range [2, 4].
sb.appendBuffer(new Uint8Array(arrayBuffer, 51003));
first = false;
} else {
ms.endOfStream();
}
});
target = targets.shift();
v.currentTime = target.currentTime;
});
});
v.addEventListener("seeked", function () {
is(v.currentTime, target.currentTime, "Video currentTime not at target");
is(v.videoWidth, target.videoWidth, "videoWidth has incorrect final value");
is(v.videoHeight, target.videoHeight, "videoHeight has incorrect final value");
target = targets.shift();
if (target) {
v.currentTime = target.currentTime;
} else {
v.parentNode.removeChild(v);
SimpleTest.finish();
}
});
});
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -52,7 +52,16 @@ runWithMSE(function () {
fetchWithXHR("seek.webm", function (arrayBuffer) {
sb.appendBuffer(new Uint8Array(arrayBuffer));
is(sb.updating, true, "SourceBuffer.updating is expected value after appendBuffer");
});
sb.addEventListener("update", function () {
is(sb.updating, false, "SourceBuffer.updating is expected value in update event");
ms.endOfStream();
});
sb.addEventListener("updateend", function () {
is(sb.updating, false, "SourceBuffer.updating is expected value in updateend event");
v.play();
});
});

Просмотреть файл

@ -25,8 +25,15 @@ runWithMSE(function () {
fetchWithXHR("seek.webm", function (arrayBuffer) {
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
ms.endOfStream();
var first = true;
sb.addEventListener("updateend", function () {
if (first) {
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
first = false;
} else {
ms.endOfStream();
}
});
v.play();
});
});

Просмотреть файл

@ -25,10 +25,17 @@ runWithMSE(function () {
fetchWithXHR("seek.webm", function (arrayBuffer) {
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
window.setTimeout(function () {
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
ms.endOfStream();
}, 1000);
var first = true;
sb.addEventListener("updateend", function () {
if (first) {
window.setTimeout(function () {
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
first = false;
}, 1000);
} else {
ms.endOfStream();
}
});
v.play();
});
});

Просмотреть файл

@ -10,9 +10,14 @@
#include "DOMMediaStream.h"
#include "MediaStreamGraph.h"
#include "mozilla/dom/MediaStreamTrackBinding.h"
#include "mozilla/dom/VideoStreamTrack.h"
namespace mozilla {
namespace dom {
class DOMFile;
}
struct VideoTrackConstraintsN;
struct AudioTrackConstraintsN;
@ -137,6 +142,29 @@ public:
/* Returns the type of media source (camera, microphone, screen, window, etc) */
virtual const MediaSourceType GetMediaSource() = 0;
// Callback interface for TakePhoto(). Either PhotoComplete() or PhotoError()
// should be called.
class PhotoCallback {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PhotoCallback)
// aBlob is the image captured by MediaEngineSource. It is
// called on main thread.
virtual nsresult PhotoComplete(already_AddRefed<dom::DOMFile> aBlob) = 0;
// It is called on main thread. aRv is the error code.
virtual nsresult PhotoError(nsresult aRv) = 0;
protected:
virtual ~PhotoCallback() {}
};
/* If implementation of MediaEngineSource supports TakePhoto(), the picture
* should be return via aCallback object. Otherwise, it returns NS_ERROR_NOT_IMPLEMENTED.
* Currently, only Gonk MediaEngineSource implementation supports it.
*/
virtual nsresult TakePhoto(PhotoCallback* aCallback) = 0;
/* Return false if device is currently allocated or started */
bool IsAvailable() {
if (mState == kAllocated || mState == kStarted) {

Просмотреть файл

@ -65,6 +65,11 @@ public:
return MediaSourceType::Camera;
}
virtual nsresult TakePhoto(PhotoCallback* aCallback)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITIMERCALLBACK
@ -125,6 +130,11 @@ public:
return MediaSourceType::Microphone;
}
virtual nsresult TakePhoto(PhotoCallback* aCallback)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITIMERCALLBACK

Просмотреть файл

@ -34,6 +34,11 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList
return MediaSourceType::Browser;
}
virtual nsresult TakePhoto(PhotoCallback* aCallback)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
void Draw();
class StartRunnable : public nsRunnable {

Просмотреть файл

@ -80,7 +80,7 @@ class GetCameraNameRunnable;
* MainThread:
* mCaptureIndex, mLastCapture, mState, mWidth, mHeight,
*
* Where mWidth, mHeight, mImage are protected by mMonitor
* Where mWidth, mHeight, mImage, mPhotoCallbacks are protected by mMonitor
* mState is protected by mCallbackMonitor
* Other variable is accessed only from single thread
*/
@ -175,6 +175,11 @@ public:
#ifndef MOZ_B2G_CAMERA
NS_DECL_THREADSAFE_ISUPPORTS
nsresult TakePhoto(PhotoCallback* aCallback)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
#else
// We are subclassed from CameraControlListener, which implements a
// threadsafe reference-count for us.
@ -193,6 +198,9 @@ public:
void SnapshotImpl();
void RotateImage(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight);
void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration);
nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE;
#endif
// This runnable is for creating a temporary file on the main thread.
@ -230,6 +238,7 @@ private:
// This is only modified on MainThread (AllocImpl and DeallocImpl)
nsRefPtr<ICameraControl> mCameraControl;
nsCOMPtr<nsIDOMFile> mLastCapture;
nsTArray<nsRefPtr<PhotoCallback>> mPhotoCallbacks;
// These are protected by mMonitor below
int mRotation;
@ -330,6 +339,11 @@ public:
return MediaSourceType::Microphone;
}
virtual nsresult TakePhoto(PhotoCallback* aCallback)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
// VoEMediaProcess.
void Process(int channel, webrtc::ProcessingTypes type,
int16_t audio10ms[], int length,

Просмотреть файл

@ -877,18 +877,95 @@ MediaEngineWebRTCVideoSource::GetRotation()
void
MediaEngineWebRTCVideoSource::OnUserError(UserContext aContext, nsresult aError)
{
ReentrantMonitorAutoEnter sync(mCallbackMonitor);
mCallbackMonitor.Notify();
{
// Scope the monitor, since there is another monitor below and we don't want
// unexpected deadlock.
ReentrantMonitorAutoEnter sync(mCallbackMonitor);
mCallbackMonitor.Notify();
}
// A main thread runnable to send error code to all queued PhotoCallbacks.
class TakePhotoError : public nsRunnable {
public:
TakePhotoError(nsTArray<nsRefPtr<PhotoCallback>>& aCallbacks,
nsresult aRv)
: mRv(aRv)
{
mCallbacks.SwapElements(aCallbacks);
}
NS_IMETHOD Run()
{
uint32_t callbackNumbers = mCallbacks.Length();
for (uint8_t i = 0; i < callbackNumbers; i++) {
mCallbacks[i]->PhotoError(mRv);
}
// PhotoCallback needs to dereference on main thread.
mCallbacks.Clear();
return NS_OK;
}
protected:
nsTArray<nsRefPtr<PhotoCallback>> mCallbacks;
nsresult mRv;
};
if (aContext == UserContext::kInTakePicture) {
MonitorAutoLock lock(mMonitor);
if (mPhotoCallbacks.Length()) {
NS_DispatchToMainThread(new TakePhotoError(mPhotoCallbacks, aError));
}
}
}
void
MediaEngineWebRTCVideoSource::OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType)
{
ReentrantMonitorAutoEnter sync(mCallbackMonitor);
mLastCapture = dom::DOMFile::CreateMemoryFile(static_cast<void*>(aData),
static_cast<uint64_t>(aLength),
aMimeType);
mCallbackMonitor.Notify();
// It needs to start preview because Gonk camera will stop preview while
// taking picture.
mCameraControl->StartPreview();
// Create a main thread runnable to generate a blob and call all current queued
// PhotoCallbacks.
class GenerateBlobRunnable : public nsRunnable {
public:
GenerateBlobRunnable(nsTArray<nsRefPtr<PhotoCallback>>& aCallbacks,
uint8_t* aData,
uint32_t aLength,
const nsAString& aMimeType)
{
mCallbacks.SwapElements(aCallbacks);
mPhoto.AppendElements(aData, aLength);
mMimeType = aMimeType;
}
NS_IMETHOD Run()
{
nsRefPtr<dom::DOMFile> blob =
dom::DOMFile::CreateMemoryFile(mPhoto.Elements(), mPhoto.Length(), mMimeType);
uint32_t callbackCounts = mCallbacks.Length();
for (uint8_t i = 0; i < callbackCounts; i++) {
nsRefPtr<dom::DOMFile> tempBlob = blob;
mCallbacks[i]->PhotoComplete(tempBlob.forget());
}
// PhotoCallback needs to dereference on main thread.
mCallbacks.Clear();
return NS_OK;
}
nsTArray<nsRefPtr<PhotoCallback>> mCallbacks;
nsTArray<uint8_t> mPhoto;
nsString mMimeType;
};
// All elements in mPhotoCallbacks will be swapped in GenerateBlobRunnable
// constructor. This captured image will be sent to all the queued
// PhotoCallbacks in this runnable.
MonitorAutoLock lock(mMonitor);
if (mPhotoCallbacks.Length()) {
NS_DispatchToMainThread(
new GenerateBlobRunnable(mPhotoCallbacks, aData, aLength, aMimeType));
}
}
void
@ -976,6 +1053,28 @@ MediaEngineWebRTCVideoSource::OnNewPreviewFrame(layers::Image* aImage, uint32_t
return true; // return true because we're accepting the frame
}
nsresult
MediaEngineWebRTCVideoSource::TakePhoto(PhotoCallback* aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock lock(mMonitor);
// If other callback exists, that means there is a captured picture on the way,
// it doesn't need to TakePicture() again.
if (!mPhotoCallbacks.Length()) {
nsresult rv = mCameraControl->TakePicture();
if (NS_FAILED(rv)) {
return rv;
}
}
mPhotoCallbacks.AppendElement(aCallback);
return NS_OK;
}
#endif
}

Просмотреть файл

@ -455,7 +455,7 @@ protected:
* If the current transcluded script is being compiled off thread, the
* source for that script.
*/
jschar* mOffThreadCompileStringBuf;
char16_t* mOffThreadCompileStringBuf;
size_t mOffThreadCompileStringLength;
/**

Просмотреть файл

@ -1584,8 +1584,8 @@ static const uint32_t sAsmJSCookie = 0x600d600d;
bool
OpenEntryForRead(nsIPrincipal* aPrincipal,
const jschar* aBegin,
const jschar* aLimit,
const char16_t* aBegin,
const char16_t* aLimit,
size_t* aSize,
const uint8_t** aMemory,
intptr_t* aFile)
@ -1643,8 +1643,8 @@ CloseEntryForRead(size_t aSize,
bool
OpenEntryForWrite(nsIPrincipal* aPrincipal,
bool aInstalled,
const jschar* aBegin,
const jschar* aEnd,
const char16_t* aBegin,
const char16_t* aEnd,
size_t aSize,
uint8_t** aMemory,
intptr_t* aFile)

Просмотреть файл

@ -80,8 +80,8 @@ struct WriteParams
// Parameters specific to opening a cache entry for reading
struct ReadParams
{
const jschar* mBegin;
const jschar* mLimit;
const char16_t* mBegin;
const char16_t* mLimit;
ReadParams()
: mBegin(nullptr),
@ -103,8 +103,8 @@ struct ReadParams
bool
OpenEntryForRead(nsIPrincipal* aPrincipal,
const jschar* aBegin,
const jschar* aLimit,
const char16_t* aBegin,
const char16_t* aLimit,
size_t* aSize,
const uint8_t** aMemory,
intptr_t *aHandle);
@ -115,8 +115,8 @@ CloseEntryForRead(size_t aSize,
bool
OpenEntryForWrite(nsIPrincipal* aPrincipal,
bool aInstalled,
const jschar* aBegin,
const jschar* aEnd,
const char16_t* aBegin,
const char16_t* aEnd,
size_t aSize,
uint8_t** aMemory,
intptr_t* aHandle);

Просмотреть файл

@ -1366,7 +1366,7 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto)
// Don't overwrite a property set by content.
bool contentDefinedProperty;
if (!::JS_AlreadyHasOwnUCProperty(cx, global, reinterpret_cast<const jschar*>(mData->mNameUTF16),
if (!::JS_AlreadyHasOwnUCProperty(cx, global, reinterpret_cast<const char16_t*>(mData->mNameUTF16),
NS_strlen(mData->mNameUTF16),
&contentDefinedProperty)) {
return NS_ERROR_FAILURE;

Просмотреть файл

@ -97,10 +97,6 @@ using namespace mozilla::dom;
const size_t gStackSize = 8192;
#ifdef PR_LOGGING
static PRLogModuleInfo* gJSDiagnostics;
#endif
// Thank you Microsoft!
#ifdef CompareString
#undef CompareString
@ -352,212 +348,102 @@ NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
return called;
}
namespace mozilla {
namespace dom {
AsyncErrorReporter::AsyncErrorReporter(JSRuntime* aRuntime,
JSErrorReport* aErrorReport,
const char* aFallbackMessage,
bool aIsChromeError,
nsPIDOMWindow* aWindow)
: mSourceLine(static_cast<const char16_t*>(aErrorReport->uclinebuf))
, mLineNumber(aErrorReport->lineno)
, mColumn(aErrorReport->column)
, mFlags(aErrorReport->flags)
{
if (!aErrorReport->filename) {
mFileName.SetIsVoid(true);
} else {
mFileName.AssignWithConversion(aErrorReport->filename);
}
const char16_t* m = static_cast<const char16_t*>(aErrorReport->ucmessage);
if (m) {
JSFlatString* name = js::GetErrorTypeName(aRuntime, aErrorReport->exnType);
if (name) {
AssignJSFlatString(mErrorMsg, name);
mErrorMsg.AppendLiteral(": ");
}
mErrorMsg.Append(m);
}
if (mErrorMsg.IsEmpty() && aFallbackMessage) {
mErrorMsg.AssignWithConversion(aFallbackMessage);
}
mCategory = aIsChromeError ? NS_LITERAL_CSTRING("chrome javascript") :
NS_LITERAL_CSTRING("content javascript");
mInnerWindowID = 0;
if (aWindow) {
MOZ_ASSERT(aWindow->IsInnerWindow());
mInnerWindowID = aWindow->WindowID();
}
}
void
AsyncErrorReporter::ReportError()
{
nsCOMPtr<nsIScriptError> errorObject =
do_CreateInstance("@mozilla.org/scripterror;1");
if (!errorObject) {
return;
}
nsresult rv = errorObject->InitWithWindowID(mErrorMsg, mFileName,
mSourceLine, mLineNumber,
mColumn, mFlags, mCategory,
mInnerWindowID);
if (NS_FAILED(rv)) {
return;
}
nsCOMPtr<nsIConsoleService> consoleService =
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (!consoleService) {
return;
}
consoleService->LogMessage(errorObject);
return;
}
} // namespace dom
} // namespace mozilla
class ScriptErrorEvent : public AsyncErrorReporter
class ScriptErrorEvent : public nsRunnable
{
public:
ScriptErrorEvent(JSRuntime* aRuntime,
JSErrorReport* aErrorReport,
const char* aFallbackMessage,
xpc::ErrorReport* aReport,
nsIPrincipal* aScriptOriginPrincipal,
nsIPrincipal* aGlobalPrincipal,
nsPIDOMWindow* aWindow,
JS::Handle<JS::Value> aError,
bool aDispatchEvent)
// Pass an empty category, then compute ours
: AsyncErrorReporter(aRuntime, aErrorReport, aFallbackMessage,
nsContentUtils::IsSystemPrincipal(aGlobalPrincipal),
aWindow)
: mReport(aReport)
, mOriginPrincipal(aScriptOriginPrincipal)
, mDispatchEvent(aDispatchEvent)
, mError(aRuntime, aError)
, mWindow(aWindow)
{
MOZ_ASSERT_IF(mWindow, mWindow->IsInnerWindow());
}
{}
NS_IMETHOD Run()
{
nsEventStatus status = nsEventStatus_eIgnore;
nsPIDOMWindow* win = mReport->mWindow;
MOZ_ASSERT(win);
// First, notify the DOM that we have a script error, but only if
// our window is still the current inner, if we're associated with a window.
if (mDispatchEvent && (!mWindow || mWindow->IsCurrentInnerWindow())) {
nsIDocShell* docShell = mWindow ? mWindow->GetDocShell() : nullptr;
if (docShell &&
!JSREPORT_IS_WARNING(mFlags) &&
!sHandlingScriptError) {
AutoRestore<bool> recursionGuard(sHandlingScriptError);
sHandlingScriptError = true;
// our window is still the current inner.
if (mDispatchEvent && win->IsCurrentInnerWindow() &&
win->GetDocShell() && !JSREPORT_IS_WARNING(mReport->mFlags) &&
!sHandlingScriptError)
{
AutoRestore<bool> recursionGuard(sHandlingScriptError);
sHandlingScriptError = true;
nsRefPtr<nsPresContext> presContext;
docShell->GetPresContext(getter_AddRefs(presContext));
nsRefPtr<nsPresContext> presContext;
win->GetDocShell()->GetPresContext(getter_AddRefs(presContext));
ThreadsafeAutoJSContext cx;
RootedDictionary<ErrorEventInit> init(cx);
init.mCancelable = true;
init.mFilename = mFileName;
init.mBubbles = true;
ThreadsafeAutoJSContext cx;
RootedDictionary<ErrorEventInit> init(cx);
init.mCancelable = true;
init.mFilename = mReport->mFileName;
init.mBubbles = true;
nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(mWindow));
NS_ENSURE_STATE(sop);
nsIPrincipal* p = sop->GetPrincipal();
NS_ENSURE_STATE(p);
nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
NS_ENSURE_STATE(sop);
nsIPrincipal* p = sop->GetPrincipal();
NS_ENSURE_STATE(p);
bool sameOrigin = !mOriginPrincipal;
bool sameOrigin = !mOriginPrincipal;
if (p && !sameOrigin) {
if (NS_FAILED(p->Subsumes(mOriginPrincipal, &sameOrigin))) {
sameOrigin = false;
}
if (p && !sameOrigin) {
if (NS_FAILED(p->Subsumes(mOriginPrincipal, &sameOrigin))) {
sameOrigin = false;
}
NS_NAMED_LITERAL_STRING(xoriginMsg, "Script error.");
if (sameOrigin) {
init.mMessage = mErrorMsg;
init.mLineno = mLineNumber;
init.mColno = mColumn;
init.mError = mError;
} else {
NS_WARNING("Not same origin error!");
init.mMessage = xoriginMsg;
init.mLineno = 0;
}
nsRefPtr<ErrorEvent> event =
ErrorEvent::Constructor(static_cast<nsGlobalWindow*>(mWindow.get()),
NS_LITERAL_STRING("error"), init);
event->SetTrusted(true);
EventDispatcher::DispatchDOMEvent(mWindow, nullptr, event, presContext,
&status);
}
NS_NAMED_LITERAL_STRING(xoriginMsg, "Script error.");
if (sameOrigin) {
init.mMessage = mReport->mErrorMsg;
init.mLineno = mReport->mLineNumber;
init.mColno = mReport->mColumn;
init.mError = mError;
} else {
NS_WARNING("Not same origin error!");
init.mMessage = xoriginMsg;
init.mLineno = 0;
}
nsRefPtr<ErrorEvent> event =
ErrorEvent::Constructor(static_cast<nsGlobalWindow*>(win),
NS_LITERAL_STRING("error"), init);
event->SetTrusted(true);
EventDispatcher::DispatchDOMEvent(win, nullptr, event, presContext,
&status);
}
if (status != nsEventStatus_eConsumeNoDefault) {
AsyncErrorReporter::ReportError();
mReport->LogToConsole();
}
return NS_OK;
}
private:
nsRefPtr<xpc::ErrorReport> mReport;
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
bool mDispatchEvent;
JS::PersistentRootedValue mError;
nsCOMPtr<nsPIDOMWindow> mWindow;
static bool sHandlingScriptError;
};
bool ScriptErrorEvent::sHandlingScriptError = false;
// NOTE: This function could be refactored to use the above. The only reason
// it has not been done is that the code below only fills the error event
// after it has a good nsPresContext - whereas using the above function
// would involve always filling it. Is that a concern?
// This temporarily lives here to avoid code churn. It will go away entirely
// soon.
namespace xpc {
void
NS_ScriptErrorReporter(JSContext *cx,
const char *message,
JSErrorReport *report)
SystemErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
// We don't want to report exceptions too eagerly, but warnings in the
// absence of werror are swallowed whole, so report those now.
if (!JSREPORT_IS_WARNING(report->flags)) {
nsIXPConnect* xpc = nsContentUtils::XPConnect();
if (JS::DescribeScriptedCaller(cx)) {
xpc->MarkErrorUnreported(cx);
return;
}
if (xpc) {
nsAXPCNativeCallContext *cc = nullptr;
xpc->GetCurrentNativeCallContext(&cc);
if (cc) {
nsAXPCNativeCallContext *prev = cc;
while (NS_SUCCEEDED(prev->GetPreviousCallContext(&prev)) && prev) {
uint16_t lang;
if (NS_SUCCEEDED(prev->GetLanguage(&lang)) &&
lang == nsAXPCNativeCallContext::LANG_JS) {
xpc->MarkErrorUnreported(cx);
return;
}
}
}
}
}
JS::Rooted<JS::Value> exception(cx);
::JS_GetPendingException(cx, &exception);
@ -566,27 +452,43 @@ NS_ScriptErrorReporter(JSContext *cx,
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
nsCOMPtr<nsIGlobalObject> globalObject;
// The eventual plan is for error reporting to happen in the AutoJSAPI
// destructor using the global with which the AutoJSAPI was initialized. We
// can't _quite_ do that yet, so we take a sloppy stab at those semantics. If
// we have an nsIScriptContext, we'll get the right answer modulo
// non-current-inners.
//
// Otherwise, we just use the privileged junk scope. This has the effect of
// causing us to report the error as "chrome javascript" rather than "content
// javascript", and not invoking any error reporters. This is exactly what we
// want here.
if (nsIScriptContext* scx = GetScriptContextFromJSContext(cx)) {
nsCOMPtr<nsPIDOMWindow> outer = do_QueryInterface(scx->GetGlobalObject());
if (outer) {
globalObject = static_cast<nsGlobalWindow*>(outer->GetCurrentInnerWindow());
}
} else {
globalObject = xpc::GetNativeForGlobal(xpc::PrivilegedJunkScope());
}
if (globalObject) {
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
MOZ_ASSERT_IF(win, win->IsInnerWindow());
nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal =
do_QueryInterface(globalObject);
NS_ASSERTION(scriptPrincipal, "Global objects must implement "
"nsIScriptObjectPrincipal");
if (globalObject) {
nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
xpcReport->Init(report, message, globalObject);
// If there's no window to fire an event at, report it to the console
// directly.
if (!xpcReport->mWindow) {
xpcReport->LogToConsole();
return;
}
// Otherwise, we need to asynchronously invoke onerror before we can decide
// whether or not to report the error to the console.
nsContentUtils::AddScriptRunner(
new ScriptErrorEvent(JS_GetRuntime(cx),
report,
message,
xpcReport,
nsJSPrincipals::get(report->originPrincipals),
scriptPrincipal->GetPrincipal(),
win,
exception,
/* We do not try to report Out Of Memory via a dom
* event because the dom event handler would
@ -597,51 +499,10 @@ NS_ScriptErrorReporter(JSContext *cx,
*/
report->errorNumber != JSMSG_OUT_OF_MEMORY));
}
if (nsContentUtils::DOMWindowDumpEnabled()) {
// Print it to stderr as well, for the benefit of those invoking
// mozilla with -console.
nsAutoCString error;
error.AssignLiteral("JavaScript ");
if (JSREPORT_IS_STRICT(report->flags))
error.AppendLiteral("strict ");
if (JSREPORT_IS_WARNING(report->flags))
error.AppendLiteral("warning: ");
else
error.AppendLiteral("error: ");
error.Append(report->filename);
error.AppendLiteral(", line ");
error.AppendInt(report->lineno, 10);
error.AppendLiteral(": ");
if (report->ucmessage) {
AppendUTF16toUTF8(reinterpret_cast<const char16_t*>(report->ucmessage),
error);
} else {
error.Append(message);
}
fprintf(stderr, "%s\n", error.get());
fflush(stderr);
}
#ifdef PR_LOGGING
if (!gJSDiagnostics)
gJSDiagnostics = PR_NewLogModule("JSDiagnostics");
if (gJSDiagnostics) {
PR_LOG(gJSDiagnostics,
JSREPORT_IS_WARNING(report->flags) ? PR_LOG_WARNING : PR_LOG_ERROR,
("file %s, line %u: %s\n%s%s",
report->filename, report->lineno, message,
report->linebuf ? report->linebuf : "",
(report->linebuf &&
report->linebuf[strlen(report->linebuf)-1] != '\n')
? "\n"
: ""));
}
#endif
}
} /* namespace xpc */
#ifdef DEBUG
// A couple of useful functions to call when you're debugging.
nsGlobalWindow *
@ -899,7 +760,7 @@ nsJSContext::InitContext()
if (!mContext)
return NS_ERROR_OUT_OF_MEMORY;
::JS_SetErrorReporter(mContext, NS_ScriptErrorReporter);
JS_SetErrorReporter(mContext, xpc::SystemErrorReporter);
JSOptionChangedCallback(js_options_dot_str, this);
@ -1071,7 +932,7 @@ nsJSContext::AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv)
p->GetData(data);
// cast is probably safe since wchar_t and jschar are expected
// cast is probably safe since wchar_t and char16_t are expected
// to be equivalent; both unsigned 16-bit entities
JSString *str =
::JS_NewUCStringCopyN(cx, data.get(), data.Length());
@ -2458,8 +2319,8 @@ NotifyGCEndRunnable::Run()
return NS_OK;
}
const jschar oomMsg[3] = { '{', '}', 0 };
const jschar *toSend = mMessage.get() ? mMessage.get() : oomMsg;
const char16_t oomMsg[3] = { '{', '}', 0 };
const char16_t *toSend = mMessage.get() ? mMessage.get() : oomMsg;
observerService->NotifyObservers(nullptr, "garbage-collection-statistics", toSend);
return NS_OK;
@ -2829,8 +2690,8 @@ NS_DOMStructuredCloneError(JSContext* cx,
static bool
AsmJSCacheOpenEntryForRead(JS::Handle<JSObject*> aGlobal,
const jschar* aBegin,
const jschar* aLimit,
const char16_t* aBegin,
const char16_t* aLimit,
size_t* aSize,
const uint8_t** aMemory,
intptr_t *aHandle)
@ -2844,8 +2705,8 @@ AsmJSCacheOpenEntryForRead(JS::Handle<JSObject*> aGlobal,
static bool
AsmJSCacheOpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
bool aInstalled,
const jschar* aBegin,
const jschar* aEnd,
const char16_t* aBegin,
const char16_t* aEnd,
size_t aSize,
uint8_t** aMemory,
intptr_t* aHandle)

Просмотреть файл

@ -14,7 +14,9 @@
#include "nsIXPConnect.h"
#include "nsIArray.h"
#include "mozilla/Attributes.h"
#include "nsPIDOMWindow.h"
#include "nsThreadUtils.h"
#include "xpcpublic.h"
class nsICycleCollectorListener;
class nsIXPConnectJSObjectHolder;
@ -189,30 +191,18 @@ class AsyncErrorReporter : public nsRunnable
{
public:
// aWindow may be null if this error report is not associated with a window
AsyncErrorReporter(JSRuntime* aRuntime,
JSErrorReport* aErrorReport,
const char* aFallbackMessage,
bool aIsChromeError, // To determine category
nsPIDOMWindow* aWindow);
AsyncErrorReporter(JSRuntime* aRuntime, xpc::ErrorReport* aReport)
: mReport(aReport)
{}
NS_IMETHOD Run()
{
ReportError();
mReport->LogToConsole();
return NS_OK;
}
protected:
// Do the actual error reporting
void ReportError();
nsString mErrorMsg;
nsString mFileName;
nsString mSourceLine;
nsCString mCategory;
uint32_t mLineNumber;
uint32_t mColumn;
uint32_t mFlags;
uint64_t mInnerWindowID;
nsRefPtr<xpc::ErrorReport> mReport;
};
} // namespace dom
@ -238,9 +228,6 @@ public:
NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSArgArray, NS_IJSARGARRAY_IID)
/* prototypes */
void NS_ScriptErrorReporter(JSContext *cx, const char *message, JSErrorReport *report);
JSObject* NS_DOMReadStructuredClone(JSContext* cx,
JSStructuredCloneReader* reader, uint32_t tag,
uint32_t data, void* closure);

Просмотреть файл

@ -42,8 +42,8 @@ protected:
private:
// aString is expected to actually be an nsAString*. Should only be
// called from StringifyToJSON.
static bool AppendJSONToString(const jschar* aJSONData, uint32_t aDataLength,
void* aString);
static bool AppendJSONToString(const char16_t* aJSONData,
uint32_t aDataLength, void* aString);
};
// Struct that serves as a base class for all typed arrays and array buffers and

Просмотреть файл

@ -157,7 +157,7 @@ ErrorResult::ReportTypeError(JSContext* aCx)
Message* message = mMessage;
const uint32_t argCount = message->mArgs.Length();
const jschar* args[11];
const char16_t* args[11];
for (uint32_t i = 0; i < argCount; ++i) {
args[i] = message->mArgs.ElementAt(i).get();
}
@ -1629,9 +1629,7 @@ DictionaryBase::ParseJSON(JSContext* aCx,
if (aJSON.IsEmpty()) {
return true;
}
return JS_ParseJSON(aCx,
static_cast<const jschar*>(PromiseFlatString(aJSON).get()),
aJSON.Length(), aVal);
return JS_ParseJSON(aCx, PromiseFlatString(aJSON).get(), aJSON.Length(), aVal);
}
bool
@ -1645,18 +1643,15 @@ DictionaryBase::StringifyToJSON(JSContext* aCx,
/* static */
bool
DictionaryBase::AppendJSONToString(const jschar* aJSONData,
DictionaryBase::AppendJSONToString(const char16_t* aJSONData,
uint32_t aDataLength,
void* aString)
{
nsAString* string = static_cast<nsAString*>(aString);
string->Append(static_cast<const char16_t*>(aJSONData),
aDataLength);
string->Append(aJSONData, aDataLength);
return true;
}
static JSString*
ConcatJSString(JSContext* cx, const char* pre, JS::Handle<JSString*> str, const char* post)
{
@ -2244,10 +2239,10 @@ ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
// and report the error outside the AutoCheckCannotGC scope.
bool foundBadChar = false;
size_t badCharIndex;
jschar badChar;
char16_t badChar;
{
JS::AutoCheckCannotGC nogc;
const jschar* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, s, &length);
const char16_t* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, s, &length);
if (!chars) {
return false;
}
@ -2270,11 +2265,11 @@ ConvertJSValueToByteString(JSContext* cx, JS::Handle<JS::Value> v,
char index[21];
static_assert(sizeof(size_t) <= 8, "index array too small");
PR_snprintf(index, sizeof(index), "%d", badCharIndex);
// A jschar is 16 bits long. The biggest unsigned 16 bit
// A char16_t is 16 bits long. The biggest unsigned 16 bit
// number (65,535) has 5 digits, plus one more for the null
// terminator.
char badCharArray[6];
static_assert(sizeof(jschar) <= 2, "badCharArray too small");
static_assert(sizeof(char16_t) <= 2, "badCharArray too small");
PR_snprintf(badCharArray, sizeof(badCharArray), "%d", badChar);
ThrowErrorMessage(cx, MSG_INVALID_BYTESTRING, index, badCharArray);
return false;

Просмотреть файл

@ -1145,8 +1145,8 @@ FindEnumStringIndex(JSContext* cx, JS::Handle<JS::Value> v, const EnumEntry* val
}
index = FindEnumStringIndexImpl(chars, length, values);
} else {
const jschar* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, str,
&length);
const char16_t* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, str,
&length);
if (!chars) {
*ok = false;
return 0;

Просмотреть файл

@ -3385,7 +3385,7 @@ class CGIsPermittedMethod(CGAbstractMethod):
self.crossOriginSetters = crossOriginSetters
self.crossOriginMethods = crossOriginMethods
args = [Argument("JSFlatString*", "prop"),
Argument("jschar", "propFirstChar"),
Argument("char16_t", "propFirstChar"),
Argument("bool", "set")]
CGAbstractMethod.__init__(self, descriptor, "IsPermitted", "bool", args,
inline=True)

Просмотреть файл

@ -150,7 +150,7 @@ GetArrayIndexFromId(JSContext* cx, JS::Handle<jsid> id)
}
if (MOZ_LIKELY(JSID_IS_ATOM(id))) {
JSAtom* atom = JSID_TO_ATOM(id);
jschar s;
char16_t s;
{
JS::AutoCheckCannotGC nogc;
if (js::AtomHasLatin1Chars(atom)) {

Просмотреть файл

@ -534,15 +534,29 @@ public:
// Allow whatever element types the bindings are willing to pass
// us in TexSubImage2D
template<class ElementType>
void TexSubImage2D(GLenum target, GLint level,
void TexSubImage2D(GLenum texImageTarget, GLint level,
GLint xoffset, GLint yoffset, GLenum format,
GLenum type, ElementType& elt, ErrorResult& rv)
{
if (IsContextLost())
return;
const GLenum target = TexImageTargetToTexTarget(texImageTarget);
if (target == LOCAL_GL_NONE)
return ErrorInvalidEnumInfo("texSubImage2D: target", texImageTarget);
if (!ValidateTexImageFormatAndType(format, type, WebGLTexImageFunc::TexImage))
return;
if (level < 0)
return ErrorInvalidValue("texSubImage2D: level is negative");
const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
if (level > maxLevel)
return ErrorInvalidValue("texSubImage2D: level %d is too large, max is %d", level, maxLevel);
// Trying to handle the video by GPU directly first
if (TexImageFromVideoElement(target, level, format, format, type, elt)) {
if (TexImageFromVideoElement(texImageTarget, level, format, format, type, elt)) {
return;
}
@ -556,7 +570,7 @@ public:
gfx::IntSize size = data->GetSize();
uint32_t byteLength = data->Stride() * size.height;
return TexSubImage2D_base(target, level, xoffset, yoffset,
return TexSubImage2D_base(texImageTarget, level, xoffset, yoffset,
size.width, size.height,
data->Stride(), format, type,
data->GetData(), byteLength,

Просмотреть файл

@ -2964,7 +2964,6 @@ WebCryptoTask::CreateUnwrapKeyTask(JSContext* aCx,
}
return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
}
} // namespace dom

Просмотреть файл

@ -103,7 +103,7 @@ GetJSValFromKeyPathString(JSContext* aCx,
NS_ASSERTION(!token.IsEmpty(), "Should be a valid keypath");
const jschar* keyPathChars = token.BeginReading();
const char16_t* keyPathChars = token.BeginReading();
const size_t keyPathLen = token.Length();
bool hasProp;

Просмотреть файл

@ -492,7 +492,7 @@ TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName,
StructuredCloneData cloneData;
JSAutoStructuredCloneBuffer buffer;
if (JS_ParseJSON(cx,
static_cast<const jschar*>(aJSONData.BeginReading()),
static_cast<const char16_t*>(aJSONData.BeginReading()),
aJSONData.Length(),
&json)) {
WriteStructuredClone(cx, json, buffer, cloneData.mClosure);

Просмотреть файл

@ -163,7 +163,7 @@ nsJSON::EncodeToStream(nsIOutputStream *aStream,
}
static bool
WriteCallback(const jschar *buf, uint32_t len, void *data)
WriteCallback(const char16_t *buf, uint32_t len, void *data)
{
nsJSONWriter *writer = static_cast<nsJSONWriter*>(data);
nsresult rv = writer->Write((const char16_t*)buf, (uint32_t)len);
@ -389,7 +389,7 @@ NS_IMETHODIMP
nsJSON::DecodeToJSVal(const nsAString &str, JSContext *cx,
JS::MutableHandle<JS::Value> result)
{
if (!JS_ParseJSON(cx, static_cast<const jschar*>(PromiseFlatString(str).get()),
if (!JS_ParseJSON(cx, static_cast<const char16_t*>(PromiseFlatString(str).get()),
str.Length(), result)) {
return NS_ERROR_UNEXPECTED;
}
@ -525,7 +525,7 @@ nsJSONListener::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
JS::Rooted<JS::Value> reviver(mCx, JS::NullValue()), value(mCx);
JS::ConstTwoByteChars chars(reinterpret_cast<const jschar*>(mBufferedChars.Elements()),
JS::ConstTwoByteChars chars(reinterpret_cast<const char16_t*>(mBufferedChars.Elements()),
mBufferedChars.Length());
bool ok = JS_ParseJSONWithReviver(mCx, chars.get(),
uint32_t(mBufferedChars.Length()),

Просмотреть файл

@ -505,15 +505,18 @@ public:
(aVideoSource ? DOMMediaStream::HINT_CONTENTS_VIDEO : 0);
nsRefPtr<nsDOMUserMediaStream> stream = new nsDOMUserMediaStream(aListener,
aAudioSource);
aAudioSource,
aVideoSource);
stream->InitTrackUnionStream(aWindow, hints);
return stream.forget();
}
nsDOMUserMediaStream(GetUserMediaCallbackMediaStreamListener* aListener,
MediaEngineSource *aAudioSource) :
MediaEngineSource *aAudioSource,
MediaEngineSource *aVideoSource) :
mListener(aListener),
mAudioSource(aAudioSource),
mVideoSource(aVideoSource),
mEchoOn(true),
mAgcOn(false),
mNoiseOn(true),
@ -625,12 +628,32 @@ public:
GetStream()->AsProcessedStream()->ForwardTrackEnabled(aID, aEnabled);
}
virtual DOMLocalMediaStream* AsDOMLocalMediaStream()
{
return this;
}
virtual MediaEngineSource* GetMediaEngine(TrackID aTrackID)
{
// MediaEngine supports only one video and on video track now and TrackID is
// fixed in MediaEngine.
if (aTrackID == kVideoTrack) {
return mVideoSource;
}
else if (aTrackID == kAudioTrack) {
return mAudioSource;
}
return nullptr;
}
// The actual MediaStream is a TrackUnionStream. But these resources need to be
// explicitly destroyed too.
nsRefPtr<SourceMediaStream> mSourceStream;
nsRefPtr<MediaInputPort> mPort;
nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
nsRefPtr<MediaEngineSource> mAudioSource; // so we can turn on AEC
nsRefPtr<MediaEngineSource> mVideoSource;
bool mEchoOn;
bool mAgcOn;
bool mNoiseOn;

Просмотреть файл

@ -23,8 +23,8 @@ DialogWatcher.prototype.init = function() {
this.findWindow = user32.declare("FindWindowW",
ctypes.winapi_abi,
ctypes.uintptr_t,
ctypes.jschar.ptr,
ctypes.jschar.ptr);
ctypes.char16_t.ptr,
ctypes.char16_t.ptr);
}
if (!this.winEventProcType) {
this.winEventProcType = ctypes.FunctionType(ctypes.stdcall_abi,
@ -94,7 +94,7 @@ DialogWatcher.prototype.init = function() {
ctypes.winapi_abi,
ctypes.int,
ctypes.uintptr_t,
ctypes.jschar.ptr,
ctypes.char16_t.ptr,
ctypes.int);
}
if (!this.messageBox) {
@ -103,14 +103,14 @@ DialogWatcher.prototype.init = function() {
ctypes.winapi_abi,
ctypes.int,
ctypes.uintptr_t,
ctypes.jschar.ptr,
ctypes.jschar.ptr,
ctypes.char16_t.ptr,
ctypes.char16_t.ptr,
ctypes.uint32_t);
}
};
DialogWatcher.prototype.getWindowText = function(hwnd) {
var bufType = ctypes.ArrayType(ctypes.jschar);
var bufType = ctypes.ArrayType(ctypes.char16_t);
var buffer = new bufType(256);
if (this.getWindowTextW(hwnd, buffer, buffer.length)) {
@ -181,4 +181,3 @@ DialogWatcher.prototype.processWindowEvents = function(timeout) {
// Returns true if the hook was successful, something was found, and we never timed out
return this.hwnd !== undefined && waitStatus == WAIT_OBJECT_0;
};

Просмотреть файл

@ -33,8 +33,8 @@ function initCTypes() {
ctypes.winapi_abi,
ctypes.int,
ctypes.uintptr_t,
ctypes.jschar.ptr,
ctypes.jschar.ptr,
ctypes.char16_t.ptr,
ctypes.char16_t.ptr,
ctypes.uint32_t);
}
if (!watcher) {

Просмотреть файл

@ -1005,19 +1005,13 @@ Promise::MaybeReportRejected()
return;
}
// Remains null in case of worker.
nsCOMPtr<nsPIDOMWindow> win;
bool isChromeError = false;
nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
if (MOZ_LIKELY(NS_IsMainThread())) {
nsIPrincipal* principal;
win = xpc::WindowGlobalOrNull(obj);
principal = nsContentUtils::ObjectPrincipal(obj);
isChromeError = nsContentUtils::IsSystemPrincipal(principal);
nsIGlobalObject* global = xpc::GetNativeForGlobal(js::GetGlobalForObjectCrossCompartment(obj));
xpcReport->Init(report.report(), report.message(), global);
} else {
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
isChromeError = worker->IsChromeWorker();
xpcReport->InitOnWorkerThread(report.report(), report.message(),
GetCurrentThreadWorkerPrivate()->IsChromeWorker());
}
// Now post an event to do the real reporting async
@ -1025,11 +1019,7 @@ Promise::MaybeReportRejected()
// AsyncErrorReporter, otherwise if the call to DispatchToMainThread fails, it
// will leak. See Bug 958684.
nsRefPtr<AsyncErrorReporter> r =
new AsyncErrorReporter(CycleCollectedJSRuntime::Get()->Runtime(),
report.report(),
report.message(),
isChromeError,
win);
new AsyncErrorReporter(CycleCollectedJSRuntime::Get()->Runtime(), xpcReport);
NS_DispatchToMainThread(r);
}

Просмотреть файл

@ -163,7 +163,7 @@ void LossyConvertUTF8toUTF16(const char* aInput, uint32_t aLength, nsAString& aO
char16_t dst[aLength]; // Allocating for worst case.
// First, count how many jschars need to be in the inflated string.
// Count how many char16_t characters are needed in the inflated string.
// |i| is the index into |src|, and |j| is the the index into |dst|.
size_t srclen = src.length();
uint32_t j = 0;
@ -214,20 +214,20 @@ void LossyConvertUTF8toUTF16(const char* aInput, uint32_t aLength, nsAString& aO
if ((src[i + m] & 0xC0) != 0x80)
INVALID(ReportInvalidCharacter, i, m);
// Determine the code unit's length in jschars and act accordingly.
// Determine the code unit's length in char16_t units and act accordingly.
v = JS::Utf8ToOneUcs4Char((uint8_t *)&src[i], n);
if (v < 0x10000) {
// The n-byte UTF8 code unit will fit in a single jschar.
dst[j] = jschar(v);
// The n-byte UTF8 code unit will fit in a single char16_t.
dst[j] = char16_t(v);
} else {
v -= 0x10000;
if (v <= 0xFFFFF) {
// The n-byte UTF8 code unit will fit in two jschars.
dst[j] = jschar((v >> 10) + 0xD800);
// The n-byte UTF8 code unit will fit in two char16_t units.
dst[j] = char16_t((v >> 10) + 0xD800);
j++;
dst[j] = jschar((v & 0x3FF) + 0xDC00);
dst[j] = char16_t((v & 0x3FF) + 0xDC00);
} else {
// The n-byte UTF8 code unit won't fit in two jschars.
// The n-byte UTF8 code unit won't fit in two char16_t units.
INVALID(ReportTooBigCharacter, v, 1);
}
}

Просмотреть файл

@ -21,7 +21,7 @@ namespace {
#ifdef BUILD_CTYPES
char*
UnicodeToNative(JSContext* aCx, const jschar* aSource, size_t aSourceLen)
UnicodeToNative(JSContext* aCx, const char16_t* aSource, size_t aSourceLen)
{
nsDependentString unicode(aSource, aSourceLen);

Просмотреть файл

@ -737,8 +737,8 @@ GetPrincipalForAsmJSCacheOp()
static bool
AsmJSCacheOpenEntryForRead(JS::Handle<JSObject*> aGlobal,
const jschar* aBegin,
const jschar* aLimit,
const char16_t* aBegin,
const char16_t* aLimit,
size_t* aSize,
const uint8_t** aMemory,
intptr_t *aHandle)
@ -755,8 +755,8 @@ AsmJSCacheOpenEntryForRead(JS::Handle<JSObject*> aGlobal,
static bool
AsmJSCacheOpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
bool aInstalled,
const jschar* aBegin,
const jschar* aEnd,
const char16_t* aBegin,
const char16_t* aEnd,
size_t aSize,
uint8_t** aMemory,
intptr_t* aHandle)

Просмотреть файл

@ -156,7 +156,7 @@ struct ScriptLoadInfo
nsString mURL;
nsCOMPtr<nsIChannel> mChannel;
jschar* mScriptTextBuf;
char16_t* mScriptTextBuf;
size_t mScriptTextLength;
nsresult mLoadResult;

Просмотреть файл

@ -337,7 +337,7 @@ nsXBLProtoImpl::UndefineFields(JSContext *cx, JS::Handle<JSObject*> obj) const
for (nsXBLProtoImplField* f = mFields; f; f = f->GetNext()) {
nsDependentString name(f->GetName());
const jschar* s = name.get();
const char16_t* s = name.get();
bool hasProp;
if (::JS_AlreadyHasOwnUCProperty(cx, obj, s, name.Length(), &hasProp) &&
hasProp) {

Просмотреть файл

@ -445,7 +445,7 @@ nsXBLProtoImplField::InstallField(JS::Handle<JSObject*> aBoundNode,
nsDependentString name(mName);
if (!JS_WrapValue(cx, &result) ||
!::JS_DefineUCProperty(cx, aBoundNode,
reinterpret_cast<const jschar*>(mName),
reinterpret_cast<const char16_t*>(mName),
name.Length(), result, mJSAttributes)) {
return NS_ERROR_OUT_OF_MEMORY;
}

Просмотреть файл

@ -115,7 +115,7 @@ nsXBLProtoImplMethod::InstallMember(JSContext* aCx,
NS_ENSURE_TRUE(method, NS_ERROR_OUT_OF_MEMORY);
if (!::JS_DefineUCProperty(aCx, aTargetClassObject,
static_cast<const jschar*>(mName),
static_cast<const char16_t*>(mName),
name.Length(), method,
JSPROP_ENUMERATE)) {
return NS_ERROR_OUT_OF_MEMORY;

Просмотреть файл

@ -147,7 +147,7 @@ nsXBLProtoImplProperty::InstallMember(JSContext *aCx,
nsDependentString name(mName);
if (!::JS_DefineUCProperty(aCx, aTargetClassObject,
static_cast<const jschar*>(mName),
static_cast<const char16_t*>(mName),
name.Length(), JS::UndefinedHandleValue, mJSAttributes,
JS_DATA_TO_FUNC_PTR(JSPropertyOp, getter.get()),
JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, setter.get())))

Просмотреть файл

@ -49,12 +49,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=502673
}
},
QueryInterface: function(iid) {
QueryInterface: SpecialPowers.wrapCallback(function(iid) {
if (iid.equals(SpecialPowers.Ci.nsIDocumentStateListener) ||
iid.equals(SpecialPowers.Ci.nsISupports))
return this;
throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
},
}),
};
function doTest() {

Просмотреть файл

@ -0,0 +1,8 @@
[DEFAULT]
skip-if = buildapp == 'b2g'
support-files =
320x240.ogv
bug449141_page.html
[test_bug449141.html]
skip-if = toolkit == 'android'

Просмотреть файл

@ -1,13 +1,9 @@
[DEFAULT]
skip-if = buildapp == 'b2g'
support-files =
320x240.ogv
bug293834_form.html
bug449141_page.html
[test_bug293834.html]
[test_bug449141.html]
skip-if = toolkit == 'android'
[test_bug499115.html]
[test_nsFind.html]
[test_private_window_from_content.html]

Просмотреть файл

@ -5,4 +5,4 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
MOCHITEST_MANIFESTS += ['mochitest.ini']
MOCHITEST_CHROME_MANIFESTS += ['chrome.ini']

Просмотреть файл

@ -5,8 +5,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=449141
-->
<head>
<title>Test for Bug 449141</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=449141">Mozilla Bug 449141</a>

Просмотреть файл

@ -406,7 +406,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState,
mApzcTreeLog << '\n';
// Accumulate the CSS transform between layers that have an APZC.
// In the terminology of the big comment above APZCTreeManager::GetInputTransforms, if
// In the terminology of the big comment above APZCTreeManager::GetScreenToApzcTransform, if
// we are at layer M, then aAncestorTransform is NC * OC * PC, and we left-multiply MC and
// compute ancestorTransform to be MC * NC * OC * PC. This gets passed down as the ancestor
// transform to layer L when we recurse into the children below. If we are at a layer
@ -495,8 +495,8 @@ ApplyTransform(nsIntPoint* aPoint, const Matrix4x4& aMatrix)
/*static*/ template<class T> void
TransformScreenToGecko(T* aPoint, AsyncPanZoomController* aApzc, APZCTreeManager* aApzcTm)
{
Matrix4x4 transformToApzc, transformToGecko;
aApzcTm->GetInputTransforms(aApzc, transformToApzc, transformToGecko);
Matrix4x4 transformToApzc = aApzcTm->GetScreenToApzcTransform(aApzc);
Matrix4x4 transformToGecko = aApzcTm->GetApzcToGeckoTransform(aApzc);
ApplyTransform(aPoint, transformToApzc * transformToGecko);
}
@ -506,7 +506,6 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
{
nsEventStatus result = nsEventStatus_eIgnore;
Matrix4x4 transformToApzc;
Matrix4x4 transformToGecko;
bool inOverscrolledApzc = false;
switch (aEvent.mInputType) {
case MULTITOUCH_INPUT: {
@ -522,7 +521,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
// transform than the one in TransformScreenToGecko, so we need to
// make a copy of the event.
PanGestureInput inputForApzc(panInput);
GetInputTransforms(apzc, transformToApzc, transformToGecko);
transformToApzc = GetScreenToApzcTransform(apzc);
ApplyTransform(&(inputForApzc.mPanStartPoint), transformToApzc);
result = apzc->ReceiveInputEvent(inputForApzc);
@ -540,7 +539,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
// transform than the one in TransformScreenToGecko, so we need to
// make a copy of the event.
PinchGestureInput inputForApzc(pinchInput);
GetInputTransforms(apzc, transformToApzc, transformToGecko);
transformToApzc = GetScreenToApzcTransform(apzc);
ApplyTransform(&(inputForApzc.mFocusPoint), transformToApzc);
result = apzc->ReceiveInputEvent(inputForApzc);
@ -558,7 +557,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
// transform than the one in TransformScreenToGecko, so we need to
// make a copy of the event.
TapGestureInput inputForApzc(tapInput);
GetInputTransforms(apzc, transformToApzc, transformToGecko);
transformToApzc = GetScreenToApzcTransform(apzc);
ApplyTransform(&(inputForApzc.mPoint), transformToApzc);
result = apzc->ReceiveInputEvent(inputForApzc);
@ -632,8 +631,7 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput,
if (mApzcForInputBlock) {
// Cache apz transform so it can be used for future events in this block.
Matrix4x4 transformToGecko;
GetInputTransforms(mApzcForInputBlock, mCachedTransformToApzcForInputBlock, transformToGecko);
mCachedTransformToApzcForInputBlock = GetScreenToApzcTransform(mApzcForInputBlock);
} else {
// Reset the cached apz transform
mCachedTransformToApzcForInputBlock = Matrix4x4();
@ -680,8 +678,8 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput,
// For computing the event to pass back to Gecko, use the up-to-date transforms.
// This ensures that transformToApzc and transformToGecko are in sync
// (note that transformToGecko isn't cached).
Matrix4x4 transformToGecko;
GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToGecko);
transformToApzc = GetScreenToApzcTransform(mApzcForInputBlock);
Matrix4x4 transformToGecko = GetApzcToGeckoTransform(mApzcForInputBlock);
Matrix4x4 outTransform = transformToApzc * transformToGecko;
for (size_t i = 0; i < aInput.mTouches.Length(); i++) {
ApplyTransform(&(aInput.mTouches[i].mScreenPoint), outTransform);
@ -721,9 +719,8 @@ APZCTreeManager::TransformCoordinateToGecko(const ScreenIntPoint& aPoint,
MOZ_ASSERT(aOutTransformedPoint);
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aPoint, nullptr);
if (apzc && aOutTransformedPoint) {
Matrix4x4 transformToApzc;
Matrix4x4 transformToGecko;
GetInputTransforms(apzc, transformToApzc, transformToGecko);
Matrix4x4 transformToApzc = GetScreenToApzcTransform(apzc);
Matrix4x4 transformToGecko = GetApzcToGeckoTransform(apzc);
Matrix4x4 outTransform = transformToApzc * transformToGecko;
*aOutTransformedPoint = TransformTo<LayoutDevicePixel>(outTransform, aPoint);
}
@ -743,9 +740,8 @@ APZCTreeManager::ProcessEvent(WidgetInputEvent& aEvent,
&inOverscrolledApzc);
if (apzc) {
apzc->GetGuid(aOutTargetGuid);
Matrix4x4 transformToApzc;
Matrix4x4 transformToGecko;
GetInputTransforms(apzc, transformToApzc, transformToGecko);
Matrix4x4 transformToApzc = GetScreenToApzcTransform(apzc);
Matrix4x4 transformToGecko = GetApzcToGeckoTransform(apzc);
Matrix4x4 outTransform = transformToApzc * transformToGecko;
ApplyTransform(&(aEvent.refPoint), outTransform);
}
@ -877,17 +873,16 @@ TransformDisplacement(APZCTreeManager* aTreeManager,
ScreenPoint& aStartPoint,
ScreenPoint& aEndPoint) {
Matrix4x4 transformToApzc;
Matrix4x4 transformToGecko; // ignored
// Convert start and end points to untransformed screen coordinates.
aTreeManager->GetInputTransforms(aSource, transformToApzc, transformToGecko);
transformToApzc = aTreeManager->GetScreenToApzcTransform(aSource);
Matrix4x4 untransformToApzc = transformToApzc;
untransformToApzc.Invert();
ApplyTransform(&aStartPoint, untransformToApzc);
ApplyTransform(&aEndPoint, untransformToApzc);
// Convert start and end points to aTarget's transformed screen coordinates.
aTreeManager->GetInputTransforms(aTarget, transformToApzc, transformToGecko);
transformToApzc = aTreeManager->GetScreenToApzcTransform(aTarget);
ApplyTransform(&aStartPoint, transformToApzc);
ApplyTransform(&aEndPoint, transformToApzc);
}
@ -1159,7 +1154,7 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc,
mTreeLock.AssertCurrentThreadOwns();
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
// explained in the comment on GetInputTransforms. This function will recurse with aApzc at L and P, and the
// explained in the comment above GetScreenToApzcTransform. This function will recurse with aApzc at L and P, and the
// comments explain what values are stored in the variables at these two levels. All the comments
// use standard matrix notation where the leftmost matrix in a multiplication is applied first.
@ -1224,8 +1219,8 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc,
return result;
}
/* This function sets the aTransformToApzcOut and aTransformToGeckoOut out-parameters
to some useful transformations that input events may need applied. This is best
/* The methods GetScreenToApzcTransform() and GetApzcToGeckoTransform() return
some useful transformations that input events may need applied. This is best
illustrated with an example. Consider a chain of layers, L, M, N, O, P, Q, R. Layer L
is the layer that corresponds to the argument |aApzc|, and layer R is the root
of the layer tree. Layer M is the parent of L, N is the parent of M, and so on.
@ -1258,7 +1253,7 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc,
MT.Inverse()
MN.Inverse()
MC.Inverse()
This combined transformation is returned in the aTransformToApzcOut out-parameter.
This combined transformation is returned by GetScreenToApzcTransform().
Next, if we want user inputs sent to gecko for event-dispatching, we will need to strip
out all of the async transforms that are involved in this chain. This is because async
@ -1290,7 +1285,7 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc,
RC
RD
This sequence can be simplified and refactored to the following:
aTransformToApzcOut
GetScreenToApzcTransform()
LA.Inverse()
LD
MC
@ -1298,9 +1293,9 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc,
...
RC
RD
Since aTransformToApzcOut is already one of the out-parameters, we set aTransformToGeckoOut
to the remaining transforms (LA.Inverse() * LD * ... * RD), so that the caller code can
combine it with aTransformToApzcOut to get the final transform required in this case.
Since GetScreenToApzcTransform() can be obtained by calling that function, GetApzcToGeckoTransform()
returns the remaining transforms (LA.Inverse() * LD * ... * RD), so that the caller code can
combine it with GetScreenToApzcTransform() to get the final transform required in this case.
Note that for many of these layers, there will be no AsyncPanZoomController attached, and
so the async transform will be the identity transform. So, in the example above, if layers
@ -1314,10 +1309,14 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc,
The APZCs also obviously have LT, LN, PT, and PN, so all of the above transformation combinations
required can be generated.
*/
void
APZCTreeManager::GetInputTransforms(AsyncPanZoomController *aApzc, Matrix4x4& aTransformToApzcOut,
Matrix4x4& aTransformToGeckoOut)
/*
* See the long comment above for a detailed explanation of this function.
*/
Matrix4x4
APZCTreeManager::GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const
{
Matrix4x4 result;
MonitorAutoLock lock(mTreeLock);
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
@ -1329,34 +1328,64 @@ APZCTreeManager::GetInputTransforms(AsyncPanZoomController *aApzc, Matrix4x4& aT
// ancestorUntransform is PC.Inverse() * OC.Inverse() * NC.Inverse() * MC.Inverse()
Matrix4x4 ancestorUntransform = aApzc->GetAncestorTransform();
ancestorUntransform.Invert();
// asyncUntransform is LA.Inverse()
Matrix4x4 asyncUntransform = aApzc->GetCurrentAsyncTransform();
asyncUntransform.Invert();
// aTransformToApzcOut is initialized to PC.Inverse() * OC.Inverse() * NC.Inverse() * MC.Inverse()
aTransformToApzcOut = ancestorUntransform;
// aTransformToGeckoOut is initialized to LA.Inverse() * LD * MC * NC * OC * PC
aTransformToGeckoOut = asyncUntransform * aApzc->GetTransformToLastDispatchedPaint() * aApzc->GetAncestorTransform();
// result is initialized to PC.Inverse() * OC.Inverse() * NC.Inverse() * MC.Inverse()
result = ancestorUntransform;
for (AsyncPanZoomController* parent = aApzc->GetParent(); parent; parent = parent->GetParent()) {
// ancestorUntransform is updated to RC.Inverse() * QC.Inverse() when parent == P
ancestorUntransform = parent->GetAncestorTransform();
ancestorUntransform.Invert();
// asyncUntransform is updated to PA.Inverse() when parent == P
asyncUntransform = parent->GetCurrentAsyncTransform();
Matrix4x4 asyncUntransform = parent->GetCurrentAsyncTransform();
asyncUntransform.Invert();
// untransformSinceLastApzc is RC.Inverse() * QC.Inverse() * PA.Inverse()
Matrix4x4 untransformSinceLastApzc = ancestorUntransform * asyncUntransform;
// aTransformToApzcOut is RC.Inverse() * QC.Inverse() * PA.Inverse() * PC.Inverse() * OC.Inverse() * NC.Inverse() * MC.Inverse()
aTransformToApzcOut = untransformSinceLastApzc * aTransformToApzcOut;
// aTransformToGeckoOut is LA.Inverse() * LD * MC * NC * OC * PC * PD * QC * RC
aTransformToGeckoOut = aTransformToGeckoOut * parent->GetTransformToLastDispatchedPaint() * parent->GetAncestorTransform();
// result is RC.Inverse() * QC.Inverse() * PA.Inverse() * PC.Inverse() * OC.Inverse() * NC.Inverse() * MC.Inverse()
result = untransformSinceLastApzc * result;
// The above values for aTransformToApzcOut and aTransformToGeckoOut when parent == P match
// the required output as explained in the comment above this method. Note that any missing
// The above value for result when parent == P matches the required output
// as explained in the comment above this method. Note that any missing
// terms are guaranteed to be identity transforms.
}
return result;
}
/*
* See the long comment above GetScreenToApzcTransform() for a detailed
* explanation of this function.
*/
Matrix4x4
APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const
{
Matrix4x4 result;
MonitorAutoLock lock(mTreeLock);
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
// explained in the comment above. This function is called with aApzc at L, and the loop
// below performs one iteration, where parent is at P. The comments explain what values are stored
// in the variables at these two levels. All the comments use standard matrix notation where the
// leftmost matrix in a multiplication is applied first.
// asyncUntransform is LA.Inverse()
Matrix4x4 asyncUntransform = aApzc->GetCurrentAsyncTransform();
asyncUntransform.Invert();
// aTransformToGeckoOut is initialized to LA.Inverse() * LD * MC * NC * OC * PC
result = asyncUntransform * aApzc->GetTransformToLastDispatchedPaint() * aApzc->GetAncestorTransform();
for (AsyncPanZoomController* parent = aApzc->GetParent(); parent; parent = parent->GetParent()) {
// aTransformToGeckoOut is LA.Inverse() * LD * MC * NC * OC * PC * PD * QC * RC
result = result * parent->GetTransformToLastDispatchedPaint() * parent->GetAncestorTransform();
// The above value for result when parent == P matches the required output
// as explained in the comment above this method. Note that any missing
// terms are guaranteed to be identity transforms.
}
return result;
}
already_AddRefed<AsyncPanZoomController>

Просмотреть файл

@ -361,8 +361,8 @@ public:
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScrollableLayerGuid& aGuid);
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScreenPoint& aPoint,
bool* aOutInOverscrolledApzc);
void GetInputTransforms(AsyncPanZoomController *aApzc, gfx::Matrix4x4& aTransformToApzcOut,
gfx::Matrix4x4& aTransformToGeckoOut);
gfx::Matrix4x4 GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const;
gfx::Matrix4x4 GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const;
private:
/* Helpers */
AsyncPanZoomController* FindTargetAPZC(AsyncPanZoomController* aApzc, FrameMetrics::ViewID aScrollId);
@ -417,7 +417,7 @@ private:
* is considered part of the APZC tree management state.
* Finally, the lock needs to be held when accessing mOverscrollHandoffChain.
* IMPORTANT: See the note about lock ordering at the top of this file. */
mozilla::Monitor mTreeLock;
mutable mozilla::Monitor mTreeLock;
nsRefPtr<AsyncPanZoomController> mRootApzc;
/* This tracks the APZC that should receive all inputs for the current input event block.
* This allows touch points to move outside the thing they started on, but still have the

Просмотреть файл

@ -927,7 +927,7 @@ AsyncPanZoomController::Destroy()
}
bool
AsyncPanZoomController::IsDestroyed()
AsyncPanZoomController::IsDestroyed() const
{
return mTreeManager == nullptr;
}
@ -1453,9 +1453,7 @@ AsyncPanZoomController::ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut
{
APZCTreeManager* treeManagerLocal = mTreeManager;
if (treeManagerLocal) {
Matrix4x4 transformToApzc;
Matrix4x4 transformToGecko;
treeManagerLocal->GetInputTransforms(this, transformToApzc, transformToGecko);
Matrix4x4 transformToGecko = treeManagerLocal->GetApzcToGeckoTransform(this);
Point result = transformToGecko * Point(aPoint.x, aPoint.y);
// NOTE: This isn't *quite* LayoutDevicePoint, we just don't have a name
// for this coordinate space and it maps the closest to LayoutDevicePoint.
@ -1544,7 +1542,9 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool
mX.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.x, aEvent.mTime);
mY.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.y, aEvent.mTime);
HandlePanningUpdate(aEvent.mPanDisplacement.x, aEvent.mPanDisplacement.y);
ScreenPoint panDisplacement = aEvent.mPanDisplacement;
ToGlobalScreenCoordinates(&panDisplacement, aEvent.mPanStartPoint);
HandlePanningUpdate(panDisplacement);
// TODO: Handle pan events sent without pan begin / pan end events properly.
if (mPanGestureState) {
@ -1694,9 +1694,49 @@ nsEventStatus AsyncPanZoomController::OnCancelTap(const TapGestureInput& aEvent)
return nsEventStatus_eIgnore;
}
float AsyncPanZoomController::PanDistance() {
ReentrantMonitorAutoEnter lock(mMonitor);
return NS_hypot(mX.PanDistance(), mY.PanDistance());
// Helper function for To[Global|Local]ScreenCoordinates().
// TODO(botond): Generalize this into a template function in UnitTransforms.h.
static void TransformVector(const Matrix4x4& aTransform,
ScreenPoint* aVector,
const ScreenPoint& aAnchor) {
ScreenPoint start = aAnchor;
ScreenPoint end = aAnchor + *aVector;
start = TransformTo<ScreenPixel>(aTransform, start);
end = TransformTo<ScreenPixel>(aTransform, end);
*aVector = end - start;
}
void AsyncPanZoomController::ToGlobalScreenCoordinates(ScreenPoint* aVector,
const ScreenPoint& aAnchor) const {
if (APZCTreeManager* treeManagerLocal = mTreeManager) {
Matrix4x4 transform = treeManagerLocal->GetScreenToApzcTransform(this);
transform.Invert();
TransformVector(transform, aVector, aAnchor);
}
}
void AsyncPanZoomController::ToLocalScreenCoordinates(ScreenPoint* aVector,
const ScreenPoint& aAnchor) const {
if (APZCTreeManager* treeManagerLocal = mTreeManager) {
Matrix4x4 transform = treeManagerLocal->GetScreenToApzcTransform(this);
TransformVector(transform, aVector, aAnchor);
}
}
float AsyncPanZoomController::PanDistance() const {
ScreenPoint panVector;
ScreenPoint panStart;
{
ReentrantMonitorAutoEnter lock(mMonitor);
panVector = ScreenPoint(mX.PanDistance(), mY.PanDistance());
panStart = PanStart();
}
ToGlobalScreenCoordinates(&panVector, panStart);
return NS_hypot(panVector.x, panVector.y);
}
ScreenPoint AsyncPanZoomController::PanStart() const {
return ScreenPoint(mX.PanStart(), mY.PanStart());
}
const ScreenPoint AsyncPanZoomController::GetVelocityVector() {
@ -1772,16 +1812,16 @@ void AsyncPanZoomController::HandlePanning(double aAngle) {
}
}
void AsyncPanZoomController::HandlePanningUpdate(float aDX, float aDY) {
void AsyncPanZoomController::HandlePanningUpdate(const ScreenPoint& aDelta) {
// If we're axis-locked, check if the user is trying to break the lock
if (GetAxisLockMode() == STICKY && !mPanDirRestricted) {
double angle = atan2(aDY, aDX); // range [-pi, pi]
double angle = atan2(aDelta.y, aDelta.x); // range [-pi, pi]
angle = fabs(angle); // range [0, pi]
float breakThreshold = gfxPrefs::APZAxisBreakoutThreshold() * APZCTreeManager::GetDPI();
if (fabs(aDX) > breakThreshold || fabs(aDY) > breakThreshold) {
if (fabs(aDelta.x) > breakThreshold || fabs(aDelta.y) > breakThreshold) {
if (mState == PANNING_LOCKED_X || mState == CROSS_SLIDING_X) {
if (!IsCloseToHorizontal(angle, gfxPrefs::APZAxisBreakoutAngle())) {
mY.SetAxisLocked(false);
@ -2026,9 +2066,11 @@ void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
ScreenPoint prevTouchPoint(mX.GetPos(), mY.GetPos());
ScreenPoint touchPoint = GetFirstTouchScreenPoint(aEvent);
float dx = mX.PanDistance(touchPoint.x);
float dy = mY.PanDistance(touchPoint.y);
HandlePanningUpdate(dx, dy);
ScreenPoint delta(mX.PanDistance(touchPoint.x),
mY.PanDistance(touchPoint.y));
const ScreenPoint panStart = PanStart();
ToGlobalScreenCoordinates(&delta, panStart);
HandlePanningUpdate(delta);
UpdateWithTouchAtDevicePoint(aEvent);
@ -2465,7 +2507,7 @@ void AsyncPanZoomController::SampleContentTransformForFrame(ViewTransform* aOutT
}
}
ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() {
ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const {
ReentrantMonitorAutoEnter lock(mMonitor);
CSSPoint lastPaintScrollOffset;
@ -2503,14 +2545,14 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() {
return ViewTransform(scale, -translation);
}
Matrix4x4 AsyncPanZoomController::GetNontransientAsyncTransform() {
Matrix4x4 AsyncPanZoomController::GetNontransientAsyncTransform() const {
ReentrantMonitorAutoEnter lock(mMonitor);
return Matrix4x4().Scale(mLastContentPaintMetrics.mResolution.scale,
mLastContentPaintMetrics.mResolution.scale,
1.0f);
}
Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() {
Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const {
ReentrantMonitorAutoEnter lock(mMonitor);
// Technically we should be taking the scroll delta in the coordinate space

Просмотреть файл

@ -88,6 +88,7 @@ public:
* device DPI, before we start panning the screen. This is to prevent us from
* accidentally processing taps as touch moves, and from very short/accidental
* touches moving the screen.
* Note: this distance is in global screen coordinates.
*/
static float GetTouchStartTolerance();
@ -212,7 +213,7 @@ public:
/**
* Returns true if Destroy() has already been called on this APZC instance.
*/
bool IsDestroyed();
bool IsDestroyed() const;
/**
* Returns the incremental transformation corresponding to the async pan/zoom
@ -220,14 +221,14 @@ public:
* existing transform, it will make the layer appear with the desired pan/zoom
* amount.
*/
ViewTransform GetCurrentAsyncTransform();
ViewTransform GetCurrentAsyncTransform() const;
/**
* Returns the part of the async transform that will remain once Gecko does a
* repaint at the desired metrics. That is, in the steady state:
* Matrix4x4(GetCurrentAsyncTransform()) === GetNontransientAsyncTransform()
*/
Matrix4x4 GetNontransientAsyncTransform();
Matrix4x4 GetNontransientAsyncTransform() const;
/**
* Returns the transform to take something from the coordinate space of the
@ -236,7 +237,7 @@ public:
* processed, this is needed to transform input events properly into a space
* gecko will understand.
*/
Matrix4x4 GetTransformToLastDispatchedPaint();
Matrix4x4 GetTransformToLastDispatchedPaint() const;
/**
* Recalculates the displayport. Ideally, this should paint an area bigger
@ -326,6 +327,28 @@ public:
*/
int32_t GetLastTouchIdentifier() const;
/**
* Convert the vector |aVector|, rooted at the point |aAnchor|, from
* this APZC's local screen coordinates into global screen coordinates.
* The anchor is necessary because with 3D tranforms, the location of the
* vector can affect the result of the transform.
* To respect the lock ordering, mMonitor must NOT be held when calling
* this function (since this function acquires the tree lock).
*/
void ToGlobalScreenCoordinates(ScreenPoint* aVector,
const ScreenPoint& aAnchor) const;
/**
* Convert the vector |aVector|, rooted at the point |aAnchor|, from
* global screen coordinates into this APZC's local screen coordinates .
* The anchor is necessary because with 3D tranforms, the location of the
* vector can affect the result of the transform.
* To respect the lock ordering, mMonitor must NOT be held when calling
* this function (since this function acquires the tree lock).
*/
void ToLocalScreenCoordinates(ScreenPoint* aVector,
const ScreenPoint& aAnchor) const;
protected:
enum PanZoomState {
NOTHING, /* no touch-start events received */
@ -462,9 +485,21 @@ protected:
* Gets the displacement of the current touch since it began. That is, it is
* the distance between the current position and the initial position of the
* current touch (this only makes sense if a touch is currently happening and
* OnTouchMove() is being invoked).
* OnTouchMove() or the equivalent for pan gestures is being invoked).
* Note: This function returns a distance in global screen coordinates,
* not the local screen coordinates of this APZC.
*/
float PanDistance();
float PanDistance() const;
/**
* Gets the start point of the current touch.
* Like PanDistance(), this only makes sense if a touch is currently
* happening and OnTouchMove() or the equivalent for pan gestures is
* being invoked.
* Unlikely PanDistance(), this function returns a point in local screen
* coordinates.
*/
ScreenPoint PanStart() const;
/**
* Gets a vector of the velocities of each axis.
@ -489,8 +524,9 @@ protected:
/**
* Update the panning state and axis locks.
* Note: |aDelta| is expected to be in global screen coordinates.
*/
void HandlePanningUpdate(float aDX, float aDY);
void HandlePanningUpdate(const ScreenPoint& aDelta);
/**
* Sets up anything needed for panning. This takes us out of the "TOUCHING"

Просмотреть файл

@ -49,7 +49,9 @@ void Axis::UpdateWithTouchAtDevicePoint(ScreenCoord aPos, uint32_t aTimestampMs)
float newVelocity = mAxisLocked ? 0.0f : (float)(mPos - aPos) / (float)(aTimestampMs - mPosTimeMs);
if (gfxPrefs::APZMaxVelocity() > 0.0f) {
newVelocity = std::min(newVelocity, gfxPrefs::APZMaxVelocity() * APZCTreeManager::GetDPI());
ScreenPoint maxVelocity = MakePoint(gfxPrefs::APZMaxVelocity() * APZCTreeManager::GetDPI());
mAsyncPanZoomController->ToLocalScreenCoordinates(&maxVelocity, mAsyncPanZoomController->PanStart());
newVelocity = std::min(newVelocity, maxVelocity.Length());
}
mVelocity = newVelocity;
@ -207,12 +209,16 @@ void Axis::ClearOverscroll() {
mOverscroll = 0;
}
float Axis::PanDistance() {
return fabsf((mPos - mStartPos).value);
ScreenCoord Axis::PanStart() const {
return mStartPos;
}
float Axis::PanDistance(ScreenCoord aPos) {
return fabsf((aPos - mStartPos).value);
ScreenCoord Axis::PanDistance() const {
return fabs(mPos - mStartPos);
}
ScreenCoord Axis::PanDistance(ScreenCoord aPos) const {
return fabs(aPos - mStartPos);
}
void Axis::EndTouch(uint32_t aTimestampMs) {
@ -387,6 +393,11 @@ CSSCoord AxisX::GetRectOffset(const CSSRect& aRect) const
return aRect.x;
}
ScreenPoint AxisX::MakePoint(ScreenCoord aCoord) const
{
return ScreenPoint(aCoord, 0);
}
AxisY::AxisY(AsyncPanZoomController* aAsyncPanZoomController)
: Axis(aAsyncPanZoomController)
{
@ -408,5 +419,10 @@ CSSCoord AxisY::GetRectOffset(const CSSRect& aRect) const
return aRect.y;
}
ScreenPoint AxisY::MakePoint(ScreenCoord aCoord) const
{
return ScreenPoint(0, aCoord);
}
}
}

Просмотреть файл

@ -119,17 +119,22 @@ public:
void ClearOverscroll();
/**
* Gets the distance between the starting position of the touch supplied in
* startTouch() and the current touch from the last
* updateWithTouchAtDevicePoint().
* Gets the starting position of the touch supplied in StartTouch().
*/
float PanDistance();
ScreenCoord PanStart() const;
/**
* Gets the distance between the starting position of the touch supplied in
* startTouch() and the supplied position.
* StartTouch() and the current touch from the last
* UpdateWithTouchAtDevicePoint().
*/
float PanDistance(ScreenCoord aPos);
ScreenCoord PanDistance() const;
/**
* Gets the distance between the starting position of the touch supplied in
* StartTouch() and the supplied position.
*/
ScreenCoord PanDistance(ScreenCoord aPos) const;
/**
* Applies friction during a fling, or cancels the fling if the velocity is
@ -217,6 +222,8 @@ public:
virtual CSSCoord GetRectLength(const CSSRect& aRect) const = 0;
virtual CSSCoord GetRectOffset(const CSSRect& aRect) const = 0;
virtual ScreenPoint MakePoint(ScreenCoord aCoord) const = 0;
protected:
ScreenCoord mPos;
uint32_t mPosTimeMs;
@ -250,6 +257,7 @@ public:
virtual CSSCoord GetPointOffset(const CSSPoint& aPoint) const;
virtual CSSCoord GetRectLength(const CSSRect& aRect) const;
virtual CSSCoord GetRectOffset(const CSSRect& aRect) const;
virtual ScreenPoint MakePoint(ScreenCoord aCoord) const;
};
class AxisY : public Axis {
@ -258,6 +266,7 @@ public:
virtual CSSCoord GetPointOffset(const CSSPoint& aPoint) const;
virtual CSSCoord GetRectLength(const CSSRect& aRect) const;
virtual CSSCoord GetRectOffset(const CSSRect& aRect) const;
virtual ScreenPoint MakePoint(ScreenCoord aCoord) const;
};
}

Просмотреть файл

@ -197,8 +197,10 @@ nsEventStatus GestureEventListener::HandleInputTouchMultiStart()
bool GestureEventListener::MoveDistanceIsLarge()
{
ScreenIntPoint delta = mLastTouchInput.mTouches[0].mScreenPoint - mTouchStartPosition;
return (NS_hypot(delta.x, delta.y) > AsyncPanZoomController::GetTouchStartTolerance());
const ScreenPoint start = mLastTouchInput.mTouches[0].mScreenPoint;
ScreenPoint delta = start - mTouchStartPosition;
mAsyncPanZoomController->ToGlobalScreenCoordinates(&delta, start);
return (delta.Length() > AsyncPanZoomController::GetTouchStartTolerance());
}
nsEventStatus GestureEventListener::HandleInputTouchMove()

Просмотреть файл

@ -252,7 +252,7 @@ private:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
MemoryPressureObserver(ClientLayerManager* aClientLayerManager)
explicit MemoryPressureObserver(ClientLayerManager* aClientLayerManager)
: mClientLayerManager(aClientLayerManager)
{
RegisterMemoryPressureEvent();

Просмотреть файл

@ -291,7 +291,8 @@ TextureClient::CreateForDrawing(ISurfaceAllocator* aAllocator,
}
if (!texture && aFormat == SurfaceFormat::B8G8R8X8 &&
aAllocator->IsSameProcess()) {
aAllocator->IsSameProcess() &&
aMoz2DBackend == gfx::BackendType::CAIRO) {
texture = new DIBTextureClient(aFormat, aTextureFlags);
}

Просмотреть файл

@ -1505,7 +1505,8 @@ protected:
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScreenPoint& aPoint) {
nsRefPtr<AsyncPanZoomController> hit = manager->GetTargetAPZC(aPoint, nullptr);
if (hit) {
manager->GetInputTransforms(hit.get(), transformToApzc, transformToGecko);
transformToApzc = manager->GetScreenToApzcTransform(hit.get());
transformToGecko = manager->GetApzcToGeckoTransform(hit.get());
}
return hit.forget();
}

Просмотреть файл

@ -4,4 +4,5 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g'
[mochitest/test_bug513439.html]
skip-if = e10s
[mochitest/test_acceleration.html]
[mochitest/test_overdraw.html]
# Disable test until bug 1064136 is fixed
# [mochitest/test_overdraw.html]

Просмотреть файл

@ -176,7 +176,7 @@ gfxUserFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeeds
class gfxOTSContext : public ots::OTSContext {
public:
gfxOTSContext(gfxUserFontEntry* aUserFontEntry)
explicit gfxOTSContext(gfxUserFontEntry* aUserFontEntry)
: mUserFontEntry(aUserFontEntry) {}
virtual ots::TableAction GetTableAction(uint32_t aTag) MOZ_OVERRIDE {

Просмотреть файл

@ -593,7 +593,6 @@ JavaScriptShared::Wrap(JSContext *cx, HandleObject aObj, InfallibleTArray<CpowEn
return true;
}
void JavaScriptShared::fixupAfterMovingGC()
{
objects_.sweep();

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше