зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-central to autoland. r=merge a=merge
This commit is contained in:
Коммит
2479eaedbf
|
@ -19,6 +19,14 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
setTimeout: "resource://gre/modules/Timer.jsm",
|
||||
});
|
||||
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager",
|
||||
"@mozilla.org/serviceworkers/manager;1",
|
||||
"nsIServiceWorkerManager");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "quotaManagerService",
|
||||
"@mozilla.org/dom/quota-manager-service;1",
|
||||
"nsIQuotaManagerService");
|
||||
|
||||
var {classes: Cc, interfaces: Ci} = Components;
|
||||
|
||||
/**
|
||||
|
@ -280,9 +288,41 @@ Sanitizer.prototype = {
|
|||
|
||||
offlineApps: {
|
||||
async clear(range) {
|
||||
// AppCache
|
||||
Components.utils.import("resource:///modules/offlineAppCache.jsm");
|
||||
// This doesn't wait for the cleanup to be complete.
|
||||
OfflineAppCacheHelper.clear();
|
||||
|
||||
// LocalStorage
|
||||
Services.obs.notifyObservers(null, "extension:purge-localStorage");
|
||||
|
||||
// ServiceWorkers
|
||||
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
|
||||
for (let i = 0; i < serviceWorkers.length; i++) {
|
||||
let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
|
||||
let host = sw.principal.URI.host;
|
||||
serviceWorkerManager.removeAndPropagate(host);
|
||||
}
|
||||
|
||||
// QuotaManager
|
||||
let promises = [];
|
||||
await new Promise(resolve => {
|
||||
quotaManagerService.getUsage(request => {
|
||||
for (let item of request.result) {
|
||||
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(item.origin);
|
||||
let uri = principal.URI;
|
||||
if (uri.scheme == "http" || uri.scheme == "https" || uri.scheme == "file") {
|
||||
promises.push(new Promise(r => {
|
||||
let req = quotaManagerService.clearStoragesForPrincipal(principal, null, true);
|
||||
req.callback = () => { r(); };
|
||||
}));
|
||||
}
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -17,6 +17,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "setTimeout",
|
|||
XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager",
|
||||
"@mozilla.org/serviceworkers/manager;1",
|
||||
"nsIServiceWorkerManager");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "quotaManagerService",
|
||||
"@mozilla.org/dom/quota-manager-service;1",
|
||||
"nsIQuotaManagerService");
|
||||
|
||||
/**
|
||||
* A number of iterations after which to yield time back
|
||||
|
@ -80,6 +83,29 @@ const clearHistory = options => {
|
|||
return sanitizer.items.history.clear(makeRange(options));
|
||||
};
|
||||
|
||||
const clearIndexedDB = async function(options) {
|
||||
let promises = [];
|
||||
|
||||
await new Promise(resolve => {
|
||||
quotaManagerService.getUsage(request => {
|
||||
for (let item of request.result) {
|
||||
let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(item.origin);
|
||||
let uri = principal.URI;
|
||||
if (uri.scheme == "http" || uri.scheme == "https" || uri.scheme == "file") {
|
||||
promises.push(new Promise(r => {
|
||||
let req = quotaManagerService.clearStoragesForPrincipal(principal, null, true);
|
||||
req.callback = () => { r(); };
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
};
|
||||
|
||||
const clearLocalStorage = async function(options) {
|
||||
Services.obs.notifyObservers(null, "extension:purge-localStorage");
|
||||
};
|
||||
|
@ -153,6 +179,9 @@ const doRemoval = (options, dataToRemove, extension) => {
|
|||
case "history":
|
||||
removalPromises.push(clearHistory(options));
|
||||
break;
|
||||
case "indexedDB":
|
||||
removalPromises.push(clearIndexedDB(options));
|
||||
break;
|
||||
case "localStorage":
|
||||
removalPromises.push(clearLocalStorage(options));
|
||||
break;
|
||||
|
@ -229,6 +258,9 @@ this.browsingData = class extends ExtensionAPI {
|
|||
removeHistory(options) {
|
||||
return doRemoval(options, {history: true});
|
||||
},
|
||||
removeIndexedDB(options) {
|
||||
return doRemoval(options, {indexedDB: true});
|
||||
},
|
||||
removeLocalStorage(options) {
|
||||
return doRemoval(options, {localStorage: true});
|
||||
},
|
||||
|
|
|
@ -22,6 +22,7 @@ support-files =
|
|||
file_dummy.html
|
||||
file_title.html
|
||||
file_inspectedwindow_reload_target.sjs
|
||||
file_indexedDB.html
|
||||
file_serviceWorker.html
|
||||
locale/chrome.manifest
|
||||
webNav_createdTarget.html
|
||||
|
@ -50,6 +51,7 @@ skip-if = (os == 'win' && !debug) # bug 1352668
|
|||
[browser_ext_browserAction_theme_icons.js]
|
||||
[browser_ext_browsingData_formData.js]
|
||||
[browser_ext_browsingData_history.js]
|
||||
[browser_ext_browsingData_indexedDB.js]
|
||||
[browser_ext_browsingData_localStorage.js]
|
||||
[browser_ext_browsingData_pluginData.js]
|
||||
[browser_ext_browsingData_serviceWorkers.js]
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set sts=2 sw=2 et tw=80: */
|
||||
/* eslint-disable mozilla/no-arbitrary-setTimeout */
|
||||
"use strict";
|
||||
|
||||
add_task(async function testIndexedDB() {
|
||||
function background() {
|
||||
const PAGE = "/browser/browser/components/extensions/test/browser/file_indexedDB.html";
|
||||
|
||||
browser.test.onMessage.addListener(async (msg) => {
|
||||
await browser.browsingData.remove({}, {indexedDB: true});
|
||||
browser.test.sendMessage("indexedDBRemoved");
|
||||
});
|
||||
|
||||
// Create two tabs.
|
||||
browser.tabs.create({url: `http://mochi.test:8888${PAGE}`});
|
||||
browser.tabs.create({url: `http://example.com${PAGE}`});
|
||||
}
|
||||
|
||||
function contentScript() {
|
||||
window.addEventListener("message", msg => { // eslint-disable-line mozilla/balanced-listeners
|
||||
browser.test.sendMessage("indexedDBCreated");
|
||||
}, true);
|
||||
}
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
background,
|
||||
manifest: {
|
||||
permissions: ["browsingData", "tabs"],
|
||||
"content_scripts": [{
|
||||
"matches": [
|
||||
"http://mochi.test/*/file_indexedDB.html",
|
||||
"http://example.com/*/file_indexedDB.html",
|
||||
],
|
||||
"js": ["script.js"],
|
||||
"run_at": "document_start",
|
||||
}],
|
||||
},
|
||||
files: {
|
||||
"script.js": contentScript,
|
||||
},
|
||||
});
|
||||
|
||||
let win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
await focusWindow(win);
|
||||
|
||||
await extension.startup();
|
||||
await extension.awaitMessage("indexedDBCreated");
|
||||
await extension.awaitMessage("indexedDBCreated");
|
||||
|
||||
let qms = SpecialPowers.Cc["@mozilla.org/dom/quota-manager-service;1"]
|
||||
.getService(Ci.nsIQuotaManagerService);
|
||||
|
||||
function getOrigins() {
|
||||
return new Promise(resolve => {
|
||||
let origins = [];
|
||||
qms.getUsage(request => {
|
||||
for (let i = 0; i < request.result.length; ++i) {
|
||||
if (request.result[i].origin.startsWith("http://mochi.test") ||
|
||||
request.result[i].origin.startsWith("http://example.com")) {
|
||||
origins.push(request.result[i].origin);
|
||||
}
|
||||
}
|
||||
resolve(origins);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let origins = await getOrigins();
|
||||
is(origins.length, 2, "IndexedDB databases have been populated.");
|
||||
|
||||
extension.sendMessage();
|
||||
|
||||
await extension.awaitMessage("indexedDBRemoved");
|
||||
|
||||
origins = await getOrigins();
|
||||
is(origins.length, 0, "IndexedDB data has been removed.");
|
||||
|
||||
await extension.unload();
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
const objectStoreName = "Objects";
|
||||
|
||||
let test = {key: 0, value: "test"};
|
||||
|
||||
let request = indexedDB.open("WebExtensionTest", 1);
|
||||
request.onupgradeneeded = event => {
|
||||
let db = event.target.result;
|
||||
let objectStore = db.createObjectStore(objectStoreName,
|
||||
{autoIncrement: 0});
|
||||
request = objectStore.add(test.value, test.key);
|
||||
request.onsuccess = event => {
|
||||
db.close();
|
||||
window.postMessage("indexedDBCreated", "*");
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
This is a test page.
|
||||
</body>
|
||||
<html>
|
|
@ -41,26 +41,3 @@ add_task(async function testInvalidArguments() {
|
|||
await extension.awaitFinish("invalidArguments");
|
||||
await extension.unload();
|
||||
});
|
||||
|
||||
add_task(async function testUnimplementedDataType() {
|
||||
function background() {
|
||||
browser.browsingData.remove({}, {indexedDB: true});
|
||||
browser.test.sendMessage("finished");
|
||||
}
|
||||
|
||||
let {messages} = await promiseConsoleOutput(async function() {
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
background: background,
|
||||
manifest: {
|
||||
permissions: ["browsingData"],
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
await extension.awaitMessage("finished");
|
||||
await extension.unload();
|
||||
});
|
||||
|
||||
let warningObserved = messages.find(line => /Firefox does not support dataTypes: indexedDB/.test(line));
|
||||
ok(warningObserved, "Warning issued when calling remove with an unimplemented dataType.");
|
||||
});
|
||||
|
|
|
@ -9,6 +9,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "OfflineAppCacheHelper",
|
|||
"resource:///modules/offlineAppCache.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
|
||||
"resource://gre/modules/ContextualIdentityService.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager",
|
||||
"@mozilla.org/serviceworkers/manager;1",
|
||||
"nsIServiceWorkerManager");
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"SiteDataManager"
|
||||
|
@ -217,6 +220,19 @@ this.SiteDataManager = {
|
|||
}
|
||||
},
|
||||
|
||||
_removeServiceWorkers(site) {
|
||||
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
|
||||
for (let i = 0; i < serviceWorkers.length; i++) {
|
||||
let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
|
||||
for (let principal of site.principals) {
|
||||
if (sw.principal.equals(principal)) {
|
||||
serviceWorkerManager.removeAndPropagate(sw.principal.URI.host);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
remove(hosts) {
|
||||
let promises = [];
|
||||
let unknownHost = "";
|
||||
|
@ -226,6 +242,7 @@ this.SiteDataManager = {
|
|||
this._removePermission(site);
|
||||
this._removeAppCache(site);
|
||||
this._removeCookie(site);
|
||||
this._removeServiceWorkers(site);
|
||||
promises.push(this._removeQuotaUsage(site));
|
||||
} else {
|
||||
unknownHost = host;
|
||||
|
@ -244,6 +261,15 @@ this.SiteDataManager = {
|
|||
Services.cache2.clear();
|
||||
Services.cookies.removeAll();
|
||||
OfflineAppCacheHelper.clear();
|
||||
|
||||
// Iterate through the service workers and remove them.
|
||||
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
|
||||
for (let i = 0; i < serviceWorkers.length; i++) {
|
||||
let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
|
||||
let host = sw.principal.URI.host;
|
||||
serviceWorkerManager.removeAndPropagate(host);
|
||||
}
|
||||
|
||||
// Refresh sites using quota usage again.
|
||||
// This is for the case:
|
||||
// 1. User goes to the about:preferences Site Data section.
|
||||
|
|
|
@ -1647,6 +1647,13 @@ var gPrivacyPane = {
|
|||
},
|
||||
|
||||
updateA11yPrefs(checked) {
|
||||
Services.prefs.setIntPref("accessibility.force_disabled", checked ? 1 : 0);
|
||||
let buttonIndex = confirmRestartPrompt(checked, 0, true, false);
|
||||
if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) {
|
||||
Services.prefs.setIntPref("accessibility.force_disabled", checked ? 1 : 0);
|
||||
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
|
||||
}
|
||||
|
||||
// Revert the checkbox in case we didn't quit
|
||||
document.getElementById("a11yPrivacyCheckbox").checked = !checked;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -702,11 +702,17 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
|
|||
host_or_target)
|
||||
|
||||
# Check that the additional flags we got are enough to not require any
|
||||
# more flags.
|
||||
if info.flags:
|
||||
flags += info.flags
|
||||
info = check_compiler(wrapper + [compiler] + flags, language,
|
||||
host_or_target)
|
||||
# more flags. If we get an exception, just ignore it; it's liable to be
|
||||
# invalid command-line flags, which means the compiler we're checking
|
||||
# doesn't support those command-line flags and will fail one or more of
|
||||
# the checks below.
|
||||
try:
|
||||
if info.flags:
|
||||
flags += info.flags
|
||||
info = check_compiler(wrapper + [compiler] + flags, language,
|
||||
host_or_target)
|
||||
except FatalCheckError:
|
||||
pass
|
||||
|
||||
if not info.target_cpu or info.target_cpu != host_or_target.cpu:
|
||||
raise FatalCheckError(
|
||||
|
@ -732,10 +738,6 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
|
|||
info.target_endianness or 'unknown', host_or_target_str,
|
||||
host_or_target.endianness))
|
||||
|
||||
if info.flags:
|
||||
raise FatalCheckError(
|
||||
'Unknown compiler or compiler not supported.')
|
||||
|
||||
# Compiler version checks
|
||||
# ===================================================
|
||||
# Check the compiler version here instead of in `compiler_version` so
|
||||
|
@ -747,7 +749,7 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
|
|||
% info.version)
|
||||
|
||||
# If you want to bump the version check here search for
|
||||
# __cpp_static_assert above, and see the associated comment.
|
||||
# cxx_alignof above, and see the associated comment.
|
||||
if info.type == 'clang' and not info.version:
|
||||
raise FatalCheckError(
|
||||
'Only clang/llvm 3.6 or newer is supported.')
|
||||
|
@ -762,6 +764,10 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None,
|
|||
'See https://developer.mozilla.org/en/'
|
||||
'Windows_Build_Prerequisites' % info.version)
|
||||
|
||||
if info.flags:
|
||||
raise FatalCheckError(
|
||||
'Unknown compiler or compiler not supported.')
|
||||
|
||||
return namespace(
|
||||
wrapper=wrapper,
|
||||
compiler=compiler,
|
||||
|
|
|
@ -1609,7 +1609,7 @@ nsDocShell::LoadURI(nsIURI* aURI,
|
|||
flags,
|
||||
target,
|
||||
nullptr, // No type hint
|
||||
NullString(), // No forced download
|
||||
VoidString(), // No forced download
|
||||
postStream,
|
||||
headersStream,
|
||||
loadType,
|
||||
|
@ -5488,8 +5488,8 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
|
|||
mozilla::net::RP_Unset,
|
||||
nsContentUtils::GetSystemPrincipal(), nullptr,
|
||||
INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
|
||||
nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
|
||||
nullptr, true, NullString(), this, nullptr, false,
|
||||
nullptr, VoidString(), nullptr, nullptr, LOAD_ERROR_PAGE,
|
||||
nullptr, true, VoidString(), this, nullptr, false,
|
||||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
|
@ -5589,7 +5589,7 @@ nsDocShell::Reload(uint32_t aReloadFlags)
|
|||
flags,
|
||||
EmptyString(), // No window target
|
||||
NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
|
||||
NullString(), // No forced download
|
||||
VoidString(), // No forced download
|
||||
nullptr, // No post data
|
||||
nullptr, // No headers data
|
||||
loadType, // Load type
|
||||
|
@ -9757,7 +9757,7 @@ public:
|
|||
mFlags, EmptyString(),
|
||||
mTypeHint.IsVoid() ? nullptr
|
||||
: mTypeHint.get(),
|
||||
NullString(), mPostData, mHeadersData,
|
||||
VoidString(), mPostData, mHeadersData,
|
||||
mLoadType, mSHEntry, mFirstParty,
|
||||
mSrcdoc, mSourceDocShell, mBaseURI,
|
||||
mCheckForPrerender, nullptr, nullptr);
|
||||
|
@ -10226,7 +10226,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
|||
aFlags,
|
||||
EmptyString(), // No window target
|
||||
aTypeHint,
|
||||
NullString(), // No forced download
|
||||
VoidString(), // No forced download
|
||||
aPostData,
|
||||
aHeadersData,
|
||||
aLoadType,
|
||||
|
@ -10837,7 +10837,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
|||
if (aFlags & INTERNAL_LOAD_FLAGS_IS_SRCDOC) {
|
||||
srcdoc = aSrcdoc;
|
||||
} else {
|
||||
srcdoc = NullString();
|
||||
srcdoc = VoidString();
|
||||
}
|
||||
|
||||
bool isTopLevelDoc = mItemType == typeContent &&
|
||||
|
@ -12860,7 +12860,7 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
|
|||
aEntry->GetBaseURI(getter_AddRefs(baseURI));
|
||||
flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
|
||||
} else {
|
||||
srcdoc = NullString();
|
||||
srcdoc = VoidString();
|
||||
}
|
||||
|
||||
if (!triggeringPrincipal) {
|
||||
|
@ -12884,7 +12884,7 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
|
|||
flags,
|
||||
EmptyString(), // No window target
|
||||
contentType.get(), // Type hint
|
||||
NullString(), // No forced file download
|
||||
VoidString(), // No forced file download
|
||||
postData, // Post data stream
|
||||
nullptr, // No headers stream
|
||||
aLoadType, // Load type
|
||||
|
@ -14454,7 +14454,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
|||
LOAD_LINK, // Load type
|
||||
nullptr, // No SHEntry
|
||||
true, // first party site
|
||||
NullString(), // No srcdoc
|
||||
VoidString(), // No srcdoc
|
||||
this, // We are the source
|
||||
nullptr, // baseURI not needed
|
||||
true, // Check for prerendered doc
|
||||
|
|
|
@ -476,7 +476,7 @@ nsSHEntry::Create(nsIURI* aURI, const nsAString& aTitle,
|
|||
mShared->mExpired = false;
|
||||
|
||||
mIsSrcdocEntry = false;
|
||||
mSrcdocData = NullString();
|
||||
mSrcdocData = VoidString();
|
||||
|
||||
mLoadedInThisProcess = true;
|
||||
|
||||
|
|
|
@ -593,6 +593,9 @@ CustomElementRegistry::Define(const nsAString& aName,
|
|||
}
|
||||
|
||||
JSContext *cx = jsapi.cx();
|
||||
// Note: No calls that might run JS or trigger CC before this point, or
|
||||
// there's a (vanishingly small) chance of our constructor being nulled
|
||||
// before we access it.
|
||||
JS::Rooted<JSObject*> constructor(cx, aFunctionConstructor.CallableOrNull());
|
||||
|
||||
/**
|
||||
|
@ -878,7 +881,7 @@ CustomElementRegistry::Get(JSContext* aCx, const nsAString& aName,
|
|||
return;
|
||||
}
|
||||
|
||||
aRetVal.setObjectOrNull(data->mConstructor->CallableOrNull());
|
||||
aRetVal.setObject(*data->mConstructor->Callback(aCx));
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
|
@ -970,9 +973,9 @@ CustomElementRegistry::Upgrade(Element* aElement,
|
|||
|
||||
LifecycleCallbackArgs args = {
|
||||
nsDependentAtomString(attrName),
|
||||
NullString(),
|
||||
(attrValue.IsEmpty() ? NullString() : attrValue),
|
||||
(namespaceURI.IsEmpty() ? NullString() : namespaceURI)
|
||||
VoidString(),
|
||||
(attrValue.IsEmpty() ? VoidString() : attrValue),
|
||||
(namespaceURI.IsEmpty() ? VoidString() : namespaceURI)
|
||||
};
|
||||
EnqueueLifecycleCallback(nsIDocument::eAttributeChanged, aElement,
|
||||
&args, aDefinition);
|
||||
|
|
|
@ -70,7 +70,7 @@ DOMImplementation::CreateDocumentType(const nsAString& aQualifiedName,
|
|||
// Indicate that there is no internal subset (not just an empty one)
|
||||
RefPtr<DocumentType> docType =
|
||||
NS_NewDOMDocumentType(mOwner->NodeInfoManager(), name, aPublicId,
|
||||
aSystemId, NullString(), aRv);
|
||||
aSystemId, VoidString(), aRv);
|
||||
return docType.forget();
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ DOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
|
|||
nsGkAtoms::html, // aName
|
||||
EmptyString(), // aPublicId
|
||||
EmptyString(), // aSystemId
|
||||
NullString()); // aInternalSubset
|
||||
VoidString()); // aInternalSubset
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
||||
|
@ -249,8 +249,7 @@ DOMImplementation::CreateHTMLDocument(const Optional<nsAString>& aTitle,
|
|||
{
|
||||
nsCOMPtr<nsIDocument> document;
|
||||
nsCOMPtr<nsIDOMDocument> domDocument;
|
||||
aRv = CreateHTMLDocument(aTitle.WasPassed() ? aTitle.Value()
|
||||
: NullString(),
|
||||
aRv = CreateHTMLDocument(aTitle.WasPassed() ? aTitle.Value() : VoidString(),
|
||||
getter_AddRefs(document),
|
||||
getter_AddRefs(domDocument));
|
||||
return document.forget();
|
||||
|
|
|
@ -308,7 +308,11 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time
|
|||
}
|
||||
root = rootFrame->GetContent()->AsElement();
|
||||
nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame);
|
||||
rootRect = scrollFrame->GetScrollPortRect();
|
||||
// If we end up with a null root frame for some reason, we'll proceed
|
||||
// with an empty root intersection rect.
|
||||
if (scrollFrame) {
|
||||
rootRect = scrollFrame->GetScrollPortRect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2642,9 +2642,9 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
|
|||
LifecycleCallbackArgs args = {
|
||||
nsDependentAtomString(aName),
|
||||
aModType == nsIDOMMutationEvent::ADDITION ?
|
||||
NullString() : nsDependentAtomString(oldValueAtom),
|
||||
VoidString() : nsDependentAtomString(oldValueAtom),
|
||||
nsDependentAtomString(newValueAtom),
|
||||
(ns.IsEmpty() ? NullString() : ns)
|
||||
(ns.IsEmpty() ? VoidString() : ns)
|
||||
};
|
||||
|
||||
nsContentUtils::EnqueueLifecycleCallback(
|
||||
|
@ -2938,8 +2938,8 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|||
LifecycleCallbackArgs args = {
|
||||
nsDependentAtomString(aName),
|
||||
nsDependentAtomString(oldValueAtom),
|
||||
NullString(),
|
||||
(ns.IsEmpty() ? NullString() : ns)
|
||||
VoidString(),
|
||||
(ns.IsEmpty() ? VoidString() : ns)
|
||||
};
|
||||
|
||||
nsContentUtils::EnqueueLifecycleCallback(
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
typedef nsTArray<RefPtr<mozilla::dom::Animation>> AnimationArray;
|
||||
|
||||
nsDOMMutationRecord(nsIAtom* aType, nsISupports* aOwner)
|
||||
: mType(aType), mAttrNamespace(NullString()), mPrevValue(NullString()), mOwner(aOwner)
|
||||
: mType(aType), mAttrNamespace(VoidString()), mPrevValue(VoidString()), mOwner(aOwner)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -3584,7 +3584,7 @@ nsIDocument::GetSrcdocData(nsAString &aSrcdocData)
|
|||
return inStrmChan->GetSrcdocData(aSrcdocData);
|
||||
}
|
||||
}
|
||||
aSrcdocData = NullString();
|
||||
aSrcdocData = VoidString();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -6549,6 +6549,9 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
|||
options.mExtends.Construct(lcName);
|
||||
}
|
||||
|
||||
// Note: No calls that might run JS or trigger CC after this, or there's a
|
||||
// (vanishingly small) risk of our constructor being nulled before Define()
|
||||
// can access it.
|
||||
RefPtr<Function> functionConstructor =
|
||||
new Function(aCx, wrappedConstructor, sgo);
|
||||
|
||||
|
@ -9793,7 +9796,7 @@ nsDocument::PreloadPictureImageSource(const nsAString& aSrcsetAttr,
|
|||
// <picture> selects the first matching source, so if this returns a URI we
|
||||
// needn't consider new sources until a new <picture> is encountered.
|
||||
bool found =
|
||||
HTMLImageElement::SelectSourceForTagWithAttrs(this, true, NullString(),
|
||||
HTMLImageElement::SelectSourceForTagWithAttrs(this, true, VoidString(),
|
||||
aSrcsetAttr, aSizesAttr,
|
||||
aTypeAttr, aMediaAttr,
|
||||
mPreloadPictureFoundSource);
|
||||
|
@ -9822,7 +9825,7 @@ nsDocument::ResolvePreloadImage(nsIURI *aBaseURI,
|
|||
// Otherwise try to use this <img> as a source
|
||||
HTMLImageElement::SelectSourceForTagWithAttrs(this, false, aSrcAttr,
|
||||
aSrcsetAttr, aSizesAttr,
|
||||
NullString(), NullString(),
|
||||
VoidString(), VoidString(),
|
||||
sourceURL);
|
||||
isImgSet = !aSrcsetAttr.IsEmpty();
|
||||
}
|
||||
|
@ -10920,11 +10923,12 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(UnblockParsingPromiseHandler)
|
||||
|
||||
explicit UnblockParsingPromiseHandler(nsIDocument* aDocument, Promise* aPromise)
|
||||
explicit UnblockParsingPromiseHandler(nsIDocument* aDocument, Promise* aPromise,
|
||||
const BlockParsingOptions& aOptions)
|
||||
: mPromise(aPromise)
|
||||
{
|
||||
nsCOMPtr<nsIParser> parser = aDocument->CreatorParserOrNull();
|
||||
if (parser) {
|
||||
if (parser && (aOptions.mBlockScriptCreated || !parser->IsScriptCreated())) {
|
||||
parser->BlockParser();
|
||||
mParser = do_GetWeakReference(parser);
|
||||
mDocument = aDocument;
|
||||
|
@ -10987,14 +10991,15 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(UnblockParsingPromiseHandler)
|
|||
NS_IMPL_CYCLE_COLLECTING_RELEASE(UnblockParsingPromiseHandler)
|
||||
|
||||
already_AddRefed<Promise>
|
||||
nsIDocument::BlockParsing(Promise& aPromise, ErrorResult& aRv)
|
||||
nsIDocument::BlockParsing(Promise& aPromise, const BlockParsingOptions& aOptions, ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<Promise> resultPromise = Promise::Create(aPromise.GetParentObject(), aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<PromiseNativeHandler> promiseHandler = new UnblockParsingPromiseHandler(this, resultPromise);
|
||||
RefPtr<PromiseNativeHandler> promiseHandler = new UnblockParsingPromiseHandler(this, resultPromise,
|
||||
aOptions);
|
||||
aPromise.AppendNativeHandler(promiseHandler);
|
||||
|
||||
return resultPromise.forget();
|
||||
|
@ -12799,7 +12804,7 @@ nsIDocument::Constructor(const GlobalObject& aGlobal,
|
|||
nsCOMPtr<nsIDOMDocument> document;
|
||||
nsresult res =
|
||||
NS_NewDOMDocument(getter_AddRefs(document),
|
||||
NullString(),
|
||||
VoidString(),
|
||||
EmptyString(),
|
||||
nullptr,
|
||||
uri,
|
||||
|
|
|
@ -2952,6 +2952,7 @@ public:
|
|||
void ObsoleteSheet(const nsAString& aSheetURI, mozilla::ErrorResult& rv);
|
||||
|
||||
already_AddRefed<mozilla::dom::Promise> BlockParsing(mozilla::dom::Promise& aPromise,
|
||||
const mozilla::dom::BlockParsingOptions& aOptions,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<nsIURI> GetMozDocumentURIIfNotForErrorPages();
|
||||
|
|
|
@ -1918,9 +1918,9 @@ GetOrCreateDOMReflectorNoWrap(JSContext* cx, T& value,
|
|||
|
||||
template <class T>
|
||||
inline JSObject*
|
||||
GetCallbackFromCallbackObject(T* aObj)
|
||||
GetCallbackFromCallbackObject(JSContext* aCx, T* aObj)
|
||||
{
|
||||
return aObj->CallbackOrNull();
|
||||
return aObj->Callback(aCx);
|
||||
}
|
||||
|
||||
// Helper for getting the callback JSObject* of a smart ptr around a
|
||||
|
@ -1929,26 +1929,26 @@ GetCallbackFromCallbackObject(T* aObj)
|
|||
template <class T, bool isSmartPtr=IsSmartPtr<T>::value>
|
||||
struct GetCallbackFromCallbackObjectHelper
|
||||
{
|
||||
static inline JSObject* Get(const T& aObj)
|
||||
static inline JSObject* Get(JSContext* aCx, const T& aObj)
|
||||
{
|
||||
return GetCallbackFromCallbackObject(aObj.get());
|
||||
return GetCallbackFromCallbackObject(aCx, aObj.get());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct GetCallbackFromCallbackObjectHelper<T, false>
|
||||
{
|
||||
static inline JSObject* Get(T& aObj)
|
||||
static inline JSObject* Get(JSContext* aCx, T& aObj)
|
||||
{
|
||||
return GetCallbackFromCallbackObject(&aObj);
|
||||
return GetCallbackFromCallbackObject(aCx, &aObj);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
inline JSObject*
|
||||
GetCallbackFromCallbackObject(T& aObj)
|
||||
GetCallbackFromCallbackObject(JSContext* aCx, T& aObj)
|
||||
{
|
||||
return GetCallbackFromCallbackObjectHelper<T>::Get(aObj);
|
||||
return GetCallbackFromCallbackObjectHelper<T>::Get(aCx, aObj);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
|
|
@ -115,6 +115,18 @@ CallbackObject::FinishSlowJSInitIfMoreThanOneOwner(JSContext* aCx)
|
|||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
CallbackObject::Callback(JSContext* aCx)
|
||||
{
|
||||
JSObject* callback = CallbackOrNull();
|
||||
if (!callback) {
|
||||
callback = JS_NewDeadWrapper(aCx);
|
||||
}
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(callback);
|
||||
return callback;
|
||||
}
|
||||
|
||||
CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
|
||||
ErrorResult& aRv,
|
||||
const char* aExecutionReason,
|
||||
|
|
|
@ -93,6 +93,10 @@ public:
|
|||
return CallbackPreserveColor();
|
||||
}
|
||||
|
||||
// Like CallbackOrNull(), but will return a new dead proxy object in the
|
||||
// caller's compartment if the callback is null.
|
||||
JSObject* Callback(JSContext* aCx);
|
||||
|
||||
JSObject* GetCreationStack() const
|
||||
{
|
||||
return mCreationStack;
|
||||
|
@ -594,12 +598,17 @@ public:
|
|||
this->get().operator=(arg);
|
||||
}
|
||||
|
||||
// Codegen relies on being able to do CallbackOrNull() on us.
|
||||
// Codegen relies on being able to do CallbackOrNull() and Callback() on us.
|
||||
JS::Handle<JSObject*> CallbackOrNull() const
|
||||
{
|
||||
return this->get()->CallbackOrNull();
|
||||
}
|
||||
|
||||
JSObject* Callback(JSContext* aCx) const
|
||||
{
|
||||
return this->get()->Callback(aCx);
|
||||
}
|
||||
|
||||
~RootedCallback()
|
||||
{
|
||||
// Ensure that our callback starts holding on to its own JS objects as
|
||||
|
|
|
@ -6912,7 +6912,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
|||
# Callbacks can store null if we nuked the compartments their
|
||||
# objects lived in.
|
||||
wrapCode = setObjectOrNull(
|
||||
"GetCallbackFromCallbackObject(%(result)s)",
|
||||
"GetCallbackFromCallbackObject(cx, %(result)s)",
|
||||
wrapAsType=type)
|
||||
if type.nullable():
|
||||
wrapCode = (
|
||||
|
|
|
@ -132,7 +132,7 @@ ToJSValue(JSContext* aCx,
|
|||
// Make sure we're called in a compartment
|
||||
MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
|
||||
|
||||
aValue.setObjectOrNull(aArgument.CallbackOrNull());
|
||||
aValue.setObjectOrNull(aArgument.Callback(aCx));
|
||||
|
||||
return MaybeWrapValue(aCx, aValue);
|
||||
}
|
||||
|
|
|
@ -1844,7 +1844,7 @@ Console::ProcessArguments(JSContext* aCx,
|
|||
int32_t diff = aSequence.Length() - aStyles.Length();
|
||||
if (diff > 0) {
|
||||
for (int32_t i = 0; i < diff; i++) {
|
||||
if (NS_WARN_IF(!aStyles.AppendElement(NullString(), fallible))) {
|
||||
if (NS_WARN_IF(!aStyles.AppendElement(VoidString(), fallible))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -324,7 +324,7 @@ DOMEventTargetHelper::GetEventHandler(nsIAtom* aType,
|
|||
{
|
||||
EventHandlerNonNull* handler = GetEventHandler(aType, EmptyString());
|
||||
if (handler) {
|
||||
*aValue = JS::ObjectOrNullValue(handler->CallableOrNull());
|
||||
*aValue = JS::ObjectValue(*handler->Callback(aCx));
|
||||
} else {
|
||||
*aValue = JS::NullValue();
|
||||
}
|
||||
|
|
|
@ -105,12 +105,20 @@ function runTest() {
|
|||
// browser to 0 using the 'blank' attribute.
|
||||
// Until the blank attribute is removed, we can't send scroll events.
|
||||
SimpleTest.waitForFocus(function() {
|
||||
SpecialPowers.loadChromeScript(_ => {
|
||||
let chromeScript = SpecialPowers.loadChromeScript(_ => {
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Services.wm.getMostRecentWindow("navigator:browser")
|
||||
.gBrowser.selectedBrowser.removeAttribute("blank");
|
||||
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
win.requestAnimationFrame(() => {
|
||||
win.gBrowser.selectedBrowser.removeAttribute("blank");
|
||||
win.requestAnimationFrame(() => {
|
||||
sendAsyncMessage("blank-attribute-removed");
|
||||
});
|
||||
});
|
||||
});
|
||||
chromeScript.promiseOneMessage("blank-attribute-removed").then(() => {
|
||||
chromeScript.destroy();
|
||||
waitForPaint(win, winUtils, callback);
|
||||
});
|
||||
waitForPaint(win, winUtils, callback);
|
||||
}, win);
|
||||
};
|
||||
|
||||
|
|
|
@ -52,12 +52,20 @@
|
|||
// browser to 0 using the 'blank' attribute.
|
||||
// Until the blank attribute is removed, we can't send scroll events.
|
||||
SimpleTest.waitForFocus(function() {
|
||||
SpecialPowers.loadChromeScript(_ => {
|
||||
let chromeScript = SpecialPowers.loadChromeScript(_ => {
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Services.wm.getMostRecentWindow("navigator:browser")
|
||||
.gBrowser.selectedBrowser.removeAttribute("blank");
|
||||
let win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
win.requestAnimationFrame(() => {
|
||||
win.gBrowser.selectedBrowser.removeAttribute("blank");
|
||||
win.requestAnimationFrame(() => {
|
||||
sendAsyncMessage("blank-attribute-removed");
|
||||
});
|
||||
});
|
||||
});
|
||||
chromeScript.promiseOneMessage("blank-attribute-removed").then(() => {
|
||||
chromeScript.destroy();
|
||||
runTests();
|
||||
});
|
||||
runTests();
|
||||
}, window);
|
||||
|
||||
SimpleTest.requestFlakyTimeout("untriaged");
|
||||
|
|
|
@ -43,7 +43,7 @@ PendingIPCBlobChild::SetPendingInfoAndDeleteActor(const nsString& aContentType,
|
|||
RefPtr<BlobImpl> blobImpl;
|
||||
blobImpl.swap(mBlobImpl);
|
||||
|
||||
blobImpl->SetLazyData(NullString(), aContentType, aLength, INT64_MAX);
|
||||
blobImpl->SetLazyData(VoidString(), aContentType, aLength, INT64_MAX);
|
||||
|
||||
PendingIPCBlobData data(nsString(aContentType), aLength, void_t());
|
||||
Unused << Send__delete__(this, data);
|
||||
|
|
|
@ -44,7 +44,7 @@ IPCResult
|
|||
PendingIPCBlobParent::Recv__delete__(const PendingIPCBlobData& aData)
|
||||
{
|
||||
if (aData.file().type() == PendingIPCFileUnion::Tvoid_t) {
|
||||
mBlobImpl->SetLazyData(NullString(), aData.type(), aData.size(), INT64_MAX);
|
||||
mBlobImpl->SetLazyData(VoidString(), aData.type(), aData.size(), INT64_MAX);
|
||||
} else {
|
||||
const PendingIPCFileData& fileData =
|
||||
aData.file().get_PendingIPCFileData();
|
||||
|
|
|
@ -802,7 +802,7 @@ HTMLFormElement::SubmitSubmission(HTMLFormSubmission* aFormSubmission)
|
|||
|
||||
rv = linkHandler->OnLinkClickSync(this, actionURI,
|
||||
target.get(),
|
||||
NullString(),
|
||||
VoidString(),
|
||||
postDataStream, nullptr, false,
|
||||
getter_AddRefs(docShell),
|
||||
getter_AddRefs(mSubmittingRequest));
|
||||
|
|
|
@ -353,7 +353,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|||
if (InResponsiveMode()) {
|
||||
if (mResponsiveSelector &&
|
||||
mResponsiveSelector->Content() == this) {
|
||||
mResponsiveSelector->SetDefaultSource(NullString());
|
||||
mResponsiveSelector->SetDefaultSource(VoidString());
|
||||
}
|
||||
QueueImageLoadTask(true);
|
||||
} else {
|
||||
|
|
|
@ -78,6 +78,7 @@ skip-if = os == "android"
|
|||
skip-if = os == "android"
|
||||
[test_input_types_pref.html]
|
||||
[test_input_typing_sanitization.html]
|
||||
skip-if = os == "android" && debug # bug 1397615
|
||||
[test_input_untrusted_key_events.html]
|
||||
[test_input_url.html]
|
||||
[test_interactive_content_in_label.html]
|
||||
|
|
|
@ -17378,7 +17378,7 @@ FileManager::InitDirectory(nsIFile* aDirectory,
|
|||
nsCOMPtr<mozIStorageConnection> connection;
|
||||
rv = CreateStorageConnection(aDatabaseFile,
|
||||
aDirectory,
|
||||
NullString(),
|
||||
VoidString(),
|
||||
aPersistenceType,
|
||||
aGroup,
|
||||
aOrigin,
|
||||
|
|
|
@ -203,7 +203,7 @@ public:
|
|||
ReadAsArrayBuffer(uint64_t aSize, ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
return Read(aSize, false, NullString(), aRv);
|
||||
return Read(aSize, false, VoidString(), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<IDBFileRequest>
|
||||
|
|
|
@ -925,7 +925,7 @@ public:
|
|||
|
||||
if (aData.tag == SCTAG_DOM_BLOB) {
|
||||
aFile.mBlob->Impl()->SetLazyData(
|
||||
NullString(), aData.type, aData.size, INT64_MAX);
|
||||
VoidString(), aData.type, aData.size, INT64_MAX);
|
||||
MOZ_ASSERT(!aFile.mBlob->IsFile());
|
||||
|
||||
// ActorsParent sends here a kind of half blob and half file wrapped into
|
||||
|
|
|
@ -768,7 +768,7 @@ private:
|
|||
AppInfo mAppInfo;
|
||||
|
||||
bool mIsForBrowser;
|
||||
nsString mRemoteType = NullString();
|
||||
nsString mRemoteType = VoidString();
|
||||
bool mIsAlive;
|
||||
nsString mProcessName;
|
||||
|
||||
|
|
|
@ -4696,7 +4696,7 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
|
|||
CommonCreateWindow(aThisTab, /* aSetOpener = */ true, aChromeFlags,
|
||||
aCalledFromJS, aPositionSpecified, aSizeSpecified,
|
||||
nullptr, aFeatures, aBaseURI, aFullZoom,
|
||||
nextTabParentId, NullString(), rv,
|
||||
nextTabParentId, VoidString(), rv,
|
||||
newRemoteTab, &cwi.windowOpened(),
|
||||
aTriggeringPrincipal);
|
||||
if (!ipcResult) {
|
||||
|
|
|
@ -1599,8 +1599,8 @@ TabChild::MaybeDispatchCoalescedMouseMoveEvents()
|
|||
// Dispatch the coalesced mousemove event. Using RecvRealMouseButtonEvent to
|
||||
// bypass the coalesce handling in RecvRealMouseMoveEvent.
|
||||
RecvRealMouseButtonEvent(*event,
|
||||
mCoalescedWheelData.GetScrollableLayerGuid(),
|
||||
mCoalescedWheelData.GetInputBlockId());
|
||||
mCoalescedMouseData.GetScrollableLayerGuid(),
|
||||
mCoalescedMouseData.GetInputBlockId());
|
||||
if (mCoalescedMouseEventFlusher) {
|
||||
mCoalescedMouseData.Reset();
|
||||
mCoalescedMouseEventFlusher->RemoveObserver();
|
||||
|
|
|
@ -426,7 +426,7 @@ public:
|
|||
if (globalWindow) {
|
||||
RefPtr<GetUserMediaRequest> req =
|
||||
new GetUserMediaRequest(globalWindow->AsInner(),
|
||||
NullString(), NullString());
|
||||
VoidString(), VoidString());
|
||||
obs->NotifyObservers(req, "recording-device-stopped", nullptr);
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -491,7 +491,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL,
|
|||
triggeringPrincipal = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
|
||||
}
|
||||
|
||||
rv = lh->OnLinkClick(content, uri, unitarget.get(), NullString(),
|
||||
rv = lh->OnLinkClick(content, uri, unitarget.get(), VoidString(),
|
||||
aPostStream, headersDataStream, true, triggeringPrincipal);
|
||||
|
||||
return rv;
|
||||
|
|
|
@ -307,7 +307,7 @@ inline nsCString
|
|||
NullableString(const char* aString)
|
||||
{
|
||||
if (!aString) {
|
||||
return NullCString();
|
||||
return VoidCString();
|
||||
}
|
||||
return nsCString(aString);
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ PresentationRequest::WrapObject(JSContext* aCx,
|
|||
already_AddRefed<Promise>
|
||||
PresentationRequest::Start(ErrorResult& aRv)
|
||||
{
|
||||
return StartWithDevice(NullString(), aRv);
|
||||
return StartWithDevice(VoidString(), aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
|
|
|
@ -5843,7 +5843,7 @@ QuotaManager::ShutdownTimerCallback(nsITimer* aTimer, void* aClosure)
|
|||
|
||||
// Abort all operations.
|
||||
for (RefPtr<Client>& client : quotaManager->mClients) {
|
||||
client->AbortOperations(NullCString());
|
||||
client->AbortOperations(VoidCString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ LocalStorage::RemoveItem(const nsAString& aKey, nsIPrincipal& aSubjectPrincipal,
|
|||
}
|
||||
|
||||
if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
|
||||
BroadcastChangeNotification(aKey, old, NullString());
|
||||
BroadcastChangeNotification(aKey, old, VoidString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ LocalStorage::Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv)
|
|||
}
|
||||
|
||||
if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
|
||||
BroadcastChangeNotification(NullString(), NullString(), NullString());
|
||||
BroadcastChangeNotification(VoidString(), VoidString(), VoidString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ SessionStorage::RemoveItem(const nsAString& aKey,
|
|||
return;
|
||||
}
|
||||
|
||||
BroadcastChangeNotification(aKey, oldValue, NullString());
|
||||
BroadcastChangeNotification(aKey, oldValue, VoidString());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -168,7 +168,7 @@ SessionStorage::Clear(nsIPrincipal& aSubjectPrincipal,
|
|||
}
|
||||
|
||||
mCache->Clear(DATASET);
|
||||
BroadcastChangeNotification(NullString(), NullString(), NullString());
|
||||
BroadcastChangeNotification(VoidString(), VoidString(), VoidString());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -385,13 +385,22 @@ partial interface Document {
|
|||
|
||||
// Blocks the initial document parser until the given promise is settled.
|
||||
[ChromeOnly, Throws]
|
||||
Promise<any> blockParsing(Promise<any> promise);
|
||||
Promise<any> blockParsing(Promise<any> promise,
|
||||
optional BlockParsingOptions options);
|
||||
|
||||
// like documentURI, except that for error pages, it returns the URI we were
|
||||
// trying to load when we hit an error, rather than the error page's own URI.
|
||||
[ChromeOnly] readonly attribute URI? mozDocumentURIIfNotForErrorPages;
|
||||
};
|
||||
|
||||
dictionary BlockParsingOptions {
|
||||
/**
|
||||
* If true, blocks script-created parsers (created via document.open()) in
|
||||
* addition to network-created parsers.
|
||||
*/
|
||||
boolean blockScriptCreated = true;
|
||||
};
|
||||
|
||||
// Extension to give chrome JS the ability to determine when a document was
|
||||
// created to satisfy an iframe with srcdoc attribute.
|
||||
partial interface Document {
|
||||
|
|
|
@ -2421,7 +2421,7 @@ RuntimeService::CreateSharedWorkerFromLoadInfo(JSContext* aCx,
|
|||
if (!workerPrivate) {
|
||||
workerPrivate =
|
||||
WorkerPrivate::Constructor(aCx, aScriptURL, false,
|
||||
WorkerTypeShared, aName, NullCString(),
|
||||
WorkerTypeShared, aName, VoidCString(),
|
||||
aLoadInfo, rv);
|
||||
NS_ENSURE_TRUE(workerPrivate, rv.StealNSResult());
|
||||
|
||||
|
|
|
@ -1878,7 +1878,7 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
|
|||
mWorkerPrivate = WorkerPrivate::Constructor(jsapi.cx(),
|
||||
scriptSpec,
|
||||
false, WorkerTypeService,
|
||||
NullString(),
|
||||
VoidString(),
|
||||
mInfo->Scope(),
|
||||
&info, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
|
|
|
@ -1061,6 +1061,34 @@ ServiceWorkerRegistrar::ProfileStopped()
|
|||
|
||||
PBackgroundChild* child = BackgroundChild::GetForCurrentThread();
|
||||
if (!child) {
|
||||
// Mutations to the ServiceWorkerRegistrar happen on the PBackground thread,
|
||||
// issued by the ServiceWorkerManagerService, so the appropriate place to
|
||||
// trigger shutdown is on that thread.
|
||||
//
|
||||
// However, it's quite possible that the PBackground thread was not brought
|
||||
// into existence for xpcshell tests. We don't cause it to be created
|
||||
// ourselves for any reason, for example.
|
||||
//
|
||||
// In this scenario, we know that:
|
||||
// - We will receive exactly one call to ourself from BlockShutdown() and
|
||||
// BlockShutdown() will be called (at most) once.
|
||||
// - The only way our Shutdown() method gets called is via
|
||||
// BackgroundParentImpl::RecvShutdownServiceWorkerRegistrar() being
|
||||
// invoked, which only happens if we get to that send below here that we
|
||||
// can't get to.
|
||||
// - All Shutdown() does is set mShuttingDown=true (essential for
|
||||
// invariants) and invoke MaybeScheduleShutdownCompleted().
|
||||
// - Since there is no PBackground thread, mRunnableCounter must be 0
|
||||
// because only ScheduleSaveData() increments it and it only runs on the
|
||||
// background thread, so it cannot have run. And so we would expect
|
||||
// MaybeScheduleShutdownCompleted() to schedule an invocation of
|
||||
// ShutdownCompleted on the main thread.
|
||||
//
|
||||
// So it's appropriate for us to set mShuttingDown=true (as Shutdown would
|
||||
// do) and directly invoke ShutdownCompleted() (as Shutdown would indirectly
|
||||
// do via MaybeScheduleShutdownCompleted).
|
||||
mShuttingDown = true;
|
||||
ShutdownCompleted();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -4646,7 +4646,7 @@ WorkerPrivate::Constructor(const GlobalObject& aGlobal,
|
|||
{
|
||||
JSContext* cx = aGlobal.Context();
|
||||
return Constructor(cx, aScriptURL, aIsChromeWorker, aWorkerType,
|
||||
aWorkerName, NullCString(), aLoadInfo, aRv);
|
||||
aWorkerName, VoidCString(), aLoadInfo, aRv);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -1530,7 +1530,7 @@ void
|
|||
XMLHttpRequestMainThread::Open(const nsACString& aMethod, const nsAString& aUrl,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Open(aMethod, aUrl, true, NullString(), NullString(), aRv);
|
||||
Open(aMethod, aUrl, true, VoidString(), VoidString(), aRv);
|
||||
}
|
||||
|
||||
// This case is hit when the async parameter is specified, even if the
|
||||
|
|
|
@ -1429,8 +1429,8 @@ OpenRunnable::MainThreadRunInternal()
|
|||
|
||||
ErrorResult rv2;
|
||||
mProxy->mXHR->Open(mMethod, mURL, true,
|
||||
mUser.WasPassed() ? mUser.Value() : NullString(),
|
||||
mPassword.WasPassed() ? mPassword.Value() : NullString(),
|
||||
mUser.WasPassed() ? mUser.Value() : VoidString(),
|
||||
mPassword.WasPassed() ? mPassword.Value() : VoidString(),
|
||||
rv2);
|
||||
|
||||
MOZ_ASSERT(mProxy->mInOpen);
|
||||
|
@ -2046,7 +2046,7 @@ XMLHttpRequestWorker::Send(JSContext* aCx,
|
|||
RefPtr<SendRunnable> sendRunnable;
|
||||
|
||||
if (aData.IsNull()) {
|
||||
sendRunnable = new SendRunnable(mWorkerPrivate, mProxy, NullString());
|
||||
sendRunnable = new SendRunnable(mWorkerPrivate, mProxy, VoidString());
|
||||
// Nothing to clone.
|
||||
}
|
||||
|
||||
|
|
|
@ -904,7 +904,7 @@ txMozillaXMLOutput::createResultDocument(const nsAString& aName, int32_t aNsID,
|
|||
doctypeName,
|
||||
mOutputFormat.mPublicId,
|
||||
mOutputFormat.mSystemId,
|
||||
NullString());
|
||||
VoidString());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIContent> docType = do_QueryInterface(documentType);
|
||||
|
|
|
@ -487,7 +487,7 @@ nsXULTemplateBuilder::HasGeneratedContent(nsIRDFResource* aResource,
|
|||
bool* aGenerated)
|
||||
{
|
||||
ErrorResult rv;
|
||||
const nsAString& tag = aTag ? nsDependentAtomString(aTag) : NullString();
|
||||
const nsAString& tag = aTag ? nsDependentAtomString(aTag) : VoidString();
|
||||
*aGenerated = HasGeneratedContent(aResource, tag, rv);
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
|
|
@ -572,7 +572,7 @@ HTMLEditUtils::SupportsAlignAttr(nsINode& aNode)
|
|||
struct ElementInfo final
|
||||
{
|
||||
#ifdef DEBUG
|
||||
eHTMLTags mTag;
|
||||
nsHTMLTag mTag;
|
||||
#endif
|
||||
uint32_t mGroup;
|
||||
uint32_t mCanContainGroups;
|
||||
|
@ -787,7 +787,7 @@ HTMLEditUtils::CanContain(int32_t aParent, int32_t aChild)
|
|||
|
||||
// Special-case button.
|
||||
if (aParent == eHTMLTag_button) {
|
||||
static const eHTMLTags kButtonExcludeKids[] = {
|
||||
static const nsHTMLTag kButtonExcludeKids[] = {
|
||||
eHTMLTag_a,
|
||||
eHTMLTag_fieldset,
|
||||
eHTMLTag_form,
|
||||
|
|
|
@ -21,7 +21,7 @@ TEST_F(InitTest, ZeroCount)
|
|||
EXPECT_EQ(pp::Token::LAST, token.type);
|
||||
}
|
||||
|
||||
TEST_F(InitTest, NullString)
|
||||
TEST_F(InitTest, VoidString)
|
||||
{
|
||||
EXPECT_FALSE(mPreprocessor.init(1, NULL, NULL));
|
||||
}
|
||||
|
|
|
@ -135,6 +135,16 @@ ImageContainer::GetImageClient()
|
|||
return imageClient.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ImageContainer::DropImageClient()
|
||||
{
|
||||
RecursiveMutexAutoLock mon(mRecursiveMutex);
|
||||
if (mImageClient) {
|
||||
mImageClient->ClearCachedResources();
|
||||
mImageClient = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImageContainer::EnsureImageClient()
|
||||
{
|
||||
|
|
|
@ -618,6 +618,8 @@ public:
|
|||
*/
|
||||
static ProducerID AllocateProducerID();
|
||||
|
||||
void DropImageClient();
|
||||
|
||||
private:
|
||||
typedef mozilla::RecursiveMutex RecursiveMutex;
|
||||
|
||||
|
|
|
@ -726,7 +726,24 @@ MessageLoop * ImageBridgeChild::GetMessageLoop() const
|
|||
ImageBridgeChild::IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier)
|
||||
{
|
||||
if (RefPtr<ImageBridgeChild> child = GetSingleton()) {
|
||||
child->IdentifyTextureHost(aIdentifier);
|
||||
child->UpdateTextureFactoryIdentifier(aIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ImageBridgeChild::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aIdentifier)
|
||||
{
|
||||
bool disablingWebRender = GetCompositorBackendType() == LayersBackend::LAYERS_WR &&
|
||||
aIdentifier.mParentBackend != LayersBackend::LAYERS_WR;
|
||||
IdentifyTextureHost(aIdentifier);
|
||||
if (disablingWebRender) {
|
||||
// ImageHost is incompatible between WebRender enabled and WebRender disabled.
|
||||
// Then drop all ImageContainers' ImageClients during disabling WebRender.
|
||||
MutexAutoLock lock(mContainerMapLock);
|
||||
for (auto iter = mImageContainers.Iter(); !iter.Done(); iter.Next()) {
|
||||
ImageContainer* container = iter.Data();
|
||||
container->DropImageClient();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -250,6 +250,8 @@ private:
|
|||
void ProxyAllocShmemNow(SynchronousTask* aTask, AllocShmemParams* aParams);
|
||||
void ProxyDeallocShmemNow(SynchronousTask* aTask, Shmem* aShmem, bool* aResult);
|
||||
|
||||
void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aIdentifier);
|
||||
|
||||
public:
|
||||
// CompositableForwarder
|
||||
|
||||
|
|
|
@ -279,18 +279,7 @@ public:
|
|||
|
||||
RefPtr<CachedSurface> surface;
|
||||
mSurfaces.Remove(aSurface->GetSurfaceKey(), getter_AddRefs(surface));
|
||||
|
||||
if (IsEmpty() && mFactor2Mode) {
|
||||
// The last surface for this cache was removed. This can happen if the
|
||||
// surface was stored in a volatile buffer and got purged, or the surface
|
||||
// expired from the cache. If the cache itself lingers for some reason
|
||||
// (e.g. in the process of performing a lookup, the cache itself is
|
||||
// locked), then we need to reset the factor of 2 state because it
|
||||
// requires at least one surface present to get the native size
|
||||
// information from the image.
|
||||
mFactor2Mode = mFactor2Pruned = false;
|
||||
}
|
||||
|
||||
AfterMaybeRemove();
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
|
@ -537,6 +526,11 @@ public:
|
|||
if (!hasNotFactorSize) {
|
||||
mFactor2Pruned = true;
|
||||
}
|
||||
|
||||
// We should never leave factor of 2 mode due to pruning in of itself, but
|
||||
// if we discarded surfaces due to the volatile buffers getting released,
|
||||
// it is possible.
|
||||
AfterMaybeRemove();
|
||||
}
|
||||
|
||||
IntSize SuggestedSize(const IntSize& aSize) const
|
||||
|
@ -548,7 +542,10 @@ public:
|
|||
|
||||
// We cannot enter factor of 2 mode unless we have a minimum number of
|
||||
// surfaces, and we should have left it if the cache was emptied.
|
||||
MOZ_ASSERT(!IsEmpty());
|
||||
if (MOZ_UNLIKELY(IsEmpty())) {
|
||||
MOZ_ASSERT_UNREACHABLE("Should not be empty and in factor of 2 mode!");
|
||||
return aSize;
|
||||
}
|
||||
|
||||
// This bit of awkwardness gets the largest native size of the image.
|
||||
auto iter = ConstIter();
|
||||
|
@ -644,6 +641,8 @@ public:
|
|||
}
|
||||
report.Add(surface, factor2Size);
|
||||
}
|
||||
|
||||
AfterMaybeRemove();
|
||||
}
|
||||
|
||||
SurfaceTable::Iterator ConstIter() const
|
||||
|
@ -655,6 +654,20 @@ public:
|
|||
bool IsLocked() const { return mLocked; }
|
||||
|
||||
private:
|
||||
void AfterMaybeRemove()
|
||||
{
|
||||
if (IsEmpty() && mFactor2Mode) {
|
||||
// The last surface for this cache was removed. This can happen if the
|
||||
// surface was stored in a volatile buffer and got purged, or the surface
|
||||
// expired from the cache. If the cache itself lingers for some reason
|
||||
// (e.g. in the process of performing a lookup, the cache itself is
|
||||
// locked), then we need to reset the factor of 2 state because it
|
||||
// requires at least one surface present to get the native size
|
||||
// information from the image.
|
||||
mFactor2Mode = mFactor2Pruned = false;
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceTable mSurfaces;
|
||||
|
||||
bool mLocked;
|
||||
|
@ -816,13 +829,7 @@ public:
|
|||
// Individual surfaces must be freed outside the lock.
|
||||
mCachedSurfacesDiscard.AppendElement(cache->Remove(aSurface));
|
||||
|
||||
// Remove the per-image cache if it's unneeded now. Keep it if the image is
|
||||
// locked, since the per-image cache is where we store that state. Note that
|
||||
// we don't push it into mImageCachesDiscard because all of its surfaces
|
||||
// have been removed, so it is safe to free while holding the lock.
|
||||
if (cache->IsEmpty() && !cache->IsLocked()) {
|
||||
mImageCaches.Remove(imageKey);
|
||||
}
|
||||
MaybeRemoveEmptyCache(imageKey, cache);
|
||||
}
|
||||
|
||||
bool StartTracking(NotNull<CachedSurface*> aSurface,
|
||||
|
@ -1093,6 +1100,8 @@ public:
|
|||
// Individual surfaces must be freed outside the lock.
|
||||
mCachedSurfacesDiscard.AppendElement(aSurface);
|
||||
});
|
||||
|
||||
MaybeRemoveEmptyCache(aImageKey, cache);
|
||||
}
|
||||
|
||||
void DiscardAll(const StaticMutexAutoLock& aAutoLock)
|
||||
|
@ -1199,6 +1208,8 @@ public:
|
|||
// Individual surfaces must be freed outside the lock.
|
||||
mCachedSurfacesDiscard.AppendElement(aSurface);
|
||||
});
|
||||
|
||||
MaybeRemoveEmptyCache(aImageKey, cache);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1209,6 +1220,18 @@ private:
|
|||
return imageCache.forget();
|
||||
}
|
||||
|
||||
void MaybeRemoveEmptyCache(const ImageKey aImageKey,
|
||||
ImageSurfaceCache* aCache)
|
||||
{
|
||||
// Remove the per-image cache if it's unneeded now. Keep it if the image is
|
||||
// locked, since the per-image cache is where we store that state. Note that
|
||||
// we don't push it into mImageCachesDiscard because all of its surfaces
|
||||
// have been removed, so it is safe to free while holding the lock.
|
||||
if (aCache->IsEmpty() && !aCache->IsLocked()) {
|
||||
mImageCaches.Remove(aImageKey);
|
||||
}
|
||||
}
|
||||
|
||||
// This is similar to CanHold() except that it takes into account the costs of
|
||||
// locked surfaces. It's used internally in Insert(), but it's not exposed
|
||||
// publicly because we permit multithreaded access to the surface cache, which
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsAppRunner.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
@ -416,7 +417,7 @@ public:
|
|||
MOZ_RELEASE_ASSERT(aMessage.transaction_id() == mTransaction);
|
||||
MOZ_RELEASE_ASSERT(!mReply);
|
||||
IPC_LOG("Reply received on worker thread: seqno=%d", mSeqno);
|
||||
mReply = new IPC::Message(Move(aMessage));
|
||||
mReply = MakeUnique<IPC::Message>(Move(aMessage));
|
||||
MOZ_RELEASE_ASSERT(IsComplete());
|
||||
}
|
||||
|
||||
|
@ -455,7 +456,7 @@ public:
|
|||
return mReply->is_reply_error();
|
||||
}
|
||||
|
||||
nsAutoPtr<IPC::Message> GetReply() {
|
||||
UniquePtr<IPC::Message> GetReply() {
|
||||
return Move(mReply);
|
||||
}
|
||||
|
||||
|
@ -480,7 +481,7 @@ private:
|
|||
AutoEnterTransaction *mNext;
|
||||
|
||||
// Pointer the a reply received for this message, if one was received.
|
||||
nsAutoPtr<IPC::Message> mReply;
|
||||
UniquePtr<IPC::Message> mReply;
|
||||
};
|
||||
|
||||
class PromiseReporter final : public nsIMemoryReporter
|
||||
|
@ -844,7 +845,7 @@ MessageChannel::CommonThreadOpenInit(MessageChannel *aTargetChan, Side aSide)
|
|||
bool
|
||||
MessageChannel::Echo(Message* aMsg)
|
||||
{
|
||||
nsAutoPtr<Message> msg(aMsg);
|
||||
UniquePtr<Message> msg(aMsg);
|
||||
AssertWorkerThread();
|
||||
mMonitor->AssertNotCurrentThreadOwns();
|
||||
if (MSG_ROUTING_NONE == msg->routing_id()) {
|
||||
|
@ -855,11 +856,11 @@ MessageChannel::Echo(Message* aMsg)
|
|||
MonitorAutoLock lock(*mMonitor);
|
||||
|
||||
if (!Connected()) {
|
||||
ReportConnectionError("MessageChannel", msg);
|
||||
ReportConnectionError("MessageChannel", msg.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
mLink->EchoMessage(msg.forget());
|
||||
mLink->EchoMessage(msg.release());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -887,7 +888,7 @@ MessageChannel::Send(Message* aMsg)
|
|||
|
||||
CxxStackFrame frame(*this, OUT_MESSAGE, aMsg);
|
||||
|
||||
nsAutoPtr<Message> msg(aMsg);
|
||||
UniquePtr<Message> msg(aMsg);
|
||||
AssertWorkerThread();
|
||||
mMonitor->AssertNotCurrentThreadOwns();
|
||||
if (MSG_ROUTING_NONE == msg->routing_id()) {
|
||||
|
@ -897,11 +898,10 @@ MessageChannel::Send(Message* aMsg)
|
|||
|
||||
MonitorAutoLock lock(*mMonitor);
|
||||
if (!Connected()) {
|
||||
ReportConnectionError("MessageChannel", msg);
|
||||
ReportConnectionError("MessageChannel", msg.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
SendMessageToLink(msg.forget());
|
||||
SendMessageToLink(msg.release());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1353,7 +1353,7 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
|||
Telemetry::Accumulate(Telemetry::IPC_MESSAGE_SIZE2, aMsg->size());
|
||||
}
|
||||
|
||||
nsAutoPtr<Message> msg(aMsg);
|
||||
UniquePtr<Message> msg(aMsg);
|
||||
|
||||
// Sanity checks.
|
||||
AssertWorkerThread();
|
||||
|
@ -1367,7 +1367,7 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
|||
AutoScopedLabel autolabel("sync message %s", aMsg->name());
|
||||
#endif
|
||||
|
||||
CxxStackFrame f(*this, OUT_MESSAGE, msg);
|
||||
CxxStackFrame f(*this, OUT_MESSAGE, msg.get());
|
||||
|
||||
MonitorAutoLock lock(*mMonitor);
|
||||
|
||||
|
@ -1427,7 +1427,7 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
|||
"not allowed to send messages while dispatching urgent messages");
|
||||
|
||||
if (!Connected()) {
|
||||
ReportConnectionError("MessageChannel::SendAndWait", msg);
|
||||
ReportConnectionError("MessageChannel::SendAndWait", msg.get());
|
||||
mLastSendError = SyncSendError::NotConnectedBeforeSend;
|
||||
return false;
|
||||
}
|
||||
|
@ -1456,7 +1456,7 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
|||
// msg will be destroyed soon, but name() is not owned by msg.
|
||||
const char* msgName = msg->name();
|
||||
|
||||
SendMessageToLink(msg.forget());
|
||||
SendMessageToLink(msg.release());
|
||||
|
||||
while (true) {
|
||||
MOZ_RELEASE_ASSERT(!transact.IsCanceled());
|
||||
|
@ -1534,7 +1534,7 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
|||
IPC_LOG("Got reply: seqno=%d, xid=%d, msgName=%s, latency=%ums",
|
||||
seqno, transaction, msgName, latencyMs);
|
||||
|
||||
nsAutoPtr<Message> reply = transact.GetReply();
|
||||
UniquePtr<Message> reply = transact.GetReply();
|
||||
|
||||
MOZ_RELEASE_ASSERT(reply);
|
||||
MOZ_RELEASE_ASSERT(reply->is_reply(), "expected reply");
|
||||
|
@ -1560,7 +1560,7 @@ MessageChannel::Send(Message* aMsg, Message* aReply)
|
|||
bool
|
||||
MessageChannel::Call(Message* aMsg, Message* aReply)
|
||||
{
|
||||
nsAutoPtr<Message> msg(aMsg);
|
||||
UniquePtr<Message> msg(aMsg);
|
||||
AssertWorkerThread();
|
||||
mMonitor->AssertNotCurrentThreadOwns();
|
||||
|
||||
|
@ -1573,11 +1573,11 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
|
|||
|
||||
// This must come before MonitorAutoLock, as its destructor acquires the
|
||||
// monitor lock.
|
||||
CxxStackFrame cxxframe(*this, OUT_MESSAGE, msg);
|
||||
CxxStackFrame cxxframe(*this, OUT_MESSAGE, msg.get());
|
||||
|
||||
MonitorAutoLock lock(*mMonitor);
|
||||
if (!Connected()) {
|
||||
ReportConnectionError("MessageChannel::Call", msg);
|
||||
ReportConnectionError("MessageChannel::Call", msg.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1593,7 +1593,7 @@ MessageChannel::Call(Message* aMsg, Message* aReply)
|
|||
msg->set_interrupt_remote_stack_depth_guess(mRemoteStackDepthGuess);
|
||||
msg->set_interrupt_local_stack_depth(1 + InterruptStackDepth());
|
||||
mInterruptStack.push(MessageInfo(*msg));
|
||||
mLink->SendMessage(msg.forget());
|
||||
mLink->SendMessage(msg.release());
|
||||
|
||||
while (true) {
|
||||
// if a handler invoked by *Dispatch*() spun a nested event
|
||||
|
|
|
@ -93,6 +93,8 @@ ActivationContext::~ActivationContext()
|
|||
Release();
|
||||
}
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
/* static */ Result<uintptr_t,HRESULT>
|
||||
ActivationContext::GetCurrent()
|
||||
{
|
||||
|
@ -104,6 +106,68 @@ ActivationContext::GetCurrent()
|
|||
return reinterpret_cast<uintptr_t>(actCtx);
|
||||
}
|
||||
|
||||
/* static */ HRESULT
|
||||
ActivationContext::GetCurrentManifestPath(nsAString& aOutManifestPath)
|
||||
{
|
||||
aOutManifestPath.Truncate();
|
||||
|
||||
SIZE_T bytesNeeded;
|
||||
BOOL ok = ::QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr,
|
||||
nullptr, ActivationContextDetailedInformation,
|
||||
nullptr, 0, &bytesNeeded);
|
||||
if (!ok) {
|
||||
DWORD err = ::GetLastError();
|
||||
if (err != ERROR_INSUFFICIENT_BUFFER) {
|
||||
return HRESULT_FROM_WIN32(err);
|
||||
}
|
||||
}
|
||||
|
||||
auto ctxBuf = MakeUnique<BYTE[]>(bytesNeeded);
|
||||
|
||||
ok = ::QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr, nullptr,
|
||||
ActivationContextDetailedInformation, ctxBuf.get(),
|
||||
bytesNeeded, nullptr);
|
||||
if (!ok) {
|
||||
return HRESULT_FROM_WIN32(::GetLastError());
|
||||
}
|
||||
|
||||
auto ctxInfo =
|
||||
reinterpret_cast<ACTIVATION_CONTEXT_DETAILED_INFORMATION*>(ctxBuf.get());
|
||||
|
||||
// assemblyIndex is 1-based, and we want the last index, so we can just copy
|
||||
// ctxInfo->ulAssemblyCount directly.
|
||||
DWORD assemblyIndex = ctxInfo->ulAssemblyCount;
|
||||
ok = ::QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr,
|
||||
&assemblyIndex,
|
||||
AssemblyDetailedInformationInActivationContext, nullptr,
|
||||
0, &bytesNeeded);
|
||||
if (!ok) {
|
||||
DWORD err = ::GetLastError();
|
||||
if (err != ERROR_INSUFFICIENT_BUFFER) {
|
||||
return HRESULT_FROM_WIN32(err);
|
||||
}
|
||||
}
|
||||
|
||||
auto assemblyBuf = MakeUnique<BYTE[]>(bytesNeeded);
|
||||
|
||||
ok = ::QueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, nullptr,
|
||||
&assemblyIndex,
|
||||
AssemblyDetailedInformationInActivationContext,
|
||||
assemblyBuf.get(), bytesNeeded, &bytesNeeded);
|
||||
if (!ok) {
|
||||
return HRESULT_FROM_WIN32(::GetLastError());
|
||||
}
|
||||
|
||||
auto assemblyInfo =
|
||||
reinterpret_cast<ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION*>(assemblyBuf.get());
|
||||
aOutManifestPath = nsDependentString(assemblyInfo->lpAssemblyManifestPath,
|
||||
(assemblyInfo->ulManifestPathLength + 1) / sizeof(wchar_t));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
ActivationContextRegion::ActivationContextRegion(const ActivationContext& aActCtx)
|
||||
: mActCtx(aActCtx)
|
||||
, mActCookie(0)
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Result.h"
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
#include "nsString.h"
|
||||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -35,7 +39,10 @@ public:
|
|||
return mActCtx != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
static Result<uintptr_t,HRESULT> GetCurrent();
|
||||
static HRESULT GetCurrentManifestPath(nsAString& aOutManifestPath);
|
||||
#endif // defined(MOZILLA_INTERNAL_API)
|
||||
|
||||
private:
|
||||
void Init(ACTCTX& aActCtx);
|
||||
|
|
|
@ -83,6 +83,7 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf,
|
|||
#if defined(ACCESSIBILITY) && defined(MOZ_CRASHREPORTER)
|
||||
const uint32_t expectedStreamLen = GetOBJREFSize(WrapNotNull(mStream));
|
||||
nsAutoCString strActCtx;
|
||||
nsAutoString manifestPath;
|
||||
#endif // defined(ACCESSIBILITY) && defined(MOZ_CRASHREPORTER)
|
||||
|
||||
HRESULT unmarshalResult = S_OK;
|
||||
|
@ -92,7 +93,7 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf,
|
|||
// actual interface later.
|
||||
|
||||
#if defined(ACCESSIBILITY) && defined(MOZ_CRASHREPORTER)
|
||||
auto marshalFn = [this, &strActCtx, &unmarshalResult, &aIID]() -> void
|
||||
auto marshalFn = [this, &strActCtx, &manifestPath, &unmarshalResult, &aIID]() -> void
|
||||
#else
|
||||
auto marshalFn = [this, &unmarshalResult, &aIID]() -> void
|
||||
#endif // defined(ACCESSIBILITY) && defined(MOZ_CRASHREPORTER)
|
||||
|
@ -104,6 +105,8 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf,
|
|||
} else {
|
||||
strActCtx.AppendPrintf("HRESULT 0x%08X", curActCtx.unwrapErr());
|
||||
}
|
||||
|
||||
ActivationContext::GetCurrentManifestPath(manifestPath);
|
||||
#endif // defined(ACCESSIBILITY) && defined(MOZ_CRASHREPORTER)
|
||||
|
||||
unmarshalResult =
|
||||
|
@ -137,6 +140,8 @@ ProxyStream::ProxyStream(REFIID aIID, const BYTE* aInitBuf,
|
|||
AnnotateClassRegistration(CLSID_AccessibleHandler);
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("UnmarshalActCtx"),
|
||||
strActCtx);
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("UnmarshalActCtxManifestPath"),
|
||||
NS_ConvertUTF16toUTF8(manifestPath));
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("A11yHandlerRegistered"),
|
||||
a11y::IsHandlerRegistered() ?
|
||||
NS_LITERAL_CSTRING("true") :
|
||||
|
@ -285,13 +290,28 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject,
|
|||
HRESULT statResult = S_OK;
|
||||
HRESULT getHGlobalResult = S_OK;
|
||||
|
||||
auto marshalFn = [&]() -> void
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
nsAutoString manifestPath;
|
||||
|
||||
auto marshalFn = [this, &aIID, aObject, mshlFlags, &stream, &streamSize,
|
||||
&hglobal, &createStreamResult, &marshalResult, &statResult,
|
||||
&getHGlobalResult, &manifestPath]() -> void
|
||||
#else
|
||||
auto marshalFn = [this, &aIID, aObject, mshlFlags, &stream, &streamSize,
|
||||
&hglobal, &createStreamResult, &marshalResult, &statResult,
|
||||
&getHGlobalResult]() -> void
|
||||
#endif // defined(MOZ_CRASHREPORTER)
|
||||
{
|
||||
createStreamResult = ::CreateStreamOnHGlobal(nullptr, TRUE, getter_AddRefs(stream));
|
||||
createStreamResult = ::CreateStreamOnHGlobal(nullptr, TRUE,
|
||||
getter_AddRefs(stream));
|
||||
if (FAILED(createStreamResult)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
ActivationContext::GetCurrentManifestPath(manifestPath);
|
||||
#endif // defined(MOZ_CRASHREPORTER)
|
||||
|
||||
marshalResult = ::CoMarshalInterface(stream, aIID, aObject, MSHCTX_LOCAL,
|
||||
nullptr, mshlFlags);
|
||||
MOZ_DIAGNOSTIC_ASSERT(marshalResult != E_INVALIDARG);
|
||||
|
@ -333,6 +353,8 @@ ProxyStream::ProxyStream(REFIID aIID, IUnknown* aObject,
|
|||
nsPrintfCString hrAsStr("0x%08X", marshalResult);
|
||||
CrashReporter::AnnotateCrashReport(
|
||||
NS_LITERAL_CSTRING("CoMarshalInterfaceFailure"), hrAsStr);
|
||||
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("MarshalActCtxManifestPath"),
|
||||
NS_ConvertUTF16toUTF8(manifestPath));
|
||||
}
|
||||
|
||||
if (FAILED(statResult)) {
|
||||
|
|
|
@ -669,12 +669,16 @@ BaselineScript::maybeICEntryFromPCOffset(uint32_t pcOffset)
|
|||
if (!ComputeBinarySearchMid(this, pcOffset, &mid))
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(mid < numICEntries());
|
||||
|
||||
// Found an IC entry with a matching PC offset. Search backward, and then
|
||||
// forward from this IC entry, looking for one with the same PC offset which
|
||||
// has isForOp() set.
|
||||
for (size_t i = mid; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i--) {
|
||||
for (size_t i = mid; icEntry(i).pcOffset() == pcOffset; i--) {
|
||||
if (icEntry(i).isForOp())
|
||||
return &icEntry(i);
|
||||
if (i == 0)
|
||||
break;
|
||||
}
|
||||
for (size_t i = mid+1; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i++) {
|
||||
if (icEntry(i).isForOp())
|
||||
|
@ -728,10 +732,13 @@ BaselineScript::callVMEntryFromPCOffset(uint32_t pcOffset)
|
|||
// inserted by VM calls.
|
||||
size_t mid;
|
||||
MOZ_ALWAYS_TRUE(ComputeBinarySearchMid(this, pcOffset, &mid));
|
||||
MOZ_ASSERT(mid < numICEntries());
|
||||
|
||||
for (size_t i = mid; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i--) {
|
||||
for (size_t i = mid; icEntry(i).pcOffset() == pcOffset; i--) {
|
||||
if (icEntry(i).kind() == ICEntry::Kind_CallVM)
|
||||
return icEntry(i);
|
||||
if (i == 0)
|
||||
break;
|
||||
}
|
||||
for (size_t i = mid+1; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i++) {
|
||||
if (icEntry(i).kind() == ICEntry::Kind_CallVM)
|
||||
|
|
|
@ -1619,7 +1619,7 @@ ControlFlowGenerator::processBreak(JSOp op, jssrcnote* sn)
|
|||
DebugOnly<bool> found = false;
|
||||
|
||||
if (SN_TYPE(sn) == SRC_BREAK2LABEL) {
|
||||
for (size_t i = labels_.length() - 1; i < labels_.length(); i--) {
|
||||
for (size_t i = labels_.length() - 1; ; i--) {
|
||||
CFGState& cfg = cfgStack_[labels_[i].cfgEntry];
|
||||
MOZ_ASSERT(cfg.state == CFGState::LABEL);
|
||||
if (cfg.stopAt == target) {
|
||||
|
@ -1627,9 +1627,11 @@ ControlFlowGenerator::processBreak(JSOp op, jssrcnote* sn)
|
|||
found = true;
|
||||
break;
|
||||
}
|
||||
if (i == 0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (size_t i = loops_.length() - 1; i < loops_.length(); i--) {
|
||||
for (size_t i = loops_.length() - 1; ; i--) {
|
||||
CFGState& cfg = cfgStack_[loops_[i].cfgEntry];
|
||||
MOZ_ASSERT(cfg.isLoop());
|
||||
if (cfg.loop.exitpc == target) {
|
||||
|
@ -1637,6 +1639,8 @@ ControlFlowGenerator::processBreak(JSOp op, jssrcnote* sn)
|
|||
found = true;
|
||||
break;
|
||||
}
|
||||
if (i == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1665,7 +1669,7 @@ ControlFlowGenerator::processContinue(JSOp op)
|
|||
// Find the target loop.
|
||||
CFGState* found = nullptr;
|
||||
jsbytecode* target = pc + GetJumpOffset(pc);
|
||||
for (size_t i = loops_.length() - 1; i < loops_.length(); i--) {
|
||||
for (size_t i = loops_.length() - 1; ; i--) {
|
||||
// +1 to skip JSOP_JUMPTARGET.
|
||||
if (loops_[i].continuepc == target + 1 ||
|
||||
EffectiveContinue(loops_[i].continuepc) == target)
|
||||
|
@ -1673,6 +1677,8 @@ ControlFlowGenerator::processContinue(JSOp op)
|
|||
found = &cfgStack_[loops_[i].cfgEntry];
|
||||
break;
|
||||
}
|
||||
if (i == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// There must always be a valid target loop structure. If not, there's
|
||||
|
@ -1698,11 +1704,13 @@ ControlFlowGenerator::processSwitchBreak(JSOp op)
|
|||
// Find the target switch.
|
||||
CFGState* found = nullptr;
|
||||
jsbytecode* target = pc + GetJumpOffset(pc);
|
||||
for (size_t i = switches_.length() - 1; i < switches_.length(); i--) {
|
||||
for (size_t i = switches_.length() - 1; ; i--) {
|
||||
if (switches_[i].continuepc == target) {
|
||||
found = &cfgStack_[switches_[i].cfgEntry];
|
||||
break;
|
||||
}
|
||||
if (i == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// There must always be a valid target loop structure. If not, there's
|
||||
|
|
|
@ -224,7 +224,7 @@ private:
|
|||
{
|
||||
MOZ_IMPLICIT URLEntry(const CacheKey& key)
|
||||
: CacheKey(key)
|
||||
, mData(NullCString())
|
||||
, mData(VoidCString())
|
||||
{}
|
||||
|
||||
explicit URLEntry(nsIFile* file)
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
JSObject* options = nullptr)
|
||||
: OptionsBase(cx, options)
|
||||
, target(cx)
|
||||
, charset(NullString())
|
||||
, charset(VoidString())
|
||||
, ignoreCache(false)
|
||||
, async(false)
|
||||
, wantReturnValue(false)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#define XPCJSMemoryReporter_h
|
||||
|
||||
class nsISupports;
|
||||
class nsIMemoryReporterCallback;
|
||||
class nsIHandleReportCallback;
|
||||
|
||||
namespace xpc {
|
||||
|
||||
|
@ -23,7 +23,7 @@ class JSReporter
|
|||
public:
|
||||
static void CollectReports(WindowPaths* windowPaths,
|
||||
WindowPaths* topWindowPaths,
|
||||
nsIMemoryReporterCallback* handleReport,
|
||||
nsIHandleReportCallback* handleReport,
|
||||
nsISupports* data,
|
||||
bool anonymize);
|
||||
};
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
class nsGlobalWindow;
|
||||
class nsIPrincipal;
|
||||
class nsScriptNameSpaceManager;
|
||||
class nsIMemoryReporterCallback;
|
||||
class nsIHandleReportCallback;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -431,7 +431,7 @@ private:
|
|||
void
|
||||
ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats& rtStats,
|
||||
const nsACString& rtPath,
|
||||
nsIMemoryReporterCallback* handleReport,
|
||||
nsIHandleReportCallback* handleReport,
|
||||
nsISupports* data,
|
||||
bool anonymize,
|
||||
size_t* rtTotal = nullptr);
|
||||
|
|
|
@ -29,6 +29,8 @@ add_task(async function() {
|
|||
let sandbox = Cu.Sandbox(window, {sandboxPrototype: window});
|
||||
|
||||
function sandboxContent() {
|
||||
window.onload = function SandboxOnLoad() {};
|
||||
|
||||
window.addEventListener("FromTest", () => {
|
||||
window.dispatchEvent(new CustomEvent("FromSandbox"));
|
||||
}, true);
|
||||
|
@ -40,6 +42,11 @@ add_task(async function() {
|
|||
let fromTestPromise = promiseEvent(window, "FromTest");
|
||||
let fromSandboxPromise = promiseEvent(window, "FromSandbox");
|
||||
|
||||
equal(typeof window.onload, "function",
|
||||
"window.onload should contain sandbox event listener");
|
||||
equal(window.onload.name, "SandboxOnLoad",
|
||||
"window.onload have the correct function name");
|
||||
|
||||
do_print("Dispatch FromTest event");
|
||||
window.dispatchEvent(new window.CustomEvent("FromTest"));
|
||||
|
||||
|
@ -70,6 +77,8 @@ add_task(async function() {
|
|||
Cu.forceGC();
|
||||
Cu.forceCC();
|
||||
|
||||
ok(Cu.isDeadWrapper(window.onload),
|
||||
"window.onload should contain a dead wrapper after sandbox is nuked");
|
||||
|
||||
do_print("Dispatch FromTest event");
|
||||
fromTestPromise = promiseEvent(window, "FromTest");
|
||||
|
|
|
@ -323,6 +323,7 @@ skip-if = toolkit == 'android' # bug 775227 for android
|
|||
[test_value_computation.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_value_storage.html]
|
||||
skip-if = toolkit == 'android' && debug # bug 1397615
|
||||
[test_variable_serialization_computed.html]
|
||||
[test_variable_serialization_specified.html]
|
||||
[test_variables.html]
|
||||
|
|
|
@ -14,6 +14,23 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/IntegerTypeTraits.h"
|
||||
|
||||
// Probe for builtin math overflow support. Disabled for 32-bit builds for now
|
||||
// since "gcc -m32" claims to support these but its implementation is buggy.
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82274
|
||||
#if defined(HAVE_64BIT_BUILD)
|
||||
#if defined(__has_builtin)
|
||||
#define MOZ_HAS_BUILTIN_OP_OVERFLOW (__has_builtin(__builtin_add_overflow))
|
||||
#elif defined(__GNUC__)
|
||||
// (clang also defines __GNUC__ but it supports __has_builtin since at least
|
||||
// v3.1 (released in 2012) so it won't get here.)
|
||||
#define MOZ_HAS_BUILTIN_OP_OVERFLOW (__GNUC__ >= 5)
|
||||
#else
|
||||
#define MOZ_HAS_BUILTIN_OP_OVERFLOW (0)
|
||||
#endif
|
||||
#else
|
||||
#define MOZ_HAS_BUILTIN_OP_OVERFLOW (0)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename T> class CheckedInt;
|
||||
|
@ -255,6 +272,10 @@ template<typename T>
|
|||
inline bool
|
||||
IsAddValid(T aX, T aY)
|
||||
{
|
||||
#if MOZ_HAS_BUILTIN_OP_OVERFLOW
|
||||
T dummy;
|
||||
return !__builtin_add_overflow(aX, aY, &dummy);
|
||||
#else
|
||||
// Addition is valid if the sign of aX+aY is equal to either that of aX or
|
||||
// that of aY. Since the value of aX+aY is undefined if we have a signed
|
||||
// type, we compute it using the unsigned type of the same size. Beware!
|
||||
|
@ -267,12 +288,17 @@ IsAddValid(T aX, T aY)
|
|||
return IsSigned<T>::value
|
||||
? HasSignBit(BinaryComplement(T((result ^ aX) & (result ^ aY))))
|
||||
: BinaryComplement(aX) >= aY;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
IsSubValid(T aX, T aY)
|
||||
{
|
||||
#if MOZ_HAS_BUILTIN_OP_OVERFLOW
|
||||
T dummy;
|
||||
return !__builtin_sub_overflow(aX, aY, &dummy);
|
||||
#else
|
||||
// Subtraction is valid if either aX and aY have same sign, or aX-aY and aX
|
||||
// have same sign. Since the value of aX-aY is undefined if we have a signed
|
||||
// type, we compute it using the unsigned type of the same size.
|
||||
|
@ -283,6 +309,7 @@ IsSubValid(T aX, T aY)
|
|||
return IsSigned<T>::value
|
||||
? HasSignBit(BinaryComplement(T((result ^ aX) & (aX ^ aY))))
|
||||
: aX >= aY;
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T,
|
||||
|
@ -339,7 +366,12 @@ template<typename T>
|
|||
inline bool
|
||||
IsMulValid(T aX, T aY)
|
||||
{
|
||||
#if MOZ_HAS_BUILTIN_OP_OVERFLOW
|
||||
T dummy;
|
||||
return !__builtin_mul_overflow(aX, aY, &dummy);
|
||||
#else
|
||||
return IsMulValidImpl<T>::run(aX, aY);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -687,12 +719,30 @@ private:
|
|||
aLhs.mIsValid && aRhs.mIsValid); \
|
||||
}
|
||||
|
||||
#if MOZ_HAS_BUILTIN_OP_OVERFLOW
|
||||
#define MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR2(NAME, OP, FUN) \
|
||||
template<typename T> \
|
||||
inline CheckedInt<T> \
|
||||
operator OP(const CheckedInt<T>& aLhs, const CheckedInt<T>& aRhs) \
|
||||
{ \
|
||||
T result; \
|
||||
if (FUN(aLhs.mValue, aRhs.mValue, &result)) { \
|
||||
return CheckedInt<T>(0, false); \
|
||||
} \
|
||||
return CheckedInt<T>(result, aLhs.mIsValid && aRhs.mIsValid); \
|
||||
}
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR2(Add, +, __builtin_add_overflow)
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR2(Sub, -, __builtin_sub_overflow)
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR2(Mul, *, __builtin_mul_overflow)
|
||||
#undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR2
|
||||
#else
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Add, +)
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Sub, -)
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mul, *)
|
||||
#endif
|
||||
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Div, /)
|
||||
MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mod, %)
|
||||
|
||||
#undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR
|
||||
|
||||
// Implement castToCheckedInt<T>(x), making sure that
|
||||
|
|
|
@ -136,6 +136,13 @@
|
|||
<item>wifi</item>
|
||||
<item>disabled</item>
|
||||
</string-array>
|
||||
<!-- This value is similar to config_longPressVibePattern in android frameworks/base/core/res/res/values/config.xml-->
|
||||
<integer-array name="long_press_vibrate_msec">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>20</item>
|
||||
<item>21</item>
|
||||
</integer-array>
|
||||
<!-- browser.image_blocking -->
|
||||
<string-array name="pref_browser_image_blocking_entries">
|
||||
<item>@string/pref_tap_to_load_images_enabled</item>
|
||||
|
|
|
@ -49,7 +49,6 @@ import android.support.v4.view.MenuItemCompat;
|
|||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -699,7 +698,7 @@ public class BrowserApp extends GeckoApp
|
|||
|
||||
final TabHistoryFragment fragment = TabHistoryFragment.newInstance(historyPageList, toIndex);
|
||||
final FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
GeckoAppShell.getHapticFeedbackDelegate().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
GeckoAppShell.vibrateOnHapticFeedbackEnabled(getResources().getIntArray(R.array.long_press_vibrate_msec));
|
||||
fragment.show(R.id.tab_history_panel, fragmentManager.beginTransaction(), TAB_HISTORY_FRAGMENT_TAG);
|
||||
}
|
||||
});
|
||||
|
@ -1659,6 +1658,7 @@ public class BrowserApp extends GeckoApp
|
|||
mLayerView.getDynamicToolbarAnimator().addMetricsListener(this);
|
||||
mLayerView.getDynamicToolbarAnimator().setToolbarChromeProxy(this);
|
||||
}
|
||||
mDynamicToolbar.setLayerView(mLayerView);
|
||||
setDynamicToolbarEnabled(mDynamicToolbar.isEnabled());
|
||||
|
||||
// Intercept key events for gamepad shortcuts
|
||||
|
|
|
@ -673,7 +673,7 @@ public abstract class GeckoApp extends GeckoActivity
|
|||
GeckoAccessibility.updateAccessibilitySettings(this);
|
||||
|
||||
} else if ("Accessibility:Event".equals(event)) {
|
||||
GeckoAccessibility.sendAccessibilityEvent(mLayerView, message);
|
||||
GeckoAccessibility.sendAccessibilityEvent(message);
|
||||
|
||||
} else if ("Bookmark:Insert".equals(event)) {
|
||||
final BrowserDB db = BrowserDB.from(getProfile());
|
||||
|
|
|
@ -57,8 +57,7 @@ import java.io.File;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GeckoApplication extends Application
|
||||
implements HapticFeedbackDelegate {
|
||||
public class GeckoApplication extends Application {
|
||||
private static final String LOG_TAG = "GeckoApplication";
|
||||
private static final String MEDIA_DECODING_PROCESS_CRASH = "MEDIA_DECODING_PROCESS_CRASH";
|
||||
|
||||
|
@ -230,7 +229,6 @@ public class GeckoApplication extends Application
|
|||
|
||||
final Context context = getApplicationContext();
|
||||
GeckoAppShell.setApplicationContext(context);
|
||||
GeckoAppShell.setHapticFeedbackDelegate(this);
|
||||
GeckoAppShell.setGeckoInterface(new GeckoAppShell.GeckoInterface() {
|
||||
@Override
|
||||
public boolean openUriExternal(final String targetURI, final String mimeType,
|
||||
|
@ -636,13 +634,4 @@ public class GeckoApplication extends Application
|
|||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@Override // HapticFeedbackDelegate
|
||||
public void performHapticFeedback(final int effect) {
|
||||
final Activity currentActivity =
|
||||
GeckoActivityMonitor.getInstance().getCurrentActivity();
|
||||
if (currentActivity != null) {
|
||||
currentActivity.getWindow().getDecorView().performHapticFeedback(effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,10 +71,22 @@ public class GeckoService extends Service {
|
|||
|
||||
private static final EventListener EVENT_LISTENER = new EventListener();
|
||||
|
||||
private static RuntimeException bug1401737Diag;
|
||||
|
||||
public static void register() {
|
||||
if (DEBUG) {
|
||||
Log.d(LOGTAG, "Registered listener");
|
||||
}
|
||||
|
||||
// Diagnose bug 1401737. register() is unexpectedly getting called a second time.
|
||||
// We know the stack for the second call, but we want to collect stack for the first call.
|
||||
if (bug1401737Diag == null) {
|
||||
bug1401737Diag = new IllegalStateException("Bug 1401737 diagnostic crash");
|
||||
} else {
|
||||
Log.e(LOGTAG, "register() is called a second time", new Exception());
|
||||
throw bug1401737Diag;
|
||||
}
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(EVENT_LISTENER,
|
||||
"Gecko:ScheduleRun");
|
||||
}
|
||||
|
|
|
@ -218,6 +218,10 @@ public class CustomTabsActivity extends AppCompatActivity
|
|||
|
||||
@Override
|
||||
public void finish() {
|
||||
if (mGeckoView != null) {
|
||||
mGeckoView.loadUri("about:blank");
|
||||
}
|
||||
|
||||
super.finish();
|
||||
|
||||
final SafeIntent intent = new SafeIntent(getIntent());
|
||||
|
|
|
@ -17,7 +17,6 @@ import android.content.Intent;
|
|||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
|
@ -260,8 +259,7 @@ public class GeckoMenu extends ListView
|
|||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
if (handleMenuItemLongClick(menuItem)) {
|
||||
GeckoAppShell.getHapticFeedbackDelegate().performHapticFeedback(
|
||||
HapticFeedbackConstants.LONG_PRESS);
|
||||
GeckoAppShell.vibrateOnHapticFeedbackEnabled(getResources().getIntArray(R.array.long_press_vibrate_msec));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -278,8 +276,7 @@ public class GeckoMenu extends ListView
|
|||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
if (handleMenuItemLongClick(menuItem)) {
|
||||
GeckoAppShell.getHapticFeedbackDelegate().performHapticFeedback(
|
||||
HapticFeedbackConstants.LONG_PRESS);
|
||||
GeckoAppShell.vibrateOnHapticFeedbackEnabled(getResources().getIntArray(R.array.long_press_vibrate_msec));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -415,7 +415,6 @@ gvjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x
|
|||
'gfx/SurfaceTextureListener.java',
|
||||
'gfx/ViewTransform.java',
|
||||
'gfx/VsyncSource.java',
|
||||
'HapticFeedbackDelegate.java',
|
||||
'InputConnectionListener.java',
|
||||
'InputMethods.java',
|
||||
'media/AsyncCodec.java',
|
||||
|
|
|
@ -7,6 +7,8 @@ package org.mozilla.gecko;
|
|||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.EventDispatcher;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
|
@ -108,8 +110,7 @@ public class GeckoAccessibility {
|
|||
return sEnabled;
|
||||
}
|
||||
|
||||
public static void sendAccessibilityEvent(final GeckoView view,
|
||||
final GeckoBundle message) {
|
||||
public static void sendAccessibilityEvent(final GeckoBundle message) {
|
||||
if (!sEnabled)
|
||||
return;
|
||||
|
||||
|
@ -119,11 +120,10 @@ public class GeckoAccessibility {
|
|||
return;
|
||||
}
|
||||
|
||||
sendAccessibilityEvent(view, message, eventType);
|
||||
sendAccessibilityEvent(message, eventType);
|
||||
}
|
||||
|
||||
public static void sendAccessibilityEvent(final GeckoView view, final GeckoBundle message,
|
||||
final int eventType) {
|
||||
public static void sendAccessibilityEvent(final GeckoBundle message, final int eventType) {
|
||||
if (!sEnabled)
|
||||
return;
|
||||
|
||||
|
@ -148,6 +148,10 @@ public class GeckoAccessibility {
|
|||
} else {
|
||||
// In Jelly Bean we populate an AccessibilityNodeInfo with the minimal amount of data to have
|
||||
// it work with TalkBack.
|
||||
final LayerView view = GeckoAppShell.getLayerView();
|
||||
if (view == null)
|
||||
return;
|
||||
|
||||
if (sVirtualCursorNode == null) {
|
||||
sVirtualCursorNode = AccessibilityNodeInfo.obtain(view, VIRTUAL_CURSOR_POSITION);
|
||||
}
|
||||
|
@ -262,12 +266,7 @@ public class GeckoAccessibility {
|
|||
AccessibilityNodeProvider mAccessibilityNodeProvider;
|
||||
|
||||
@Override
|
||||
public AccessibilityNodeProvider getAccessibilityNodeProvider(final View hostView) {
|
||||
if (!(hostView instanceof GeckoView)) {
|
||||
return super.getAccessibilityNodeProvider(hostView);
|
||||
}
|
||||
final GeckoView host = (GeckoView) hostView;
|
||||
|
||||
public AccessibilityNodeProvider getAccessibilityNodeProvider(final View host) {
|
||||
if (mAccessibilityNodeProvider == null)
|
||||
// The accessibility node structure for web content consists of 3 LayerView child nodes:
|
||||
// 1. VIRTUAL_ENTRY_POINT_BEFORE: Represents the entry point before the LayerView.
|
||||
|
@ -320,7 +319,7 @@ public class GeckoAccessibility {
|
|||
// The accessibility focus is permanently on the middle node, VIRTUAL_CURSOR_POSITION.
|
||||
// When we enter the view forward or backward we just ask Gecko to get focus, keeping the current position.
|
||||
if (virtualViewId == VIRTUAL_CURSOR_POSITION && sHoverEnter != null) {
|
||||
GeckoAccessibility.sendAccessibilityEvent(host, sHoverEnter, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
|
||||
GeckoAccessibility.sendAccessibilityEvent(sHoverEnter, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
|
||||
} else {
|
||||
final GeckoBundle data = new GeckoBundle(1);
|
||||
data.putBoolean("gainFocus", true);
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.mozilla.gecko.annotation.JNITarget;
|
|||
import org.mozilla.gecko.annotation.RobocopTarget;
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.permissions.Permissions;
|
||||
import org.mozilla.gecko.process.GeckoProcessManager;
|
||||
import org.mozilla.gecko.util.HardwareCodecCapabilityUtils;
|
||||
|
@ -221,8 +222,21 @@ public class GeckoAppShell
|
|||
@WrapForJNI(dispatchTo = "gecko")
|
||||
public static native void notifyUriVisited(String uri);
|
||||
|
||||
private static LayerView sLayerView;
|
||||
private static Rect sScreenSize;
|
||||
|
||||
public static void setLayerView(LayerView lv) {
|
||||
if (sLayerView == lv) {
|
||||
return;
|
||||
}
|
||||
sLayerView = lv;
|
||||
}
|
||||
|
||||
@RobocopTarget
|
||||
public static LayerView getLayerView() {
|
||||
return sLayerView;
|
||||
}
|
||||
|
||||
@WrapForJNI(stubName = "NotifyObservers", dispatchTo = "gecko")
|
||||
private static native void nativeNotifyObservers(String topic, String data);
|
||||
|
||||
|
@ -367,8 +381,7 @@ public class GeckoAppShell
|
|||
LocationListener,
|
||||
NotificationListener,
|
||||
ScreenOrientationDelegate,
|
||||
WakeLockDelegate,
|
||||
HapticFeedbackDelegate {
|
||||
WakeLockDelegate {
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
}
|
||||
|
@ -548,22 +561,6 @@ public class GeckoAppShell
|
|||
mWakeLocks.remove(lock);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performHapticFeedback(final int effect) {
|
||||
final int[] pattern;
|
||||
// Use default platform values.
|
||||
if (effect == HapticFeedbackConstants.KEYBOARD_TAP) {
|
||||
pattern = new int[] { 40 };
|
||||
} else if (effect == HapticFeedbackConstants.LONG_PRESS) {
|
||||
pattern = new int[] { 0, 1, 20, 21 };
|
||||
} else if (effect == HapticFeedbackConstants.VIRTUAL_KEY) {
|
||||
pattern = new int[] { 0, 10, 20, 30 };
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
vibrateOnHapticFeedbackEnabled(pattern);
|
||||
}
|
||||
}
|
||||
|
||||
private static final DefaultListeners DEFAULT_LISTENERS = new DefaultListeners();
|
||||
|
@ -571,7 +568,6 @@ public class GeckoAppShell
|
|||
private static LocationListener sLocationListener = DEFAULT_LISTENERS;
|
||||
private static NotificationListener sNotificationListener = DEFAULT_LISTENERS;
|
||||
private static WakeLockDelegate sWakeLockDelegate = DEFAULT_LISTENERS;
|
||||
private static HapticFeedbackDelegate sHapticFeedbackDelegate = DEFAULT_LISTENERS;
|
||||
|
||||
/**
|
||||
* A delegate for supporting the Screen Orientation API.
|
||||
|
@ -618,14 +614,6 @@ public class GeckoAppShell
|
|||
sWakeLockDelegate = (delegate != null) ? delegate : DEFAULT_LISTENERS;
|
||||
}
|
||||
|
||||
public static HapticFeedbackDelegate getHapticFeedbackDelegate() {
|
||||
return sHapticFeedbackDelegate;
|
||||
}
|
||||
|
||||
public static void setHapticFeedbackDelegate(final HapticFeedbackDelegate delegate) {
|
||||
sHapticFeedbackDelegate = (delegate != null) ? delegate : DEFAULT_LISTENERS;
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static void enableSensor(int aSensortype) {
|
||||
final SensorManager sm = (SensorManager)
|
||||
|
@ -1014,11 +1002,10 @@ public class GeckoAppShell
|
|||
// Don't perform haptic feedback if a vibration is currently playing,
|
||||
// because the haptic feedback will nuke the vibration.
|
||||
if (!sVibrationMaybePlaying || System.nanoTime() >= sVibrationEndTime) {
|
||||
getHapticFeedbackDelegate().performHapticFeedback(
|
||||
aIsLongPress ? HapticFeedbackConstants.LONG_PRESS
|
||||
: HapticFeedbackConstants.VIRTUAL_KEY);
|
||||
sVibrationMaybePlaying = false;
|
||||
sVibrationEndTime = 0;
|
||||
LayerView layerView = getLayerView();
|
||||
layerView.performHapticFeedback(aIsLongPress ?
|
||||
HapticFeedbackConstants.LONG_PRESS :
|
||||
HapticFeedbackConstants.VIRTUAL_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1036,14 +1023,10 @@ public class GeckoAppShell
|
|||
}
|
||||
|
||||
// Vibrate only if haptic feedback is enabled.
|
||||
private static void vibrateOnHapticFeedbackEnabled(int[] milliseconds) {
|
||||
public static void vibrateOnHapticFeedbackEnabled(int[] milliseconds) {
|
||||
if (Settings.System.getInt(getApplicationContext().getContentResolver(),
|
||||
Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) > 0) {
|
||||
if (milliseconds.length == 1) {
|
||||
vibrate(milliseconds[0]);
|
||||
} else {
|
||||
vibrate(convertIntToLongArray(milliseconds), -1);
|
||||
}
|
||||
vibrate(convertIntToLongArray(milliseconds), -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1056,10 +1039,10 @@ public class GeckoAppShell
|
|||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static void vibrate(long[] pattern, int repeat) {
|
||||
// If pattern.length is odd, the last element in the pattern is a
|
||||
// If pattern.length is even, the last element in the pattern is a
|
||||
// meaningless delay, so don't include it in vibrationDuration.
|
||||
long vibrationDuration = 0;
|
||||
int iterLen = pattern.length & ~1;
|
||||
int iterLen = pattern.length - (pattern.length % 2 == 0 ? 1 : 0);
|
||||
for (int i = 0; i < iterLen; i++) {
|
||||
vibrationDuration += pattern[i];
|
||||
}
|
||||
|
@ -1570,6 +1553,21 @@ public class GeckoAppShell
|
|||
return HardwareUtils.isTablet();
|
||||
}
|
||||
|
||||
private static boolean sImeWasEnabledOnLastResize = false;
|
||||
public static void viewSizeChanged() {
|
||||
GeckoView v = (GeckoView) getLayerView();
|
||||
if (v == null) {
|
||||
return;
|
||||
}
|
||||
boolean imeIsEnabled = v.isIMEEnabled();
|
||||
if (imeIsEnabled && !sImeWasEnabledOnLastResize) {
|
||||
// The IME just came up after not being up, so let's scroll
|
||||
// to the focused input.
|
||||
EventDispatcher.getInstance().dispatch("ScrollTo:FocusedInput", null);
|
||||
}
|
||||
sImeWasEnabledOnLastResize = imeIsEnabled;
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static double[] getCurrentNetworkInformation() {
|
||||
return GeckoNetworkManager.getInstance().getCurrentInformation();
|
||||
|
|
|
@ -72,7 +72,7 @@ class GeckoInputConnection
|
|||
|
||||
private String mCurrentInputMethod = "";
|
||||
|
||||
private final GeckoView mView;
|
||||
private final View mView;
|
||||
private final GeckoEditableClient mEditableClient;
|
||||
protected int mBatchEditCount;
|
||||
private ExtractedTextRequest mUpdateRequest;
|
||||
|
@ -83,7 +83,7 @@ class GeckoInputConnection
|
|||
// Prevent showSoftInput and hideSoftInput from causing reentrant calls on some devices.
|
||||
private volatile boolean mSoftInputReentrancyGuard;
|
||||
|
||||
public static GeckoEditableListener create(GeckoView targetView,
|
||||
public static GeckoEditableListener create(View targetView,
|
||||
GeckoEditableClient editable) {
|
||||
if (DEBUG)
|
||||
return DebugGeckoInputConnection.create(targetView, editable);
|
||||
|
@ -91,7 +91,7 @@ class GeckoInputConnection
|
|||
return new GeckoInputConnection(targetView, editable);
|
||||
}
|
||||
|
||||
protected GeckoInputConnection(GeckoView targetView,
|
||||
protected GeckoInputConnection(View targetView,
|
||||
GeckoEditableClient editable) {
|
||||
super(targetView, true);
|
||||
mView = targetView;
|
||||
|
@ -204,7 +204,7 @@ class GeckoInputConnection
|
|||
return extract;
|
||||
}
|
||||
|
||||
private GeckoView getView() {
|
||||
private View getView() {
|
||||
return mView;
|
||||
}
|
||||
|
||||
|
@ -236,10 +236,7 @@ class GeckoInputConnection
|
|||
v.clearFocus();
|
||||
v.requestFocus();
|
||||
}
|
||||
final GeckoView view = getView();
|
||||
if (view != null) {
|
||||
view.getDynamicToolbarAnimator().showToolbar(/*immediately*/ true);
|
||||
}
|
||||
GeckoAppShell.getLayerView().getDynamicToolbarAnimator().showToolbar(/*immediately*/true);
|
||||
mSoftInputReentrancyGuard = true;
|
||||
imm.showSoftInput(v, 0);
|
||||
mSoftInputReentrancyGuard = false;
|
||||
|
@ -362,18 +359,18 @@ class GeckoInputConnection
|
|||
mCursorAnchorInfoBuilder.reset();
|
||||
|
||||
// Calculate Gecko logical coords to screen coords
|
||||
final GeckoView view = getView();
|
||||
if (view == null) {
|
||||
final View v = getView();
|
||||
if (v == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int[] viewCoords = new int[2];
|
||||
view.getLocationOnScreen(viewCoords);
|
||||
v.getLocationOnScreen(viewCoords);
|
||||
|
||||
DynamicToolbarAnimator animator = view.getDynamicToolbarAnimator();
|
||||
float toolbarHeight = (float) animator.getCurrentToolbarHeight();
|
||||
DynamicToolbarAnimator animator = GeckoAppShell.getLayerView().getDynamicToolbarAnimator();
|
||||
float toolbarHeight = (float)animator.getCurrentToolbarHeight();
|
||||
|
||||
Matrix matrix = view.getMatrixForLayerRectToViewRect();
|
||||
Matrix matrix = GeckoAppShell.getLayerView().getMatrixForLayerRectToViewRect();
|
||||
if (matrix == null) {
|
||||
if (DEBUG) {
|
||||
Log.d(LOGTAG, "Cannot get Matrix to convert from Gecko coords to layer view coords");
|
||||
|
@ -1037,13 +1034,13 @@ final class DebugGeckoInputConnection
|
|||
private InputConnection mProxy;
|
||||
private final StringBuilder mCallLevel;
|
||||
|
||||
private DebugGeckoInputConnection(GeckoView targetView,
|
||||
private DebugGeckoInputConnection(View targetView,
|
||||
GeckoEditableClient editable) {
|
||||
super(targetView, editable);
|
||||
mCallLevel = new StringBuilder();
|
||||
}
|
||||
|
||||
public static GeckoEditableListener create(GeckoView targetView,
|
||||
public static GeckoEditableListener create(View targetView,
|
||||
GeckoEditableClient editable) {
|
||||
final Class<?>[] PROXY_INTERFACES = { InputConnection.class,
|
||||
InputConnectionListener.class,
|
||||
|
|
|
@ -488,6 +488,9 @@ public class GeckoView extends LayerView {
|
|||
private void init(final Context context, final GeckoViewSettings settings) {
|
||||
preload(context);
|
||||
|
||||
// Perform common initialization for Fennec/GeckoView.
|
||||
GeckoAppShell.setLayerView(this);
|
||||
|
||||
initializeView();
|
||||
mListener.registerListeners();
|
||||
|
||||
|
@ -748,8 +751,7 @@ public class GeckoView extends LayerView {
|
|||
mInputConnectionListener.onKeyMultiple(keyCode, repeatCount, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIMEEnabled() {
|
||||
/* package */ boolean isIMEEnabled() {
|
||||
return mInputConnectionListener != null &&
|
||||
mInputConnectionListener.isIMEEnabled();
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.view.HapticFeedbackConstants;
|
||||
|
||||
/**
|
||||
* A <code>HapticFeedbackDelegate</code> is responsible for performing haptic feedback.
|
||||
*/
|
||||
public interface HapticFeedbackDelegate {
|
||||
/**
|
||||
* Perform a haptic feedback effect. Called from the Gecko thread.
|
||||
*
|
||||
* @param effect Effect to perform from <code>android.view.HapticFeedbackConstants</code>.
|
||||
*/
|
||||
void performHapticFeedback(int effect);
|
||||
}
|
|
@ -33,7 +33,6 @@ class GeckoLayerClient implements LayerView.Listener
|
|||
private IntSize mWindowSize;
|
||||
|
||||
private boolean mForceRedraw;
|
||||
private boolean mImeWasEnabledOnLastResize;
|
||||
|
||||
/* The current viewport metrics.
|
||||
* This is volatile so that we can read and write to it from different threads.
|
||||
|
@ -154,13 +153,7 @@ class GeckoLayerClient implements LayerView.Listener
|
|||
// the following call also sends gecko a message, which will be processed after the resize
|
||||
// message above has updated the viewport. this message ensures that if we have just put
|
||||
// focus in a text field, we scroll the content so that the text field is in view.
|
||||
final boolean imeIsEnabled = mView.isIMEEnabled();
|
||||
if (imeIsEnabled && !mImeWasEnabledOnLastResize) {
|
||||
// The IME just came up after not being up, so let's scroll
|
||||
// to the focused input.
|
||||
EventDispatcher.getInstance().dispatch("ScrollTo:FocusedInput", null);
|
||||
}
|
||||
mImeWasEnabledOnLastResize = imeIsEnabled;
|
||||
GeckoAppShell.viewSizeChanged();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -824,9 +824,5 @@ public class LayerView extends FrameLayout {
|
|||
if (isCompositorReady()) {
|
||||
mCompositor.setDefaultClearColor(mDefaultClearColor);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isIMEEnabled() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -356,7 +356,7 @@ public class FennecNativeActions implements Actions {
|
|||
|
||||
PaintExpecter() {
|
||||
final PaintExpecter expecter = this;
|
||||
mLayerView = (LayerView) mSolo.getView(R.id.layer_view);
|
||||
mLayerView = GeckoAppShell.getLayerView();
|
||||
mDrawListener = new DrawListener() {
|
||||
@Override
|
||||
public void drawFinished() {
|
||||
|
|
|
@ -356,8 +356,7 @@ abstract class BaseTest extends BaseRobocopTest {
|
|||
|
||||
// If we don't see the item, scroll down once in case it's off-screen.
|
||||
// Hacky way to scroll down. solo.scroll* does not work in dialogs.
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mSolo,
|
||||
mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
meh.dragSync(mScreenMidWidth, mScreenMidHeight+100, mScreenMidWidth, mScreenMidHeight-100);
|
||||
|
||||
foundText = mSolo.waitForText(txt);
|
||||
|
|
|
@ -5,11 +5,8 @@
|
|||
package org.mozilla.gecko.tests;
|
||||
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.PrefsHelper;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
|
||||
import com.robotium.solo.Solo;
|
||||
import org.mozilla.gecko.PrefsHelper;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.os.SystemClock;
|
||||
|
@ -29,12 +26,11 @@ class MotionEventHelper {
|
|||
private float mTouchStartTolerance;
|
||||
private final int mDpi;
|
||||
|
||||
public MotionEventHelper(Instrumentation inst, Solo solo,
|
||||
int surfaceOffsetX, int surfaceOffsetY) {
|
||||
public MotionEventHelper(Instrumentation inst, int surfaceOffsetX, int surfaceOffsetY) {
|
||||
mInstrumentation = inst;
|
||||
mSurfaceOffsetX = surfaceOffsetX;
|
||||
mSurfaceOffsetY = surfaceOffsetY;
|
||||
layerView = (LayerView) solo.getView(R.id.layer_view);
|
||||
layerView = GeckoAppShell.getLayerView();
|
||||
mApzEnabled = false;
|
||||
mTouchStartTolerance = 0.0f;
|
||||
mDpi = GeckoAppShell.getDpi();
|
||||
|
|
|
@ -19,8 +19,7 @@ public class testAxisLocking extends PixelTest {
|
|||
public void testAxisLocking() {
|
||||
String url = getAbsoluteUrl(mStringHelper.ROBOCOP_BOXES_URL);
|
||||
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mSolo,
|
||||
mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
|
||||
blockForGeckoReady();
|
||||
|
||||
|
|
|
@ -17,8 +17,7 @@ public class testFlingCorrectness extends PixelTest {
|
|||
public void testFlingCorrectness() {
|
||||
String url = getAbsoluteUrl(mStringHelper.ROBOCOP_BOXES_URL);
|
||||
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mSolo,
|
||||
mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
|
||||
blockForGeckoReady();
|
||||
|
||||
|
|
|
@ -17,8 +17,7 @@ public class testPanCorrectness extends PixelTest {
|
|||
public void testPanCorrectness() {
|
||||
String url = getAbsoluteUrl(mStringHelper.ROBOCOP_BOXES_URL);
|
||||
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mSolo,
|
||||
mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
|
||||
blockForGeckoReady();
|
||||
|
||||
|
|
|
@ -29,8 +29,7 @@ public class testVkbOverlap extends PixelTest {
|
|||
|
||||
// scroll to the bottom of the page and let it settle
|
||||
Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint();
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mSolo,
|
||||
mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
meh.dragSync(10, 150, 10, 50);
|
||||
|
||||
// the input field has a green background, so let's count the number of green pixels
|
||||
|
|
|
@ -684,7 +684,7 @@ nsHtml5TreeOperation::AppendDoctypeToDocument(nsIAtom* aName,
|
|||
aName,
|
||||
aPublicId,
|
||||
aSystemId,
|
||||
NullString());
|
||||
VoidString());
|
||||
NS_ASSERTION(docType, "Doctype creation failed.");
|
||||
nsCOMPtr<nsIContent> asContent = do_QueryInterface(docType);
|
||||
return AppendToDocument(asContent, aBuilder);
|
||||
|
|
|
@ -1,18 +1,66 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 et tw=78: */
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#include "nsIAtom.h"
|
||||
#include "nsElementTable.h"
|
||||
|
||||
/*****************************************************************************
|
||||
Now it's time to list all the html elements all with their capabilities...
|
||||
******************************************************************************/
|
||||
static const int kNone= 0x0;
|
||||
|
||||
// The Element Table (sung to the tune of Modern Major General)
|
||||
static const int kHTMLContent = 0x0001; // HEAD, (FRAMESET | BODY)
|
||||
static const int kHeadContent = 0x0002; // Elements that *must* be in the head.
|
||||
static const int kHeadMisc = 0x0004; // Elements that *can* be in the head.
|
||||
|
||||
static const int kSpecial = 0x0008; // A, IMG, APPLET, OBJECT, FONT, BASEFONT, BR, SCRIPT,
|
||||
// MAP, Q, SUB, SUP, SPAN, BDO, IFRAME
|
||||
|
||||
static const int kFormControl = 0x0010; // INPUT SELECT TEXTAREA LABEL BUTTON
|
||||
static const int kPreformatted = 0x0020; // PRE
|
||||
static const int kPreExclusion = 0x0040; // IMG, OBJECT, APPLET, BIG, SMALL, SUB, SUP, FONT, BASEFONT
|
||||
static const int kFontStyle = 0x0080; // TT, I, B, U, S, STRIKE, BIG, SMALL
|
||||
static const int kPhrase = 0x0100; // EM, STRONG, DFN, CODE, SAMP, KBD, VAR, CITE, ABBR, ACRONYM
|
||||
static const int kHeading = 0x0200; // H1..H6
|
||||
static const int kBlockMisc = 0x0400; // OBJECT, SCRIPT
|
||||
static const int kBlock = 0x0800; // ADDRESS, BLOCKQUOTE, CENTER, DIV, DL, FIELDSET, FORM,
|
||||
// ISINDEX, HR, NOSCRIPT, NOFRAMES, P, TABLE
|
||||
static const int kList = 0x1000; // UL, OL, DIR, MENU
|
||||
static const int kPCDATA = 0x2000; // plain text and entities...
|
||||
static const int kSelf = 0x4000; // whatever THIS tag is...
|
||||
static const int kExtensions = 0x8000; // BGSOUND, WBR, NOBR
|
||||
static const int kTable = 0x10000;// TR,TD,THEAD,TBODY,TFOOT,CAPTION,TH
|
||||
static const int kDLChild = 0x20000;// DL, DT
|
||||
static const int kCDATA = 0x40000;// just plain text...
|
||||
|
||||
static const int kInlineEntity = (kPCDATA|kFontStyle|kPhrase|kSpecial|kFormControl|kExtensions); // #PCDATA, %fontstyle, %phrase, %special, %formctrl
|
||||
static const int kBlockEntity = (kHeading|kList|kPreformatted|kBlock); // %heading, %list, %preformatted, %block
|
||||
static const int kFlowEntity = (kBlockEntity|kInlineEntity); // %blockentity, %inlineentity
|
||||
static const int kAllTags = 0xffffff;
|
||||
|
||||
// Is aTest a member of aBitset?
|
||||
static bool
|
||||
TestBits(int32_t aBitset, int32_t aTest)
|
||||
{
|
||||
if (aTest) {
|
||||
int32_t result = aBitset & aTest;
|
||||
return result == aTest;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct HTMLElement
|
||||
{
|
||||
bool IsMemberOf(int32_t aBitset) const
|
||||
{
|
||||
return TestBits(aBitset, mParentBits);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsHTMLTag mTagID;
|
||||
#endif
|
||||
int mParentBits; // defines groups that can contain this element
|
||||
bool mLeaf;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ELEM(tag, parent, leaf) { eHTMLTag_##tag, parent, leaf },
|
||||
|
@ -20,7 +68,7 @@
|
|||
#define ELEM(tag, parent, leaf) { parent, leaf },
|
||||
#endif
|
||||
|
||||
const nsHTMLElement gHTMLElements[] = {
|
||||
static const HTMLElement gHTMLElements[] = {
|
||||
ELEM(unknown, kNone, true)
|
||||
ELEM(a, kSpecial, false)
|
||||
ELEM(abbr, kPhrase, false)
|
||||
|
@ -172,19 +220,14 @@ const nsHTMLElement gHTMLElements[] = {
|
|||
|
||||
#undef ELEM
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
bool nsHTMLElement::IsMemberOf(int32_t aSet) const
|
||||
{
|
||||
return TestBits(aSet, mParentBits);
|
||||
}
|
||||
|
||||
bool nsHTMLElement::IsContainer(eHTMLTags aId)
|
||||
bool
|
||||
nsHTMLElement::IsContainer(nsHTMLTag aId)
|
||||
{
|
||||
return !gHTMLElements[aId].mLeaf;
|
||||
}
|
||||
|
||||
bool nsHTMLElement::IsBlock(eHTMLTags aId)
|
||||
bool
|
||||
nsHTMLElement::IsBlock(nsHTMLTag aId)
|
||||
{
|
||||
return gHTMLElements[aId].IsMemberOf(kBlock) ||
|
||||
gHTMLElements[aId].IsMemberOf(kBlockEntity) ||
|
||||
|
@ -194,10 +237,14 @@ bool nsHTMLElement::IsBlock(eHTMLTags aId)
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void CheckElementTable()
|
||||
void
|
||||
CheckElementTable()
|
||||
{
|
||||
for (eHTMLTags t = eHTMLTag_unknown; t <= eHTMLTag_userdefined; t = eHTMLTags(t + 1)) {
|
||||
NS_ASSERTION(gHTMLElements[t].mTagID == t, "gHTMLElements entries does match tag list.");
|
||||
for (nsHTMLTag t = eHTMLTag_unknown;
|
||||
t <= eHTMLTag_userdefined;
|
||||
t = nsHTMLTag(t + 1)) {
|
||||
MOZ_ASSERT(gHTMLElements[t].mTagID == t,
|
||||
"gHTMLElements entries does match tag list.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,95 +1,22 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
/**
|
||||
* MODULE NOTES:
|
||||
* @update gess 4/1/98
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _NSELEMENTABLE
|
||||
#define _NSELEMENTABLE
|
||||
#ifndef nsElementTable_h
|
||||
#define nsElementTable_h
|
||||
|
||||
#include "nsHTMLTags.h"
|
||||
#include "nsIDTD.h"
|
||||
|
||||
//*********************************************************************************************
|
||||
// The following ints define the standard groups of HTML elements...
|
||||
//*********************************************************************************************
|
||||
|
||||
static const int kNone= 0x0;
|
||||
|
||||
static const int kHTMLContent = 0x0001; // HEAD, (FRAMESET | BODY)
|
||||
static const int kHeadContent = 0x0002; // Elements that *must* be in the head.
|
||||
static const int kHeadMisc = 0x0004; // Elements that *can* be in the head.
|
||||
|
||||
static const int kSpecial = 0x0008; // A, IMG, APPLET, OBJECT, FONT, BASEFONT, BR, SCRIPT,
|
||||
// MAP, Q, SUB, SUP, SPAN, BDO, IFRAME
|
||||
|
||||
static const int kFormControl = 0x0010; // INPUT SELECT TEXTAREA LABEL BUTTON
|
||||
static const int kPreformatted = 0x0020; // PRE
|
||||
static const int kPreExclusion = 0x0040; // IMG, OBJECT, APPLET, BIG, SMALL, SUB, SUP, FONT, BASEFONT
|
||||
static const int kFontStyle = 0x0080; // TT, I, B, U, S, STRIKE, BIG, SMALL
|
||||
static const int kPhrase = 0x0100; // EM, STRONG, DFN, CODE, SAMP, KBD, VAR, CITE, ABBR, ACRONYM
|
||||
static const int kHeading = 0x0200; // H1..H6
|
||||
static const int kBlockMisc = 0x0400; // OBJECT, SCRIPT
|
||||
static const int kBlock = 0x0800; // ADDRESS, BLOCKQUOTE, CENTER, DIV, DL, FIELDSET, FORM,
|
||||
// ISINDEX, HR, NOSCRIPT, NOFRAMES, P, TABLE
|
||||
static const int kList = 0x1000; // UL, OL, DIR, MENU
|
||||
static const int kPCDATA = 0x2000; // plain text and entities...
|
||||
static const int kSelf = 0x4000; // whatever THIS tag is...
|
||||
static const int kExtensions = 0x8000; // BGSOUND, WBR, NOBR
|
||||
static const int kTable = 0x10000;// TR,TD,THEAD,TBODY,TFOOT,CAPTION,TH
|
||||
static const int kDLChild = 0x20000;// DL, DT
|
||||
static const int kCDATA = 0x40000;// just plain text...
|
||||
|
||||
static const int kInlineEntity = (kPCDATA|kFontStyle|kPhrase|kSpecial|kFormControl|kExtensions); // #PCDATA, %fontstyle, %phrase, %special, %formctrl
|
||||
static const int kBlockEntity = (kHeading|kList|kPreformatted|kBlock); // %heading, %list, %preformatted, %block
|
||||
static const int kFlowEntity = (kBlockEntity|kInlineEntity); // %blockentity, %inlineentity
|
||||
static const int kAllTags = 0xffffff;
|
||||
|
||||
|
||||
//*********************************************************************************************
|
||||
// The following ints define the standard groups of HTML elements...
|
||||
//*********************************************************************************************
|
||||
|
||||
#ifdef DEBUG
|
||||
extern void CheckElementTable();
|
||||
void CheckElementTable();
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* We're asking the question: is aTest a member of bitset.
|
||||
*
|
||||
* @param
|
||||
* @return TRUE or FALSE
|
||||
*/
|
||||
inline bool TestBits(int aBitset,int aTest) {
|
||||
if(aTest) {
|
||||
int32_t result=(aBitset & aTest);
|
||||
return bool(result==aTest);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct nsHTMLElement {
|
||||
bool IsMemberOf(int32_t aType) const;
|
||||
|
||||
#ifdef DEBUG
|
||||
eHTMLTags mTagID;
|
||||
#endif
|
||||
int mParentBits; //defines groups that can contain this element
|
||||
bool mLeaf;
|
||||
|
||||
static bool IsContainer(eHTMLTags aTag);
|
||||
static bool IsBlock(eHTMLTags aTag);
|
||||
struct nsHTMLElement
|
||||
{
|
||||
static bool IsContainer(nsHTMLTag aTag);
|
||||
static bool IsBlock(nsHTMLTag aTag);
|
||||
};
|
||||
|
||||
extern const nsHTMLElement gHTMLElements[];
|
||||
|
||||
#endif
|
||||
#endif // nsElementTable_h
|
||||
|
|
|
@ -84,6 +84,4 @@ private:
|
|||
static PLHashTable* gTagAtomTable;
|
||||
};
|
||||
|
||||
#define eHTMLTags nsHTMLTag
|
||||
|
||||
#endif /* nsHTMLTags_h___ */
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче