Merge mozilla-central to autoland. r=merge a=merge CLOSED TREE

This commit is contained in:
Margareta Eliza Balazs 2018-01-09 12:14:48 +02:00
Родитель 37f03700ef 03877052c1
Коммит 30e58c79b0
139 изменённых файлов: 1629 добавлений и 1629 удалений

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

@ -7,10 +7,13 @@
#include "Compatibility.h"
#include "mozilla/Telemetry.h"
#include "mozilla/WindowsVersion.h"
#include "nsDataHashtable.h"
#include "nsPrintfCString.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "nsTHashtable.h"
#include "nsUnicharUtils.h"
#include "nsWinUtils.h"
@ -31,32 +34,102 @@
#endif // defined(UIA_LOGGING)
static bool
GetLocalObjectHandle(DWORD aSrcPid, HANDLE aSrcHandle, nsAutoHandle& aProcess,
nsAutoHandle& aLocal)
struct ByteArrayDeleter
{
aLocal.reset();
if (!aProcess) {
HANDLE rawProcess = ::OpenProcess(PROCESS_DUP_HANDLE, FALSE, aSrcPid);
if (!rawProcess) {
LOG_ERROR(OpenProcess);
return false;
}
aProcess.own(rawProcess);
void operator()(void* aBuf)
{
delete[] reinterpret_cast<char*>(aBuf);
}
};
HANDLE rawDuped;
if (!::DuplicateHandle(aProcess.get(), aSrcHandle, ::GetCurrentProcess(),
&rawDuped, GENERIC_READ, FALSE, 0)) {
LOG_ERROR(DuplicateHandle);
typedef UniquePtr<OBJECT_DIRECTORY_INFORMATION, ByteArrayDeleter> ObjDirInfoPtr;
// ComparatorFnT returns true to continue searching, or else false to indicate
// search completion.
template <typename ComparatorFnT>
static bool
FindNamedObject(ComparatorFnT aComparator)
{
// We want to enumerate every named kernel object in our session. We do this
// by opening a directory object using a path constructed using the session
// id under which our process resides.
DWORD sessionId;
if (!::ProcessIdToSessionId(::GetCurrentProcessId(), &sessionId)) {
return false;
}
aLocal.own(rawDuped);
nsAutoString path;
path.AppendPrintf("\\Sessions\\%u\\BaseNamedObjects", sessionId);
return true;
UNICODE_STRING baseNamedObjectsName;
::RtlInitUnicodeString(&baseNamedObjectsName, path.get());
OBJECT_ATTRIBUTES attributes;
InitializeObjectAttributes(&attributes, &baseNamedObjectsName, 0,
nullptr, nullptr);
HANDLE rawBaseNamedObjects;
NTSTATUS ntStatus = ::NtOpenDirectoryObject(&rawBaseNamedObjects,
DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
&attributes);
if (!NT_SUCCESS(ntStatus)) {
return false;
}
nsAutoHandle baseNamedObjects(rawBaseNamedObjects);
ULONG context = 0, returnedLen;
ULONG objDirInfoBufLen = 1024 * sizeof(OBJECT_DIRECTORY_INFORMATION);
ObjDirInfoPtr objDirInfo(
reinterpret_cast<OBJECT_DIRECTORY_INFORMATION*>(new char[objDirInfoBufLen]));
// Now query that directory object for every named object that it contains.
BOOL firstCall = TRUE;
do {
ntStatus = ::NtQueryDirectoryObject(baseNamedObjects, objDirInfo.get(),
objDirInfoBufLen, FALSE, firstCall,
&context, &returnedLen);
#if defined(HAVE_64BIT_BUILD)
if (!NT_SUCCESS(ntStatus)) {
return false;
}
#else
if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
// This case only occurs on 32-bit builds running atop WOW64.
// (See https://bugzilla.mozilla.org/show_bug.cgi?id=1423999#c3)
objDirInfo.reset(reinterpret_cast<OBJECT_DIRECTORY_INFORMATION*>(new char[returnedLen]));
objDirInfoBufLen = returnedLen;
continue;
} else if (!NT_SUCCESS(ntStatus)) {
return false;
}
#endif
// NtQueryDirectoryObject gave us an array of OBJECT_DIRECTORY_INFORMATION
// structures whose final entry is zeroed out.
OBJECT_DIRECTORY_INFORMATION* curDir = objDirInfo.get();
while (curDir->mName.Length && curDir->mTypeName.Length) {
// We use nsDependentSubstring here because UNICODE_STRINGs are not
// guaranteed to be null-terminated.
nsDependentSubstring objName(curDir->mName.Buffer,
curDir->mName.Length / sizeof(wchar_t));
nsDependentSubstring typeName(curDir->mTypeName.Buffer,
curDir->mTypeName.Length / sizeof(wchar_t));
if (!aComparator(objName, typeName)) {
return true;
}
++curDir;
}
firstCall = FALSE;
} while (ntStatus == STATUS_MORE_ENTRIES);
return false;
}
namespace mozilla {
@ -74,15 +147,6 @@ Compatibility::OnUIAMessage(WPARAM aWParam, LPARAM aLParam)
Telemetry::AutoTimer<Telemetry::A11Y_UIA_DETECTION_TIMING_MS> timer;
static auto pNtQuerySystemInformation =
reinterpret_cast<decltype(&::NtQuerySystemInformation)>(
::GetProcAddress(::GetModuleHandleW(L"ntdll.dll"),
"NtQuerySystemInformation"));
static auto pNtQueryObject =
reinterpret_cast<decltype(&::NtQueryObject)>(
::GetProcAddress(::GetModuleHandleW(L"ntdll.dll"), "NtQueryObject"));
// UIA creates a section containing the substring "HOOK_SHMEM_"
NS_NAMED_LITERAL_STRING(kStrHookShmem, "HOOK_SHMEM_");
@ -90,7 +154,27 @@ Compatibility::OnUIAMessage(WPARAM aWParam, LPARAM aLParam)
// current thread id and the UIA message's WPARAM and LPARAM.
nsAutoString partialSectionSuffix;
partialSectionSuffix.AppendPrintf("_%08x_%08x_%08x", ::GetCurrentThreadId(),
aLParam, aWParam);
static_cast<DWORD>(aLParam), aWParam);
// Find any named Section that matches the naming convention of the UIA shared
// memory.
nsAutoHandle section;
auto comparator = [&](const nsDependentSubstring& aName,
const nsDependentSubstring& aType) -> bool {
if (aType.Equals(NS_LITERAL_STRING("Section")) &&
FindInReadable(kStrHookShmem, aName) &&
StringEndsWith(aName, partialSectionSuffix)) {
section.own(::OpenFileMapping(GENERIC_READ, FALSE,
PromiseFlatString(aName).get()));
return false;
}
return true;
};
if (!FindNamedObject(comparator) || !section) {
return Nothing();
}
NTSTATUS ntStatus;
@ -105,7 +189,7 @@ Compatibility::OnUIAMessage(WPARAM aWParam, LPARAM aLParam)
while (true) {
handleInfoBuf = MakeUnique<char[]>(handleInfoBufLen);
ntStatus = pNtQuerySystemInformation(
ntStatus = ::NtQuerySystemInformation(
(SYSTEM_INFORMATION_CLASS) SystemExtendedHandleInformation,
handleInfoBuf.get(), handleInfoBufLen, &handleInfoBufLen);
if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) {
@ -119,161 +203,99 @@ Compatibility::OnUIAMessage(WPARAM aWParam, LPARAM aLParam)
break;
}
// Now we iterate through the system handle list, searching for a section
// handle whose name matches the section name used by UIA.
static Maybe<USHORT> sSectionObjTypeIndex;
const DWORD ourPid = ::GetCurrentProcessId();
Maybe<PVOID> kernelObject;
ULONG lastPid = 0;
nsAutoHandle process;
static Maybe<USHORT> sectionObjTypeIndex;
nsTHashtable<nsUint32HashKey> nonSectionObjTypes;
nsDataHashtable<nsVoidPtrHashKey, DWORD> objMap;
auto handleInfo = reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(handleInfoBuf.get());
for (ULONG index = 0; index < handleInfo->mHandleCount; ++index) {
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX& curHandle = handleInfo->mHandles[index];
if (lastPid && lastPid == curHandle.mPid && !process) {
// During the previous iteration, we could not obtain a handle for this
// pid. Skip any remaining handles belonging to that pid.
HANDLE handle = reinterpret_cast<HANDLE>(curHandle.mHandle);
// The mapping of the curHandle.mObjectTypeIndex field depends on the
// underlying OS kernel. As we scan through the handle list, we record the
// type indices such that we may use those values to skip over handles that
// refer to non-section objects.
if (sectionObjTypeIndex) {
// If we know the type index for Sections, that's the fastest check...
if (sectionObjTypeIndex.value() != curHandle.mObjectTypeIndex) {
// Not a section
continue;
}
} else if (nonSectionObjTypes.Contains(static_cast<uint32_t>(
curHandle.mObjectTypeIndex))) {
// Otherwise we check whether or not the object type is definitely _not_
// a Section...
continue;
}
// As a perf optimization, we reuse the same process handle as long as we're
// still looking at the same pid. Once the pid changes, we need to reset
// process so that we open a new handle to the newly-seen process.
if (lastPid != curHandle.mPid) {
process.reset();
}
nsAutoHandle handle;
if (kernelObject.isSome() && kernelObject.value() == curHandle.mObject) {
// If we know the value of the underlying kernel object, we can immediately
// check for equality by comparing against curHandle.mObject
remotePid = Some(static_cast<DWORD>(curHandle.mPid));
break;
} else if (sSectionObjTypeIndex.isSome()) {
// Otherwise, if we know which object type value corresponds to a Section
// object, we can use that to eliminate any handles that are not sections.
if (curHandle.mObjectTypeIndex != sSectionObjTypeIndex.value()) {
// Not a section handle
continue;
}
} else {
// Otherwise we need to query the handle to determine its type. Note that
// each handle in the system list is relative to its owning process, so
// we cannot do anything with it until we duplicate the handle into our
// own process.
lastPid = curHandle.mPid;
if (!GetLocalObjectHandle((DWORD) curHandle.mPid,
(HANDLE) curHandle.mHandle,
process, handle)) {
// We don't have access to do this, assume this handle isn't relevant
continue;
}
// Now we have our own handle to the object, lets find out what type of
// object this handle represents. Any handle whose type is not "Section"
// is of no interest to us.
} else if (ourPid == curHandle.mPid) {
// Otherwise we need to issue some system calls to find out the object
// type corresponding to the current handle's type index.
ULONG objTypeBufLen;
ntStatus = pNtQueryObject(handle, ObjectTypeInformation, nullptr,
0, &objTypeBufLen);
ntStatus = ::NtQueryObject(handle, ObjectTypeInformation,
nullptr, 0, &objTypeBufLen);
if (ntStatus != STATUS_INFO_LENGTH_MISMATCH) {
continue;
}
auto objTypeBuf = MakeUnique<char[]>(objTypeBufLen);
ntStatus = pNtQueryObject(handle, ObjectTypeInformation, objTypeBuf.get(),
objTypeBufLen, &objTypeBufLen);
ntStatus = ::NtQueryObject(handle, ObjectTypeInformation, objTypeBuf.get(),
objTypeBufLen, &objTypeBufLen);
if (!NT_SUCCESS(ntStatus)) {
// We don't have access to do this, assume this handle isn't relevant
continue;
}
auto objType =
reinterpret_cast<PUBLIC_OBJECT_TYPE_INFORMATION*>(objTypeBuf.get());
nsDependentString objTypeName(objType->TypeName.Buffer,
objType->TypeName.Length / sizeof(wchar_t));
// Now we check whether the object's type name matches "Section"
nsDependentSubstring objTypeName(objType->TypeName.Buffer,
objType->TypeName.Length / sizeof(wchar_t));
if (!objTypeName.Equals(NS_LITERAL_STRING("Section"))) {
// Not a section, so we don't care about this handle anymore.
nonSectionObjTypes.PutEntry(static_cast<uint32_t>(curHandle.mObjectTypeIndex));
continue;
}
// We have a section, save this handle's type code so that we can go
// faster in future iterations.
sSectionObjTypeIndex = Some(curHandle.mObjectTypeIndex);
sectionObjTypeIndex = Some(curHandle.mObjectTypeIndex);
}
// If we reached this point without needing to query the handle, then we
// need to open it here so that we can query its name.
lastPid = curHandle.mPid;
// At this point we know that curHandle references a Section object.
// Now we can do some actual tests on it.
if ((!process || !handle) &&
!GetLocalObjectHandle((DWORD) curHandle.mPid, (HANDLE) curHandle.mHandle,
process, handle)) {
// We don't have access to do this, assume this handle isn't relevant
continue;
}
if (ourPid != curHandle.mPid) {
if (kernelObject && kernelObject.value() == curHandle.mObject) {
// The kernel objects match -- we have found the remote pid!
remotePid = Some(curHandle.mPid);
break;
}
// At this point, |handle| is a valid section handle. Let's try to find
// out the name of its underlying object.
ULONG objNameBufLen;
ntStatus = pNtQueryObject(handle,
(OBJECT_INFORMATION_CLASS)ObjectNameInformation,
nullptr, 0, &objNameBufLen);
if (ntStatus != STATUS_INFO_LENGTH_MISMATCH) {
continue;
}
auto objNameBuf = MakeUnique<char[]>(objNameBufLen);
ntStatus = pNtQueryObject(handle,
(OBJECT_INFORMATION_CLASS)ObjectNameInformation,
objNameBuf.get(), objNameBufLen, &objNameBufLen);
if (!NT_SUCCESS(ntStatus)) {
continue;
}
auto objNameInfo = reinterpret_cast<OBJECT_NAME_INFORMATION*>(objNameBuf.get());
if (!objNameInfo->mName.Length) {
// This section is unnamed. We don't care about those.
continue;
}
nsDependentString objName(objNameInfo->mName.Buffer,
objNameInfo->mName.Length / sizeof(wchar_t));
// Check to see if the section's name matches our expected name.
if (!FindInReadable(kStrHookShmem, objName) ||
!StringEndsWith(objName, partialSectionSuffix)) {
// The names don't match, continue searching.
continue;
}
// At this point we have a section handle whose name matches the one that
// we're looking for.
if (curHandle.mPid == ourPid) {
// Our own process also has a handle to the section of interest. While we
// don't want our own pid, this *does* give us an opportunity to speed up
// future iterations by examining each handle for its kernel object (which
// is the same for all processes) instead of searching by name.
// An object that is not ours. Since we do not yet know which kernel
// object we're interested in, we'll save the current object for later.
objMap.Put(curHandle.mObject, curHandle.mPid);
} else if (handle == section.get()) {
// This is the file mapping that we opened above. We save this mObject
// in order to compare to Section objects opened by other processes.
kernelObject = Some(curHandle.mObject);
continue;
}
// Bingo! We want this pid!
remotePid = Some(static_cast<DWORD>(curHandle.mPid));
break;
}
if (!kernelObject) {
return Nothing();
}
if (!remotePid) {
// We found kernelObject *after* we saw the remote process's copy. Now we
// must look it up in objMap.
DWORD pid;
if (objMap.Get(kernelObject.value(), &pid)) {
remotePid = Some(pid);
}
}
if (!remotePid) {
return Nothing();
}

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

@ -9,10 +9,22 @@
#include <winternl.h>
#if defined(__cplusplus)
extern "C" {
#endif
#ifndef STATUS_INFO_LENGTH_MISMATCH
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#endif
#ifndef STATUS_BUFFER_TOO_SMALL
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#endif
#ifndef STATUS_MORE_ENTRIES
#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
#endif
enum UndocSystemInformationClass
{
SystemExtendedHandleInformation = 64
@ -47,4 +59,36 @@ struct OBJECT_NAME_INFORMATION
UNICODE_STRING mName;
};
// The following declarations are documented on MSDN but are not included in
// public user-mode headers.
enum DirectoryObjectAccessFlags
{
DIRECTORY_QUERY = 0x0001,
DIRECTORY_TRAVERSE = 0x0002,
DIRECTORY_CREATE_OBJECT = 0x0004,
DIRECTORY_CREATE_SUBDIRECTORY = 0x0008,
DIRECTORY_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | 0x000F
};
NTSTATUS WINAPI
NtOpenDirectoryObject(PHANDLE aDirectoryHandle, ACCESS_MASK aDesiredAccess,
POBJECT_ATTRIBUTES aObjectAttributes);
struct OBJECT_DIRECTORY_INFORMATION
{
UNICODE_STRING mName;
UNICODE_STRING mTypeName;
};
NTSTATUS WINAPI
NtQueryDirectoryObject(HANDLE aDirectoryHandle, PVOID aOutBuffer,
ULONG aBufferLength, BOOLEAN aReturnSingleEntry,
BOOLEAN aRestartScan, PULONG aContext,
PULONG aOutReturnLength);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // mozilla_NtUndoc_h

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

@ -46,6 +46,10 @@ SOURCES += [
'ServiceProvider.cpp',
]
OS_LIBS += [
'ntdll',
]
if CONFIG['MOZ_XUL']:
UNIFIED_SOURCES += [
'XULListboxAccessibleWrap.cpp',

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

@ -819,7 +819,16 @@ WindowHelper.prototype = {
});
}
Services.ww.registerNotification(windowObserver);
Services.ww.openWindow(null,
let browserWin = null;
if (Services.appinfo.OS !== "Darwin") {
// Retrieve the browser window so we can specify it as the parent
// of the dialog to simulate the way the user opens the dialog
// on Windows and Linux.
browserWin = Services.wm.getMostRecentWindow("navigator:browser");
}
Services.ww.openWindow(browserWin,
"chrome://browser/content/sanitize.xul",
"SanitizeDialog",
"chrome,titlebar,dialog,centerscreen,modal",

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

@ -2834,10 +2834,14 @@ nsDocShell::MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal)
return;
}
nsCOMPtr<nsIURI> uri;
MOZ_ALWAYS_SUCCEEDS(
NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank")));
// We're done if there is no parent controller or if this docshell
// is not permitted to control for some reason.
Maybe<ServiceWorkerDescriptor> controller(parentInner->GetController());
if (controller.isNothing() || !ServiceWorkerAllowedToControlWindow(nullptr)) {
if (controller.isNothing() || !ServiceWorkerAllowedToControlWindow(principal, uri)) {
return;
}
@ -11354,6 +11358,20 @@ nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
nsIPresShell::SCROLL_SMOOTH_AUTO);
}
if (NS_FAILED(rv)) {
char* str = ToNewCString(aNewHash);
if (!str) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsUnescape(str);
NS_ConvertUTF8toUTF16 utf16Str(str);
if (!utf16Str.IsEmpty()) {
rv = shell->GoToAnchor(utf16Str, scroll,
nsIPresShell::SCROLL_SMOOTH_AUTO);
}
free(str);
}
// Above will fail if the anchor name is not UTF-8. Need to
// convert from document charset to unicode.
if (NS_FAILED(rv)) {
@ -14098,51 +14116,26 @@ nsDocShell::CanSetOriginAttributes()
}
bool
nsDocShell::ServiceWorkerAllowedToControlWindow(nsIURI* aURI)
nsDocShell::ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
nsIURI* aURI)
{
// NOTE: Ideally this method would call one of the
// nsContentUtils::StorageAllowed*() methods to determine if the
// interception is allowed. Unfortunately we cannot safely do this
// before the first window loads in the child process because the
// permission manager might not have all its data yet. Therefore,
// we use this somewhat lame alternate implementation here. Once
// interception is moved to the parent process we should switch
// to calling nsContentUtils::StorageAllowed*(). See bug 1428130.
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(aURI);
if (UsePrivateBrowsing() || mSandboxFlags) {
return false;
}
uint32_t cookieBehavior = nsContentUtils::CookiesBehavior();
uint32_t lifetimePolicy = nsContentUtils::CookiesLifetimePolicy();
if (cookieBehavior == nsICookieService::BEHAVIOR_REJECT ||
lifetimePolicy == nsICookieService::ACCEPT_SESSION) {
return false;
}
if (!aURI || cookieBehavior == nsICookieService::BEHAVIOR_ACCEPT) {
return true;
}
nsCOMPtr<nsIDocShellTreeItem> parent;
GetSameTypeParent(getter_AddRefs(parent));
nsCOMPtr<nsPIDOMWindowOuter> parentWindow = parent ? parent->GetWindow()
: nullptr;
if (parentWindow) {
nsresult rv = NS_OK;
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
do_GetService(THIRDPARTYUTIL_CONTRACTID, &rv);
if (thirdPartyUtil) {
bool isThirdPartyURI = true;
rv = thirdPartyUtil->IsThirdPartyWindow(parentWindow, aURI,
&isThirdPartyURI);
if (NS_SUCCEEDED(rv) && isThirdPartyURI) {
return false;
}
}
}
nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
nsPIDOMWindowInner* parentInner =
parentOuter ? parentOuter->GetCurrentInnerWindow() : nullptr;
return true;
nsContentUtils::StorageAccess storage =
nsContentUtils::StorageAllowedForNewWindow(aPrincipal, aURI, parentInner);
return storage == nsContentUtils::StorageAccess::eAllow;
}
nsresult
@ -14369,9 +14362,12 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNonSubresourceReques
return NS_OK;
}
nsCOMPtr<nsIPrincipal> principal =
BasePrincipal::CreateCodebasePrincipal(aURI, mOriginAttributes);
// For navigations, first check to see if we are allowed to control a
// window with the given URL.
if (!ServiceWorkerAllowedToControlWindow(aURI)) {
if (!ServiceWorkerAllowedToControlWindow(principal, aURI)) {
return NS_OK;
}
@ -14382,8 +14378,6 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNonSubresourceReques
// We're allowed to control a window, so check with the ServiceWorkerManager
// for a matching service worker.
nsCOMPtr<nsIPrincipal> principal =
BasePrincipal::CreateCodebasePrincipal(aURI, mOriginAttributes);
*aShouldIntercept = swm->IsAvailable(principal, aURI);
return NS_OK;
}

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

@ -792,10 +792,8 @@ private: // member functions
// controlled. The caller must still consult either the parent controller
// or the ServiceWorkerManager to determine if a service worker should
// actually control the window.
//
// A nullptr URL is considered to be an about:blank window and will not
// trigger 3rd party iframe checks.
bool ServiceWorkerAllowedToControlWindow(nsIURI* aURI);
bool ServiceWorkerAllowedToControlWindow(nsIPrincipal* aPrincipal,
nsIURI* aURI);
// Return the ClientInfo for the initial about:blank window, if it exists
// or we have speculatively created a ClientSource in

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

@ -13,7 +13,6 @@
#include "nsMimeTypeArray.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/dom/BodyExtractor.h"
#include "mozilla/dom/DesktopNotification.h"
#include "mozilla/dom/FetchBinding.h"
#include "mozilla/dom/File.h"
#include "nsGeolocation.h"
@ -195,7 +194,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
@ -238,11 +236,6 @@ Navigator::Invalidate()
mGeolocation = nullptr;
}
if (mNotification) {
mNotification->Shutdown();
mNotification = nullptr;
}
if (mBatteryManager) {
mBatteryManager->Shutdown();
mBatteryManager = nullptr;
@ -1316,22 +1309,6 @@ Navigator::MozGetUserMediaDevices(const MediaStreamConstraints& aConstraints,
aInnerWindowID, aCallID);
}
DesktopNotificationCenter*
Navigator::GetMozNotification(ErrorResult& aRv)
{
if (mNotification) {
return mNotification;
}
if (!mWindow || !mWindow->GetDocShell()) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
mNotification = new DesktopNotificationCenter(mWindow);
return mNotification;
}
//*****************************************************************************
// Navigator::nsINavigatorBattery
//*****************************************************************************

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

@ -59,7 +59,6 @@ class BatteryManager;
class Promise;
class DesktopNotificationCenter;
class MozIdleObserver;
class Gamepad;
class GamepadServiceTest;
@ -178,7 +177,6 @@ public:
void AddIdleObserver(MozIdleObserver& aObserver, ErrorResult& aRv);
void RemoveIdleObserver(MozIdleObserver& aObserver, ErrorResult& aRv);
DesktopNotificationCenter* GetMozNotification(ErrorResult& aRv);
already_AddRefed<LegacyMozTCPSocket> MozTCPSocket();
network::Connection* GetConnection(ErrorResult& aRv);
MediaDevices* GetMediaDevices(ErrorResult& aRv);
@ -275,7 +273,6 @@ private:
RefPtr<nsPluginArray> mPlugins;
RefPtr<Permissions> mPermissions;
RefPtr<Geolocation> mGeolocation;
RefPtr<DesktopNotificationCenter> mNotification;
RefPtr<battery::BatteryManager> mBatteryManager;
RefPtr<Promise> mBatteryPromise;
RefPtr<network::Connection> mConnection;

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

@ -8896,7 +8896,7 @@ nsContentUtils::StorageAllowedForWindow(nsPIDOMWindowInner* aWindow)
{
if (nsIDocument* document = aWindow->GetExtantDoc()) {
nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
return InternalStorageAllowedForPrincipal(principal, aWindow);
return InternalStorageAllowedForPrincipal(principal, aWindow, nullptr);
}
return StorageAccess::eDeny;
@ -8910,17 +8910,30 @@ nsContentUtils::StorageAllowedForDocument(nsIDocument* aDoc)
if (nsPIDOMWindowInner* inner = aDoc->GetInnerWindow()) {
nsCOMPtr<nsIPrincipal> principal = aDoc->NodePrincipal();
return InternalStorageAllowedForPrincipal(principal, inner);
return InternalStorageAllowedForPrincipal(principal, inner, nullptr);
}
return StorageAccess::eDeny;
}
// static, public
nsContentUtils::StorageAccess
nsContentUtils::StorageAllowedForNewWindow(nsIPrincipal* aPrincipal,
nsIURI* aURI,
nsPIDOMWindowInner* aParent)
{
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(aURI);
// parent may be nullptr
return InternalStorageAllowedForPrincipal(aPrincipal, aParent, aURI);
}
// static, public
nsContentUtils::StorageAccess
nsContentUtils::StorageAllowedForPrincipal(nsIPrincipal* aPrincipal)
{
return InternalStorageAllowedForPrincipal(aPrincipal, nullptr);
return InternalStorageAllowedForPrincipal(aPrincipal, nullptr, nullptr);
}
// static, private
@ -8979,7 +8992,8 @@ nsContentUtils::GetCookieBehaviorForPrincipal(nsIPrincipal* aPrincipal,
// static, private
nsContentUtils::StorageAccess
nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
nsPIDOMWindowInner* aWindow)
nsPIDOMWindowInner* aWindow,
nsIURI* aURI)
{
MOZ_ASSERT(aPrincipal);
@ -9049,9 +9063,11 @@ nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
// affected, which is desireable due to the lack of automated testing for about:
// URIs with these preferences set, and the importance of the correct functioning
// of these URIs even with custom preferences.
nsCOMPtr<nsIURI> uri;
nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
if (NS_SUCCEEDED(rv) && uri) {
nsCOMPtr<nsIURI> uri = aURI;
if (!uri) {
Unused << aPrincipal->GetURI(getter_AddRefs(uri));
}
if (uri) {
bool isAbout = false;
MOZ_ALWAYS_SUCCEEDS(uri->SchemeIs("about", &isAbout));
if (isAbout) {
@ -9073,7 +9089,7 @@ nsContentUtils::InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
bool thirdPartyWindow = false;
if (NS_SUCCEEDED(thirdPartyUtil->IsThirdPartyWindow(
aWindow->GetOuterWindow(), nullptr, &thirdPartyWindow)) && thirdPartyWindow) {
aWindow->GetOuterWindow(), aURI, &thirdPartyWindow)) && thirdPartyWindow) {
// XXX For non-cookie forms of storage, we handle BEHAVIOR_LIMIT_FOREIGN by
// simply rejecting the request to use the storage. In the future, if we
// change the meaning of BEHAVIOR_LIMIT_FOREIGN to be one which makes sense

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

@ -2913,16 +2913,6 @@ public:
static bool IsNonSubresourceRequest(nsIChannel* aChannel);
static uint32_t CookiesBehavior()
{
return sCookiesBehavior;
}
static uint32_t CookiesLifetimePolicy()
{
return sCookiesLifetimePolicy;
}
// The order of these entries matters, as we use std::min for total ordering
// of permissions. Private Browsing is considered to be more limiting
// then session scoping
@ -2961,6 +2951,14 @@ public:
*/
static StorageAccess StorageAllowedForDocument(nsIDocument* aDoc);
/*
* Checks if storage should be allowed for a new window with the given
* principal, load URI, and parent.
*/
static StorageAccess StorageAllowedForNewWindow(nsIPrincipal* aPrincipal,
nsIURI* aURI,
nsPIDOMWindowInner* aParent);
/*
* Checks if storage for the given principal is permitted by the user's
* preferences. The caller is assumed to not be a third-party iframe.
@ -3338,13 +3336,15 @@ private:
* Checks if storage for a given principal is permitted by the user's
* preferences. If aWindow is non-null, its principal must be passed as
* aPrincipal, and the third-party iframe and sandboxing status of the window
* are also checked.
* are also checked. If aURI is non-null, then it is used as the comparison
* against aWindow to determine if this is a third-party load.
*
* Used in the implementation of StorageAllowedForWindow and
* StorageAllowedForPrincipal.
*/
static StorageAccess InternalStorageAllowedForPrincipal(nsIPrincipal* aPrincipal,
nsPIDOMWindowInner* aWindow);
nsPIDOMWindowInner* aWindow,
nsIURI* aURI);
static nsINode* GetCommonAncestorHelper(nsINode* aNode1, nsINode* aNode2);
static nsIContent* GetCommonFlattenedTreeAncestorHelper(nsIContent* aContent1,

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

@ -10035,10 +10035,7 @@ nsDocument::ScrollToRef()
rv = NS_ERROR_FAILURE;
}
// If UTF-8 URI failed then try to assume the string as a
// document's charset.
if (NS_FAILED(rv)) {
auto encoding = GetDocumentCharacterSet();
char* tmpstr = ToNewCString(mScrollToRef);
if (!tmpstr) {
return;
@ -10048,10 +10045,19 @@ nsDocument::ScrollToRef()
unescapedRef.Assign(tmpstr);
free(tmpstr);
rv = encoding->DecodeWithoutBOMHandling(unescapedRef, ref);
NS_ConvertUTF8toUTF16 utf16Str(unescapedRef);
if (!utf16Str.IsEmpty()) {
rv = shell->GoToAnchor(utf16Str, mChangeScrollPosWhenScrollingToRef);
}
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
rv = shell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
// If UTF-8 URI failed then try to assume the string as a
// document's charset.
if (NS_FAILED(rv)) {
const Encoding* encoding = GetDocumentCharacterSet();
rv = encoding->DecodeWithoutBOMHandling(unescapedRef, ref);
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
rv = shell->GoToAnchor(ref, mChangeScrollPosWhenScrollingToRef);
}
}
}
if (NS_SUCCEEDED(rv)) {

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

@ -14,7 +14,7 @@
#include "gfxPattern.h"
#include "gfxPrefs.h"
#include "gfxUtils.h"
#include "gfx/gl/MozFramebuffer.h"
#include "MozFramebuffer.h"
#include "GLBlitHelper.h"
#include "GLContext.h"
#include "GLContextProvider.h"

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

@ -6,7 +6,7 @@
#include "WebGLContext.h"
#include "GeckoProfiler.h"
#include "gfx/gl/MozFramebuffer.h"
#include "MozFramebuffer.h"
#include "GLContext.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/UniquePtrExtensions.h"

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

@ -1,332 +0,0 @@
/* -*- 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 "mozilla/dom/DesktopNotification.h"
#include "mozilla/dom/DesktopNotificationBinding.h"
#include "mozilla/dom/AppNotificationServiceOptionsBinding.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/EventStateManager.h"
#include "nsComponentManagerUtils.h"
#include "nsContentPermissionHelper.h"
#include "nsXULAppAPI.h"
#include "mozilla/dom/PBrowserChild.h"
#include "mozilla/Preferences.h"
#include "nsGlobalWindow.h"
#include "nsIScriptSecurityManager.h"
#include "nsServiceManagerUtils.h"
#include "PermissionMessageUtils.h"
#include "nsILoadContext.h"
namespace mozilla {
namespace dom {
/*
* Simple Request
*/
class DesktopNotificationRequest : public nsIContentPermissionRequest
, public Runnable
{
virtual ~DesktopNotificationRequest()
{
}
nsCOMPtr<nsIContentPermissionRequester> mRequester;
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSICONTENTPERMISSIONREQUEST
explicit DesktopNotificationRequest(DesktopNotification* aNotification)
: Runnable("dom::DesktopNotificationRequest")
, mDesktopNotification(aNotification)
{
mRequester = new nsContentPermissionRequester(mDesktopNotification->GetOwner());
}
NS_IMETHOD Run() override
{
nsCOMPtr<nsPIDOMWindowInner> window = mDesktopNotification->GetOwner();
nsContentPermissionUtils::AskPermission(this, window);
return NS_OK;
}
RefPtr<DesktopNotification> mDesktopNotification;
};
/* ------------------------------------------------------------------------ */
/* AlertServiceObserver */
/* ------------------------------------------------------------------------ */
NS_IMPL_ISUPPORTS(AlertServiceObserver, nsIObserver)
/* ------------------------------------------------------------------------ */
/* DesktopNotification */
/* ------------------------------------------------------------------------ */
uint32_t DesktopNotification::sCount = 0;
nsresult
DesktopNotification::PostDesktopNotification()
{
if (!mObserver) {
mObserver = new AlertServiceObserver(this);
}
nsCOMPtr<nsIAlertsService> alerts = do_GetService("@mozilla.org/alerts-service;1");
if (!alerts) {
return NS_ERROR_NOT_IMPLEMENTED;
}
// Generate a unique name (which will also be used as a cookie) because
// the nsIAlertsService will coalesce notifications with the same name.
// In the case of IPC, the parent process will use the cookie to map
// to nsIObservers, thus cookies must be unique to differentiate observers.
nsString uniqueName = NS_LITERAL_STRING("desktop-notification:");
uniqueName.AppendInt(sCount++);
nsCOMPtr<nsPIDOMWindowInner> owner = GetOwner();
if (!owner) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocument> doc = owner->GetDoc();
nsIPrincipal* principal = doc->NodePrincipal();
nsCOMPtr<nsILoadContext> loadContext = doc->GetLoadContext();
bool inPrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
nsCOMPtr<nsIAlertNotification> alert =
do_CreateInstance(ALERT_NOTIFICATION_CONTRACTID);
NS_ENSURE_TRUE(alert, NS_ERROR_FAILURE);
nsresult rv = alert->Init(uniqueName, mIconURL, mTitle,
mDescription,
true,
uniqueName,
NS_LITERAL_STRING("auto"),
EmptyString(),
EmptyString(),
principal,
inPrivateBrowsing,
false /* requireInteraction */);
NS_ENSURE_SUCCESS(rv, rv);
return alerts->ShowAlert(alert, mObserver);
}
DesktopNotification::DesktopNotification(const nsAString & title,
const nsAString & description,
const nsAString & iconURL,
nsPIDOMWindowInner* aWindow,
bool aIsHandlingUserInput,
nsIPrincipal* principal)
: DOMEventTargetHelper(aWindow)
, mTitle(title)
, mDescription(description)
, mIconURL(iconURL)
, mPrincipal(principal)
, mIsHandlingUserInput(aIsHandlingUserInput)
, mAllow(false)
, mShowHasBeenCalled(false)
{
if (Preferences::GetBool("notification.disabled", false)) {
return;
}
// If we are in testing mode (running mochitests, for example)
// and we are suppose to allow requests, then just post an allow event.
if (Preferences::GetBool("notification.prompt.testing", false) &&
Preferences::GetBool("notification.prompt.testing.allow", true)) {
mAllow = true;
}
}
void
DesktopNotification::Init()
{
RefPtr<DesktopNotificationRequest> request = new DesktopNotificationRequest(this);
NS_DispatchToMainThread(request);
}
DesktopNotification::~DesktopNotification()
{
if (mObserver) {
mObserver->Disconnect();
}
}
void
DesktopNotification::DispatchNotificationEvent(const nsString& aName)
{
if (NS_FAILED(CheckInnerWindowCorrectness())) {
return;
}
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
// it doesn't bubble, and it isn't cancelable
event->InitEvent(aName, false, false);
event->SetTrusted(true);
bool dummy;
DispatchEvent(event, &dummy);
}
nsresult
DesktopNotification::SetAllow(bool aAllow)
{
mAllow = aAllow;
// if we have called Show() already, lets go ahead and post a notification
if (mShowHasBeenCalled && aAllow) {
return PostDesktopNotification();
}
return NS_OK;
}
void
DesktopNotification::HandleAlertServiceNotification(const char *aTopic)
{
if (NS_FAILED(CheckInnerWindowCorrectness())) {
return;
}
if (!strcmp("alertclickcallback", aTopic)) {
DispatchNotificationEvent(NS_LITERAL_STRING("click"));
} else if (!strcmp("alertfinished", aTopic)) {
DispatchNotificationEvent(NS_LITERAL_STRING("close"));
}
}
void
DesktopNotification::Show(ErrorResult& aRv)
{
mShowHasBeenCalled = true;
if (!mAllow) {
return;
}
aRv = PostDesktopNotification();
}
JSObject*
DesktopNotification::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return DesktopNotificationBinding::Wrap(aCx, this, aGivenProto);
}
/* ------------------------------------------------------------------------ */
/* DesktopNotificationCenter */
/* ------------------------------------------------------------------------ */
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(DesktopNotificationCenter)
NS_IMPL_CYCLE_COLLECTING_ADDREF(DesktopNotificationCenter)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DesktopNotificationCenter)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DesktopNotificationCenter)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
already_AddRefed<DesktopNotification>
DesktopNotificationCenter::CreateNotification(const nsAString& aTitle,
const nsAString& aDescription,
const nsAString& aIconURL)
{
MOZ_ASSERT(mOwner);
RefPtr<DesktopNotification> notification =
new DesktopNotification(aTitle,
aDescription,
aIconURL,
mOwner,
EventStateManager::IsHandlingUserInput(),
mPrincipal);
notification->Init();
return notification.forget();
}
JSObject*
DesktopNotificationCenter::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return DesktopNotificationCenterBinding::Wrap(aCx, this, aGivenProto);
}
/* ------------------------------------------------------------------------ */
/* DesktopNotificationRequest */
/* ------------------------------------------------------------------------ */
NS_IMPL_ISUPPORTS_INHERITED(DesktopNotificationRequest, Runnable,
nsIContentPermissionRequest)
NS_IMETHODIMP
DesktopNotificationRequest::GetPrincipal(nsIPrincipal * *aRequestingPrincipal)
{
if (!mDesktopNotification) {
return NS_ERROR_NOT_INITIALIZED;
}
NS_IF_ADDREF(*aRequestingPrincipal = mDesktopNotification->mPrincipal);
return NS_OK;
}
NS_IMETHODIMP
DesktopNotificationRequest::GetWindow(mozIDOMWindow** aRequestingWindow)
{
if (!mDesktopNotification) {
return NS_ERROR_NOT_INITIALIZED;
}
NS_IF_ADDREF(*aRequestingWindow = mDesktopNotification->GetOwner());
return NS_OK;
}
NS_IMETHODIMP
DesktopNotificationRequest::GetElement(nsIDOMElement * *aElement)
{
NS_ENSURE_ARG_POINTER(aElement);
*aElement = nullptr;
return NS_OK;
}
NS_IMETHODIMP
DesktopNotificationRequest::GetIsHandlingUserInput(bool *aIsHandlingUserInput)
{
*aIsHandlingUserInput = mDesktopNotification->mIsHandlingUserInput;
return NS_OK;
}
NS_IMETHODIMP
DesktopNotificationRequest::Cancel()
{
nsresult rv = mDesktopNotification->SetAllow(false);
mDesktopNotification = nullptr;
return rv;
}
NS_IMETHODIMP
DesktopNotificationRequest::Allow(JS::HandleValue aChoices)
{
MOZ_ASSERT(aChoices.isUndefined());
nsresult rv = mDesktopNotification->SetAllow(true);
mDesktopNotification = nullptr;
return rv;
}
NS_IMETHODIMP
DesktopNotificationRequest::GetRequester(nsIContentPermissionRequester** aRequester)
{
NS_ENSURE_ARG_POINTER(aRequester);
nsCOMPtr<nsIContentPermissionRequester> requester = mRequester;
requester.forget(aRequester);
return NS_OK;
}
NS_IMETHODIMP
DesktopNotificationRequest::GetTypes(nsIArray** aTypes)
{
nsTArray<nsString> emptyOptions;
return nsContentPermissionUtils::CreatePermissionArray(NS_LITERAL_CSTRING("desktop-notification"),
NS_LITERAL_CSTRING("unused"),
emptyOptions,
aTypes);
}
} // namespace dom
} // namespace mozilla

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

@ -1,178 +0,0 @@
/* -*- 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/. */
#ifndef mozilla_dom_DesktopNotification_h
#define mozilla_dom_DesktopNotification_h
#include "nsIPrincipal.h"
#include "nsIAlertsService.h"
#include "nsIContentPermissionPrompt.h"
#include "nsIObserver.h"
#include "nsString.h"
#include "nsWeakPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDOMWindow.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIDOMEvent.h"
#include "mozilla/Attributes.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/ErrorResult.h"
#include "nsWrapperCache.h"
namespace mozilla {
namespace dom {
class AlertServiceObserver;
class DesktopNotification;
/*
* DesktopNotificationCenter
* Object hangs off of the navigator object and hands out DesktopNotification objects
*/
class DesktopNotificationCenter final : public nsISupports,
public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DesktopNotificationCenter)
explicit DesktopNotificationCenter(nsPIDOMWindowInner* aWindow)
{
MOZ_ASSERT(aWindow);
mOwner = aWindow;
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aWindow);
MOZ_ASSERT(sop);
mPrincipal = sop->GetPrincipal();
MOZ_ASSERT(mPrincipal);
}
void Shutdown() {
mOwner = nullptr;
}
nsPIDOMWindowInner* GetParentObject() const
{
return mOwner;
}
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
already_AddRefed<DesktopNotification>
CreateNotification(const nsAString& title,
const nsAString& description,
const nsAString& iconURL);
private:
virtual ~DesktopNotificationCenter()
{
}
nsCOMPtr<nsPIDOMWindowInner> mOwner;
nsCOMPtr<nsIPrincipal> mPrincipal;
};
class DesktopNotificationRequest;
class DesktopNotification final : public DOMEventTargetHelper
{
friend class DesktopNotificationRequest;
public:
DesktopNotification(const nsAString& aTitle,
const nsAString& aDescription,
const nsAString& aIconURL,
nsPIDOMWindowInner* aWindow,
bool aIsHandlingUserInput,
nsIPrincipal* principal);
virtual ~DesktopNotification();
void Init();
/*
* PostDesktopNotification
* Uses alert service to display a notification
*/
nsresult PostDesktopNotification();
nsresult SetAllow(bool aAllow);
/*
* Creates and dispatches a dom event of type aName
*/
void DispatchNotificationEvent(const nsString& aName);
void HandleAlertServiceNotification(const char *aTopic);
// WebIDL
nsPIDOMWindowInner* GetParentObject() const
{
return GetOwner();
}
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
void Show(ErrorResult& aRv);
IMPL_EVENT_HANDLER(click)
IMPL_EVENT_HANDLER(close)
protected:
nsString mTitle;
nsString mDescription;
nsString mIconURL;
RefPtr<AlertServiceObserver> mObserver;
nsCOMPtr<nsIPrincipal> mPrincipal;
bool mIsHandlingUserInput;
bool mAllow;
bool mShowHasBeenCalled;
static uint32_t sCount;
};
class AlertServiceObserver: public nsIObserver
{
public:
NS_DECL_ISUPPORTS
explicit AlertServiceObserver(DesktopNotification* notification)
: mNotification(notification) {}
void Disconnect() { mNotification = nullptr; }
NS_IMETHOD
Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData) override
{
// forward to parent
if (mNotification) {
mNotification->HandleAlertServiceNotification(aTopic);
}
return NS_OK;
};
private:
virtual ~AlertServiceObserver() {}
DesktopNotification* mNotification;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_DesktopNotification_h */

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

@ -17,13 +17,11 @@ EXTRA_JS_MODULES += [
]
EXPORTS.mozilla.dom += [
'DesktopNotification.h',
'Notification.h',
'NotificationEvent.h',
]
UNIFIED_SOURCES += [
'DesktopNotification.cpp',
'Notification.cpp',
'NotificationEvent.cpp',
]
@ -40,6 +38,8 @@ LOCAL_INCLUDES += [
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
MOCHITEST_MANIFESTS += ['test/mochitest/mochitest.ini']
MOCHITEST_CHROME_MANIFESTS += ['test/chrome/chrome.ini']
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
CXXFLAGS += ['-Wno-error=shadow']

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

@ -0,0 +1 @@
[test_notification_system_principal.xul]

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

@ -1,6 +1,7 @@
[DEFAULT]
support-files =
create_notification.html
MockServices.js
NotificationTest.js
@ -8,3 +9,4 @@ support-files =
[test_notification_storage.html]
[test_bug931307.html]
skip-if = (os == 'android') # Bug 1258975 on android.
[test_notification_tag.html]

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

@ -91,12 +91,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=782211
// Load two frames with the same origin that create notification with the same tag.
// Both pages should generate notifications with the same name, and thus the second
// notification should replace the first.
frames["sameDomain"].location.href = "http://test1.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html";
frames["anotherSameDomain"].location.href = "http://test1.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html";
frames["sameDomain"].location.href = "http://test1.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
frames["anotherSameDomain"].location.href = "http://test1.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
// Load a frame with a different origin that creates a notification with the same tag.
// The notification name should be different and thus no notifications should be replaced.
frames["crossDomain"].location.href = "http://test2.example.org:80/tests/dom/tests/mochitest/notification/create_notification.html";
frames["crossDomain"].location.href = "http://test2.example.org:80/tests/dom/notification/test/mochitest/create_notification.html";
}
SpecialPowers.pushPrefEnv({'set': [["notification.prompt.testing", true],

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

@ -2385,12 +2385,12 @@ nsSVGElement::DidAnimateTransformList(int32_t aModType)
transformAttr,
aModType);
// When script changes the 'transform' attribute, Element::SetAttrAndNotify
// will call nsNodeUtills::AttributeChanged, under which
// will call nsNodeUtils::AttributeChanged, under which
// SVGTransformableElement::GetAttributeChangeHint will be called and an
// appropriate change event posted to update our frame's overflow rects.
// The SetAttrAndNotify doesn't happen for transform changes caused by
// 'animateTransform' though (and sending out the mutation events that
// nsNodeUtills::AttributeChanged dispatches would be inappropriate
// nsNodeUtils::AttributeChanged dispatches would be inappropriate
// anyway), so we need to post the change event ourself.
nsChangeHint changeHint = GetAttributeChangeHint(transformAttr, aModType);
if (changeHint) {

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

@ -270,10 +270,6 @@ var interfaceNamesInGlobalScope =
"DataTransferItemList",
// IMPORTANT: Do not change this list without review from a DOM peer!
"DelayNode",
// IMPORTANT: Do not change this list without review from a DOM peer!
"DesktopNotification",
// IMPORTANT: Do not change this list without review from a DOM peer!
"DesktopNotificationCenter",
// IMPORTANT: Do not change this list without review from a DOM peer!
"DeviceLightEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!

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

@ -1,6 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.

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

@ -1,70 +0,0 @@
const MOCK_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components).ID("{48068bc2-40ab-4904-8afd-4cdfb3a385f3}");
const ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/alerts-service;1";
const MOCK_SYSTEM_ALERTS_CID = SpecialPowers.wrap(SpecialPowers.Components).ID("{e86d888c-e41b-4b78-9104-2f2742a532de}");
const SYSTEM_ALERTS_SERVICE_CONTRACT_ID = "@mozilla.org/system-alerts-service;1";
var registrar = SpecialPowers.wrap(SpecialPowers.Components).manager.
QueryInterface(SpecialPowers.Ci.nsIComponentRegistrar);
var mockAlertsService = {
showAlert: function(alert, alertListener) {
// probably should do this async....
SpecialPowers.wrap(alertListener).observe(null, "alertshow", alert.cookie);
if (SpecialPowers.getBoolPref("notification.prompt.testing.click_on_notification") == true) {
SpecialPowers.wrap(alertListener).observe(null, "alertclickcallback", alert.cookie);
}
SpecialPowers.wrap(alertListener).observe(null, "alertfinished", alert.cookie);
},
showAlertNotification: function(imageUrl, title, text, textClickable,
cookie, alertListener, name, bidi,
lang, data) {
return this.showAlert({
cookie: cookie
}, alertListener);
},
QueryInterface: function(aIID) {
if (SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsISupports) ||
SpecialPowers.wrap(aIID).equals(SpecialPowers.Ci.nsIAlertsService)) {
return this;
}
throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE;
},
createInstance: function(aOuter, aIID) {
if (aOuter != null) {
throw SpecialPowers.Components.results.NS_ERROR_NO_AGGREGATION;
}
return this.QueryInterface(aIID);
}
};
mockAlertsService = SpecialPowers.wrapCallbackObject(mockAlertsService);
function setup_notifications(allowPrompt, forceClick, callback) {
SpecialPowers.pushPrefEnv({'set': [["notification.prompt.testing", true],
["notification.prompt.testing.allow", allowPrompt],
["notification.prompt.testing.click_on_notification", forceClick]]},
callback);
registrar.registerFactory(MOCK_SYSTEM_ALERTS_CID, "system alerts service",
SYSTEM_ALERTS_SERVICE_CONTRACT_ID,
mockAlertsService);
registrar.registerFactory(MOCK_ALERTS_CID, "alerts service",
ALERTS_SERVICE_CONTRACT_ID,
mockAlertsService);
}
function reset_notifications() {
registrar.unregisterFactory(MOCK_SYSTEM_ALERTS_CID, mockAlertsService);
registrar.unregisterFactory(MOCK_ALERTS_CID, mockAlertsService);
}
function is_feature_enabled() {
return navigator.mozNotification && SpecialPowers.getBoolPref("notification.feature.enabled");
}

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

@ -1,50 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=573588
-->
<head>
<title>Basic functional test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="notification_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=573588">Basic property tests</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script type="text/javascript">
if (is_feature_enabled()) {
SimpleTest.waitForExplicitFinish();
function showNotifications() {
ok(navigator.mozNotification, "test for notification.");
var notification = navigator.mozNotification.createNotification("test", "test");
ok(notification, "test to ensure we can create a notification");
notification.onclose = function() {
ok(true, "notification was display and is now closing");
reset_notifications();
SimpleTest.finish();
};
notification.onclick = function() {
ok(false, "Click should not have been called.");
reset_notifications();
SimpleTest.finish();
};
notification.show();
}
setup_notifications(true, false, showNotifications);
} else {
ok(true, "Desktop notifications not enabled.");
}
</script>
</body>
</html>

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

@ -1,53 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=573588
-->
<head>
<title>Basic functional test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="notification_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=573588">Basic property tests</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script type="text/javascript">
if (is_feature_enabled()) {
SimpleTest.waitForExplicitFinish();
var click_was_called = false;
function showNotifications() {
ok(navigator.mozNotification, "test for notification.");
var notification = navigator.mozNotification.createNotification("test", "test");
ok(notification, "test to ensure we can create a notification");
notification.onclose = function() {
ok(true, "notification was display and is now closing");
ok(click_was_called, "was notification clicked?");
reset_notifications();
SimpleTest.finish();
};
notification.onclick = function() {
ok(true, "Click was called. Good.");
click_was_called = true;
};
notification.show();
}
setup_notifications(true, true, showNotifications);
} else {
ok(true, "Desktop notifications not enabled.");
}
</script>
</body>
</html>

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

@ -1,34 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=605309
-->
<head>
<title>Test for leak when window closes</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="notification_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script>
if (is_feature_enabled()) {
SimpleTest.waitForExplicitFinish();
function boom()
{
document.documentElement.focus();
var x = navigator.mozNotification;
document.documentElement.addEventListener('', function(){x});
ok(true, "load callback called");
SimpleTest.finish();
}
window.addEventListener("load", boom);
} else {
ok(true, "Desktop notifications not enabled.");
}
</script>
</head>
<body>
<p> I like to write tests </p>
</body>
</html>

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

@ -96,7 +96,7 @@ AssembleClientData(const nsAString& aOrigin, const nsAString& aTyp,
static void
RegisteredKeysToScopedCredentialList(const nsAString& aAppId,
const nsTArray<RegisteredKey>& aKeys,
nsTArray<WebAuthnScopedCredentialDescriptor>& aList)
nsTArray<WebAuthnScopedCredential>& aList)
{
for (const RegisteredKey& key : aKeys) {
// Check for required attributes
@ -116,7 +116,7 @@ RegisteredKeysToScopedCredentialList(const nsAString& aAppId,
continue;
}
WebAuthnScopedCredentialDescriptor c;
WebAuthnScopedCredential c;
c.id() = keyHandle;
aList.AppendElement(c);
}
@ -392,7 +392,7 @@ U2F::Register(const nsAString& aAppId,
}
// Build the exclusion list, if any
nsTArray<WebAuthnScopedCredentialDescriptor> excludeList;
nsTArray<WebAuthnScopedCredential> excludeList;
RegisteredKeysToScopedCredentialList(adjustedAppId, aRegisteredKeys,
excludeList);
@ -540,7 +540,7 @@ U2F::Sign(const nsAString& aAppId,
}
// Build the key list, if any
nsTArray<WebAuthnScopedCredentialDescriptor> permittedList;
nsTArray<WebAuthnScopedCredential> permittedList;
RegisteredKeysToScopedCredentialList(adjustedAppId, aRegisteredKeys,
permittedList);
@ -573,6 +573,7 @@ U2F::Sign(const nsAString& aAppId,
clientDataHash,
adjustedTimeoutMillis,
permittedList,
false, /* requireUserVerification */
extensions);
MOZ_ASSERT(mTransaction.isNothing());

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

@ -20,13 +20,14 @@ namespace mozilla {
namespace dom {
struct WebAuthnAuthenticatorSelection {
bool requireResidentKey;
bool requireUserVerification;
bool requirePlatformAttachment;
bool requireResidentKey;
bool requireUserVerification;
bool requirePlatformAttachment;
};
struct WebAuthnScopedCredentialDescriptor {
struct WebAuthnScopedCredential {
uint8_t[] id;
uint8_t transports;
};
struct WebAuthnExtension {
@ -37,7 +38,7 @@ struct WebAuthnMakeCredentialInfo {
uint8_t[] RpIdHash;
uint8_t[] ClientDataHash;
uint32_t TimeoutMS;
WebAuthnScopedCredentialDescriptor[] ExcludeList;
WebAuthnScopedCredential[] ExcludeList;
WebAuthnExtension[] Extensions;
WebAuthnAuthenticatorSelection AuthenticatorSelection;
};
@ -46,7 +47,8 @@ struct WebAuthnGetAssertionInfo {
uint8_t[] RpIdHash;
uint8_t[] ClientDataHash;
uint32_t TimeoutMS;
WebAuthnScopedCredentialDescriptor[] AllowList;
WebAuthnScopedCredential[] AllowList;
bool RequireUserVerification;
WebAuthnExtension[] Extensions;
};

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

@ -100,7 +100,7 @@ U2FHIDTokenManager::~U2FHIDTokenManager()
// * attestation signature
//
RefPtr<U2FRegisterPromise>
U2FHIDTokenManager::Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
U2FHIDTokenManager::Register(const nsTArray<WebAuthnScopedCredential>& aCredentials,
const WebAuthnAuthenticatorSelection &aAuthenticatorSelection,
const nsTArray<uint8_t>& aApplication,
const nsTArray<uint8_t>& aChallenge,
@ -130,7 +130,7 @@ U2FHIDTokenManager::Register(const nsTArray<WebAuthnScopedCredentialDescriptor>&
aChallenge.Length(),
aApplication.Elements(),
aApplication.Length(),
U2FKeyHandles(aDescriptors).Get());
U2FKeyHandles(aCredentials).Get());
if (mTransactionId == 0) {
return U2FRegisterPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
@ -156,22 +156,31 @@ U2FHIDTokenManager::Register(const nsTArray<WebAuthnScopedCredentialDescriptor>&
// * Signature
//
RefPtr<U2FSignPromise>
U2FHIDTokenManager::Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
U2FHIDTokenManager::Sign(const nsTArray<WebAuthnScopedCredential>& aCredentials,
const nsTArray<uint8_t>& aApplication,
const nsTArray<uint8_t>& aChallenge,
bool aRequireUserVerification,
uint32_t aTimeoutMS)
{
MOZ_ASSERT(NS_GetCurrentThread() == gPBackgroundThread);
uint64_t signFlags = 0;
// Set flags for credential requests.
if (aRequireUserVerification) {
signFlags |= U2F_FLAG_REQUIRE_USER_VERIFICATION;
}
ClearPromises();
mTransactionId = rust_u2f_mgr_sign(mU2FManager,
signFlags,
(uint64_t)aTimeoutMS,
u2f_sign_callback,
aChallenge.Elements(),
aChallenge.Length(),
aApplication.Elements(),
aApplication.Length(),
U2FKeyHandles(aDescriptors).Get());
U2FKeyHandles(aCredentials).Get());
if (mTransactionId == 0) {
return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
}

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

@ -20,12 +20,15 @@ namespace dom {
class U2FKeyHandles {
public:
explicit U2FKeyHandles(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors)
explicit U2FKeyHandles(const nsTArray<WebAuthnScopedCredential>& aCredentials)
{
mKeyHandles = rust_u2f_khs_new();
for (auto desc: aDescriptors) {
rust_u2f_khs_add(mKeyHandles, desc.id().Elements(), desc.id().Length());
for (auto cred: aCredentials) {
rust_u2f_khs_add(mKeyHandles,
cred.id().Elements(),
cred.id().Length(),
cred.transports());
}
}
@ -91,16 +94,17 @@ public:
explicit U2FHIDTokenManager();
virtual RefPtr<U2FRegisterPromise>
Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
Register(const nsTArray<WebAuthnScopedCredential>& aCredentials,
const WebAuthnAuthenticatorSelection &aAuthenticatorSelection,
const nsTArray<uint8_t>& aApplication,
const nsTArray<uint8_t>& aChallenge,
uint32_t aTimeoutMS) override;
virtual RefPtr<U2FSignPromise>
Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
Sign(const nsTArray<WebAuthnScopedCredential>& aCredentials,
const nsTArray<uint8_t>& aApplication,
const nsTArray<uint8_t>& aChallenge,
bool aRequireUserVerification,
uint32_t aTimeoutMS) override;
void Cancel() override;

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

@ -625,7 +625,7 @@ U2FSoftTokenManager::IsRegistered(const nsTArray<uint8_t>& aKeyHandle,
// * attestation signature
//
RefPtr<U2FRegisterPromise>
U2FSoftTokenManager::Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
U2FSoftTokenManager::Register(const nsTArray<WebAuthnScopedCredential>& aCredentials,
const WebAuthnAuthenticatorSelection &aAuthenticatorSelection,
const nsTArray<uint8_t>& aApplication,
const nsTArray<uint8_t>& aChallenge,
@ -652,9 +652,9 @@ U2FSoftTokenManager::Register(const nsTArray<WebAuthnScopedCredentialDescriptor>
}
// Optional exclusion list.
for (auto desc: aDescriptors) {
for (auto cred: aCredentials) {
bool isRegistered = false;
nsresult rv = IsRegistered(desc.id(), aApplication, isRegistered);
nsresult rv = IsRegistered(cred.id(), aApplication, isRegistered);
if (NS_FAILED(rv)) {
return U2FRegisterPromise::CreateAndReject(rv, __func__);
}
@ -758,9 +758,10 @@ U2FSoftTokenManager::Register(const nsTArray<WebAuthnScopedCredentialDescriptor>
// * Signature
//
RefPtr<U2FSignPromise>
U2FSoftTokenManager::Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
U2FSoftTokenManager::Sign(const nsTArray<WebAuthnScopedCredential>& aCredentials,
const nsTArray<uint8_t>& aApplication,
const nsTArray<uint8_t>& aChallenge,
bool aRequireUserVerification,
uint32_t aTimeoutMS)
{
nsNSSShutDownPreventionLock locker;
@ -768,12 +769,17 @@ U2FSoftTokenManager::Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aD
return U2FSignPromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE, __func__);
}
// The U2F softtoken doesn't support user verification.
if (aRequireUserVerification) {
return U2FSignPromise::CreateAndReject(NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
}
nsTArray<uint8_t> keyHandle;
for (auto desc: aDescriptors) {
for (auto cred: aCredentials) {
bool isRegistered = false;
nsresult rv = IsRegistered(desc.id(), aApplication, isRegistered);
nsresult rv = IsRegistered(cred.id(), aApplication, isRegistered);
if (NS_SUCCEEDED(rv) && isRegistered) {
keyHandle.Assign(desc.id());
keyHandle.Assign(cred.id());
break;
}
}

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

@ -26,16 +26,17 @@ public:
explicit U2FSoftTokenManager(uint32_t aCounter);
virtual RefPtr<U2FRegisterPromise>
Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
Register(const nsTArray<WebAuthnScopedCredential>& aCredentials,
const WebAuthnAuthenticatorSelection &aAuthenticatorSelection,
const nsTArray<uint8_t>& aApplication,
const nsTArray<uint8_t>& aChallenge,
uint32_t aTimeoutMS) override;
virtual RefPtr<U2FSignPromise>
Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
Sign(const nsTArray<WebAuthnScopedCredential>& aCredentials,
const nsTArray<uint8_t>& aApplication,
const nsTArray<uint8_t>& aChallenge,
bool aRequireUserVerification,
uint32_t aTimeoutMS) override;
virtual void Cancel() override;

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

@ -322,6 +322,7 @@ U2FTokenManager::Sign(PWebAuthnTransactionParent* aTransactionParent,
mTokenManagerImpl->Sign(aTransactionInfo.AllowList(),
aTransactionInfo.RpIdHash(),
aTransactionInfo.ClientDataHash(),
aTransactionInfo.RequireUserVerification(),
aTransactionInfo.TimeoutMS())
->Then(GetCurrentThreadSerialEventTarget(), __func__,
[tid, startTime](U2FSignResult&& aResult) {

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

@ -63,16 +63,17 @@ public:
U2FTokenTransport() {}
virtual RefPtr<U2FRegisterPromise>
Register(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
Register(const nsTArray<WebAuthnScopedCredential>& aCredentials,
const WebAuthnAuthenticatorSelection &aAuthenticatorSelection,
const nsTArray<uint8_t>& aApplication,
const nsTArray<uint8_t>& aChallenge,
uint32_t aTimeoutMS) = 0;
virtual RefPtr<U2FSignPromise>
Sign(const nsTArray<WebAuthnScopedCredentialDescriptor>& aDescriptors,
Sign(const nsTArray<WebAuthnScopedCredential>& aCredentials,
const nsTArray<uint8_t>& aApplication,
const nsTArray<uint8_t>& aChallenge,
bool aRequireUserVerification,
uint32_t aTimeoutMS) = 0;
virtual void Cancel() = 0;

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

@ -361,9 +361,9 @@ WebAuthnManager::MakeCredential(const MakePublicKeyCredentialOptions& aOptions,
return promise.forget();
}
nsTArray<WebAuthnScopedCredentialDescriptor> excludeList;
nsTArray<WebAuthnScopedCredential> excludeList;
for (const auto& s: aOptions.mExcludeCredentials) {
WebAuthnScopedCredentialDescriptor c;
WebAuthnScopedCredential c;
CryptoBuffer cb;
cb.Assign(s.mId);
c.id() = cb;
@ -533,13 +533,33 @@ WebAuthnManager::GetAssertion(const PublicKeyCredentialRequestOptions& aOptions,
return promise.forget();
}
nsTArray<WebAuthnScopedCredentialDescriptor> allowList;
nsTArray<WebAuthnScopedCredential> allowList;
for (const auto& s: aOptions.mAllowCredentials) {
WebAuthnScopedCredentialDescriptor c;
CryptoBuffer cb;
cb.Assign(s.mId);
c.id() = cb;
allowList.AppendElement(c);
if (s.mType == PublicKeyCredentialType::Public_key) {
WebAuthnScopedCredential c;
CryptoBuffer cb;
cb.Assign(s.mId);
c.id() = cb;
// Serialize transports.
if (s.mTransports.WasPassed()) {
uint8_t transports = 0;
for (const auto& t: s.mTransports.Value()) {
if (t == AuthenticatorTransport::Usb) {
transports |= U2F_AUTHENTICATOR_TRANSPORT_USB;
}
if (t == AuthenticatorTransport::Nfc) {
transports |= U2F_AUTHENTICATOR_TRANSPORT_NFC;
}
if (t == AuthenticatorTransport::Ble) {
transports |= U2F_AUTHENTICATOR_TRANSPORT_BLE;
}
}
c.transports() = transports;
}
allowList.AppendElement(c);
}
}
if (!MaybeCreateBackgroundActor()) {
@ -547,6 +567,10 @@ WebAuthnManager::GetAssertion(const PublicKeyCredentialRequestOptions& aOptions,
return promise.forget();
}
// Does the RP require user verification?
bool requireUserVerification =
aOptions.mUserVerification == UserVerificationRequirement::Required;
// TODO: Add extension list building
// If extensions was specified, process any extensions supported by this
// client platform, to produce the extension data that needs to be sent to the
@ -559,6 +583,7 @@ WebAuthnManager::GetAssertion(const PublicKeyCredentialRequestOptions& aOptions,
clientDataHash,
adjustedTimeout,
allowList,
requireUserVerification,
extensions);
ListenForVisibilityEvents();

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

@ -8,6 +8,7 @@ scheme = https
[test_webauthn_abort_signal.html]
[test_webauthn_authenticator_selection.html]
[test_webauthn_authenticator_transports.html]
[test_webauthn_loopback.html]
[test_webauthn_no_token.html]
[test_webauthn_make_credential.html]

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

@ -11,6 +11,7 @@
<h1>W3C Web Authentication - Authenticator Selection Criteria</h1>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1406462">Mozilla Bug 1406462</a>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1406467">Mozilla Bug 1406467</a>
<script class="testbody" type="text/javascript">
"use strict";
@ -27,6 +28,10 @@
ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError, got " + aResult);
}
// We store the credential of the first successful make credential
// operation so we can use it for get assertion tests later.
let gCredential;
add_task(() => {
// Enable the softtoken.
return SpecialPowers.pushPrefEnv({"set": [
@ -50,10 +55,34 @@
return navigator.credentials.create({publicKey});
}
// Test success cases.
// Start a new GetAssertion() request.
function requestGetAssertion(userVerification) {
let newCredential = {
type: "public-key",
id: gCredential,
transports: ["usb"],
};
let publicKey = {
challenge: crypto.getRandomValues(new Uint8Array(16)),
timeout: 5000, // the minimum timeout is actually 15 seconds
rpId: document.domain,
allowCredentials: [newCredential]
};
if (userVerification) {
publicKey.userVerification = userVerification;
}
return navigator.credentials.get({publicKey});
}
// Test success cases for make credential.
add_task(async () => {
// No selection criteria.
await requestMakeCredential({})
// Save the credential so we can use it for sign success tests.
.then(res => gCredential = res.rawId)
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
@ -78,7 +107,25 @@
.catch(arrivingHereIsBad);
});
// Test the failure cases.
// Test success cases for get assertion.
add_task(async () => {
// No selection criteria.
await requestGetAssertion()
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
// Prefer user verification.
await requestGetAssertion("preferred")
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
// Discourage user verification.
await requestGetAssertion("discouraged")
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
});
// Test failure cases for make credential.
add_task(async () => {
// Request a platform authenticator.
await requestMakeCredential({authenticatorAttachment: "platform"})
@ -95,6 +142,14 @@
.then(arrivingHereIsBad)
.catch(expectNotAllowedError);
});
// Test failure cases for get assertion.
add_task(async () => {
// Require user verification.
await requestGetAssertion("required")
.then(arrivingHereIsBad)
.catch(expectNotAllowedError);
});
</script>
</body>

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

@ -0,0 +1,150 @@
<!DOCTYPE html>
<meta charset=utf-8>
<head>
<title>W3C Web Authentication - Authenticator Transports</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<script type="text/javascript" src="u2futil.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<h1>W3C Web Authentication - Authenticator Transports</h1>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1406467">Mozilla Bug 1406467</a>
<script class="testbody" type="text/javascript">
"use strict";
function arrivingHereIsGood(aResult) {
ok(true, "Good result! Received a: " + aResult);
}
function arrivingHereIsBad(aResult) {
ok(false, "Bad result! Received a: " + aResult);
}
function expectNotAllowedError(aResult) {
ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError, got " + aResult);
}
// Store the credential of the first successful make credential
// operation so we can use it to get assertions later.
let gCredential;
add_task(() => {
// Enable the softtoken.
return SpecialPowers.pushPrefEnv({"set": [
["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
["security.webauth.webauthn_enable_usbtoken", false],
]});
});
// Start a new MakeCredential() request.
function requestMakeCredential(excludeCredentials) {
let publicKey = {
rp: {id: document.domain, name: "none", icon: "none"},
user: {id: new Uint8Array(), name: "none", icon: "none", displayName: "none"},
challenge: crypto.getRandomValues(new Uint8Array(16)),
timeout: 5000, // the minimum timeout is actually 15 seconds
pubKeyCredParams: [{type: "public-key", alg: cose_alg_ECDSA_w_SHA256}],
excludeCredentials
};
return navigator.credentials.create({publicKey});
}
// Start a new GetAssertion() request.
function requestGetAssertion(allowCredentials) {
let publicKey = {
challenge: crypto.getRandomValues(new Uint8Array(16)),
timeout: 5000, // the minimum timeout is actually 15 seconds
rpId: document.domain,
allowCredentials
};
return navigator.credentials.get({publicKey});
}
// Test make credential behavior.
add_task(async () => {
// Make a credential.
await requestMakeCredential([])
// Save the credential for later.
.then(res => gCredential = res.rawId)
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
// Pass a random credential to exclude.
await requestMakeCredential([{
type: "public-key",
id: crypto.getRandomValues(new Uint8Array(16)),
transports: ["usb"],
}]).then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
// Pass gCredential with transport=usb.
await requestMakeCredential([{
type: "public-key",
id: gCredential,
transports: ["usb"],
}]).then(arrivingHereIsBad)
.catch(expectNotAllowedError);
// Pass gCredential with transport=nfc.
// The softoken pretends to support all transports.
await requestMakeCredential([{
type: "public-key",
id: gCredential,
transports: ["nfc"],
}]).then(arrivingHereIsBad)
.catch(expectNotAllowedError);
// Pass gCredential with an empty transports list.
await requestMakeCredential([{
type: "public-key",
id: gCredential,
transports: [],
}]).then(arrivingHereIsBad)
.catch(expectNotAllowedError);
});
// Test get assertion behavior.
add_task(async () => {
// Request an assertion for gCredential.
await requestGetAssertion([{
type: "public-key",
id: gCredential,
transports: ["usb"],
}]).then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
// Request an assertion for a random credential.
await requestGetAssertion([{
type: "public-key",
id: crypto.getRandomValues(new Uint8Array(16)),
transports: ["usb"],
}]).then(arrivingHereIsBad)
.catch(expectNotAllowedError);
// Request an assertion for gCredential with transport=nfc.
// The softoken pretends to support all transports.
await requestGetAssertion([{
type: "public-key",
id: gCredential,
transports: ["nfc"],
}]).then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
// Request an assertion for gCredential with an empty transports list.
await requestGetAssertion([{
type: "public-key",
id: gCredential,
transports: [],
}]).then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
});
</script>
</body>
</html>

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

@ -9,7 +9,7 @@ use crypto::digest::Digest;
use crypto::sha2::Sha256;
use std::io;
use std::sync::mpsc::channel;
use u2fhid::{RegisterFlags, U2FManager};
use u2fhid::{AuthenticatorTransports, KeyHandle, RegisterFlags, SignFlags, U2FManager};
extern crate log;
extern crate env_logger;
@ -66,11 +66,17 @@ fn main() {
let register_data = rx.recv().unwrap();
println!("Register result: {}", base64::encode(&register_data));
println!("Asking a security key to sign now, with the data from the register...");
let key_handle = u2f_get_key_handle_from_register_response(&register_data).unwrap();
let credential = u2f_get_key_handle_from_register_response(&register_data).unwrap();
let key_handle = KeyHandle {
credential,
transports: AuthenticatorTransports::empty(),
};
let flags = SignFlags::empty();
let (tx, rx) = channel();
manager
.sign(
flags,
15_000,
chall_bytes,
app_bytes,

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

@ -9,7 +9,7 @@ use std::{ptr, slice};
use U2FManager;
type U2FKeyHandles = Vec<Vec<u8>>;
type U2FKeyHandles = Vec<::KeyHandle>;
type U2FResult = HashMap<u8, Vec<u8>>;
type U2FCallback = extern "C" fn(u64, *mut U2FResult);
@ -52,8 +52,12 @@ pub unsafe extern "C" fn rust_u2f_khs_add(
khs: *mut U2FKeyHandles,
key_handle_ptr: *const u8,
key_handle_len: usize,
transports: u8,
) {
(*khs).push(from_raw(key_handle_ptr, key_handle_len));
(*khs).push(::KeyHandle {
credential: from_raw(key_handle_ptr, key_handle_len),
transports: ::AuthenticatorTransports::from_bits_truncate(transports),
});
}
#[no_mangle]
@ -156,6 +160,7 @@ pub unsafe extern "C" fn rust_u2f_mgr_register(
#[no_mangle]
pub unsafe extern "C" fn rust_u2f_mgr_sign(
mgr: *mut U2FManager,
flags: u64,
timeout: u64,
callback: U2FCallback,
challenge_ptr: *const u8,
@ -178,21 +183,29 @@ pub unsafe extern "C" fn rust_u2f_mgr_sign(
return 0;
}
let flags = ::SignFlags::from_bits_truncate(flags);
let challenge = from_raw(challenge_ptr, challenge_len);
let application = from_raw(application_ptr, application_len);
let key_handles = (*khs).clone();
let tid = new_tid();
let res = (*mgr).sign(timeout, challenge, application, key_handles, move |rv| {
if let Ok((key_handle, signature)) = rv {
let mut result = U2FResult::new();
result.insert(RESBUF_ID_KEYHANDLE, key_handle);
result.insert(RESBUF_ID_SIGNATURE, signature);
callback(tid, Box::into_raw(Box::new(result)));
} else {
callback(tid, ptr::null_mut());
};
});
let res = (*mgr).sign(
flags,
timeout,
challenge,
application,
key_handles,
move |rv| {
if let Ok((key_handle, signature)) = rv {
let mut result = U2FResult::new();
result.insert(RESBUF_ID_KEYHANDLE, key_handle);
result.insert(RESBUF_ID_SIGNATURE, signature);
callback(tid, Box::into_raw(Box::new(result)));
} else {
callback(tid, ptr::null_mut());
};
},
);
if res.is_ok() { tid } else { 0 }
}

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

@ -56,6 +56,24 @@ bitflags! {
const REQUIRE_PLATFORM_ATTACHMENT = 4;
}
}
bitflags! {
pub struct SignFlags: u64 {
const REQUIRE_USER_VERIFICATION = 1;
}
}
bitflags! {
pub struct AuthenticatorTransports: u8 {
const USB = 1;
const NFC = 2;
const BLE = 4;
}
}
#[derive(Clone)]
pub struct KeyHandle {
pub credential: Vec<u8>,
pub transports: AuthenticatorTransports,
}
#[cfg(fuzzing)]
pub use u2fprotocol::*;

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

@ -17,14 +17,15 @@ enum QueueAction {
timeout: u64,
challenge: Vec<u8>,
application: Vec<u8>,
key_handles: Vec<Vec<u8>>,
key_handles: Vec<::KeyHandle>,
callback: OnceCallback<Vec<u8>>,
},
Sign {
flags: ::SignFlags,
timeout: u64,
challenge: Vec<u8>,
application: Vec<u8>,
key_handles: Vec<Vec<u8>>,
key_handles: Vec<::KeyHandle>,
callback: OnceCallback<(Vec<u8>, Vec<u8>)>,
},
Cancel,
@ -64,6 +65,7 @@ impl U2FManager {
);
}
Ok(QueueAction::Sign {
flags,
timeout,
challenge,
application,
@ -71,7 +73,14 @@ impl U2FManager {
callback,
}) => {
// This must not block, otherwise we can't cancel.
sm.sign(timeout, challenge, application, key_handles, callback);
sm.sign(
flags,
timeout,
challenge,
application,
key_handles,
callback,
);
}
Ok(QueueAction::Cancel) => {
// Cancelling must block so that we don't start a new
@ -101,7 +110,7 @@ impl U2FManager {
timeout: u64,
challenge: Vec<u8>,
application: Vec<u8>,
key_handles: Vec<Vec<u8>>,
key_handles: Vec<::KeyHandle>,
callback: F,
) -> io::Result<()>
where
@ -116,7 +125,7 @@ impl U2FManager {
}
for key_handle in &key_handles {
if key_handle.len() > 256 {
if key_handle.credential.len() > 256 {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"Key handle too large",
@ -138,10 +147,11 @@ impl U2FManager {
pub fn sign<F>(
&self,
flags: ::SignFlags,
timeout: u64,
challenge: Vec<u8>,
application: Vec<u8>,
key_handles: Vec<Vec<u8>>,
key_handles: Vec<::KeyHandle>,
callback: F,
) -> io::Result<()>
where
@ -163,7 +173,7 @@ impl U2FManager {
}
for key_handle in &key_handles {
if key_handle.len() > 256 {
if key_handle.credential.len() > 256 {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"Key handle too large",
@ -173,6 +183,7 @@ impl U2FManager {
let callback = OnceCallback::new(callback);
let action = QueueAction::Sign {
flags,
timeout,
challenge,
application,

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

@ -10,6 +10,10 @@ use std::time::Duration;
use util::{io_err, OnceCallback};
use u2fprotocol::{u2f_init_device, u2f_is_keyhandle_valid, u2f_register, u2f_sign};
fn is_valid_transport(transports: ::AuthenticatorTransports) -> bool {
transports.is_empty() || transports.contains(::AuthenticatorTransports::USB)
}
#[derive(Default)]
pub struct StateMachine {
transaction: Option<Transaction>,
@ -26,7 +30,7 @@ impl StateMachine {
timeout: u64,
challenge: Vec<u8>,
application: Vec<u8>,
key_handles: Vec<Vec<u8>>,
key_handles: Vec<::KeyHandle>,
callback: OnceCallback<Vec<u8>>,
) {
// Abort any prior register/sign calls.
@ -60,8 +64,9 @@ impl StateMachine {
// Iterate the exclude list and see if there are any matches.
// Abort the state machine if we found a valid key handle.
if key_handles.iter().any(|key_handle| {
u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
.unwrap_or(false) /* no match on failure */
is_valid_transport(key_handle.transports) &&
u2f_is_keyhandle_valid(dev, &challenge, &application, &key_handle.credential)
.unwrap_or(false) /* no match on failure */
})
{
return;
@ -85,10 +90,11 @@ impl StateMachine {
pub fn sign(
&mut self,
flags: ::SignFlags,
timeout: u64,
challenge: Vec<u8>,
application: Vec<u8>,
key_handles: Vec<Vec<u8>>,
key_handles: Vec<::KeyHandle>,
callback: OnceCallback<(Vec<u8>, Vec<u8>)>,
) {
// Abort any prior register/sign calls.
@ -108,15 +114,38 @@ impl StateMachine {
return;
}
// We currently don't support user verification because we can't
// ask tokens whether they do support that. If the flag is set,
// ignore all tokens for now.
//
// Technically, this is a ConstraintError because we shouldn't talk
// to this authenticator in the first place. But the result is the
// same anyway.
if !flags.is_empty() {
return;
}
// Find all matching key handles.
let key_handles = key_handles
.iter()
.filter(|key_handle| {
u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
u2f_is_keyhandle_valid(dev, &challenge, &application, &key_handle.credential)
.unwrap_or(false) /* no match on failure */
})
.collect::<Vec<_>>();
// Aggregate distinct transports from all given credentials.
let transports = key_handles.iter().fold(
::AuthenticatorTransports::empty(),
|t, k| t | k.transports,
);
// We currently only support USB. If the RP specifies transports
// and doesn't include USB it's probably lying.
if !is_valid_transport(transports) {
return;
}
while alive() {
// If the device matches none of the given key handles
// then just make it blink with bogus data.
@ -129,8 +158,14 @@ impl StateMachine {
} else {
// Otherwise, try to sign.
for key_handle in &key_handles {
if let Ok(bytes) = u2f_sign(dev, &challenge, &application, key_handle) {
callback.call(Ok((key_handle.to_vec(), bytes)));
if let Ok(bytes) = u2f_sign(
dev,
&challenge,
&application,
&key_handle.credential,
)
{
callback.call(Ok((key_handle.credential.clone(), bytes)));
break;
}
}

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

@ -19,6 +19,10 @@ const uint64_t U2F_FLAG_REQUIRE_RESIDENT_KEY = 1;
const uint64_t U2F_FLAG_REQUIRE_USER_VERIFICATION = 2;
const uint64_t U2F_FLAG_REQUIRE_PLATFORM_ATTACHMENT = 4;
const uint8_t U2F_AUTHENTICATOR_TRANSPORT_USB = 1;
const uint8_t U2F_AUTHENTICATOR_TRANSPORT_NFC = 2;
const uint8_t U2F_AUTHENTICATOR_TRANSPORT_BLE = 4;
// NOTE: Preconditions
// * All rust_u2f_mgr* pointers must refer to pointers which are returned
// by rust_u2f_mgr_new, and must be freed with rust_u2f_mgr_free.
@ -56,6 +60,7 @@ uint64_t rust_u2f_mgr_register(rust_u2f_manager* mgr,
const rust_u2f_key_handles* khs);
uint64_t rust_u2f_mgr_sign(rust_u2f_manager* mgr,
uint64_t flags,
uint64_t timeout,
rust_u2f_callback,
const uint8_t* challenge_ptr,
@ -72,7 +77,8 @@ uint64_t rust_u2f_mgr_cancel(rust_u2f_manager* mgr);
rust_u2f_key_handles* rust_u2f_khs_new();
void rust_u2f_khs_add(rust_u2f_key_handles* khs,
const uint8_t* key_handle,
size_t key_handle_len);
size_t key_handle_len,
uint8_t transports);
/* unsafe */ void rust_u2f_khs_free(rust_u2f_key_handles* khs);

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

@ -1,26 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
interface MozObserver;
[HeaderFile="mozilla/dom/DesktopNotification.h"]
interface DesktopNotificationCenter
{
[NewObject]
DesktopNotification createNotification(DOMString title,
DOMString description,
optional DOMString iconURL = "");
};
interface DesktopNotification : EventTarget
{
[Throws]
void show();
attribute EventHandler onclick;
attribute EventHandler onclose;
};

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

@ -200,12 +200,6 @@ partial interface Navigator {
void removeIdleObserver(MozIdleObserver aIdleObserver);
};
// nsIDOMNavigatorDesktopNotification
partial interface Navigator {
[Throws, Pref="notification.feature.enabled", UnsafeInPrerendering]
readonly attribute DesktopNotificationCenter mozNotification;
};
// NetworkInformation
partial interface Navigator {
[Throws, Pref="dom.netinfo.enabled"]

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

@ -4,7 +4,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* https://www.w3.org/TR/webauthn/
* https://w3c.github.io/webauthn/
*/
/***** Interfaces to Data *****/
@ -94,6 +94,7 @@ dictionary PublicKeyCredentialRequestOptions {
unsigned long timeout;
USVString rpId;
sequence<PublicKeyCredentialDescriptor> allowCredentials = [];
UserVerificationRequirement userVerification = "preferred";
// Extensions are not supported yet.
// AuthenticationExtensions extensions; // Add in Bug 1406458
};

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

@ -97,9 +97,6 @@ with Files("DelayNode.webidl"):
with Files("DynamicsCompressorNode.webidl"):
BUG_COMPONENT = ("Core", "Web Audio")
with Files("DesktopNotification.webidl"):
BUG_COMPONENT = ("Toolkit", "Notifications and Alerts")
with Files("FakePluginTagInit.webidl"):
BUG_COMPONENT = ("Core", "Plug-ins")
@ -478,7 +475,6 @@ WEBIDL_FILES = [
'DecoderDoctorNotification.webidl',
'DedicatedWorkerGlobalScope.webidl',
'DelayNode.webidl',
'DesktopNotification.webidl',
'DeviceMotionEvent.webidl',
'Directory.webidl',
'Document.webidl',

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

@ -9,6 +9,7 @@ support-files =
file_userContextId_openWindow.js
force_refresh_browser_worker.js
empty.html
empty.js
server_multie10s_update.sjs
[browser_devtools_serviceworker_interception.js]
@ -16,5 +17,6 @@ support-files =
[browser_download.js]
[browser_multie10s_update.js]
skip-if = !e10s || os != "win" # Bug 1404914
[browser_storage_permission.js]
[browser_userContextId_openWindow.js]
skip-if = !e10s

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

@ -0,0 +1,123 @@
"use strict";
const { interfaces: Ci } = Components;
const BASE_URI = "http://mochi.test:8888/browser/dom/workers/test/serviceworkers/";
const PAGE_URI = BASE_URI + "empty.html";
const SCOPE = PAGE_URI + "?storage_permission";
const SW_SCRIPT = BASE_URI + "empty.js";
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({"set": [
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
]});
let tab = BrowserTestUtils.addTab(gBrowser, PAGE_URI);
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
await ContentTask.spawn(browser, { script: SW_SCRIPT, scope: SCOPE },
async function(opts) {
let reg = await content.navigator.serviceWorker.register(opts.script,
{ scope: opts.scope });
let worker = reg.installing || reg.waiting || reg.active;
await new Promise(resolve => {
if (worker.state === "activated") {
resolve();
return;
}
worker.addEventListener("statechange", function onStateChange() {
if (worker.state === "activated") {
worker.removeEventListener("statechange", onStateChange);
resolve();
}
});
});
}
);
await BrowserTestUtils.removeTab(tab);
});
add_task(async function test_allow_permission() {
Services.perms.add(Services.io.newURI(PAGE_URI), "cookie",
Ci.nsICookiePermission.ACCESS_ALLOW);
let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
let controller = await ContentTask.spawn(browser, null, async function() {
return content.navigator.serviceWorker.controller;
});
ok(!!controller, "page should be controlled with storage allowed");
await BrowserTestUtils.removeTab(tab);
});
add_task(async function test_deny_permission() {
Services.perms.add(Services.io.newURI(PAGE_URI), "cookie",
Ci.nsICookiePermission.ACCESS_DENY);
let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
let controller = await ContentTask.spawn(browser, null, async function() {
return content.navigator.serviceWorker.controller;
});
is(controller, null, "page should be not controlled with storage denied");
await BrowserTestUtils.removeTab(tab);
Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
});
add_task(async function test_session_permission() {
Services.perms.add(Services.io.newURI(PAGE_URI), "cookie",
Ci.nsICookiePermission.ACCESS_SESSION);
let tab = BrowserTestUtils.addTab(gBrowser, SCOPE);
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
let controller = await ContentTask.spawn(browser, null, async function() {
return content.navigator.serviceWorker.controller;
});
is(controller, null, "page should be not controlled with session storage");
await BrowserTestUtils.removeTab(tab);
Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
});
add_task(async function cleanup() {
Services.perms.remove(Services.io.newURI(PAGE_URI), "cookie");
let tab = BrowserTestUtils.addTab(gBrowser, PAGE_URI);
let browser = gBrowser.getBrowserForTab(tab);
await BrowserTestUtils.browserLoaded(browser);
await ContentTask.spawn(browser, SCOPE, async function(uri) {
let reg = await content.navigator.serviceWorker.getRegistration(uri);
let worker = reg.active;
await reg.unregister();
await new Promise(resolve => {
if (worker.state === "redundant") {
resolve();
return;
}
worker.addEventListener("statechange", function onStateChange() {
if (worker.state === "redundant") {
worker.removeEventListener("statechange", onStateChange);
resolve();
}
});
});
});
await BrowserTestUtils.removeTab(tab);
});

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

@ -1,12 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
title="Textbox tests">
<script type="text/javascript" src="platform.js"/>
<textbox type="timed"/>
</window>

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

@ -10,7 +10,6 @@ fails-if(Android) skip-if(winWidget) == emptytextbox-1.xul emptytextbox-ref.xul
fails-if(Android) skip-if(winWidget) == emptytextbox-2.xul emptytextbox-ref.xul # Windows: bug 1239170
!= emptytextbox-3.xul emptytextbox-ref.xul
!= emptytextbox-4.xul emptytextbox-ref.xul
fails-if(Android) skip-if(winWidget) == emptytextbox-5.xul emptytextbox-ref.xul # Windows: bug 1239170
# There is no way to simulate a number textbox in windows XP/Vista/7 default theme using CSS.
# Therefore, the equlity tests below should be marked as failing.
!= number-1.xul number-ref.xul

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

@ -126,7 +126,13 @@ static const char* kPreloadPermissions[] = {
"beacon",
"fetch",
"image",
"manifest"
"manifest",
// This permission is preloaded to support properly blocking service worker
// interception when a user has disabled storage for a specific site. Once
// service worker interception moves to the parent process this should be
// removed. See bug 1428130.
"cookie"
};
// A list of permissions that can have a fallback default permission

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

@ -1656,28 +1656,31 @@ GLContext::InitExtensions()
std::vector<nsCString> driverExtensionList;
if (mSymbols.fGetStringi) {
GLuint count = 0;
GetUIntegerv(LOCAL_GL_NUM_EXTENSIONS, &count);
for (GLuint i = 0; i < count; i++) {
// This is UTF-8.
const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i);
[&]() {
if (mSymbols.fGetStringi) {
GLuint count = 0;
if (GetPotentialInteger(LOCAL_GL_NUM_EXTENSIONS, (GLint*)&count)) {
for (GLuint i = 0; i < count; i++) {
// This is UTF-8.
const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i);
// We CANNOT use nsDependentCString here, because the spec doesn't guarantee
// that the pointers returned are different, only that their contents are.
// On Flame, each of these index string queries returns the same address.
driverExtensionList.push_back(nsCString(rawExt));
// We CANNOT use nsDependentCString here, because the spec doesn't guarantee
// that the pointers returned are different, only that their contents are.
// On Flame, each of these index string queries returns the same address.
driverExtensionList.push_back(nsCString(rawExt));
}
return;
}
}
} else {
MOZ_ALWAYS_TRUE(!fGetError());
const char* rawExts = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
MOZ_ALWAYS_TRUE(!fGetError());
const char* rawExts = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
if (rawExts) {
nsDependentCString exts(rawExts);
SplitByChar(exts, ' ', &driverExtensionList);
}
}
}();
const auto err = fGetError();
MOZ_ALWAYS_TRUE(!err);
const bool shouldDumpExts = ShouldDumpExts();
if (shouldDumpExts) {

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

@ -161,12 +161,14 @@ MacIOSurfaceTextureHostOGL::PushResourceUpdates(wr::ResourceUpdateQueue& aResour
switch (GetFormat()) {
case gfx::SurfaceFormat::R8G8B8X8:
case gfx::SurfaceFormat::R8G8B8A8:
case gfx::SurfaceFormat::B8G8R8A8:
case gfx::SurfaceFormat::B8G8R8X8: {
case gfx::SurfaceFormat::R8G8B8A8: {
MOZ_ASSERT(aImageKeys.length() == 1);
MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
wr::ImageDescriptor descriptor(GetSize(), GetFormat());
// The internal pixel format of MacIOSurface is always BGRX or BGRA
// format.
auto format = GetFormat() == gfx::SurfaceFormat::R8G8B8A8 ? gfx::SurfaceFormat::B8G8R8A8
: gfx::SurfaceFormat::B8G8R8X8;
wr::ImageDescriptor descriptor(GetSize(), format);
(aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0);
break;
}
@ -177,7 +179,7 @@ MacIOSurfaceTextureHostOGL::PushResourceUpdates(wr::ResourceUpdateQueue& aResour
// and YCbCr at OpenGL 3.1)
MOZ_ASSERT(aImageKeys.length() == 1);
MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
wr::ImageDescriptor descriptor(GetSize(), gfx::SurfaceFormat::R8G8B8X8);
wr::ImageDescriptor descriptor(GetSize(), gfx::SurfaceFormat::B8G8R8X8);
(aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0);
break;
}

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

@ -508,7 +508,8 @@ gfxMacFont::GetScaledFont(DrawTarget *aTarget)
GetUnscaledFont(),
GetAdjustedSize(),
Color::FromABGR(mFontSmoothingBackgroundColor),
!mStyle.useGrayscaleAntialiasing);
!mStyle.useGrayscaleAntialiasing,
IsSyntheticBold());
if (!mAzureScaledFont) {
return nullptr;
}

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

@ -66,9 +66,10 @@ inline Maybe<wr::ImageFormat>
SurfaceFormatToImageFormat(gfx::SurfaceFormat aFormat) {
switch (aFormat) {
case gfx::SurfaceFormat::R8G8B8X8:
// TODO: use RGBA + opaque flag
case gfx::SurfaceFormat::R8G8B8A8:
return Some(wr::ImageFormat::BGRA8);
// WebRender not support RGBA8 and RGBX8. Assert here.
MOZ_ASSERT(false);
return Nothing();
case gfx::SurfaceFormat::B8G8R8X8:
// TODO: WebRender will have a BGRA + opaque flag for this but does not
// have it yet (cf. issue #732).

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

@ -9478,7 +9478,7 @@ CodeGenerator::generateWasm(wasm::SigIdDesc sigId, wasm::BytecodeOffset trapOffs
// Since we just overflowed the stack, to be on the safe side, pop the
// stack so that, when the trap exit stub executes, it is a safe
// distance away from the end of the native stack.
wasm::TrapDesc trap(trapOffset, wasm::Trap::StackOverflow, /* framePushed = */ 0);
wasm::OldTrapDesc trap(trapOffset, wasm::Trap::StackOverflow, /* framePushed = */ 0);
if (frameSize() > 0) {
masm.bind(&onOverflow);
masm.addToStackPtr(Imm32(frameSize()));
@ -9496,7 +9496,7 @@ CodeGenerator::generateWasm(wasm::SigIdDesc sigId, wasm::BytecodeOffset trapOffs
if (!generateOutOfLineCode())
return false;
masm.wasmEmitTrapOutOfLineCode();
masm.wasmEmitOldTrapOutOfLineCode();
masm.flush();
if (masm.oom())
@ -12350,7 +12350,7 @@ CodeGenerator::visitWasmTrap(LWasmTrap* lir)
MOZ_ASSERT(gen->compilingWasm());
const MWasmTrap* mir = lir->mir();
masm.jump(trap(mir, mir->trap()));
masm.jump(oldTrap(mir, mir->trap()));
}
void
@ -12363,7 +12363,7 @@ CodeGenerator::visitWasmBoundsCheck(LWasmBoundsCheck* ins)
Register ptr = ToRegister(ins->ptr());
Register boundsCheckLimit = ToRegister(ins->boundsCheckLimit());
masm.wasmBoundsCheck(Assembler::AboveOrEqual, ptr, boundsCheckLimit,
trap(mir, wasm::Trap::OutOfBounds));
oldTrap(mir, wasm::Trap::OutOfBounds));
#endif
}
@ -12373,7 +12373,7 @@ CodeGenerator::visitWasmAlignmentCheck(LWasmAlignmentCheck* ins)
const MWasmAlignmentCheck* mir = ins->mir();
Register ptr = ToRegister(ins->ptr());
masm.branchTest32(Assembler::NonZero, ptr, Imm32(mir->byteSize() - 1),
trap(mir, wasm::Trap::UnalignedAccess));
oldTrap(mir, wasm::Trap::UnalignedAccess));
}
void

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

@ -2844,7 +2844,7 @@ MacroAssembler::callWithABINoProfiler(void* fun, MoveOp::Type result, CheckUnsaf
}
void
MacroAssembler::callWithABI(wasm::BytecodeOffset callOffset, wasm::SymbolicAddress imm,
MacroAssembler::callWithABI(wasm::BytecodeOffset bytecode, wasm::SymbolicAddress imm,
MoveOp::Type result)
{
MOZ_ASSERT(wasm::NeedsBuiltinThunk(imm));
@ -2861,7 +2861,7 @@ MacroAssembler::callWithABI(wasm::BytecodeOffset callOffset, wasm::SymbolicAddre
// points when placing arguments.
loadWasmTlsRegFromFrame();
call(wasm::CallSiteDesc(callOffset.bytecodeOffset, wasm::CallSite::Symbolic), imm);
call(wasm::CallSiteDesc(bytecode.offset, wasm::CallSite::Symbolic), imm);
callWithABIPost(stackAdjust, result, /* callFromWasm = */ true);
Pop(WasmTlsReg);
@ -3006,7 +3006,7 @@ MacroAssembler::wasmCallIndirect(const wasm::CallSiteDesc& desc, const wasm::Cal
if (needsBoundsCheck) {
loadWasmGlobalPtr(callee.tableLengthGlobalDataOffset(), scratch);
wasm::TrapDesc oobTrap(trapOffset, wasm::Trap::OutOfBounds, framePushed());
wasm::OldTrapDesc oobTrap(trapOffset, wasm::Trap::OutOfBounds, framePushed());
branch32(Assembler::Condition::AboveOrEqual, index, scratch, oobTrap);
}
@ -3014,7 +3014,7 @@ MacroAssembler::wasmCallIndirect(const wasm::CallSiteDesc& desc, const wasm::Cal
loadWasmGlobalPtr(callee.tableBaseGlobalDataOffset(), scratch);
// Load the callee from the table.
wasm::TrapDesc nullTrap(trapOffset, wasm::Trap::IndirectCallToNull, framePushed());
wasm::OldTrapDesc nullTrap(trapOffset, wasm::Trap::IndirectCallToNull, framePushed());
if (callee.wasmTableIsExternal()) {
static_assert(sizeof(wasm::ExternalTableElem) == 8 || sizeof(wasm::ExternalTableElem) == 16,
"elements of external tables are two words");
@ -3040,21 +3040,21 @@ MacroAssembler::wasmCallIndirect(const wasm::CallSiteDesc& desc, const wasm::Cal
}
void
MacroAssembler::wasmEmitTrapOutOfLineCode()
MacroAssembler::wasmEmitOldTrapOutOfLineCode()
{
for (const wasm::TrapSite& site : trapSites()) {
for (const wasm::OldTrapSite& site : oldTrapSites()) {
// Trap out-of-line codes are created for two kinds of trap sites:
// - jumps, which are bound directly to the trap out-of-line path
// - memory accesses, which can fault and then have control transferred
// to the out-of-line path directly via signal handler setting pc
switch (site.kind) {
case wasm::TrapSite::Jump: {
case wasm::OldTrapSite::Jump: {
RepatchLabel jump;
jump.use(site.codeOffset);
bind(&jump);
break;
}
case wasm::TrapSite::MemoryAccess: {
case wasm::OldTrapSite::MemoryAccess: {
append(wasm::MemoryAccess(site.codeOffset, currentOffset()));
break;
}
@ -3072,7 +3072,7 @@ MacroAssembler::wasmEmitTrapOutOfLineCode()
// directly to the trap exit stub. This takes advantage of the fact
// that there is already a CallSite for call_indirect and the
// current pre-prologue stack/register state.
append(wasm::TrapFarJump(site.trap, farJumpWithPatch()));
append(wasm::OldTrapFarJump(site.trap, farJumpWithPatch()));
} else {
// Inherit the frame depth of the trap site. This value is captured
// by the wasm::CallSite to allow unwinding this frame.
@ -3098,7 +3098,7 @@ MacroAssembler::wasmEmitTrapOutOfLineCode()
// trap-handling function. The frame iterator knows to skip the trap
// exit's frame so that unwinding begins at the frame and offset of
// the trapping instruction.
wasm::CallSiteDesc desc(site.bytecodeOffset, wasm::CallSiteDesc::TrapExit);
wasm::CallSiteDesc desc(site.offset, wasm::CallSiteDesc::OldTrapExit);
call(desc, site.trap);
}
@ -3113,7 +3113,7 @@ MacroAssembler::wasmEmitTrapOutOfLineCode()
// iterator to find the right CodeRange while walking the stack.
breakpoint();
trapSites().clear();
oldTrapSites().clear();
}
void

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

@ -1506,7 +1506,7 @@ class MacroAssembler : public MacroAssemblerSpecific
// Emit the out-of-line trap code to which trapping jumps/branches are
// bound. This should be called once per function after all other codegen,
// including "normal" OutOfLineCode.
void wasmEmitTrapOutOfLineCode();
void wasmEmitOldTrapOutOfLineCode();
// Perform a stack-overflow test, branching to the given Label on overflow.
void wasmEmitStackCheck(Register sp, Register scratch, Label* onOverflow);

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

@ -2453,7 +2453,7 @@ Assembler::as_b(Label* l, Condition c)
}
BufferOffset
Assembler::as_b(wasm::TrapDesc target, Condition c)
Assembler::as_b(wasm::OldTrapDesc target, Condition c)
{
Label l;
BufferOffset ret = as_b(&l, c);
@ -2894,12 +2894,12 @@ Assembler::bind(Label* label, BufferOffset boff)
}
void
Assembler::bindLater(Label* label, wasm::TrapDesc target)
Assembler::bindLater(Label* label, wasm::OldTrapDesc target)
{
if (label->used()) {
BufferOffset b(label);
do {
append(wasm::TrapSite(target, b.getOffset()));
append(wasm::OldTrapSite(target, b.getOffset()));
} while (nextLink(b, &b));
}
label->reset();

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

@ -1614,7 +1614,7 @@ class Assembler : public AssemblerShared
BufferOffset as_b(BOffImm off, Condition c, Label* documentation = nullptr);
BufferOffset as_b(Label* l, Condition c = Always);
BufferOffset as_b(wasm::TrapDesc target, Condition c = Always);
BufferOffset as_b(wasm::OldTrapDesc target, Condition c = Always);
BufferOffset as_b(BOffImm off, Condition c, BufferOffset inst);
// blx can go to either an immediate or a register. When blx'ing to a
@ -1722,7 +1722,7 @@ class Assembler : public AssemblerShared
bool nextLink(BufferOffset b, BufferOffset* next);
void bind(Label* label, BufferOffset boff = BufferOffset());
void bind(RepatchLabel* label);
void bindLater(Label* label, wasm::TrapDesc target);
void bindLater(Label* label, wasm::OldTrapDesc target);
uint32_t currentOffset() {
return nextOffset().getOffset();
}

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

@ -531,7 +531,7 @@ CodeGeneratorARM::divICommon(MDiv* mir, Register lhs, Register rhs, Register out
masm.ma_cmp(rhs, Imm32(-1), scratch, Assembler::Equal);
if (mir->canTruncateOverflow()) {
if (mir->trapOnError()) {
masm.ma_b(trap(mir, wasm::Trap::IntegerOverflow), Assembler::Equal);
masm.ma_b(oldTrap(mir, wasm::Trap::IntegerOverflow), Assembler::Equal);
} else {
// (-INT32_MIN)|0 = INT32_MIN
Label skip;
@ -551,7 +551,7 @@ CodeGeneratorARM::divICommon(MDiv* mir, Register lhs, Register rhs, Register out
masm.as_cmp(rhs, Imm8(0));
if (mir->canTruncateInfinities()) {
if (mir->trapOnError()) {
masm.ma_b(trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
masm.ma_b(oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
} else {
// Infinity|0 == 0
Label skip;
@ -714,7 +714,7 @@ CodeGeneratorARM::modICommon(MMod* mir, Register lhs, Register rhs, Register out
// wasm allows negative lhs and return 0 in this case.
MOZ_ASSERT(mir->isTruncated());
masm.as_cmp(rhs, Imm8(0));
masm.ma_b(trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
masm.ma_b(oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
return;
}
@ -2120,7 +2120,7 @@ CodeGeneratorARM::visitWasmAddOffset(LWasmAddOffset* lir)
ScratchRegisterScope scratch(masm);
masm.ma_add(base, Imm32(mir->offset()), out, scratch, SetCC);
masm.ma_b(trap(mir, wasm::Trap::OutOfBounds), Assembler::CarrySet);
masm.ma_b(oldTrap(mir, wasm::Trap::OutOfBounds), Assembler::CarrySet);
}
template <typename T>
@ -2417,7 +2417,7 @@ CodeGeneratorARM::generateUDivModZeroCheck(Register rhs, Register output, Label*
masm.as_cmp(rhs, Imm8(0));
if (mir->isTruncated()) {
if (mir->trapOnError()) {
masm.ma_b(trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
masm.ma_b(oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
} else {
Label skip;
masm.ma_b(&skip, Assembler::NotEqual);
@ -2768,7 +2768,7 @@ CodeGeneratorARM::visitDivOrModI64(LDivOrModI64* lir)
if (lir->canBeDivideByZero()) {
Register temp = WasmGetTemporaryForDivOrMod(lhs, rhs);
masm.branchTest64(Assembler::Zero, rhs, rhs, temp,
trap(lir, wasm::Trap::IntegerDivideByZero));
oldTrap(lir, wasm::Trap::IntegerDivideByZero));
}
auto* mir = lir->mir();
@ -2781,7 +2781,7 @@ CodeGeneratorARM::visitDivOrModI64(LDivOrModI64* lir)
if (mir->isMod())
masm.xor64(output, output);
else
masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
masm.jump(oldTrap(lir, wasm::Trap::IntegerOverflow));
masm.jump(&done);
masm.bind(&notmin);
}
@ -2814,7 +2814,7 @@ CodeGeneratorARM::visitUDivOrModI64(LUDivOrModI64* lir)
if (lir->canBeDivideByZero()) {
Register temp = WasmGetTemporaryForDivOrMod(lhs, rhs);
masm.branchTest64(Assembler::Zero, rhs, rhs, temp,
trap(lir, wasm::Trap::IntegerDivideByZero));
oldTrap(lir, wasm::Trap::IntegerDivideByZero));
}
masm.setupWasmABICall();

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

@ -1390,7 +1390,7 @@ MacroAssemblerARM::ma_b(Label* dest, Assembler::Condition c)
}
BufferOffset
MacroAssemblerARM::ma_b(wasm::TrapDesc target, Assembler::Condition c)
MacroAssemblerARM::ma_b(wasm::OldTrapDesc target, Assembler::Condition c)
{
return as_b(target, c);
}
@ -5751,12 +5751,12 @@ MacroAssemblerARM::outOfLineWasmTruncateToIntCheck(FloatRegister input, MIRType
// Handle errors.
bind(&fail);
asMasm().jump(wasm::TrapDesc(trapOffset, wasm::Trap::IntegerOverflow,
asMasm().framePushed()));
asMasm().jump(wasm::OldTrapDesc(trapOffset, wasm::Trap::IntegerOverflow,
asMasm().framePushed()));
bind(&inputIsNaN);
asMasm().jump(wasm::TrapDesc(trapOffset, wasm::Trap::InvalidConversionToInteger,
asMasm().framePushed()));
asMasm().jump(wasm::OldTrapDesc(trapOffset, wasm::Trap::InvalidConversionToInteger,
asMasm().framePushed()));
}
void

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

@ -346,7 +346,7 @@ class MacroAssemblerARM : public Assembler
// Branches when done from within arm-specific code.
BufferOffset ma_b(Label* dest, Condition c = Always);
BufferOffset ma_b(wasm::TrapDesc target, Condition c = Always);
BufferOffset ma_b(wasm::OldTrapDesc target, Condition c = Always);
void ma_b(void* target, Condition c = Always);
void ma_bx(Register dest, Condition c = Always);
@ -677,7 +677,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
ma_ldr(addr, scratch, scratch2);
ma_bx(scratch);
}
void jump(wasm::TrapDesc target) {
void jump(wasm::OldTrapDesc target) {
as_b(target);
}

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

@ -215,7 +215,7 @@ class Assembler : public vixl::Assembler
void bind(Label* label) { bind(label, nextOffset()); }
void bind(Label* label, BufferOffset boff);
void bind(RepatchLabel* label);
void bindLater(Label* label, wasm::TrapDesc target) {
void bindLater(Label* label, wasm::OldTrapDesc target) {
MOZ_CRASH("NYI");
}

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

@ -493,10 +493,10 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
}
using vixl::MacroAssembler::B;
void B(wasm::TrapDesc) {
void B(wasm::OldTrapDesc) {
MOZ_CRASH("NYI");
}
void B(wasm::TrapDesc, Condition cond) {
void B(wasm::OldTrapDesc, Condition cond) {
MOZ_CRASH("NYI");
}
@ -673,7 +673,7 @@ class MacroAssemblerCompat : public vixl::MacroAssembler
loadPtr(addr, ip0);
Br(vixl::ip0);
}
void jump(wasm::TrapDesc target) {
void jump(wasm::OldTrapDesc target) {
MOZ_CRASH("NYI");
}

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

@ -1809,7 +1809,7 @@ AssemblerMIPSShared::bind(Label* label, BufferOffset boff)
}
void
AssemblerMIPSShared::bindLater(Label* label, wasm::TrapDesc target)
AssemblerMIPSShared::bindLater(Label* label, wasm::OldTrapDesc target)
{
if (label->used()) {
int32_t next;
@ -1818,7 +1818,7 @@ AssemblerMIPSShared::bindLater(Label* label, wasm::TrapDesc target)
do {
Instruction* inst = editSrc(b);
append(wasm::TrapSite(target, b.getOffset()));
append(wasm::OldTrapSite(target, b.getOffset()));
next = inst[1].encode();
inst[1].makeNop();

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

@ -1231,7 +1231,7 @@ class AssemblerMIPSShared : public AssemblerShared
// label operations
void bind(Label* label, BufferOffset boff = BufferOffset());
void bindLater(Label* label, wasm::TrapDesc target);
void bindLater(Label* label, wasm::OldTrapDesc target);
virtual void bind(InstImm* inst, uintptr_t branch, uintptr_t target) = 0;
void bind(CodeOffset* label) {
label->bind(currentOffset());

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

@ -568,7 +568,7 @@ CodeGeneratorMIPSShared::visitDivI(LDivI* ins)
// Handle divide by zero.
if (mir->canBeDivideByZero()) {
if (mir->trapOnError()) {
masm.ma_b(rhs, rhs, trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
masm.ma_b(rhs, rhs, oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
} else if (mir->canTruncateInfinities()) {
// Truncated division by zero is zero (Infinity|0 == 0)
Label notzero;
@ -590,7 +590,7 @@ CodeGeneratorMIPSShared::visitDivI(LDivI* ins)
masm.move32(Imm32(-1), temp);
if (mir->trapOnError()) {
masm.ma_b(rhs, temp, trap(mir, wasm::Trap::IntegerOverflow), Assembler::Equal);
masm.ma_b(rhs, temp, oldTrap(mir, wasm::Trap::IntegerOverflow), Assembler::Equal);
} else if (mir->canTruncateOverflow()) {
// (-INT32_MIN)|0 == INT32_MIN
Label skip;
@ -718,7 +718,7 @@ CodeGeneratorMIPSShared::visitModI(LModI* ins)
if (mir->canBeDivideByZero()) {
if (mir->isTruncated()) {
if (mir->trapOnError()) {
masm.ma_b(rhs, rhs, trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
masm.ma_b(rhs, rhs, oldTrap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
} else {
Label skip;
masm.ma_b(rhs, Imm32(0), &skip, Assembler::NotEqual, ShortJump);
@ -1559,10 +1559,10 @@ CodeGeneratorMIPSShared::visitOutOfLineWasmTruncateCheck(OutOfLineWasmTruncateCh
// Handle errors.
masm.bind(&fail);
masm.jump(trap(ool, wasm::Trap::IntegerOverflow));
masm.jump(oldTrap(ool, wasm::Trap::IntegerOverflow));
masm.bind(&inputIsNaN);
masm.jump(trap(ool, wasm::Trap::InvalidConversionToInteger));
masm.jump(oldTrap(ool, wasm::Trap::InvalidConversionToInteger));
}
void
@ -2415,7 +2415,7 @@ CodeGeneratorMIPSShared::visitUDivOrMod(LUDivOrMod* ins)
if (ins->canBeDivideByZero()) {
if (ins->mir()->isTruncated()) {
if (ins->trapOnError()) {
masm.ma_b(rhs, rhs, trap(ins, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
masm.ma_b(rhs, rhs, oldTrap(ins, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
} else {
// Infinity|0 == 0
Label notzero;
@ -2767,7 +2767,7 @@ CodeGeneratorMIPSShared::visitWasmAddOffset(LWasmAddOffset* lir)
Register base = ToRegister(lir->base());
Register out = ToRegister(lir->output());
masm.ma_addTestCarry(out, base, Imm32(mir->offset()), trap(mir, wasm::Trap::OutOfBounds));
masm.ma_addTestCarry(out, base, Imm32(mir->offset()), oldTrap(mir, wasm::Trap::OutOfBounds));
}
template <typename T>

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

@ -337,8 +337,8 @@ template void
MacroAssemblerMIPSShared::ma_addTestCarry<Label*>(Register rd, Register rs,
Register rt, Label* overflow);
template void
MacroAssemblerMIPSShared::ma_addTestCarry<wasm::TrapDesc>(Register rd, Register rs, Register rt,
wasm::TrapDesc overflow);
MacroAssemblerMIPSShared::ma_addTestCarry<wasm::OldTrapDesc>(Register rd, Register rs, Register rt,
wasm::OldTrapDesc overflow);
template <typename L>
void
@ -352,8 +352,8 @@ template void
MacroAssemblerMIPSShared::ma_addTestCarry<Label*>(Register rd, Register rs,
Imm32 imm, Label* overflow);
template void
MacroAssemblerMIPSShared::ma_addTestCarry<wasm::TrapDesc>(Register rd, Register rs, Imm32 imm,
wasm::TrapDesc overflow);
MacroAssemblerMIPSShared::ma_addTestCarry<wasm::OldTrapDesc>(Register rd, Register rs, Imm32 imm,
wasm::OldTrapDesc overflow);
// Subtract.
void
@ -796,7 +796,7 @@ MacroAssemblerMIPSShared::ma_b(Register lhs, ImmPtr imm, Label* l, Condition c,
template <typename T>
void
MacroAssemblerMIPSShared::ma_b(Register lhs, T rhs, wasm::TrapDesc target, Condition c,
MacroAssemblerMIPSShared::ma_b(Register lhs, T rhs, wasm::OldTrapDesc target, Condition c,
JumpKind jumpKind)
{
Label label;
@ -805,13 +805,13 @@ MacroAssemblerMIPSShared::ma_b(Register lhs, T rhs, wasm::TrapDesc target, Condi
}
template void MacroAssemblerMIPSShared::ma_b<Register>(Register lhs, Register rhs,
wasm::TrapDesc target, Condition c,
wasm::OldTrapDesc target, Condition c,
JumpKind jumpKind);
template void MacroAssemblerMIPSShared::ma_b<Imm32>(Register lhs, Imm32 rhs,
wasm::TrapDesc target, Condition c,
wasm::OldTrapDesc target, Condition c,
JumpKind jumpKind);
template void MacroAssemblerMIPSShared::ma_b<ImmTag>(Register lhs, ImmTag rhs,
wasm::TrapDesc target, Condition c,
wasm::OldTrapDesc target, Condition c,
JumpKind jumpKind);
void
@ -821,7 +821,7 @@ MacroAssemblerMIPSShared::ma_b(Label* label, JumpKind jumpKind)
}
void
MacroAssemblerMIPSShared::ma_b(wasm::TrapDesc target, JumpKind jumpKind)
MacroAssemblerMIPSShared::ma_b(wasm::OldTrapDesc target, JumpKind jumpKind)
{
Label label;
asMasm().branchWithCode(getBranchCode(BranchIsJump), &label, jumpKind);

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

@ -164,11 +164,11 @@ class MacroAssemblerMIPSShared : public Assembler
ma_b(lhs, ScratchRegister, l, c, jumpKind);
}
template <typename T>
void ma_b(Register lhs, T rhs, wasm::TrapDesc target, Condition c,
void ma_b(Register lhs, T rhs, wasm::OldTrapDesc target, Condition c,
JumpKind jumpKind = LongJump);
void ma_b(Label* l, JumpKind jumpKind = LongJump);
void ma_b(wasm::TrapDesc target, JumpKind jumpKind = LongJump);
void ma_b(wasm::OldTrapDesc target, JumpKind jumpKind = LongJump);
// fp instructions
void ma_lis(FloatRegister dest, float value);

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

@ -380,7 +380,7 @@ CodeGeneratorMIPS::visitDivOrModI64(LDivOrModI64* lir)
// Handle divide by zero.
if (lir->canBeDivideByZero())
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, trap(lir, wasm::Trap::IntegerDivideByZero));
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
// Handle an integer overflow exception from INT64_MIN / -1.
if (lir->canBeNegativeOverflow()) {
@ -390,7 +390,7 @@ CodeGeneratorMIPS::visitDivOrModI64(LDivOrModI64* lir)
if (lir->mir()->isMod()) {
masm.xor64(output, output);
} else {
masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
masm.jump(oldTrap(lir, wasm::Trap::IntegerOverflow));
}
masm.jump(&done);
masm.bind(&notmin);
@ -433,7 +433,7 @@ CodeGeneratorMIPS::visitUDivOrModI64(LUDivOrModI64* lir)
// Prevent divide by zero.
if (lir->canBeDivideByZero())
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, trap(lir, wasm::Trap::IntegerDivideByZero));
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
masm.setupWasmABICall();
masm.passABIArg(lhs.high);

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

@ -238,8 +238,8 @@ template void
MacroAssemblerMIPS::ma_addTestOverflow<Label*>(Register rd, Register rs,
Register rt, Label* overflow);
template void
MacroAssemblerMIPS::ma_addTestOverflow<wasm::TrapDesc>(Register rd, Register rs, Register rt,
wasm::TrapDesc overflow);
MacroAssemblerMIPS::ma_addTestOverflow<wasm::OldTrapDesc>(Register rd, Register rs, Register rt,
wasm::OldTrapDesc overflow);
template <typename L>
void
@ -270,8 +270,8 @@ template void
MacroAssemblerMIPS::ma_addTestOverflow<Label*>(Register rd, Register rs,
Imm32 imm, Label* overflow);
template void
MacroAssemblerMIPS::ma_addTestOverflow<wasm::TrapDesc>(Register rd, Register rs, Imm32 imm,
wasm::TrapDesc overflow);
MacroAssemblerMIPS::ma_addTestOverflow<wasm::OldTrapDesc>(Register rd, Register rs, Imm32 imm,
wasm::OldTrapDesc overflow);
// Subtract.
void

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

@ -306,7 +306,7 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS
branch(code);
}
void jump(wasm::TrapDesc target) {
void jump(wasm::OldTrapDesc target) {
ma_b(target);
}

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

@ -362,7 +362,7 @@ CodeGeneratorMIPS64::visitDivOrModI64(LDivOrModI64* lir)
// Handle divide by zero.
if (lir->canBeDivideByZero())
masm.ma_b(rhs, rhs, trap(lir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
masm.ma_b(rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
// Handle an integer overflow exception from INT64_MIN / -1.
if (lir->canBeNegativeOverflow()) {
@ -372,7 +372,7 @@ CodeGeneratorMIPS64::visitDivOrModI64(LDivOrModI64* lir)
if (lir->mir()->isMod()) {
masm.ma_xor(output, output);
} else {
masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
masm.jump(oldTrap(lir, wasm::Trap::IntegerOverflow));
}
masm.jump(&done);
masm.bind(&notmin);
@ -399,7 +399,7 @@ CodeGeneratorMIPS64::visitUDivOrModI64(LUDivOrModI64* lir)
// Prevent divide by zero.
if (lir->canBeDivideByZero())
masm.ma_b(rhs, rhs, trap(lir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
masm.ma_b(rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero), Assembler::Zero);
masm.as_ddivu(lhs, rhs);

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

@ -489,8 +489,8 @@ template void
MacroAssemblerMIPS64::ma_addTestOverflow<Label*>(Register rd, Register rs,
Register rt, Label* overflow);
template void
MacroAssemblerMIPS64::ma_addTestOverflow<wasm::TrapDesc>(Register rd, Register rs, Register rt,
wasm::TrapDesc overflow);
MacroAssemblerMIPS64::ma_addTestOverflow<wasm::OldTrapDesc>(Register rd, Register rs, Register rt,
wasm::OldTrapDesc overflow);
template <typename L>
void
@ -511,8 +511,8 @@ template void
MacroAssemblerMIPS64::ma_addTestOverflow<Label*>(Register rd, Register rs,
Imm32 imm, Label* overflow);
template void
MacroAssemblerMIPS64::ma_addTestOverflow<wasm::TrapDesc>(Register rd, Register rs, Imm32 imm,
wasm::TrapDesc overflow);
MacroAssemblerMIPS64::ma_addTestOverflow<wasm::OldTrapDesc>(Register rd, Register rs, Imm32 imm,
wasm::OldTrapDesc overflow);
// Subtract.
void

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

@ -335,7 +335,7 @@ class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64
branch(code);
}
void jump(wasm::TrapDesc target) {
void jump(wasm::OldTrapDesc target) {
ma_b(target);
}

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

@ -210,7 +210,7 @@ class MacroAssemblerNone : public Assembler
void flushBuffer() { MOZ_CRASH(); }
template <typename T> void bind(T) { MOZ_CRASH(); }
void bindLater(Label*, wasm::TrapDesc) { MOZ_CRASH(); }
void bindLater(Label*, wasm::OldTrapDesc) { MOZ_CRASH(); }
template <typename T> void j(Condition, T) { MOZ_CRASH(); }
template <typename T> void jump(T) { MOZ_CRASH(); }
void writeCodePointer(CodeOffset* label) { MOZ_CRASH(); }

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

@ -811,47 +811,47 @@ struct CallFarJump
typedef Vector<CallFarJump, 0, SystemAllocPolicy> CallFarJumpVector;
// The TrapDesc struct describes a wasm trap that is about to be emitted. This
// The OldTrapDesc struct describes a wasm trap that is about to be emitted. This
// includes the logical wasm bytecode offset to report, the kind of instruction
// causing the trap, and the stack depth right before control is transferred to
// the trap out-of-line path.
struct TrapDesc : BytecodeOffset
struct OldTrapDesc : BytecodeOffset
{
enum Kind { Jump, MemoryAccess };
Kind kind;
Trap trap;
uint32_t framePushed;
TrapDesc(BytecodeOffset offset, Trap trap, uint32_t framePushed, Kind kind = Jump)
OldTrapDesc(BytecodeOffset offset, Trap trap, uint32_t framePushed, Kind kind = Jump)
: BytecodeOffset(offset), kind(kind), trap(trap), framePushed(framePushed)
{}
};
// A TrapSite captures all relevant information at the point of emitting the
// An OldTrapSite captures all relevant information at the point of emitting the
// in-line trapping instruction for the purpose of generating the out-of-line
// trap code (at the end of the function).
struct TrapSite : TrapDesc
struct OldTrapSite : OldTrapDesc
{
uint32_t codeOffset;
TrapSite(TrapDesc trap, uint32_t codeOffset)
: TrapDesc(trap), codeOffset(codeOffset)
OldTrapSite(OldTrapDesc trap, uint32_t codeOffset)
: OldTrapDesc(trap), codeOffset(codeOffset)
{}
};
typedef Vector<TrapSite, 0, SystemAllocPolicy> TrapSiteVector;
typedef Vector<OldTrapSite, 0, SystemAllocPolicy> OldTrapSiteVector;
// A TrapFarJump records the offset of a jump that needs to be patched to a trap
// An OldTrapFarJump records the offset of a jump that needs to be patched to a trap
// exit at the end of the module when trap exits are emitted.
struct TrapFarJump
struct OldTrapFarJump
{
Trap trap;
jit::CodeOffset jump;
TrapFarJump(Trap trap, jit::CodeOffset jump)
OldTrapFarJump(Trap trap, jit::CodeOffset jump)
: trap(trap), jump(jump)
{}
@ -860,7 +860,7 @@ struct TrapFarJump
}
};
typedef Vector<TrapFarJump, 0, SystemAllocPolicy> TrapFarJumpVector;
typedef Vector<OldTrapFarJump, 0, SystemAllocPolicy> OldTrapFarJumpVector;
} // namespace wasm
@ -871,8 +871,8 @@ class AssemblerShared
{
wasm::CallSiteVector callSites_;
wasm::CallSiteTargetVector callSiteTargets_;
wasm::TrapSiteVector trapSites_;
wasm::TrapFarJumpVector trapFarJumps_;
wasm::OldTrapSiteVector oldTrapSites_;
wasm::OldTrapFarJumpVector oldTrapFarJumps_;
wasm::CallFarJumpVector callFarJumps_;
wasm::MemoryAccessVector memoryAccesses_;
wasm::SymbolicAccessVector symbolicAccesses_;
@ -930,11 +930,11 @@ class AssemblerShared
enoughMemory_ &= callSites_.emplaceBack(desc, retAddr.offset());
enoughMemory_ &= callSiteTargets_.emplaceBack(mozilla::Forward<Args>(args)...);
}
void append(wasm::TrapSite trapSite) {
enoughMemory_ &= trapSites_.append(trapSite);
void append(wasm::OldTrapSite trapSite) {
enoughMemory_ &= oldTrapSites_.append(trapSite);
}
void append(wasm::TrapFarJump jmp) {
enoughMemory_ &= trapFarJumps_.append(jmp);
void append(wasm::OldTrapFarJump jmp) {
enoughMemory_ &= oldTrapFarJumps_.append(jmp);
}
void append(wasm::CallFarJump jmp) {
enoughMemory_ &= callFarJumps_.append(jmp);
@ -945,11 +945,11 @@ class AssemblerShared
void append(const wasm::MemoryAccessDesc& access, size_t codeOffset, size_t framePushed) {
if (access.hasTrap()) {
// If a memory access is trapping (wasm, SIMD.js, Atomics), create a
// TrapSite now which will generate a trap out-of-line path at the end
// OldTrapSite now which will generate a trap out-of-line path at the end
// of the function which will *then* append a MemoryAccess.
wasm::TrapDesc trap(access.trapOffset(), wasm::Trap::OutOfBounds, framePushed,
wasm::TrapSite::MemoryAccess);
append(wasm::TrapSite(trap, codeOffset));
wasm::OldTrapDesc trap(access.trapOffset(), wasm::Trap::OutOfBounds, framePushed,
wasm::OldTrapSite::MemoryAccess);
append(wasm::OldTrapSite(trap, codeOffset));
} else {
// Otherwise, this is a plain asm.js access. On WASM_HUGE_MEMORY
// platforms, asm.js uses signal handlers to remove bounds checks
@ -966,8 +966,8 @@ class AssemblerShared
wasm::CallSiteVector& callSites() { return callSites_; }
wasm::CallSiteTargetVector& callSiteTargets() { return callSiteTargets_; }
wasm::TrapSiteVector& trapSites() { return trapSites_; }
wasm::TrapFarJumpVector& trapFarJumps() { return trapFarJumps_; }
wasm::OldTrapSiteVector& oldTrapSites() { return oldTrapSites_; }
wasm::OldTrapFarJumpVector& oldTrapFarJumps() { return oldTrapFarJumps_; }
wasm::CallFarJumpVector& callFarJumps() { return callFarJumps_; }
wasm::MemoryAccessVector& memoryAccesses() { return memoryAccesses_; }
wasm::SymbolicAccessVector& symbolicAccesses() { return symbolicAccesses_; }

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

@ -503,8 +503,8 @@ class CodeGeneratorShared : public LElementVisitor
#endif
template <class T>
wasm::TrapDesc trap(T* mir, wasm::Trap trap) {
return wasm::TrapDesc(mir->bytecodeOffset(), trap, masm.framePushed());
wasm::OldTrapDesc oldTrap(T* mir, wasm::Trap trap) {
return wasm::OldTrapDesc(mir->bytecodeOffset(), trap, masm.framePushed());
}
private:

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

@ -285,7 +285,7 @@ CodeGeneratorX64::visitDivOrModI64(LDivOrModI64* lir)
// Handle divide by zero.
if (lir->canBeDivideByZero()) {
masm.branchTestPtr(Assembler::Zero, rhs, rhs, trap(lir, wasm::Trap::IntegerDivideByZero));
masm.branchTestPtr(Assembler::Zero, rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
}
// Handle an integer overflow exception from INT64_MIN / -1.
@ -296,7 +296,7 @@ CodeGeneratorX64::visitDivOrModI64(LDivOrModI64* lir)
if (lir->mir()->isMod())
masm.xorl(output, output);
else
masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
masm.jump(oldTrap(lir, wasm::Trap::IntegerOverflow));
masm.jump(&done);
masm.bind(&notmin);
}
@ -328,7 +328,7 @@ CodeGeneratorX64::visitUDivOrModI64(LUDivOrModI64* lir)
// Prevent divide by zero.
if (lir->canBeDivideByZero())
masm.branchTestPtr(Assembler::Zero, rhs, rhs, trap(lir, wasm::Trap::IntegerDivideByZero));
masm.branchTestPtr(Assembler::Zero, rhs, rhs, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
// Zero extend the lhs into rdx to make (rdx:rax).
masm.xorl(rdx, rdx);

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

@ -922,12 +922,12 @@ class AssemblerX86Shared : public AssemblerShared
void j(Condition cond, RepatchLabel* label) { jSrc(cond, label); }
void jmp(RepatchLabel* label) { jmpSrc(label); }
void j(Condition cond, wasm::TrapDesc target) {
void j(Condition cond, wasm::OldTrapDesc target) {
Label l;
j(cond, &l);
bindLater(&l, target);
}
void jmp(wasm::TrapDesc target) {
void jmp(wasm::OldTrapDesc target) {
Label l;
jmp(&l);
bindLater(&l, target);
@ -963,11 +963,11 @@ class AssemblerX86Shared : public AssemblerShared
}
label->bind(dst.offset());
}
void bindLater(Label* label, wasm::TrapDesc target) {
void bindLater(Label* label, wasm::OldTrapDesc target) {
if (label->used()) {
JmpSrc jmp(label->offset());
do {
append(wasm::TrapSite(target, jmp.offset()));
append(wasm::OldTrapSite(target, jmp.offset()));
} while (masm.nextJump(jmp, &jmp));
}
label->reset();

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

@ -435,7 +435,7 @@ CodeGeneratorX86Shared::visitWasmAddOffset(LWasmAddOffset* lir)
masm.move32(base, out);
masm.add32(Imm32(mir->offset()), out);
masm.j(Assembler::CarrySet, trap(mir, wasm::Trap::OutOfBounds));
masm.j(Assembler::CarrySet, oldTrap(mir, wasm::Trap::OutOfBounds));
}
void
@ -1026,7 +1026,7 @@ CodeGeneratorX86Shared::visitUDivOrMod(LUDivOrMod* ins)
masm.test32(rhs, rhs);
if (ins->mir()->isTruncated()) {
if (ins->trapOnError()) {
masm.j(Assembler::Zero, trap(ins, wasm::Trap::IntegerDivideByZero));
masm.j(Assembler::Zero, oldTrap(ins, wasm::Trap::IntegerDivideByZero));
} else {
ool = new(alloc()) ReturnZero(output);
masm.j(Assembler::Zero, ool->entry());
@ -1074,7 +1074,7 @@ CodeGeneratorX86Shared::visitUDivOrModConstant(LUDivOrModConstant *ins) {
if (d == 0) {
if (ins->mir()->isTruncated()) {
if (ins->trapOnError())
masm.jump(trap(ins, wasm::Trap::IntegerDivideByZero));
masm.jump(oldTrap(ins, wasm::Trap::IntegerDivideByZero));
else
masm.xorl(output, output);
} else {
@ -1213,7 +1213,7 @@ CodeGeneratorX86Shared::visitDivPowTwoI(LDivPowTwoI* ins)
if (!mir->isTruncated())
bailoutIf(Assembler::Overflow, ins->snapshot());
else if (mir->trapOnError())
masm.j(Assembler::Overflow, trap(mir, wasm::Trap::IntegerOverflow));
masm.j(Assembler::Overflow, oldTrap(mir, wasm::Trap::IntegerOverflow));
} else if (mir->isUnsigned() && !mir->isTruncated()) {
// Unsigned division by 1 can overflow if output is not
// truncated.
@ -1332,7 +1332,7 @@ CodeGeneratorX86Shared::visitDivI(LDivI* ins)
if (mir->canBeDivideByZero()) {
masm.test32(rhs, rhs);
if (mir->trapOnError()) {
masm.j(Assembler::Zero, trap(mir, wasm::Trap::IntegerDivideByZero));
masm.j(Assembler::Zero, oldTrap(mir, wasm::Trap::IntegerDivideByZero));
} else if (mir->canTruncateInfinities()) {
// Truncated division by zero is zero (Infinity|0 == 0)
if (!ool)
@ -1351,7 +1351,7 @@ CodeGeneratorX86Shared::visitDivI(LDivI* ins)
masm.j(Assembler::NotEqual, &notmin);
masm.cmp32(rhs, Imm32(-1));
if (mir->trapOnError()) {
masm.j(Assembler::Equal, trap(mir, wasm::Trap::IntegerOverflow));
masm.j(Assembler::Equal, oldTrap(mir, wasm::Trap::IntegerOverflow));
} else if (mir->canTruncateOverflow()) {
// (-INT32_MIN)|0 == INT32_MIN and INT32_MIN is already in the
// output register (lhs == eax).
@ -1501,7 +1501,7 @@ CodeGeneratorX86Shared::visitModI(LModI* ins)
masm.test32(rhs, rhs);
if (mir->isTruncated()) {
if (mir->trapOnError()) {
masm.j(Assembler::Zero, trap(mir, wasm::Trap::IntegerDivideByZero));
masm.j(Assembler::Zero, oldTrap(mir, wasm::Trap::IntegerDivideByZero));
} else {
if (!ool)
ool = new(alloc()) ReturnZero(edx);
@ -2523,7 +2523,7 @@ CodeGeneratorX86Shared::visitOutOfLineSimdFloatToIntCheck(OutOfLineSimdFloatToIn
masm.jump(ool->rejoin());
if (gen->compilingWasm()) {
masm.bindLater(&onConversionError, trap(ool, wasm::Trap::ImpreciseSimdConversion));
masm.bindLater(&onConversionError, oldTrap(ool, wasm::Trap::ImpreciseSimdConversion));
} else {
masm.bind(&onConversionError);
bailout(ool->ins()->snapshot());
@ -2603,7 +2603,7 @@ CodeGeneratorX86Shared::visitFloat32x4ToUint32x4(LFloat32x4ToUint32x4* ins)
masm.cmp32(temp, Imm32(0));
if (gen->compilingWasm())
masm.j(Assembler::NotEqual, trap(mir, wasm::Trap::ImpreciseSimdConversion));
masm.j(Assembler::NotEqual, oldTrap(mir, wasm::Trap::ImpreciseSimdConversion));
else
bailoutIf(Assembler::NotEqual, ins->snapshot());
}

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

@ -686,10 +686,10 @@ struct MOZ_RAII AutoHandleWasmTruncateToIntErrors
~AutoHandleWasmTruncateToIntErrors() {
// Handle errors.
masm.bind(&fail);
masm.jump(wasm::TrapDesc(off, wasm::Trap::IntegerOverflow, masm.framePushed()));
masm.jump(wasm::OldTrapDesc(off, wasm::Trap::IntegerOverflow, masm.framePushed()));
masm.bind(&inputIsNaN);
masm.jump(wasm::TrapDesc(off, wasm::Trap::InvalidConversionToInteger, masm.framePushed()));
masm.jump(wasm::OldTrapDesc(off, wasm::Trap::InvalidConversionToInteger, masm.framePushed()));
}
};

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

@ -202,7 +202,7 @@ class MacroAssemblerX86Shared : public Assembler
void jump(const Address& addr) {
jmp(Operand(addr));
}
void jump(wasm::TrapDesc target) {
void jump(wasm::OldTrapDesc target) {
jmp(target);
}

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

@ -1031,7 +1031,7 @@ CodeGeneratorX86::visitDivOrModI64(LDivOrModI64* lir)
// Handle divide by zero.
if (lir->canBeDivideByZero())
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, trap(lir, wasm::Trap::IntegerDivideByZero));
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
MDefinition* mir = lir->mir();
@ -1043,7 +1043,7 @@ CodeGeneratorX86::visitDivOrModI64(LDivOrModI64* lir)
if (mir->isMod())
masm.xor64(output, output);
else
masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
masm.jump(oldTrap(lir, wasm::Trap::IntegerOverflow));
masm.jump(&done);
masm.bind(&notmin);
}
@ -1079,7 +1079,7 @@ CodeGeneratorX86::visitUDivOrModI64(LUDivOrModI64* lir)
// Prevent divide by zero.
if (lir->canBeDivideByZero())
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, trap(lir, wasm::Trap::IntegerDivideByZero));
masm.branchTest64(Assembler::Zero, rhs, rhs, temp, oldTrap(lir, wasm::Trap::IntegerDivideByZero));
masm.setupWasmABICall();
masm.passABIArg(lhs.high);

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

@ -20,6 +20,9 @@
#include "vm/ErrorReporting.h"
#include "vm/MallocProvider.h"
#include "vm/Runtime.h"
#ifdef XP_DARWIN
# include "wasm/WasmSignalHandlers.h"
#endif
#ifdef _MSC_VER
#pragma warning(push)

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

@ -22,9 +22,6 @@
#include "jsatom.h"
#include "jsscript.h"
#ifdef XP_DARWIN
# include "wasm/WasmSignalHandlers.h"
#endif
#include "builtin/AtomicsObject.h"
#include "builtin/Intl.h"
#include "builtin/Promise.h"

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

@ -1709,7 +1709,7 @@ jit::JitActivation::startWasmInterrupt(const JS::ProfilingFrameIterator::Registe
bool ignoredUnwound;
wasm::UnwindState unwindState;
MOZ_ALWAYS_TRUE(wasm::StartUnwinding(*this, state, &unwindState, &ignoredUnwound));
MOZ_ALWAYS_TRUE(wasm::StartUnwinding(state, &unwindState, &ignoredUnwound));
void* pc = unwindState.pc;
MOZ_ASSERT(wasm::LookupCode(pc)->lookupRange(pc)->isFunction());

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

@ -3020,7 +3020,7 @@ class BaseCompiler final : public BaseCompilerInterface
if (fr.initialSize() > debugFrameReserved)
masm.addToStackPtr(Imm32(fr.initialSize() - debugFrameReserved));
BytecodeOffset prologueTrapOffset(func_.lineOrBytecode);
masm.jump(TrapDesc(prologueTrapOffset, Trap::StackOverflow, debugFrameReserved));
masm.jump(OldTrapDesc(prologueTrapOffset, Trap::StackOverflow, debugFrameReserved));
masm.bind(&returnLabel_);
@ -3045,7 +3045,7 @@ class BaseCompiler final : public BaseCompilerInterface
if (!generateOutOfLineCode())
return false;
masm.wasmEmitTrapOutOfLineCode();
masm.wasmEmitOldTrapOutOfLineCode();
offsets_.end = masm.currentOffset();
@ -3453,12 +3453,12 @@ class BaseCompiler final : public BaseCompilerInterface
}
void checkDivideByZeroI32(RegI32 rhs, RegI32 srcDest, Label* done) {
masm.branchTest32(Assembler::Zero, rhs, rhs, trap(Trap::IntegerDivideByZero));
masm.branchTest32(Assembler::Zero, rhs, rhs, oldTrap(Trap::IntegerDivideByZero));
}
void checkDivideByZeroI64(RegI64 r) {
ScratchI32 scratch(*this);
masm.branchTest64(Assembler::Zero, r, r, scratch, trap(Trap::IntegerDivideByZero));
masm.branchTest64(Assembler::Zero, r, r, scratch, oldTrap(Trap::IntegerDivideByZero));
}
void checkDivideSignedOverflowI32(RegI32 rhs, RegI32 srcDest, Label* done, bool zeroOnOverflow) {
@ -3469,7 +3469,7 @@ class BaseCompiler final : public BaseCompilerInterface
moveImm32(0, srcDest);
masm.jump(done);
} else {
masm.branch32(Assembler::Equal, rhs, Imm32(-1), trap(Trap::IntegerOverflow));
masm.branch32(Assembler::Equal, rhs, Imm32(-1), oldTrap(Trap::IntegerOverflow));
}
masm.bind(&notMin);
}
@ -3482,7 +3482,7 @@ class BaseCompiler final : public BaseCompilerInterface
masm.xor64(srcDest, srcDest);
masm.jump(done);
} else {
masm.jump(trap(Trap::IntegerOverflow));
masm.jump(oldTrap(Trap::IntegerOverflow));
}
masm.bind(&notmin);
}
@ -3809,7 +3809,7 @@ class BaseCompiler final : public BaseCompilerInterface
void unreachableTrap()
{
masm.jump(trap(Trap::Unreachable));
masm.jump(oldTrap(Trap::Unreachable));
#ifdef DEBUG
masm.breakpoint();
#endif
@ -3940,7 +3940,7 @@ class BaseCompiler final : public BaseCompilerInterface
(access->isAtomic() && !check->omitAlignmentCheck && !check->onlyPointerAlignment))
{
masm.branchAdd32(Assembler::CarrySet, Imm32(access->offset()), ptr,
trap(Trap::OutOfBounds));
oldTrap(Trap::OutOfBounds));
access->clearOffset();
check->onlyPointerAlignment = true;
}
@ -3951,7 +3951,7 @@ class BaseCompiler final : public BaseCompilerInterface
MOZ_ASSERT(check->onlyPointerAlignment);
// We only care about the low pointer bits here.
masm.branchTest32(Assembler::NonZero, ptr, Imm32(access->byteSize() - 1),
trap(Trap::UnalignedAccess));
oldTrap(Trap::UnalignedAccess));
}
// Ensure no tls if we don't need it.
@ -3972,7 +3972,7 @@ class BaseCompiler final : public BaseCompilerInterface
if (!check->omitBoundsCheck) {
masm.wasmBoundsCheck(Assembler::AboveOrEqual, ptr,
Address(tls, offsetof(TlsData, boundsCheckLimit)),
trap(Trap::OutOfBounds));
oldTrap(Trap::OutOfBounds));
}
#endif
}
@ -4905,11 +4905,11 @@ class BaseCompiler final : public BaseCompilerInterface
return iter_.bytecodeOffset();
}
TrapDesc trap(Trap t) const {
OldTrapDesc oldTrap(Trap t) const {
// Use masm.framePushed() because the value needed by the trap machinery
// is the size of the frame overall, not the height of the stack area of
// the frame.
return TrapDesc(bytecodeOffset(), t, masm.framePushed());
return OldTrapDesc(bytecodeOffset(), t, masm.framePushed());
}
////////////////////////////////////////////////////////////
@ -8395,7 +8395,7 @@ BaseCompiler::emitWait(ValType type, uint32_t byteSize)
default:
MOZ_CRASH();
}
masm.branchTest32(Assembler::Signed, ReturnReg, ReturnReg, trap(Trap::ThrowReported));
masm.branchTest32(Assembler::Signed, ReturnReg, ReturnReg, oldTrap(Trap::ThrowReported));
return true;
}
@ -8414,7 +8414,7 @@ BaseCompiler::emitWake()
return true;
emitInstanceCall(lineOrBytecode, SigPII_, ExprType::I32, SymbolicAddress::Wake);
masm.branchTest32(Assembler::Signed, ReturnReg, ReturnReg, trap(Trap::ThrowReported));
masm.branchTest32(Assembler::Signed, ReturnReg, ReturnReg, oldTrap(Trap::ThrowReported));
return true;
}

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

@ -96,17 +96,24 @@ static bool
WasmHandleDebugTrap()
{
JitActivation* activation = CallingActivation();
MOZ_ASSERT(activation);
JSContext* cx = activation->cx();
Frame* fp = activation->wasmExitFP();
Instance* instance = fp->tls->instance;
const Code& code = instance->code();
MOZ_ASSERT(code.metadata().debugEnabled);
WasmFrameIter frame(activation);
MOZ_ASSERT(frame.debugEnabled());
const CallSite* site = frame.debugTrapCallsite();
// The debug trap stub is the innermost frame. It's return address is the
// actual trap site.
const CallSite* site = code.lookupCallSite(fp->returnAddress);
MOZ_ASSERT(site);
// Advance to the actual trapping frame.
fp = fp->callerFP;
DebugFrame* debugFrame = DebugFrame::from(fp);
if (site->kind() == CallSite::EnterFrame) {
if (!frame.instance()->enterFrameTrapsEnabled())
if (!instance->enterFrameTrapsEnabled())
return true;
DebugFrame* debugFrame = frame.debugFrame();
debugFrame->setIsDebuggee();
debugFrame->observe(cx);
// TODO call onEnterFrame
@ -121,15 +128,13 @@ WasmHandleDebugTrap()
return status == JSTRAP_CONTINUE;
}
if (site->kind() == CallSite::LeaveFrame) {
DebugFrame* debugFrame = frame.debugFrame();
debugFrame->updateReturnJSValue();
bool ok = Debugger::onLeaveFrame(cx, debugFrame, nullptr, true);
debugFrame->leave(cx);
return ok;
}
DebugFrame* debugFrame = frame.debugFrame();
DebugState& debug = frame.instance()->debug();
DebugState& debug = instance->debug();
MOZ_ASSERT(debug.hasBreakpointTrapAtOffset(site->lineOrBytecode()));
if (debug.stepModeEnabled(debugFrame->funcIndex())) {
RootedValue result(cx, UndefinedValue());
@ -234,7 +239,7 @@ WasmHandleThrow()
}
static void
WasmReportTrap(int32_t trapIndex)
WasmOldReportTrap(int32_t trapIndex)
{
JSContext* cx = TlsContext.get();
@ -439,9 +444,9 @@ AddressOf(SymbolicAddress imm, ABIFunctionType* abiType)
case SymbolicAddress::HandleThrow:
*abiType = Args_General0;
return FuncCast(WasmHandleThrow, *abiType);
case SymbolicAddress::ReportTrap:
case SymbolicAddress::OldReportTrap:
*abiType = Args_General1;
return FuncCast(WasmReportTrap, *abiType);
return FuncCast(WasmOldReportTrap, *abiType);
case SymbolicAddress::ReportOutOfBounds:
*abiType = Args_General0;
return FuncCast(WasmReportOutOfBounds, *abiType);
@ -595,7 +600,7 @@ wasm::NeedsBuiltinThunk(SymbolicAddress sym)
case SymbolicAddress::HandleExecutionInterrupt: // GenerateInterruptExit
case SymbolicAddress::HandleDebugTrap: // GenerateDebugTrapStub
case SymbolicAddress::HandleThrow: // GenerateThrowStub
case SymbolicAddress::ReportTrap: // GenerateTrapExit
case SymbolicAddress::OldReportTrap: // GenerateOldTrapExit
case SymbolicAddress::ReportOutOfBounds: // GenerateOutOfBoundsExit
case SymbolicAddress::ReportUnalignedAccess: // GeneratesUnalignedExit
case SymbolicAddress::CallImport_Void: // GenerateImportInterpExit
@ -891,8 +896,8 @@ wasm::EnsureBuiltinThunksInitialized()
MOZ_ASSERT(masm.callSites().empty());
MOZ_ASSERT(masm.callSiteTargets().empty());
MOZ_ASSERT(masm.callFarJumps().empty());
MOZ_ASSERT(masm.trapSites().empty());
MOZ_ASSERT(masm.trapFarJumps().empty());
MOZ_ASSERT(masm.oldTrapSites().empty());
MOZ_ASSERT(masm.oldTrapFarJumps().empty());
MOZ_ASSERT(masm.callFarJumps().empty());
MOZ_ASSERT(masm.memoryAccesses().empty());
MOZ_ASSERT(masm.symbolicAccesses().empty());

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

@ -767,46 +767,6 @@ struct CallSiteRetAddrOffset
}
};
size_t
Code::serializedSize() const
{
return metadata().serializedSize() +
segment(Tier::Serialized).serializedSize();
}
uint8_t*
Code::serialize(uint8_t* cursor, const LinkData& linkData) const
{
MOZ_RELEASE_ASSERT(!metadata().debugEnabled);
cursor = metadata().serialize(cursor);
cursor = segment(Tier::Serialized).serialize(cursor, linkData.linkData(Tier::Serialized));
return cursor;
}
const uint8_t*
Code::deserialize(const uint8_t* cursor, const SharedBytes& bytecode, const LinkData& linkData,
Metadata& metadata)
{
cursor = metadata.deserialize(cursor);
if (!cursor)
return nullptr;
UniqueCodeSegment codeSegment = js::MakeUnique<CodeSegment>();
if (!codeSegment)
return nullptr;
cursor = codeSegment->deserialize(cursor, *bytecode, linkData.linkData(Tier::Serialized),
metadata);
if (!cursor)
return nullptr;
segment1_ = takeOwnership(Move(codeSegment));
metadata_ = &metadata;
return cursor;
}
const CallSite*
Code::lookupCallSite(void* returnAddress) const
{
@ -959,3 +919,43 @@ Code::addSizeOfMiscIfNotSeen(MallocSizeOf mallocSizeOf,
for (auto t : tiers())
segment(t).addSizeOfMisc(mallocSizeOf, code, data);
}
size_t
Code::serializedSize() const
{
return metadata().serializedSize() +
segment(Tier::Serialized).serializedSize();
}
uint8_t*
Code::serialize(uint8_t* cursor, const LinkData& linkData) const
{
MOZ_RELEASE_ASSERT(!metadata().debugEnabled);
cursor = metadata().serialize(cursor);
cursor = segment(Tier::Serialized).serialize(cursor, linkData.linkData(Tier::Serialized));
return cursor;
}
const uint8_t*
Code::deserialize(const uint8_t* cursor, const SharedBytes& bytecode, const LinkData& linkData,
Metadata& metadata)
{
cursor = metadata.deserialize(cursor);
if (!cursor)
return nullptr;
UniqueCodeSegment codeSegment = js::MakeUnique<CodeSegment>();
if (!codeSegment)
return nullptr;
cursor = codeSegment->deserialize(cursor, *bytecode, linkData.linkData(Tier::Serialized),
metadata);
if (!cursor)
return nullptr;
segment1_ = takeOwnership(Move(codeSegment));
metadata_ = &metadata;
return cursor;
}

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

@ -130,7 +130,7 @@ class CodeSegment
code_ = code;
}
const Code* code() const { MOZ_ASSERT(code_); return code_; }
const Code& code() const { MOZ_ASSERT(code_); return *code_; }
Tier tier() const { return tier_; }
uint8_t* base() const { return bytes_.get(); }

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

@ -35,24 +35,13 @@ using mozilla::Swap;
WasmFrameIter::WasmFrameIter(JitActivation* activation, wasm::Frame* fp)
: activation_(activation),
code_(nullptr),
callsite_(nullptr),
codeRange_(nullptr),
lineOrBytecode_(0),
fp_(fp ? fp : activation->wasmExitFP()),
unwind_(Unwind::False)
{
MOZ_ASSERT(fp_);
// Normally, execution exits wasm code via an exit stub which sets exitFP
// to the exit stub's frame. Thus, in this case, we want to start iteration
// at the caller of the exit frame, whose Code, CodeRange and CallSite are
// indicated by the returnAddress of the exit stub's frame.
if (!activation->isWasmInterrupted()) {
popFrame();
MOZ_ASSERT(!done());
return;
}
// When asynchronously interrupted, exitFP is set to the interrupted frame
// itself and so we do not want to skip it. Instead, we can recover the
// Code and CodeRange from the JitActivation, which are set when control
@ -61,12 +50,25 @@ WasmFrameIter::WasmFrameIter(JitActivation* activation, wasm::Frame* fp)
// for which we can use the beginning of the function from the CodeRange
// instead.
code_ = &fp_->tls->instance->code();
MOZ_ASSERT(code_ == LookupCode(activation->wasmUnwindPC()));
if (activation->isWasmInterrupted()) {
code_ = &fp_->tls->instance->code();
MOZ_ASSERT(code_ == LookupCode(activation->wasmUnwindPC()));
codeRange_ = code_->lookupRange(activation->wasmUnwindPC());
MOZ_ASSERT(codeRange_->kind() == CodeRange::Function);
codeRange_ = code_->lookupRange(activation->wasmUnwindPC());
MOZ_ASSERT(codeRange_->kind() == CodeRange::Function);
lineOrBytecode_ = codeRange_->funcLineOrBytecode();
MOZ_ASSERT(!done());
return;
}
// Otherwise, execution exits wasm code via an exit stub which sets exitFP
// to the exit stub's frame. Thus, in this case, we want to start iteration
// at the caller of the exit frame, whose Code, CodeRange and CallSite are
// indicated by the returnAddress of the exit stub's frame.
popFrame();
MOZ_ASSERT(!done());
}
@ -112,7 +114,6 @@ WasmFrameIter::popFrame()
if (!fp_) {
code_ = nullptr;
codeRange_ = nullptr;
callsite_ = nullptr;
if (unwind_ == Unwind::True) {
// TODO with bug 1319203, there may be other JIT frames above.
@ -132,8 +133,10 @@ WasmFrameIter::popFrame()
codeRange_ = code_->lookupRange(returnAddress);
MOZ_ASSERT(codeRange_->kind() == CodeRange::Function);
callsite_ = code_->lookupCallSite(returnAddress);
MOZ_ASSERT(callsite_);
const CallSite* callsite = code_->lookupCallSite(returnAddress);
MOZ_ASSERT(callsite);
lineOrBytecode_ = callsite->lineOrBytecode();
MOZ_ASSERT(!done());
}
@ -178,8 +181,7 @@ unsigned
WasmFrameIter::lineOrBytecode() const
{
MOZ_ASSERT(!done());
MOZ_ASSERT_IF(!callsite_, activation_->isWasmInterrupted());
return callsite_ ? callsite_->lineOrBytecode() : codeRange_->funcLineOrBytecode();
return lineOrBytecode_;
}
Instance*
@ -216,20 +218,7 @@ DebugFrame*
WasmFrameIter::debugFrame() const
{
MOZ_ASSERT(!done());
MOZ_ASSERT(debugEnabled());
return reinterpret_cast<DebugFrame*>((uint8_t*)fp_ - DebugFrame::offsetOfFrame());
}
const CallSite*
WasmFrameIter::debugTrapCallsite() const
{
MOZ_ASSERT(!done());
MOZ_ASSERT(callsite_);
MOZ_ASSERT(debugEnabled());
MOZ_ASSERT(callsite_->kind() == CallSite::EnterFrame ||
callsite_->kind() == CallSite::LeaveFrame ||
callsite_->kind() == CallSite::Breakpoint);
return callsite_;
return DebugFrame::from(fp_);
}
/*****************************************************************************/
@ -446,7 +435,7 @@ wasm::GenerateFunctionPrologue(MacroAssembler& masm, unsigned framePushed, const
// Generate table entry:
offsets->begin = masm.currentOffset();
BytecodeOffset trapOffset(0); // ignored by masm.wasmEmitTrapOutOfLineCode
TrapDesc trap(trapOffset, Trap::IndirectCallBadSig, masm.framePushed());
OldTrapDesc trap(trapOffset, Trap::IndirectCallBadSig, masm.framePushed());
switch (sigId.kind()) {
case SigIdDesc::Kind::Global: {
Register scratch = WasmTableCallScratchReg;
@ -547,8 +536,7 @@ wasm::GenerateJitExitEpilogue(MacroAssembler& masm, unsigned framePushed, Callab
// ProfilingFrameIterator
ProfilingFrameIterator::ProfilingFrameIterator()
: activation_(nullptr),
code_(nullptr),
: code_(nullptr),
codeRange_(nullptr),
callerFP_(nullptr),
callerPC_(nullptr),
@ -559,8 +547,7 @@ ProfilingFrameIterator::ProfilingFrameIterator()
}
ProfilingFrameIterator::ProfilingFrameIterator(const JitActivation& activation)
: activation_(&activation),
code_(nullptr),
: code_(nullptr),
codeRange_(nullptr),
callerFP_(nullptr),
callerPC_(nullptr),
@ -571,8 +558,7 @@ ProfilingFrameIterator::ProfilingFrameIterator(const JitActivation& activation)
}
ProfilingFrameIterator::ProfilingFrameIterator(const JitActivation& activation, const Frame* fp)
: activation_(&activation),
code_(nullptr),
: code_(nullptr),
codeRange_(nullptr),
callerFP_(nullptr),
callerPC_(nullptr),
@ -584,7 +570,7 @@ ProfilingFrameIterator::ProfilingFrameIterator(const JitActivation& activation,
}
static inline void
AssertMatchesCallSite(const JitActivation& activation, void* callerPC, Frame* callerFP)
AssertMatchesCallSite(void* callerPC, Frame* callerFP)
{
#ifdef DEBUG
const Code* code = LookupCode(callerPC);
@ -633,12 +619,12 @@ ProfilingFrameIterator::initFromExitFP(const Frame* fp)
fp = fp->callerFP;
callerPC_ = fp->returnAddress;
callerFP_ = fp->callerFP;
AssertMatchesCallSite(*activation_, callerPC_, callerFP_);
AssertMatchesCallSite(callerPC_, callerFP_);
break;
case CodeRange::ImportJitExit:
case CodeRange::ImportInterpExit:
case CodeRange::BuiltinThunk:
case CodeRange::TrapExit:
case CodeRange::OldTrapExit:
case CodeRange::DebugTrap:
case CodeRange::OutOfBoundsExit:
case CodeRange::UnalignedExit:
@ -652,8 +638,8 @@ ProfilingFrameIterator::initFromExitFP(const Frame* fp)
}
bool
js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& registers,
UnwindState* unwindState, bool* unwoundCaller)
js::wasm::StartUnwinding(const RegisterState& registers, UnwindState* unwindState,
bool* unwoundCaller)
{
// Shorthands.
uint8_t* const pc = (uint8_t*) registers.pc;
@ -673,7 +659,7 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
const CodeSegment* codeSegment = LookupCodeSegment(pc);
if (codeSegment) {
code = codeSegment->code();
code = &codeSegment->code();
codeRange = code->lookupRange(pc);
codeBase = codeSegment->base();
} else if (!LookupBuiltinThunk(pc, &codeRange, &codeBase)) {
@ -717,7 +703,7 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
case CodeRange::ImportJitExit:
case CodeRange::ImportInterpExit:
case CodeRange::BuiltinThunk:
case CodeRange::TrapExit:
case CodeRange::OldTrapExit:
case CodeRange::DebugTrap:
#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
if ((offsetFromEntry >= BeforePushRetAddr && offsetFromEntry < PushedFP) || codeRange->isThunk()) {
@ -731,14 +717,14 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
// fp holds the caller's fp.
fixedPC = (uint8_t*) registers.lr;
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
AssertMatchesCallSite(fixedPC, fixedFP);
} else
#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
if (offsetFromEntry == BeforePushRetAddr || codeRange->isThunk()) {
// The return address is still in lr and fp holds the caller's fp.
fixedPC = (uint8_t*) registers.lr;
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
AssertMatchesCallSite(fixedPC, fixedFP);
} else
#endif
if (offsetFromEntry == PushedRetAddr || codeRange->isThunk()) {
@ -746,26 +732,26 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
// points to the caller's fp.
fixedPC = sp[0];
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
AssertMatchesCallSite(fixedPC, fixedFP);
} else if (offsetFromEntry >= PushedTLS && offsetFromEntry < PushedFP) {
// The return address and caller's TLS have been pushed on the
// stack; fp is still the caller's fp.
fixedPC = sp[1];
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
AssertMatchesCallSite(fixedPC, fixedFP);
} else if (offsetFromEntry == PushedFP) {
// The full Frame has been pushed; fp is still the caller's fp.
MOZ_ASSERT(fp == reinterpret_cast<Frame*>(sp)->callerFP);
fixedPC = reinterpret_cast<Frame*>(sp)->returnAddress;
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
AssertMatchesCallSite(fixedPC, fixedFP);
} else if (offsetInCode >= codeRange->ret() - PoppedFP &&
offsetInCode < codeRange->ret() - PoppedTLSReg)
{
// The fixedFP field of the Frame has been popped into fp.
fixedPC = sp[1];
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
AssertMatchesCallSite(fixedPC, fixedFP);
#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
} else if (offsetInCode >= codeRange->ret() - PoppedTLSReg &&
offsetInCode < codeRange->ret())
@ -774,20 +760,20 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
// exit reason hasn't been popped yet.
fixedPC = sp[0];
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
AssertMatchesCallSite(fixedPC, fixedFP);
} else if (offsetInCode == codeRange->ret()) {
// Both the TLS, fixedFP and ra have been popped and fp now
// points to the caller's frame.
fixedPC = (uint8_t*) registers.lr;
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
AssertMatchesCallSite(fixedPC, fixedFP);
#else
} else if (offsetInCode == codeRange->ret()) {
// Both the TLS and fixedFP fields have been popped and fp now
// points to the caller's frame.
fixedPC = sp[0];
fixedFP = fp;
AssertMatchesCallSite(activation, fixedPC, fixedFP);
AssertMatchesCallSite(fixedPC, fixedFP);
#endif
} else {
if (codeRange->kind() == CodeRange::ImportJitExit) {
@ -804,7 +790,7 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
fixedPC = pc;
fixedFP = fp;
*unwoundCaller = false;
AssertMatchesCallSite(activation, fp->returnAddress, fp->callerFP);
AssertMatchesCallSite(fp->returnAddress, fp->callerFP);
break;
}
break;
@ -815,7 +801,7 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
fixedPC = pc;
fixedFP = fp;
*unwoundCaller = false;
AssertMatchesCallSite(activation, fp->returnAddress, fp->callerFP);
AssertMatchesCallSite(fp->returnAddress, fp->callerFP);
break;
case CodeRange::InterpEntry:
// The entry trampoline is the final frame in an wasm JitActivation. The
@ -843,8 +829,7 @@ js::wasm::StartUnwinding(const JitActivation& activation, const RegisterState& r
ProfilingFrameIterator::ProfilingFrameIterator(const JitActivation& activation,
const RegisterState& state)
: activation_(&activation),
code_(nullptr),
: code_(nullptr),
codeRange_(nullptr),
callerFP_(nullptr),
callerPC_(nullptr),
@ -862,7 +847,7 @@ ProfilingFrameIterator::ProfilingFrameIterator(const JitActivation& activation,
bool unwoundCaller;
UnwindState unwindState;
if (!StartUnwinding(*activation_, state, &unwindState, &unwoundCaller)) {
if (!StartUnwinding(state, &unwindState, &unwoundCaller)) {
MOZ_ASSERT(done());
return;
}
@ -917,14 +902,14 @@ ProfilingFrameIterator::operator++()
case CodeRange::ImportJitExit:
case CodeRange::ImportInterpExit:
case CodeRange::BuiltinThunk:
case CodeRange::TrapExit:
case CodeRange::OldTrapExit:
case CodeRange::DebugTrap:
case CodeRange::OutOfBoundsExit:
case CodeRange::UnalignedExit:
case CodeRange::FarJumpIsland:
stackAddress_ = callerFP_;
callerPC_ = callerFP_->returnAddress;
AssertMatchesCallSite(*activation_, callerPC_, callerFP_->callerFP);
AssertMatchesCallSite(callerPC_, callerFP_->callerFP);
callerFP_ = callerFP_->callerFP;
break;
case CodeRange::InterpEntry:
@ -945,7 +930,7 @@ ThunkedNativeToDescription(SymbolicAddress func)
case SymbolicAddress::HandleExecutionInterrupt:
case SymbolicAddress::HandleDebugTrap:
case SymbolicAddress::HandleThrow:
case SymbolicAddress::ReportTrap:
case SymbolicAddress::OldReportTrap:
case SymbolicAddress::ReportOutOfBounds:
case SymbolicAddress::ReportUnalignedAccess:
case SymbolicAddress::CallImport_Void:
@ -1075,7 +1060,7 @@ ProfilingFrameIterator::label() const
case CodeRange::ImportJitExit: return importJitDescription;
case CodeRange::BuiltinThunk: return builtinNativeDescription;
case CodeRange::ImportInterpExit: return importInterpDescription;
case CodeRange::TrapExit: return trapDescription;
case CodeRange::OldTrapExit: return trapDescription;
case CodeRange::DebugTrap: return debugTrapDescription;
case CodeRange::OutOfBoundsExit: return "out-of-bounds stub (in wasm)";
case CodeRange::UnalignedExit: return "unaligned trap stub (in wasm)";
@ -1096,7 +1081,7 @@ wasm::LookupFaultingInstance(const CodeSegment& codeSegment, void* pc, void* fp)
// simulators which call this function at every load/store before even
// knowing whether there is a fault.
const CodeRange* codeRange = codeSegment.code()->lookupRange(pc);
const CodeRange* codeRange = codeSegment.code().lookupRange(pc);
if (!codeRange || !codeRange->isFunction())
return nullptr;
@ -1107,7 +1092,7 @@ wasm::LookupFaultingInstance(const CodeSegment& codeSegment, void* pc, void* fp)
return nullptr;
Instance* instance = reinterpret_cast<Frame*>(fp)->tls->instance;
MOZ_RELEASE_ASSERT(&instance->code() == codeSegment.code());
MOZ_RELEASE_ASSERT(&instance->code() == &codeSegment.code());
return instance;
}

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

@ -66,8 +66,8 @@ class WasmFrameIter
private:
jit::JitActivation* activation_;
const Code* code_;
const CallSite* callsite_;
const CodeRange* codeRange_;
unsigned lineOrBytecode_;
Frame* fp_;
Unwind unwind_;
void** unwoundAddressOfReturnAddress_;
@ -91,7 +91,6 @@ class WasmFrameIter
void** unwoundAddressOfReturnAddress() const;
bool debugEnabled() const;
DebugFrame* debugFrame() const;
const CallSite* debugTrapCallsite() const;
};
enum class SymbolicAddress;
@ -160,7 +159,6 @@ class ExitReason
// asynchronously-interrupted thread's state.
class ProfilingFrameIterator
{
const jit::JitActivation* activation_;
const Code* code_;
const CodeRange* codeRange_;
Frame* callerFP_;
@ -253,8 +251,8 @@ typedef JS::ProfilingFrameIterator::RegisterState RegisterState;
// frame should be ignored.
bool
StartUnwinding(const jit::JitActivation& activation, const RegisterState& registers,
UnwindState* unwindState, bool* unwoundCaller);
StartUnwinding(const RegisterState& registers, UnwindState* unwindState,
bool* unwoundCaller);
} // namespace wasm
} // namespace js

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

@ -47,9 +47,9 @@ CompiledCode::swap(MacroAssembler& masm)
callSites.swap(masm.callSites());
callSiteTargets.swap(masm.callSiteTargets());
trapSites.swap(masm.trapSites());
oldTrapSites.swap(masm.oldTrapSites());
callFarJumps.swap(masm.callFarJumps());
trapFarJumps.swap(masm.trapFarJumps());
oldTrapFarJumps.swap(masm.oldTrapFarJumps());
memoryAccesses.swap(masm.memoryAccesses());
symbolicAccesses.swap(masm.symbolicAccesses());
codeLabels.swap(masm.codeLabels());
@ -75,7 +75,7 @@ ModuleGenerator::ModuleGenerator(const CompileArgs& args, ModuleEnvironment* env
lifo_(GENERATOR_LIFO_DEFAULT_CHUNK_SIZE),
masmAlloc_(&lifo_),
masm_(MacroAssembler::WasmToken(), masmAlloc_),
trapCodeOffsets_(),
oldTrapCodeOffsets_(),
debugTrapCodeOffset_(),
lastPatchedCallSite_(0),
startOfUnpatchedCallsites_(0),
@ -86,7 +86,7 @@ ModuleGenerator::ModuleGenerator(const CompileArgs& args, ModuleEnvironment* env
finishedFuncDefs_(false)
{
MOZ_ASSERT(IsCompilingWasm());
std::fill(trapCodeOffsets_.begin(), trapCodeOffsets_.end(), 0);
std::fill(oldTrapCodeOffsets_.begin(), oldTrapCodeOffsets_.end(), 0);
}
ModuleGenerator::~ModuleGenerator()
@ -206,8 +206,8 @@ ModuleGenerator::init(Metadata* maybeAsmJSMetadata)
if (!metadataTier_->codeRanges.reserve(2 * env_->numFuncDefs()))
return false;
const size_t CallSitesPerByteCode = 10;
if (!metadataTier_->callSites.reserve(codeSectionSize / CallSitesPerByteCode))
const size_t ByteCodesPerCallSite = 10;
if (!metadataTier_->callSites.reserve(codeSectionSize / ByteCodesPerCallSite))
return false;
const size_t MemoryAccessesPerByteCode = 10;
@ -436,14 +436,14 @@ ModuleGenerator::linkCallSites()
masm_.patchCall(callerOffset, p->value());
break;
}
case CallSiteDesc::TrapExit: {
case CallSiteDesc::OldTrapExit: {
if (!existingTrapFarJumps[target.trap()]) {
// See MacroAssembler::wasmEmitTrapOutOfLineCode for why we must
// See MacroAssembler::wasmEmitOldTrapOutOfLineCode for why we must
// reload the TLS register on this path.
Offsets offsets;
offsets.begin = masm_.currentOffset();
masm_.loadPtr(Address(FramePointer, offsetof(Frame, tls)), WasmTlsReg);
if (!trapFarJumps_.emplaceBack(target.trap(), masm_.farJumpWithPatch()))
if (!oldTrapFarJumps_.emplaceBack(target.trap(), masm_.farJumpWithPatch()))
return false;
offsets.end = masm_.currentOffset();
if (masm_.oom())
@ -503,9 +503,9 @@ ModuleGenerator::noteCodeRange(uint32_t codeRangeIndex, const CodeRange& codeRan
case CodeRange::ImportInterpExit:
metadataTier_->funcImports[codeRange.funcIndex()].initInterpExitOffset(codeRange.begin());
break;
case CodeRange::TrapExit:
MOZ_ASSERT(!trapCodeOffsets_[codeRange.trap()]);
trapCodeOffsets_[codeRange.trap()] = codeRange.begin();
case CodeRange::OldTrapExit:
MOZ_ASSERT(!oldTrapCodeOffsets_[codeRange.trap()]);
oldTrapCodeOffsets_[codeRange.trap()] = codeRange.begin();
break;
case CodeRange::DebugTrap:
MOZ_ASSERT(!debugTrapCodeOffset_);
@ -580,10 +580,10 @@ ModuleGenerator::linkCompiledCode(const CompiledCode& code)
if (!callSiteTargets_.appendAll(code.callSiteTargets))
return false;
MOZ_ASSERT(code.trapSites.empty());
MOZ_ASSERT(code.oldTrapSites.empty());
auto trapFarJumpOp = [=](uint32_t, TrapFarJump* tfj) { tfj->offsetBy(offsetInModule); };
if (!AppendForEach(&trapFarJumps_, code.trapFarJumps, trapFarJumpOp))
auto trapFarJumpOp = [=](uint32_t, OldTrapFarJump* tfj) { tfj->offsetBy(offsetInModule); };
if (!AppendForEach(&oldTrapFarJumps_, code.oldTrapFarJumps, trapFarJumpOp))
return false;
auto callFarJumpOp = [=](uint32_t, CallFarJump* cfj) { cfj->offsetBy(offsetInModule); };
@ -788,8 +788,8 @@ ModuleGenerator::finishCode()
for (CallFarJump far : callFarJumps_)
masm_.patchFarJump(far.jump, funcCodeRange(far.funcIndex).funcNormalEntry());
for (TrapFarJump far : trapFarJumps_)
masm_.patchFarJump(far.jump, trapCodeOffsets_[far.trap]);
for (OldTrapFarJump far : oldTrapFarJumps_)
masm_.patchFarJump(far.jump, oldTrapCodeOffsets_[far.trap]);
for (CodeOffset farJump : debugTrapFarJumps_)
masm_.patchFarJump(farJump, debugTrapCodeOffset_);
@ -798,8 +798,8 @@ ModuleGenerator::finishCode()
MOZ_ASSERT(masm_.callSites().empty());
MOZ_ASSERT(masm_.callSiteTargets().empty());
MOZ_ASSERT(masm_.trapSites().empty());
MOZ_ASSERT(masm_.trapFarJumps().empty());
MOZ_ASSERT(masm_.oldTrapSites().empty());
MOZ_ASSERT(masm_.oldTrapFarJumps().empty());
MOZ_ASSERT(masm_.callFarJumps().empty());
MOZ_ASSERT(masm_.memoryAccesses().empty());
MOZ_ASSERT(masm_.symbolicAccesses().empty());

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

@ -64,8 +64,8 @@ struct CompiledCode
CodeRangeVector codeRanges;
CallSiteVector callSites;
CallSiteTargetVector callSiteTargets;
TrapSiteVector trapSites;
TrapFarJumpVector trapFarJumps;
OldTrapSiteVector oldTrapSites;
OldTrapFarJumpVector oldTrapFarJumps;
CallFarJumpVector callFarJumps;
MemoryAccessVector memoryAccesses;
SymbolicAccessVector symbolicAccesses;
@ -78,8 +78,8 @@ struct CompiledCode
codeRanges.clear();
callSites.clear();
callSiteTargets.clear();
trapSites.clear();
trapFarJumps.clear();
oldTrapSites.clear();
oldTrapFarJumps.clear();
callFarJumps.clear();
memoryAccesses.clear();
symbolicAccesses.clear();
@ -92,8 +92,8 @@ struct CompiledCode
codeRanges.empty() &&
callSites.empty() &&
callSiteTargets.empty() &&
trapSites.empty() &&
trapFarJumps.empty() &&
oldTrapSites.empty() &&
oldTrapFarJumps.empty() &&
callFarJumps.empty() &&
memoryAccesses.empty() &&
symbolicAccesses.empty() &&
@ -145,7 +145,7 @@ struct CompileTask
class MOZ_STACK_CLASS ModuleGenerator
{
typedef Vector<CompileTask, 0, SystemAllocPolicy> CompileTaskVector;
typedef EnumeratedArray<Trap, Trap::Limit, uint32_t> Uint32TrapArray;
typedef EnumeratedArray<Trap, Trap::Limit, uint32_t> OldTrapOffsetArray;
typedef Vector<jit::CodeOffset, 0, SystemAllocPolicy> CodeOffsetVector;
// Constant parameters
@ -168,9 +168,9 @@ class MOZ_STACK_CLASS ModuleGenerator
jit::TempAllocator masmAlloc_;
jit::MacroAssembler masm_;
Uint32Vector funcToCodeRange_;
Uint32TrapArray trapCodeOffsets_;
OldTrapOffsetArray oldTrapCodeOffsets_;
uint32_t debugTrapCodeOffset_;
TrapFarJumpVector trapFarJumps_;
OldTrapFarJumpVector oldTrapFarJumps_;
CallFarJumpVector callFarJumps_;
CallSiteTargetVector callSiteTargets_;
uint32_t lastPatchedCallSite_;

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