Merge mozilla-central to autoland. a=merge CLOSED TREE
Merge mozilla-central to autoland. a=merge CLOSED TREE
--- a/accessible/windows/msaa/Compatibility.cpp
+++ b/accessible/windows/msaa/Compatibility.cpp
@@ -90,17 +90,18 @@ Compatibility::IsModuleVersionLessThan(H
}
////////////////////////////////////////////////////////////////////////////////
// Compatibility
////////////////////////////////////////////////////////////////////////////////
static WindowsDllInterceptor sUser32Interceptor;
-static decltype(&InSendMessageEx) sInSendMessageExStub = nullptr;
+static WindowsDllInterceptor::FuncHookType<decltype(&InSendMessageEx)>
+ sInSendMessageExStub;
static bool sInSendMessageExHackEnabled = false;
static PVOID sVectoredExceptionHandler = nullptr;
#if defined(_MSC_VER)
#include <intrin.h>
#pragma intrinsic(_ReturnAddress)
#define RETURN_ADDRESS() _ReturnAddress()
#elif defined(__GNUC__) || defined(__clang__)
@@ -262,21 +263,19 @@ Compatibility::Init()
}
// If we have a consumer who is not NVDA, we enable detection for the
// InSendMessageEx compatibility hack. NVDA does not require this.
// We also skip UIA, as we see crashes there.
if ((sConsumers & (~(UIAUTOMATION | NVDA))) &&
BrowserTabsRemoteAutostart()) {
sUser32Interceptor.Init("user32.dll");
- if (!sInSendMessageExStub) {
- sUser32Interceptor.AddHook("InSendMessageEx",
- reinterpret_cast<intptr_t>(&InSendMessageExHook),
- (void**)&sInSendMessageExStub);
- }
+ sInSendMessageExStub.Set(sUser32Interceptor, "InSendMessageEx",
+ &InSendMessageExHook);
+
// The vectored exception handler allows us to catch exceptions ahead of any
// SEH handlers.
if (!sVectoredExceptionHandler) {
// We need to let ASan's ShadowExceptionHandler remain in the firstHandler
// position, otherwise we'll get infinite recursion when our handler
// faults on shadow memory.
const ULONG firstHandler = FALSE;
sVectoredExceptionHandler =
--- a/browser/app/winlauncher/DllBlocklistWin.cpp
+++ b/browser/app/winlauncher/DllBlocklistWin.cpp
@@ -241,17 +241,18 @@ IsDllAllowed(const UNICODE_STRING& aLeaf
gBlockSet.Add(info->name, version);
return false;
}
return true;
}
typedef decltype(&NtMapViewOfSection) NtMapViewOfSection_func;
-static NtMapViewOfSection_func stub_NtMapViewOfSection;
+static mozilla::CrossProcessDllInterceptor::FuncHookType<NtMapViewOfSection_func>
+ stub_NtMapViewOfSection;
static NTSTATUS NTAPI
patched_NtMapViewOfSection(HANDLE aSection, HANDLE aProcess, PVOID* aBaseAddress,
ULONG_PTR aZeroBits, SIZE_T aCommitSize,
PLARGE_INTEGER aSectionOffset, PSIZE_T aViewSize,
SECTION_INHERIT aInheritDisposition,
ULONG aAllocationType, ULONG aProtectionFlags)
{
@@ -351,19 +352,18 @@ private:
DWORD mPrevProt;
};
bool
InitializeDllBlocklistOOP(HANDLE aChildProcess)
{
mozilla::CrossProcessDllInterceptor intcpt(aChildProcess);
intcpt.Init(L"ntdll.dll");
- bool ok = intcpt.AddDetour("NtMapViewOfSection",
- reinterpret_cast<intptr_t>(&patched_NtMapViewOfSection),
- (void**) &stub_NtMapViewOfSection);
+ bool ok = stub_NtMapViewOfSection.SetDetour(intcpt, "NtMapViewOfSection",
+ &patched_NtMapViewOfSection);
if (!ok) {
return false;
}
// Set the child process's copy of stub_NtMapViewOfSection
SIZE_T bytesWritten;
ok = !!::WriteProcessMemory(aChildProcess, &stub_NtMapViewOfSection,
&stub_NtMapViewOfSection,
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -990,22 +990,32 @@ nsContextMenu.prototype = {
}
if (!name)
name = "snapshot.jpg";
mm.sendAsyncMessage("ContextMenu:SaveVideoFrameAsImage", {}, {
target: this.target,
});
+ // Cache this because we fetch the data async
+ let {documentURIObject} = gContextMenuContentData;
+
let onMessage = (message) => {
mm.removeMessageListener("ContextMenu:SaveVideoFrameAsImage:Result", onMessage);
+ // FIXME can we switch this to a blob URL?
let dataURL = message.data.dataURL;
- saveImageURL(dataURL, name, "SaveImageTitle", true, false,
- document.documentURIObject, null, null, null,
- isPrivate);
+ saveImageURL(dataURL, name, "SaveImageTitle",
+ true, // bypass cache
+ false, // don't skip prompt for where to save
+ documentURIObject, // referrer
+ null, // document
+ null, // content type
+ null, // content disposition
+ isPrivate,
+ this.principal);
};
mm.addMessageListener("ContextMenu:SaveVideoFrameAsImage:Result", onMessage);
},
leaveDOMFullScreen() {
document.exitFullscreen();
},
@@ -1233,23 +1243,25 @@ nsContextMenu.prototype = {
let isContentWindowPrivate = this.isRemote ? this.ownerDoc.isPrivate : undefined;
let referrerURI = gContextMenuContentData.documentURIObject;
let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(this.browser);
if (this.onCanvas) {
// Bypass cache, since it's a data: URL.
this._canvasToBlobURL(this.target).then(function(blobURL) {
saveImageURL(blobURL, "canvas.png", "SaveImageTitle",
true, false, referrerURI, null, null, null,
- isPrivate);
+ isPrivate,
+ document.nodePrincipal /* system, because blob: */);
}, Cu.reportError);
} else if (this.onImage) {
urlSecurityCheck(this.mediaURL, this.principal);
saveImageURL(this.mediaURL, null, "SaveImageTitle", false,
false, referrerURI, null, gContextMenuContentData.contentType,
- gContextMenuContentData.contentDisposition, isPrivate);
+ gContextMenuContentData.contentDisposition, isPrivate,
+ this.principal);
} else if (this.onVideo || this.onAudio) {
var dialogTitle = this.onVideo ? "SaveVideoTitle" : "SaveAudioTitle";
this.saveHelper(this.mediaURL, null, dialogTitle, false, doc, referrerURI,
this.frameOuterWindowID, "", isContentWindowPrivate);
}
},
// Backwards-compatibility wrapper
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -684,17 +684,18 @@ function saveMedia() {
null, gDocInfo.isContentWindowPrivate);
}
} else {
selectSaveFolder(function(aDirectory) {
if (aDirectory) {
var saveAnImage = function(aURIString, aChosenData, aBaseURI) {
uniqueFile(aChosenData.file);
internalSave(aURIString, null, null, null, null, false, "SaveImageTitle",
- aChosenData, aBaseURI, null, false, null, gDocInfo.isContentWindowPrivate);
+ aChosenData, aBaseURI, null, false, null,
+ gDocInfo.isContentWindowPrivate, gDocInfo.principal);
};
for (var i = 0; i < rowArray.length; i++) {
let v = rowArray[i];
let dir = aDirectory.clone();
let item = gImageView.data[v][COL_IMAGE_NODE];
let uriString = gImageView.data[v][COL_IMAGE_ADDRESS];
let uri = makeURI(uriString);
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -300,17 +300,18 @@ function openLinkIn(url, where, params)
params.forceAboutBlankViewerInCurrent;
var aResolveOnNewTabCreated = params.resolveOnNewTabCreated;
if (where == "save") {
// TODO(1073187): propagate referrerPolicy.
// ContentClick.jsm passes isContentWindowPrivate for saveURL instead of passing a CPOW initiatingDoc
if ("isContentWindowPrivate" in params) {
- saveURL(url, null, null, true, true, aNoReferrer ? null : aReferrerURI, null, params.isContentWindowPrivate);
+ saveURL(url, null, null, true, true, aNoReferrer ? null : aReferrerURI,
+ null, params.isContentWindowPrivate, aPrincipal);
} else {
if (!aInitiatingDoc) {
Cu.reportError("openUILink/openLinkIn was called with " +
"where == 'save' but without initiatingDoc. See bug 814264.");
return;
}
saveURL(url, null, null, true, true, aNoReferrer ? null : aReferrerURI, aInitiatingDoc);
}
--- a/browser/components/shell/nsMacShellService.cpp
+++ b/browser/components/shell/nsMacShellService.cpp
@@ -148,17 +148,17 @@ nsMacShellService::SetDesktopBackground(
nsCOMPtr<nsILoadContext> loadContext;
nsCOMPtr<nsISupports> container = aElement->OwnerDoc()->GetContainer();
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
if (docShell) {
loadContext = do_QueryInterface(docShell);
}
- return wbp->SaveURI(imageURI, 0,
+ return wbp->SaveURI(imageURI, aElement->NodePrincipal(), 0,
docURI, aElement->OwnerDoc()->GetReferrerPolicy(),
nullptr, nullptr,
mBackgroundFile, loadContext);
}
NS_IMETHODIMP
nsMacShellService::OnProgressChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
--- a/devtools/shared/gcli/commands/screenshot.js
+++ b/devtools/shared/gcli/commands/screenshot.js
@@ -549,17 +549,16 @@ var saveToFile = Task.async(function* (c
// Create download and track its progress.
// This is adapted from saveURL in contentAreaUtils.js, but simplified greatly
// and modified to allow saving to arbitrary paths on disk. Using these
// objects as opposed to just writing with OS.File allows us to tie into the
// download manager to record a download entry and to get visual feedback from
// the downloads toolbar button when the save is done.
const nsIWBP = Ci.nsIWebBrowserPersist;
const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
- nsIWBP.PERSIST_FLAGS_FORCE_ALLOW_COOKIES |
nsIWBP.PERSIST_FLAGS_BYPASS_CACHE |
nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
const isPrivate =
PrivateBrowsingUtils.isContentWindowPrivate(document.defaultView);
const persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(Ci.nsIWebBrowserPersist);
persist.persistFlags = flags;
const tr = Cc["@mozilla.org/transfer;1"].createInstance(Ci.nsITransfer);
@@ -568,17 +567,19 @@ var saveToFile = Task.async(function* (c
"",
null,
null,
null,
persist,
isPrivate);
const listener = new DownloadListener(window, tr);
persist.progressListener = listener;
+ const principal = Services.scriptSecurityManager.getSystemPrincipal();
persist.savePrivacyAwareURI(sourceURI,
+ principal,
0,
document.documentURIObject,
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
null,
null,
targetFileURI,
isPrivate);
--- a/devtools/shared/webconsole/screenshot-helper.js
+++ b/devtools/shared/webconsole/screenshot-helper.js
@@ -350,17 +350,16 @@ async function saveToFile(window, image)
// Create download and track its progress.
// This is adapted from saveURL in contentAreaUtils.js, but simplified greatly
// and modified to allow saving to arbitrary paths on disk. Using these
// objects as opposed to just writing with OS.File allows us to tie into the
// download manager to record a download entry and to get visual feedback from
// the downloads toolbar button when the save is done.
const nsIWBP = Ci.nsIWebBrowserPersist;
const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
- nsIWBP.PERSIST_FLAGS_FORCE_ALLOW_COOKIES |
nsIWBP.PERSIST_FLAGS_BYPASS_CACHE |
nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
const isPrivate =
PrivateBrowsingUtils.isContentWindowPrivate(document.defaultView);
const persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(Ci.nsIWebBrowserPersist);
persist.persistFlags = flags;
const tr = Cc["@mozilla.org/transfer;1"].createInstance(Ci.nsITransfer);
@@ -369,17 +368,19 @@ async function saveToFile(window, image)
"",
null,
null,
null,
persist,
isPrivate);
const listener = new DownloadListener(window, tr);
persist.progressListener = listener;
+ const principal = Services.scriptSecurityManager.getSystemPrincipal();
persist.savePrivacyAwareURI(sourceURI,
+ principal,
0,
document.documentURIObject,
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
null,
null,
targetFileURI,
isPrivate);
--- a/devtools/startup/devtools-startup.js
+++ b/devtools/startup/devtools-startup.js
@@ -35,16 +35,18 @@ const { XPCOMUtils } = ChromeUtils.impor
ChromeUtils.defineModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
ChromeUtils.defineModuleGetter(this, "AppConstants",
"resource://gre/modules/AppConstants.jsm");
ChromeUtils.defineModuleGetter(this, "CustomizableUI",
"resource:///modules/CustomizableUI.jsm");
ChromeUtils.defineModuleGetter(this, "CustomizableWidgets",
"resource:///modules/CustomizableWidgets.jsm");
+ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
+ "resource://gre/modules/PrivateBrowsingUtils.jsm");
// We don't want to spend time initializing the full loader here so we create
// our own lazy require.
XPCOMUtils.defineLazyGetter(this, "Telemetry", function() {
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
// eslint-disable-next-line no-shadow
const Telemetry = require("devtools/client/shared/telemetry");
@@ -943,26 +945,42 @@ const JsonView = {
*/
onSave: function(message) {
const chrome = Services.wm.getMostRecentWindow("navigator:browser");
const browser = chrome.gBrowser.selectedBrowser;
if (message.data === null) {
// Save original contents
chrome.saveBrowser(browser);
} else {
+ if (!message.data.startsWith("blob:null") || !browser.contentPrincipal.isNullPrincipal) {
+ Cu.reportError("Got invalid request to save JSON data");
+ return;
+ }
// The following code emulates saveBrowser, but:
// - Uses the given blob URL containing the custom contents to save.
// - Obtains the file name from the URL of the document, not the blob.
+ // - avoids passing the document and explicitly passes system principal.
+ // We have a blob created by a null principal to save, and the null
+ // principal is from the child. Null principals don't survive crossing
+ // over IPC, so there's no other principal that'll work.
const persistable = browser.frameLoader;
persistable.startPersistence(0, {
onDocumentReady(doc) {
const uri = chrome.makeURI(doc.documentURI, doc.characterSet);
const filename = chrome.getDefaultFileName(undefined, uri, doc, null);
- chrome.internalSave(message.data, doc, filename, null, doc.contentType,
- false, null, null, null, doc, false, null, undefined);
+ chrome.internalSave(message.data, null, filename, null, doc.contentType,
+ false /* bypass cache */,
+ null, /* filepicker title key */
+ null, /* file chosen */
+ null, /* referrer */
+ null, /* initiating document */
+ false, /* don't skip prompt for a location */
+ null, /* cache key */
+ PrivateBrowsingUtils.isBrowserPrivate(browser), /* private browsing ? */
+ Services.scriptSecurityManager.getSystemPrincipal());
},
onError(status) {
throw new Error("JSON Viewer's onSave failed in startPersistence");
}
});
}
}
};
--- a/dom/base/UseCounters.conf
+++ b/dom/base/UseCounters.conf
@@ -110,8 +110,12 @@ method console.groupCollapsed
method console.groupEnd
method console.time
method console.timeLog
method console.timeEnd
method console.exception
method console.timeStamp
method console.profile
method console.profileEnd
+
+// document.open information
+custom DocumentOpen calls document.open in a way that creates a new Window object
+custom DocumentOpenReplace calls document.open in a way that creates a new Window object and replaces the old history entry.
--- a/dom/base/nsContentAreaDragDrop.cpp
+++ b/dom/base/nsContentAreaDragDrop.cpp
@@ -136,16 +136,17 @@ nsContentAreaDragDrop::GetDragData(nsPID
NS_IMPL_ISUPPORTS(nsContentAreaDragDropDataProvider, nsIFlavorDataProvider)
// SaveURIToFile
// used on platforms where it's possible to drag items (e.g. images)
// into the file system
nsresult
nsContentAreaDragDropDataProvider::SaveURIToFile(nsIURI* inSourceURI,
+ nsIPrincipal* inTriggeringPrincipal,
nsIFile* inDestFile,
bool isPrivate)
{
nsCOMPtr<nsIURL> sourceURL = do_QueryInterface(inSourceURI);
if (!sourceURL) {
return NS_ERROR_NO_INTERFACE;
}
@@ -157,17 +158,18 @@ nsContentAreaDragDropDataProvider::SaveU
nsCOMPtr<nsIWebBrowserPersist> persist =
do_CreateInstance("@mozilla.org/embedding/browser/nsWebBrowserPersist;1",
&rv);
NS_ENSURE_SUCCESS(rv, rv);
persist->SetPersistFlags(nsIWebBrowserPersist::PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION);
// referrer policy can be anything since the referrer is nullptr
- return persist->SavePrivacyAwareURI(inSourceURI, 0, nullptr,
+ return persist->SavePrivacyAwareURI(inSourceURI,
+ inTriggeringPrincipal, 0, nullptr,
mozilla::net::RP_Unset,
nullptr, nullptr,
inDestFile, isPrivate);
}
/*
* Check if the provided filename extension is valid for the MIME type and
* return the MIME type's primary extension.
@@ -337,17 +339,19 @@ nsContentAreaDragDropDataProvider::GetFl
rv = destDirectory->Clone(getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
file->Append(targetFilename);
bool isPrivate;
aTransferable->GetIsPrivateData(&isPrivate);
- rv = SaveURIToFile(sourceURI, file, isPrivate);
+ nsCOMPtr<nsIPrincipal> principal;
+ aTransferable->GetRequestingPrincipal(getter_AddRefs(principal));
+ rv = SaveURIToFile(sourceURI, principal, file, isPrivate);
// send back an nsIFile
if (NS_SUCCEEDED(rv)) {
CallQueryInterface(file, aData);
*aDataLen = sizeof(nsIFile*);
}
}
return rv;
--- a/dom/base/nsContentAreaDragDrop.h
+++ b/dom/base/nsContentAreaDragDrop.h
@@ -72,14 +72,15 @@ class nsContentAreaDragDropDataProvider
{
virtual ~nsContentAreaDragDropDataProvider() {}
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIFLAVORDATAPROVIDER
nsresult SaveURIToFile(nsIURI* inSourceURI,
+ nsIPrincipal* inTriggeringPrincipal,
nsIFile* inDestFile, bool isPrivate);
};
#endif /* nsContentAreaDragDrop_h__ */
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1334,16 +1334,24 @@ nsHTMLDocument::Open(JSContext* cx,
callerDocURI ? callerDocURI->GetSpecOrDefault().get() : "",
thisURI ? thisURI->GetSpecOrDefault().get() : "");
#endif
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
return nullptr;
}
+ // At this point we know this is a valid-enough document.open() call
+ // and not a no-op. Increment our use counters.
+ SetDocumentAndPageUseCounter(eUseCounter_custom_DocumentOpen);
+ bool isReplace = aReplace.LowerCaseEqualsLiteral("replace");
+ if (isReplace) {
+ SetDocumentAndPageUseCounter(eUseCounter_custom_DocumentOpenReplace);
+ }
+
// Stop current loads targeted at the window this document is in.
if (mScriptGlobalObject) {
nsCOMPtr<nsIContentViewer> cv;
shell->GetContentViewer(getter_AddRefs(cv));
if (cv) {
bool okToUnload;
if (NS_SUCCEEDED(cv->PermitUnload(&okToUnload)) && !okToUnload) {
@@ -1562,18 +1570,17 @@ nsHTMLDocument::Open(JSContext* cx,
// Prepare the docshell and the document viewer for the impending
// out of band document.write()
shell->PrepareForNewContentModel();
// Now check whether we were opened with a "replace" argument. If
// so, we need to tell the docshell to not create a new history
// entry for this load. Otherwise, make sure that we're doing a normal load,
// not whatever type of load was previously done on this docshell.
- shell->SetLoadType(aReplace.LowerCaseEqualsLiteral("replace") ?
- LOAD_NORMAL_REPLACE : LOAD_NORMAL);
+ shell->SetLoadType(isReplace ? LOAD_NORMAL_REPLACE : LOAD_NORMAL);
nsCOMPtr<nsIContentViewer> cv;
shell->GetContentViewer(getter_AddRefs(cv));
if (cv) {
cv->LoadStart(this);
}
// Add a wyciwyg channel request into the document load group
--- a/dom/media/gmp/ChromiumCDMAdapter.cpp
+++ b/dom/media/gmp/ChromiumCDMAdapter.cpp
@@ -192,17 +192,18 @@ ChromiumCDMAdapter::Supports(int32_t aMo
#ifdef XP_WIN
static WindowsDllInterceptor sKernel32Intercept;
typedef DWORD(WINAPI* QueryDosDeviceWFnPtr)(_In_opt_ LPCWSTR lpDeviceName,
_Out_ LPWSTR lpTargetPath,
_In_ DWORD ucchMax);
-static QueryDosDeviceWFnPtr sOriginalQueryDosDeviceWFnPtr = nullptr;
+static WindowsDllInterceptor::FuncHookType<QueryDosDeviceWFnPtr>
+ sOriginalQueryDosDeviceWFnPtr;
static std::unordered_map<std::wstring, std::wstring>* sDeviceNames = nullptr;
DWORD WINAPI
QueryDosDeviceWHook(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
{
if (!sDeviceNames) {
return 0;
@@ -271,19 +272,18 @@ InitializeHooks()
}
initialized = true;
sDeviceNames = new std::unordered_map<std::wstring, std::wstring>();
for (const std::wstring& name : GetDosDeviceNames()) {
sDeviceNames->emplace(name, GetDeviceMapping(name));
}
sKernel32Intercept.Init("kernelbase.dll");
- sKernel32Intercept.AddHook("QueryDosDeviceW",
- reinterpret_cast<intptr_t>(QueryDosDeviceWHook),
- (void**)(&sOriginalQueryDosDeviceWFnPtr));
+ sOriginalQueryDosDeviceWFnPtr.Set(sKernel32Intercept, "QueryDosDeviceW",
+ &QueryDosDeviceWHook);
}
#endif
HostFile::HostFile(HostFile&& aOther)
: mPath(aOther.mPath)
, mFile(aOther.TakePlatformFile())
{
}
--- a/dom/plugins/base/nsPluginNativeWindowWin.cpp
+++ b/dom/plugins/base/nsPluginNativeWindowWin.cpp
@@ -352,29 +352,33 @@ static WindowsDllInterceptor sUser32Inte
typedef LONG_PTR
(WINAPI *User32SetWindowLongPtrA)(HWND hWnd,
int nIndex,
LONG_PTR dwNewLong);
typedef LONG_PTR
(WINAPI *User32SetWindowLongPtrW)(HWND hWnd,
int nIndex,
LONG_PTR dwNewLong);
-static User32SetWindowLongPtrA sUser32SetWindowLongAHookStub = nullptr;
-static User32SetWindowLongPtrW sUser32SetWindowLongWHookStub = nullptr;
+static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrA>
+ sUser32SetWindowLongAHookStub;
+static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrW>
+ sUser32SetWindowLongWHookStub;
#else
typedef LONG
(WINAPI *User32SetWindowLongA)(HWND hWnd,
int nIndex,
LONG dwNewLong);
typedef LONG
(WINAPI *User32SetWindowLongW)(HWND hWnd,
int nIndex,
LONG dwNewLong);
-static User32SetWindowLongA sUser32SetWindowLongAHookStub = nullptr;
-static User32SetWindowLongW sUser32SetWindowLongWHookStub = nullptr;
+static WindowsDllInterceptor::FuncHookType<User32SetWindowLongA>
+ sUser32SetWindowLongAHookStub;
+static WindowsDllInterceptor::FuncHookType<User32SetWindowLongW>
+ sUser32SetWindowLongWHookStub;
#endif
static inline bool
SetWindowLongHookCheck(HWND hWnd,
int nIndex,
LONG_PTR newLong)
{
nsPluginNativeWindowWin * win =
(nsPluginNativeWindowWin *)GetProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
@@ -443,33 +447,25 @@ SetWindowLongWHook(HWND hWnd,
return proc;
}
static void
HookSetWindowLongPtr()
{
sUser32Intercept.Init("user32.dll");
#ifdef _WIN64
- if (!sUser32SetWindowLongAHookStub)
- sUser32Intercept.AddHook("SetWindowLongPtrA",
- reinterpret_cast<intptr_t>(SetWindowLongPtrAHook),
- (void**) &sUser32SetWindowLongAHookStub);
- if (!sUser32SetWindowLongWHookStub)
- sUser32Intercept.AddHook("SetWindowLongPtrW",
- reinterpret_cast<intptr_t>(SetWindowLongPtrWHook),
- (void**) &sUser32SetWindowLongWHookStub);
+ sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongPtrA",
+ &SetWindowLongPtrAHook);
+ sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongPtrW",
+ &SetWindowLongPtrWHook);
#else
- if (!sUser32SetWindowLongAHookStub)
- sUser32Intercept.AddHook("SetWindowLongA",
- reinterpret_cast<intptr_t>(SetWindowLongAHook),
- (void**) &sUser32SetWindowLongAHookStub);
- if (!sUser32SetWindowLongWHookStub)
- sUser32Intercept.AddHook("SetWindowLongW",
- reinterpret_cast<intptr_t>(SetWindowLongWHook),
- (void**) &sUser32SetWindowLongWHookStub);
+ sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongA",
+ &SetWindowLongAHook);
+ sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongW",
+ &SetWindowLongWHook);
#endif
}
/**
* nsPluginNativeWindowWin implementation
*/
nsPluginNativeWindowWin::nsPluginNativeWindowWin() : nsPluginNativeWindow()
{
--- a/dom/plugins/ipc/FunctionHook.cpp
+++ b/dom/plugins/ipc/FunctionHook.cpp
@@ -163,23 +163,23 @@ BOOL WINAPI PrintDlgWHook(LPPRINTDLGW aD
// Hooking CreateFileW for protected-mode magic
static WindowsDllInterceptor sKernel32Intercept;
typedef HANDLE (WINAPI *CreateFileWPtr)(LPCWSTR aFname, DWORD aAccess,
DWORD aShare,
LPSECURITY_ATTRIBUTES aSecurity,
DWORD aCreation, DWORD aFlags,
HANDLE aFTemplate);
-static CreateFileWPtr sCreateFileWStub = nullptr;
+static WindowsDllInterceptor::FuncHookType<CreateFileWPtr> sCreateFileWStub;
typedef HANDLE (WINAPI *CreateFileAPtr)(LPCSTR aFname, DWORD aAccess,
DWORD aShare,
LPSECURITY_ATTRIBUTES aSecurity,
DWORD aCreation, DWORD aFlags,
HANDLE aFTemplate);
-static CreateFileAPtr sCreateFileAStub = nullptr;
+static WindowsDllInterceptor::FuncHookType<CreateFileAPtr> sCreateFileAStub;
// Windows 8 RTM (kernelbase's version is 6.2.9200.16384) doesn't call
// CreateFileW from CreateFileA.
// So we hook CreateFileA too to use CreateFileW hook.
static HANDLE WINAPI
CreateFileAHookFn(LPCSTR aFname, DWORD aAccess, DWORD aShare,
LPSECURITY_ATTRIBUTES aSecurity, DWORD aCreation, DWORD aFlags,
HANDLE aFTemplate)
@@ -258,17 +258,17 @@ CreateFileWHookFn(LPCWSTR aFname, DWORD
if (GetTempFileNameW(tempPath, L"fx", 0, tempFile) == 0) {
break;
}
HANDLE replacement =
sCreateFileWStub(tempFile, GENERIC_READ | GENERIC_WRITE, aShare,
aSecurity, TRUNCATE_EXISTING,
FILE_ATTRIBUTE_TEMPORARY |
FILE_FLAG_DELETE_ON_CLOSE,
- NULL);
+ nullptr);
if (replacement == INVALID_HANDLE_VALUE) {
break;
}
HANDLE original = sCreateFileWStub(aFname, aAccess, aShare, aSecurity,
aCreation, aFlags, aFTemplate);
if (original != INVALID_HANDLE_VALUE) {
// copy original to replacement
@@ -295,33 +295,22 @@ CreateFileWHookFn(LPCWSTR aFname, DWORD
return replacement;
}
return sCreateFileWStub(aFname, aAccess, aShare, aSecurity, aCreation, aFlags,
aFTemplate);
}
void FunctionHook::HookProtectedMode()
{
- // Make sure we only do this once.
- static bool sRunOnce = false;
- if (sRunOnce) {
- return;
- }
- sRunOnce = true;
-
// Legacy code. Uses the nsWindowsDLLInterceptor directly instead of
// using the FunctionHook
sKernel32Intercept.Init("kernel32.dll");
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Plugin);
- sKernel32Intercept.AddHook("CreateFileW",
- reinterpret_cast<intptr_t>(CreateFileWHookFn),
- (void**) &sCreateFileWStub);
- sKernel32Intercept.AddHook("CreateFileA",
- reinterpret_cast<intptr_t>(CreateFileAHookFn),
- (void**) &sCreateFileAStub);
+ sCreateFileWStub.Set(sKernel32Intercept, "CreateFileW", &CreateFileWHookFn);
+ sCreateFileAStub.Set(sKernel32Intercept, "CreateFileA", &CreateFileAHookFn);
}
#endif // defined(XP_WIN)
#define FUN_HOOK(x) static_cast<FunctionHook*>(x)
void
FunctionHook::AddFunctionHooks(FunctionHookArray& aHooks)
--- a/dom/plugins/ipc/FunctionHook.h
+++ b/dom/plugins/ipc/FunctionHook.h
@@ -4,16 +4,17 @@
* 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 dom_plugins_ipc_functionhook_h
#define dom_plugins_ipc_functionhook_h 1
#include "IpdlTuple.h"
#include "base/process.h"
+#include "mozilla/Atomics.h"
#if defined(XP_WIN)
#include "nsWindowsDllInterceptor.h"
#endif
namespace mozilla {
namespace plugins {
@@ -91,22 +92,29 @@ public:
};
// Type of function that returns true if a function should be hooked according to quirks.
typedef bool(ShouldHookFunc)(int aQuirks);
template<FunctionHookId functionId, typename FunctionType>
class BasicFunctionHook : public FunctionHook
{
+#if defined(XP_WIN)
+ using FuncHookType = WindowsDllInterceptor::FuncHookType<FunctionType*>;
+#endif // defined(XP_WIN)
+
public:
BasicFunctionHook(const char* aModuleName,
const char* aFunctionName, FunctionType* aOldFunction,
- FunctionType* aNewFunction) :
- mOldFunction(aOldFunction), mRegistration(UNREGISTERED), mModuleName(aModuleName),
- mFunctionName(aFunctionName), mNewFunction(aNewFunction)
+ FunctionType* aNewFunction)
+ : mOldFunction(aOldFunction)
+ , mRegistration(UNREGISTERED)
+ , mModuleName(aModuleName)
+ , mFunctionName(aFunctionName)
+ , mNewFunction(aNewFunction)
{
MOZ_ASSERT(mOldFunction);
MOZ_ASSERT(mNewFunction);
}
/**
* Hooks the function if we haven't already and if ShouldHook() says to.
*/
@@ -123,17 +131,20 @@ public:
FunctionHookId FunctionId() const override { return functionId; }
FunctionType* OriginalFunction() const { return mOldFunction; }
protected:
// Once the function is hooked, this field will take the value of a pointer to
// a function that performs the old behavior. Before that, it is a pointer to
// the original function.
- FunctionType* mOldFunction;
+ Atomic<FunctionType*> mOldFunction;
+#if defined(XP_WIN)
+ FuncHookType mStub;
+#endif // defined(XP_WIN)
enum RegistrationStatus { UNREGISTERED, FAILED, SUCCEEDED };
RegistrationStatus mRegistration;
// The name of the module containing the function to hook. E.g. "user32.dll".
const nsCString mModuleName;
// The name of the function in the module.
const nsCString mFunctionName;
@@ -165,24 +176,26 @@ BasicFunctionHook<functionId, FunctionTy
#if defined(XP_WIN)
WindowsDllInterceptor* dllInterceptor =
FunctionHook::GetDllInterceptorFor(mModuleName.Data());
if (!dllInterceptor) {
return false;
}
- isHooked =
- dllInterceptor->AddHook(mFunctionName.Data(), reinterpret_cast<intptr_t>(mNewFunction),
- reinterpret_cast<void**>(&mOldFunction));
+ isHooked = mStub.Set(*dllInterceptor, mFunctionName.Data(), mNewFunction);
#endif
if (isHooked) {
+#if defined(XP_WIN)
+ mOldFunction = mStub.GetStub();
+#endif
mRegistration = SUCCEEDED;
}
+
HOOK_LOG(LogLevel::Debug,
("Registering to intercept function '%s' : '%s'", mFunctionName.Data(),
SuccessMsg(isHooked)));
return isHooked;
}
}
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -68,31 +68,27 @@ typedef BOOL (WINAPI *User32TrackPopupMe
UINT uFlags,
int x,
int y,
int nReserved,
HWND hWnd,
CONST RECT *prcRect);
static WindowsDllInterceptor sUser32Intercept;
static HWND sWinlessPopupSurrogateHWND = nullptr;
-static User32TrackPopupMenu sUser32TrackPopupMenuStub = nullptr;
+static WindowsDllInterceptor::FuncHookType<User32TrackPopupMenu> sUser32TrackPopupMenuStub;
static WindowsDllInterceptor sImm32Intercept;
-static decltype(ImmGetContext)* sImm32ImmGetContextStub = nullptr;
-static decltype(ImmGetCompositionStringW)* sImm32ImmGetCompositionStringStub =
- nullptr;
-static decltype(ImmSetCandidateWindow)* sImm32ImmSetCandidateWindowStub =
- nullptr;
-static decltype(ImmNotifyIME)* sImm32ImmNotifyIME = nullptr;
-static decltype(ImmAssociateContextEx)* sImm32ImmAssociateContextExStub =
- nullptr;
+static WindowsDllInterceptor::FuncHookType<decltype(&ImmGetContext)> sImm32ImmGetContextStub;
+static WindowsDllInterceptor::FuncHookType<decltype(&ImmGetCompositionStringW)> sImm32ImmGetCompositionStringStub;
+static WindowsDllInterceptor::FuncHookType<decltype(&ImmSetCandidateWindow)> sImm32ImmSetCandidateWindowStub;
+static WindowsDllInterceptor::FuncHookType<decltype(&ImmNotifyIME)> sImm32ImmNotifyIME;
+static WindowsDllInterceptor::FuncHookType<decltype(&ImmAssociateContextEx)> sImm32ImmAssociateContextExStub;
+
static PluginInstanceChild* sCurrentPluginInstance = nullptr;
static const HIMC sHookIMC = (const HIMC)0xefefefef;
-static bool sPopupMenuHookSet;
-static bool sSetWindowLongHookSet;
using mozilla::gfx::SharedDIB;
// Flash WM_USER message delay time for PostDelayedTask. Borrowed
// from Chromium's web plugin delegate src. See 'flash msg throttling
// helpers' section for details.
const int kFlashWMUSERMessageThrottleDelayMs = 5;
@@ -1788,29 +1784,29 @@ PluginInstanceChild::MaybePostKeyMessage
typedef LONG_PTR
(WINAPI *User32SetWindowLongPtrA)(HWND hWnd,
int nIndex,
LONG_PTR dwNewLong);
typedef LONG_PTR
(WINAPI *User32SetWindowLongPtrW)(HWND hWnd,
int nIndex,
LONG_PTR dwNewLong);
-static User32SetWindowLongPtrA sUser32SetWindowLongAHookStub = nullptr;
-static User32SetWindowLongPtrW sUser32SetWindowLongWHookStub = nullptr;
+static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrA> sUser32SetWindowLongAHookStub;
+static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrW> sUser32SetWindowLongWHookStub;
#else
typedef LONG
(WINAPI *User32SetWindowLongA)(HWND hWnd,
int nIndex,
LONG dwNewLong);
typedef LONG
(WINAPI *User32SetWindowLongW)(HWND hWnd,
int nIndex,
LONG dwNewLong);
-static User32SetWindowLongA sUser32SetWindowLongAHookStub = nullptr;
-static User32SetWindowLongW sUser32SetWindowLongWHookStub = nullptr;
+static WindowsDllInterceptor::FuncHookType<User32SetWindowLongA> sUser32SetWindowLongAHookStub;
+static WindowsDllInterceptor::FuncHookType<User32SetWindowLongW> sUser32SetWindowLongWHookStub;
#endif
extern LRESULT CALLBACK
NeuteredWindowProc(HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
@@ -1910,37 +1906,27 @@ PluginInstanceChild::SetWindowLongWHook(
void
PluginInstanceChild::HookSetWindowLongPtr()
{
if (!(GetQuirks() & QUIRK_FLASH_HOOK_SETLONGPTR)) {
return;
}
- // Only pass through here once
- if (sSetWindowLongHookSet) {
- return;
- }
- sSetWindowLongHookSet = true;
-
sUser32Intercept.Init("user32.dll");
#ifdef _WIN64
- if (!sUser32SetWindowLongAHookStub)
- sUser32Intercept.AddHook("SetWindowLongPtrA", reinterpret_cast<intptr_t>(SetWindowLongPtrAHook),
- (void**) &sUser32SetWindowLongAHookStub);
- if (!sUser32SetWindowLongWHookStub)
- sUser32Intercept.AddHook("SetWindowLongPtrW", reinterpret_cast<intptr_t>(SetWindowLongPtrWHook),
- (void**) &sUser32SetWindowLongWHookStub);
+ sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongPtrA",
+ &SetWindowLongPtrAHook);
+ sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongPtrW",
+ &SetWindowLongPtrWHook);
#else
- if (!sUser32SetWindowLongAHookStub)
- sUser32Intercept.AddHook("SetWindowLongA", reinterpret_cast<intptr_t>(SetWindowLongAHook),
- (void**) &sUser32SetWindowLongAHookStub);
- if (!sUser32SetWindowLongWHookStub)
- sUser32Intercept.AddHook("SetWindowLongW", reinterpret_cast<intptr_t>(SetWindowLongWHook),
- (void**) &sUser32SetWindowLongWHookStub);
+ sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongA",
+ &SetWindowLongAHook);
+ sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongW",
+ &SetWindowLongWHook);
#endif
}
/* windowless track popup menu helpers */
BOOL
WINAPI
PluginInstanceChild::TrackPopupHookProc(HMENU hMenu,
@@ -1998,29 +1984,23 @@ PluginInstanceChild::TrackPopupHookProc(
void
PluginInstanceChild::InitPopupMenuHook()
{
if (!(GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK)) {
return;
}
- // Only pass through here once
- if (sPopupMenuHookSet) {
- return;
- }
- sPopupMenuHookSet = true;
-
// Note, once WindowsDllInterceptor is initialized for a module,
// it remains initialized for that particular module for it's
// lifetime. Additional instances are needed if other modules need
// to be hooked.
sUser32Intercept.Init("user32.dll");
- sUser32Intercept.AddHook("TrackPopupMenu", reinterpret_cast<intptr_t>(TrackPopupHookProc),
- (void**) &sUser32TrackPopupMenuStub);
+ sUser32TrackPopupMenuStub.Set(sUser32Intercept, "TrackPopupMenu",
+ &TrackPopupHookProc);
}
void
PluginInstanceChild::CreateWinlessPopupSurrogate()
{
// already initialized
if (mWinlessPopupSurrogateHWND)
return;
@@ -2152,46 +2132,33 @@ PluginInstanceChild::ImmAssociateContext
void
PluginInstanceChild::InitImm32Hook()
{
if (!(GetQuirks() & QUIRK_WINLESS_HOOK_IME)) {
return;
}
- if (sImm32ImmGetContextStub) {
- return;
- }
-
// When using windowless plugin, IMM API won't work due ot OOP.
//
// ImmReleaseContext on Windows 7+ just returns TRUE only, so we don't
// need to hook this.
sImm32Intercept.Init("imm32.dll");
- sImm32Intercept.AddHook(
- "ImmGetContext",
- reinterpret_cast<intptr_t>(ImmGetContextProc),
- (void**)&sImm32ImmGetContextStub);
- sImm32Intercept.AddHook(
- "ImmGetCompositionStringW",
- reinterpret_cast<intptr_t>(ImmGetCompositionStringProc),
- (void**)&sImm32ImmGetCompositionStringStub);
- sImm32Intercept.AddHook(
- "ImmSetCandidateWindow",
- reinterpret_cast<intptr_t>(ImmSetCandidateWindowProc),
- (void**)&sImm32ImmSetCandidateWindowStub);
- sImm32Intercept.AddHook(
- "ImmNotifyIME",
- reinterpret_cast<intptr_t>(ImmNotifyIME),
- (void**)&sImm32ImmNotifyIME);
- sImm32Intercept.AddHook(
- "ImmAssociateContextEx",
- reinterpret_cast<intptr_t>(ImmAssociateContextExProc),
- (void**)&sImm32ImmAssociateContextExStub);
+ sImm32ImmGetContextStub.Set(sImm32Intercept, "ImmGetContext",
+ &ImmGetContextProc);
+ sImm32ImmGetCompositionStringStub.Set(sImm32Intercept,
+ "ImmGetCompositionStringW",
+ &ImmGetCompositionStringProc);
+ sImm32ImmSetCandidateWindowStub.Set(sImm32Intercept,
+ "ImmSetCandidateWindow",
+ &ImmSetCandidateWindowProc);
+ sImm32ImmNotifyIME.Set(sImm32Intercept, "ImmNotifyIME", &ImmNotifyIME);
+ sImm32ImmAssociateContextExStub.Set(sImm32Intercept, "ImmAssociateContextEx",
+ &ImmAssociateContextExProc);
}
void
PluginInstanceChild::DestroyWinlessPopupSurrogate()
{
if (mWinlessPopupSurrogateHWND)
DestroyWindow(mWinlessPopupSurrogateHWND);
mWinlessPopupSurrogateHWND = nullptr;
--- a/dom/tests/browser/browser.ini
+++ b/dom/tests/browser/browser.ini
@@ -52,16 +52,20 @@ support-files =
run-if = e10s
[browser_largeAllocation_win32.js]
skip-if = !e10s || os != "win" || processor != "x86" # Large-Allocation requires e10s
[browser_largeAllocation_non_win32.js]
skip-if = !e10s || (os == "win" && processor == "x86") || (verify && debug && (os == 'linux')) # Large-Allocation requires e10s
[browser_localStorage_e10s.js]
skip-if = !e10s || verify # This is a test of e10s functionality.
[browser_localStorage_privatestorageevent.js]
+[browser_persist_cookies.js]
+support-files =
+ set-samesite-cookies-and-redirect.sjs
+ mimeme.sjs
[browser_test_focus_after_modal_state.js]
skip-if = verify
support-files =
focus_after_prompt.html
[browser_test_new_window_from_content.js]
tags = openwindow
skip-if = toolkit == 'android' || (os == "linux" && debug) # see bug 1261495 for Linux debug time outs
support-files =
new file mode 100644
--- /dev/null
+++ b/dom/tests/browser/browser_persist_cookies.js
@@ -0,0 +1,94 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.org");
+const TEST_PATH2 = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.com");
+
+var MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init(window);
+
+registerCleanupFunction(async function() {
+ info("Running the cleanup code");
+ MockFilePicker.cleanup();
+ Services.obs.removeObserver(checkRequest, "http-on-modify-request");
+ if (gTestDir && gTestDir.exists()) {
+ // On Windows, sometimes nsIFile.remove() throws, probably because we're
+ // still writing to the directory we're trying to remove, despite
+ // waiting for the download to complete. Just retry a bit later...
+ let succeeded = false;
+ while (!succeeded) {
+ try {
+ gTestDir.remove(true);
+ succeeded = true;
+ } catch (ex) {
+ await new Promise(requestAnimationFrame);
+ }
+ }
+ }
+});
+
+let gTestDir = null;
+
+
+function checkRequest(subject) {
+ let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
+ let spec = httpChannel.URI.spec;
+ // Ignore initial requests for page that sets cookies and its favicon, which may not have
+ // cookies.
+ if (httpChannel.URI.host == "example.org" && !spec.endsWith("favicon.ico") && !spec.includes("redirect.sjs")) {
+ let cookie = httpChannel.getRequestHeader("cookie");
+ is(cookie.trim(), "normalCookie=true", "Should have correct cookie in request for " + spec);
+ }
+}
+
+function createTemporarySaveDirectory() {
+ var saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
+ saveDir.append("testsavedir");
+ if (!saveDir.exists()) {
+ info("create testsavedir!");
+ saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
+ }
+ info("return from createTempSaveDir: " + saveDir.path);
+ return saveDir;
+}
+
+add_task(async function() {
+ await BrowserTestUtils.withNewTab("about:blank", async function(browser) {
+ Services.obs.addObserver(checkRequest, "http-on-modify-request");
+ BrowserTestUtils.loadURI(browser, TEST_PATH + "set-samesite-cookies-and-redirect.sjs");
+ // Test that the original document load doesn't send same-site cookies.
+ await BrowserTestUtils.browserLoaded(browser, true, TEST_PATH2 + "set-samesite-cookies-and-redirect.sjs");
+ // Now check the saved page.
+ // Create the folder the link will be saved into.
+ gTestDir = createTemporarySaveDirectory();
+ let destFile = gTestDir.clone();
+
+ MockFilePicker.displayDirectory = gTestDir;
+ let fileName;
+ MockFilePicker.showCallback = function(fp) {
+ info("showCallback");
+ fileName = fp.defaultString;
+ info("fileName: " + fileName);
+ destFile.append(fileName);
+ info("path: " + destFile.path);
+ MockFilePicker.setFiles([destFile]);
+ MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
+ info("done showCallback");
+ };
+ saveBrowser(browser);
+ await new Promise(async (resolve) => {
+ let dls = await Downloads.getList(Downloads.PUBLIC);
+ dls.addView({
+ onDownloadChanged(download) {
+ if (download.succeeded) {
+ dls.removeView(this);
+ dls.removeFinished();
+ resolve();
+ }
+ }
+ });
+ });
+ });
+});
new file mode 100644
--- /dev/null
+++ b/dom/tests/browser/mimeme.sjs
@@ -0,0 +1,26 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function handleRequest(request, response) {
+ let mimeType = request.queryString.match(/type=([a-z]*)/)[1];
+ switch (mimeType) {
+ case "css":
+ response.setHeader("Content-Type", "text/css");
+ response.write("#hi {color: red}");
+ break;
+ case "js":
+ response.setHeader("Content-Type", "application/javascript");
+ response.write("var foo;");
+ break;
+ case "png":
+ response.setHeader("Content-Type", "image/png");
+ response.write("");
+ break;
+ case "html":
+ response.setHeader("Content-Type", "text/html");
+ response.write("<body>I am a subframe</body>");
+ break;
+ }
+}
new file mode 100644
--- /dev/null
+++ b/dom/tests/browser/set-samesite-cookies-and-redirect.sjs
@@ -0,0 +1,33 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function handleRequest(request, response) {
+ // Set cookies and redirect for .org:
+ if (request.host.endsWith(".org")) {
+ response.setHeader("Set-Cookie", "normalCookie=true; path=/;", true);
+ response.setHeader("Set-Cookie", "laxHeader=true; path=/; SameSite=Lax", true);
+ response.setHeader("Set-Cookie", "strictHeader=true; path=/; SameSite=Strict", true);
+ response.write(`
+ <head>
+ <meta http-equiv='set-cookie' content='laxMeta=true; path=/; SameSite=Lax'>
+ <meta http-equiv='set-cookie' content='strictMeta=true; path=/; SameSite=Strict'>
+ </head>
+ <body>
+ <script>
+ document.cookie = 'laxScript=true; path=/; SameSite=Lax';
+ document.cookie = 'strictScript=true; path=/; SameSite=Strict';
+ location.href = location.href.replace(/\.org/, ".com");
+ </script>
+ </body>`);
+ } else {
+ let baseURI = "https://example.org/" + request.path.replace(/[a-z-]*\.sjs/, "mimeme.sjs?type=");
+ response.write(`
+ <link rel="stylesheet" type="text/css" href="${baseURI}css">
+ <iframe src="${baseURI}html"></iframe>
+ <script src="${baseURI}js"></script>
+ <img src="${baseURI}png">
+ `);
+ }
+}
--- a/dom/webbrowserpersist/PWebBrowserPersistDocument.ipdl
+++ b/dom/webbrowserpersist/PWebBrowserPersistDocument.ipdl
@@ -5,16 +5,17 @@
include protocol PContent;
include protocol PWebBrowserPersistResources;
include protocol PWebBrowserPersistSerialize;
include protocol PFileDescriptorSet;
include protocol PChildToParentStream; //FIXME: bug #792908
include protocol PParentToChildStream; //FIXME: bug #792908
+include PBackgroundSharedTypes;
include IPCStream;
namespace mozilla {
// nsIWebBrowserPersistDocument has attributes which can be read
// synchronously. To avoid using sync IPC for them, the actor sends
// this structure from the child to the parent before the parent actor
// is exposed to XPCOM.
@@ -24,16 +25,17 @@ struct WebBrowserPersistDocumentAttrs {
nsCString baseURI;
nsCString contentType;
nsCString characterSet;
nsString title;
nsString referrer;
nsString contentDisposition;
uint32_t cacheKey;
uint32_t persistFlags;
+ PrincipalInfo principal;
};
// IPDL doesn't have tuples, so this gives the pair of strings from
// nsIWebBrowserPersistURIMap::getURIMapping a name.
struct WebBrowserPersistURIMapEntry {
nsCString mapFrom;
nsCString mapTo;
};
--- a/dom/webbrowserpersist/WebBrowserPersistDocumentChild.cpp
+++ b/dom/webbrowserpersist/WebBrowserPersistDocumentChild.cpp
@@ -36,16 +36,17 @@ void
WebBrowserPersistDocumentChild::Start(nsIWebBrowserPersistDocument* aDocument)
{
MOZ_ASSERT(!mDocument);
if (!aDocument) {
SendInitFailure(NS_ERROR_FAILURE);
return;
}
+ nsCOMPtr<nsIPrincipal> principal;
WebBrowserPersistDocumentAttrs attrs;
nsCOMPtr<nsIInputStream> postDataStream;
#define ENSURE(e) do { \
nsresult rv = (e); \
if (NS_FAILED(rv)) { \
SendInitFailure(rv); \
return; \
} \
@@ -55,16 +56,20 @@ WebBrowserPersistDocumentChild::Start(ns
ENSURE(aDocument->GetBaseURI(attrs.baseURI()));
ENSURE(aDocument->GetContentType(attrs.contentType()));
ENSURE(aDocument->GetCharacterSet(attrs.characterSet()));
ENSURE(aDocument->GetTitle(attrs.title()));
ENSURE(aDocument->GetReferrer(attrs.referrer()));
ENSURE(aDocument->GetContentDisposition(attrs.contentDisposition()));
ENSURE(aDocument->GetCacheKey(&(attrs.cacheKey())));
ENSURE(aDocument->GetPersistFlags(&(attrs.persistFlags())));
+
+ ENSURE(aDocument->GetPrincipal(getter_AddRefs(principal)));
+ ENSURE(ipc::PrincipalToPrincipalInfo(principal, &(attrs.principal())));
+
ENSURE(aDocument->GetPostData(getter_AddRefs(postDataStream)));
#undef ENSURE
mozilla::ipc::AutoIPCStream autoStream;
autoStream.Serialize(postDataStream,
static_cast<mozilla::dom::ContentChild*>(Manager()));
mDocument = aDocument;
--- a/dom/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
+++ b/dom/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
@@ -179,16 +179,24 @@ WebBrowserPersistLocalDocument::GetPostD
nsCOMPtr<nsISHEntry> history = GetHistory();
if (!history) {
*aStream = nullptr;
return NS_OK;
}
return history->GetPostData(aStream);
}
+NS_IMETHODIMP
+WebBrowserPersistLocalDocument::GetPrincipal(nsIPrincipal** aPrincipal)
+{
+ nsCOMPtr<nsIPrincipal> nodePrincipal = mDocument->NodePrincipal();
+ nodePrincipal.forget(aPrincipal);
+ return NS_OK;
+}
+
already_AddRefed<nsISHEntry>
WebBrowserPersistLocalDocument::GetHistory()
{
nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetDefaultView();
if (NS_WARN_IF(!window)) {
return nullptr;
}
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(window);
--- a/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.cpp
+++ b/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.cpp
@@ -4,30 +4,35 @@
* 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 "WebBrowserPersistRemoteDocument.h"
#include "WebBrowserPersistDocumentParent.h"
#include "WebBrowserPersistResourcesParent.h"
#include "WebBrowserPersistSerializeParent.h"
#include "mozilla/Unused.h"
+#include "mozilla/ipc/BackgroundUtils.h"
+
+#include "nsIPrincipal.h"
namespace mozilla {
NS_IMPL_ISUPPORTS(WebBrowserPersistRemoteDocument,
nsIWebBrowserPersistDocument)
WebBrowserPersistRemoteDocument
::WebBrowserPersistRemoteDocument(WebBrowserPersistDocumentParent* aActor,
const Attrs& aAttrs,
nsIInputStream* aPostData)
: mActor(aActor)
, mAttrs(aAttrs)
, mPostData(aPostData)
{
+ nsresult rv;
+ mPrincipal = ipc::PrincipalInfoToPrincipal(mAttrs.principal(), &rv);
}
WebBrowserPersistRemoteDocument::~WebBrowserPersistRemoteDocument()
{
if (mActor) {
Unused << WebBrowserPersistDocumentParent::Send__delete__(mActor);
// That will call mActor->ActorDestroy, which calls this->ActorDestroy
// (whether or not the IPC send succeeds).
@@ -128,16 +133,24 @@ NS_IMETHODIMP
WebBrowserPersistRemoteDocument::GetPostData(nsIInputStream** aStream)
{
nsCOMPtr<nsIInputStream> stream = mPostData;
stream.forget(aStream);
return NS_OK;
}
NS_IMETHODIMP
+WebBrowserPersistRemoteDocument::GetPrincipal(nsIPrincipal** aPrincipal)
+{
+ nsCOMPtr<nsIPrincipal> nodePrincipal = mPrincipal;
+ nodePrincipal.forget(aPrincipal);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
WebBrowserPersistRemoteDocument::ReadResources(nsIWebBrowserPersistResourceVisitor* aVisitor)
{
if (!mActor) {
return NS_ERROR_FAILURE;
}
RefPtr<WebBrowserPersistResourcesParent> subActor =
new WebBrowserPersistResourcesParent(this, aVisitor);
return mActor->SendPWebBrowserPersistResourcesConstructor(
--- a/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.h
+++ b/dom/webbrowserpersist/WebBrowserPersistRemoteDocument.h
@@ -8,16 +8,18 @@
#define WebBrowserPersistRemoteDocument_h__
#include "mozilla/Maybe.h"
#include "mozilla/PWebBrowserPersistDocumentParent.h"
#include "nsCOMPtr.h"
#include "nsIWebBrowserPersistDocument.h"
#include "nsIInputStream.h"
+class nsIPrincipal;
+
// This class is the XPCOM half of the glue between the
// nsIWebBrowserPersistDocument interface and a remote document; it is
// created by WebBrowserPersistDocumentParent when (and if) it
// receives the information needed to populate the interface's
// properties.
//
// This object has a normal refcounted lifetime. The corresponding
// IPC actor holds a weak reference to this class; when the last
@@ -35,16 +37,17 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIWEBBROWSERPERSISTDOCUMENT
private:
using Attrs = WebBrowserPersistDocumentAttrs;
WebBrowserPersistDocumentParent* mActor;
Attrs mAttrs;
nsCOMPtr<nsIInputStream> mPostData;
+ nsCOMPtr<nsIPrincipal> mPrincipal;
friend class WebBrowserPersistDocumentParent;
WebBrowserPersistRemoteDocument(WebBrowserPersistDocumentParent* aActor,
const Attrs& aAttrs,
nsIInputStream* aPostData);
~WebBrowserPersistRemoteDocument();
void ActorDestroy(void);
--- a/dom/webbrowserpersist/nsIWebBrowserPersist.idl
+++ b/dom/webbrowserpersist/nsIWebBrowserPersist.idl
@@ -7,16 +7,17 @@
#include "nsICancelable.idl"
interface nsIURI;
interface nsIInputStream;
interface nsIWebProgressListener;
interface nsIFile;
interface nsIChannel;
interface nsILoadContext;
+interface nsIPrincipal;
/**
* Interface for persisting DOM documents and URIs to local or remote storage.
*/
[scriptable, uuid(8cd752a4-60b1-42c3-a819-65c7a1138a28)]
interface nsIWebBrowserPersist : nsICancelable
{
/** No special persistence behaviour. */
@@ -61,22 +62,16 @@ interface nsIWebBrowserPersist : nsICanc
const unsigned long PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION = 16384;
/**
* Append the downloaded data to the target file.
* This can only be used when persisting to a local file.
*/
const unsigned long PERSIST_FLAGS_APPEND_TO_FILE = 32768;
/**
- * Force relevant cookies to be sent with this load even if normally they
- * wouldn't be.
- */
- const unsigned long PERSIST_FLAGS_FORCE_ALLOW_COOKIES = 65536;
-
- /**
* Flags governing how data is fetched and saved from the network.
* It is best to set this value explicitly unless you are prepared
* to accept the default values.
*/
attribute unsigned long persistFlags;
/** Persister is ready to save data */
const unsigned long PERSIST_STATE_READY = 1;
@@ -111,16 +106,18 @@ interface nsIWebBrowserPersist : nsICanc
attribute nsIWebProgressListener progressListener;
/**
* Save the specified URI to file.
*
* @param aURI URI to save to file. Some implementations of this interface
* may also support <CODE>nullptr</CODE> to imply the currently
* loaded URI.
+ * @param aTriggeringPrincipal
+ * The triggering principal for the URI we're saving.
* @param aCacheKey The necko cache key integer.
* @param aReferrer The referrer URI to pass with an HTTP request or
* <CODE>nullptr</CODE>.
* @param aReferrerPolicy The referrer policy for when and what to send via
* HTTP Referer header. Ignored if aReferrer is
* <CODE>nullptr</CODE>. Taken from REFERRER_POLICY
* constants in nsIHttpChannel.
* @param aPostData Post data to pass with an HTTP request or
@@ -137,29 +134,31 @@ interface nsIWebBrowserPersist : nsICanc
* window or document)
*
* @see nsIFile
* @see nsIURI
* @see nsIInputStream
*
* @throws NS_ERROR_INVALID_ARG One or more arguments was invalid.
*/
- void saveURI(in nsIURI aURI, in unsigned long aCacheKey,
+ void saveURI(in nsIURI aURI, in nsIPrincipal aTriggeringPrincipal,
+ in unsigned long aCacheKey,
in nsIURI aReferrer, in unsigned long aReferrerPolicy,
in nsIInputStream aPostData,
in string aExtraHeaders, in nsISupports aFile,
in nsILoadContext aPrivacyContext);
/**
* @param aIsPrivate Treat the save operation as private (ie. with
* regards to networking operations and persistence
* of intermediate data, etc.)
* @see saveURI for all other parameter descriptions
*/
- void savePrivacyAwareURI(in nsIURI aURI, in unsigned long aCacheKey,
+ void savePrivacyAwareURI(in nsIURI aURI,
+ in nsIPrincipal aTriggeringPrincipal, in unsigned long aCacheKey,
in nsIURI aReferrer, in unsigned long aReferrerPolicy,
in nsIInputStream aPostData,
in string aExtraHeaders, in nsISupports aFile,
in boolean aIsPrivate);
/**
* Save a channel to a file. It must not be opened yet.
* @see saveURI
--- a/dom/webbrowserpersist/nsIWebBrowserPersistDocument.idl
+++ b/dom/webbrowserpersist/nsIWebBrowserPersistDocument.idl
@@ -3,16 +3,17 @@
* 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 "nsISupports.idl"
interface nsIInputStream;
interface nsIOutputStream;
+interface nsIPrincipal;
interface nsITabParent;
interface nsIWebBrowserPersistResourceVisitor;
interface nsIWebBrowserPersistWriteCompletion;
/**
* Interface for the URI-mapping information that can be supplied when
* serializing the DOM of an nsIWebBrowserPersistDocument.
*
@@ -55,16 +56,17 @@ interface nsIWebBrowserPersistDocument :
readonly attribute AUTF8String documentURI;
readonly attribute AUTF8String baseURI;
readonly attribute ACString contentType;
readonly attribute ACString characterSet;
readonly attribute AString title;
readonly attribute AString referrer;
readonly attribute AString contentDisposition;
readonly attribute nsIInputStream postData;
+ readonly attribute nsIPrincipal principal;
/**
* The cache key. Unlike in nsISHEntry, where it's wrapped in an
* nsISupportsPRUint32, this is just the integer.
*/
readonly attribute unsigned long cacheKey;
/**
--- a/dom/webbrowserpersist/nsWebBrowserPersist.cpp
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.cpp
@@ -78,16 +78,17 @@ struct nsWebBrowserPersist::WalkData
};
// Information about a DOM document
struct nsWebBrowserPersist::DocData
{
nsCOMPtr<nsIURI> mBaseURI;
nsCOMPtr<nsIWebBrowserPersistDocument> mDocument;
nsCOMPtr<nsIURI> mFile;
+ nsCOMPtr<nsIPrincipal> mPrincipal;
nsCString mCharset;
};
// Information about a URI
struct nsWebBrowserPersist::URIData
{
bool mNeedsPersisting;
bool mSaved;
@@ -408,44 +409,48 @@ NS_IMETHODIMP nsWebBrowserPersist::SetPr
{
mProgressListener = aProgressListener;
mProgressListener2 = do_QueryInterface(aProgressListener);
mEventSink = do_GetInterface(aProgressListener);
return NS_OK;
}
NS_IMETHODIMP nsWebBrowserPersist::SaveURI(
- nsIURI *aURI, uint32_t aCacheKey,
+ nsIURI *aURI, nsIPrincipal *aPrincipal, uint32_t aCacheKey,
nsIURI *aReferrer, uint32_t aReferrerPolicy,
nsIInputStream *aPostData, const char *aExtraHeaders,
nsISupports *aFile, nsILoadContext* aPrivacyContext)
{
- return SavePrivacyAwareURI(aURI, aCacheKey, aReferrer, aReferrerPolicy,
- aPostData, aExtraHeaders, aFile,
- aPrivacyContext && aPrivacyContext->UsePrivateBrowsing());
+ bool isPrivate =
+ aPrivacyContext && aPrivacyContext->UsePrivateBrowsing();
+ return SavePrivacyAwareURI(aURI, aPrincipal, aCacheKey,
+ aReferrer, aReferrerPolicy,
+ aPostData, aExtraHeaders, aFile, isPrivate);
}
NS_IMETHODIMP nsWebBrowserPersist::SavePrivacyAwareURI(
- nsIURI *aURI, uint32_t aCacheKey,
+ nsIURI *aURI, nsIPrincipal *aPrincipal, uint32_t aCacheKey,
nsIURI *aReferrer, uint32_t aReferrerPolicy,
nsIInputStream *aPostData, const char *aExtraHeaders,
nsISupports *aFile, bool aIsPrivate)
{
NS_ENSURE_TRUE(mFirstAndOnlyUse, NS_ERROR_FAILURE);
mFirstAndOnlyUse = false; // Stop people from reusing this object!
nsCOMPtr<nsIURI> fileAsURI;
nsresult rv;
rv = GetValidURIFromObject(aFile, getter_AddRefs(fileAsURI));
NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_ARG);
// SaveURI doesn't like broken uris.
mPersistFlags |= PERSIST_FLAGS_FAIL_ON_BROKEN_LINKS;
- rv = SaveURIInternal(aURI, aCacheKey, aReferrer, aReferrerPolicy,
- aPostData, aExtraHeaders, fileAsURI, false, aIsPrivate);
+ rv = SaveURIInternal(aURI, aPrincipal, aCacheKey,
+ aReferrer, aReferrerPolicy,
+ aPostData, aExtraHeaders, fileAsURI,
+ false, aIsPrivate);
return NS_FAILED(rv) ? rv : NS_OK;
}
NS_IMETHODIMP nsWebBrowserPersist::SaveChannel(
nsIChannel *aChannel, nsISupports *aFile)
{
NS_ENSURE_TRUE(mFirstAndOnlyUse, NS_ERROR_FAILURE);
mFirstAndOnlyUse = false; // Stop people from reusing this object!
@@ -594,27 +599,32 @@ nsWebBrowserPersist::SerializeNextFile()
URIData *data = iter.UserData();
if (data->mNeedsPersisting && !data->mSaved) {
urisToPersist++;
}
}
}
if (urisToPersist > 0) {
+ nsCOMPtr<nsIPrincipal> docPrincipal;
+ //XXXgijs I *think* this is already always true, but let's be sure.
+ MOZ_ASSERT(mDocList.Length() > 0,
+ "Should have the document for any walked URIs to persist!");
+ nsresult rv = mDocList.ElementAt(0)->mDocument->
+ GetPrincipal(getter_AddRefs(docPrincipal));
+ NS_ENSURE_SUCCESS_VOID(rv);
// Persist each file in the uri map. The document(s)
// will be saved after the last one of these is saved.
for (auto iter = mURIMap.Iter(); !iter.Done(); iter.Next()) {
URIData *data = iter.UserData();
if (!data->mNeedsPersisting || data->mSaved) {
continue;
}
- nsresult rv;
-
// Create a URI from the key.
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), iter.Key(),
data->mCharset.get());
if (NS_WARN_IF(NS_FAILED(rv))) {
break;
}
@@ -622,17 +632,17 @@ nsWebBrowserPersist::SerializeNextFile()
nsCOMPtr<nsIURI> fileAsURI = data->mDataPath;
rv = AppendPathToURI(fileAsURI, data->mFilename, fileAsURI);
if (NS_WARN_IF(NS_FAILED(rv))) {
break;
}
// The Referrer Policy doesn't matter here since the referrer is
// nullptr.
- rv = SaveURIInternal(uri, 0, nullptr,
+ rv = SaveURIInternal(uri, docPrincipal, 0, nullptr,
mozilla::net::RP_Unset, nullptr, nullptr,
fileAsURI, true, mIsPrivate);
// If SaveURIInternal fails, then it will have called EndDownload,
// which means that |data| is no longer valid memory. We MUST bail.
if (NS_WARN_IF(NS_FAILED(rv))) {
break;
}
@@ -1319,17 +1329,18 @@ nsWebBrowserPersist::AppendPathToURI(nsI
AppendUTF16toUTF8(aPath, newPath);
return NS_MutateURI(aURI)
.SetPathQueryRef(newPath)
.Finalize(aOutURI);
}
nsresult nsWebBrowserPersist::SaveURIInternal(
- nsIURI *aURI, uint32_t aCacheKey, nsIURI *aReferrer,
+ nsIURI *aURI, nsIPrincipal* aTriggeringPrincipal,
+ uint32_t aCacheKey, nsIURI *aReferrer,
uint32_t aReferrerPolicy, nsIInputStream *aPostData,
const char *aExtraHeaders, nsIURI *aFile,
bool aCalcFileExt, bool aIsPrivate)
{
NS_ENSURE_ARG_POINTER(aURI);
NS_ENSURE_ARG_POINTER(aFile);
nsresult rv = NS_OK;
@@ -1345,17 +1356,17 @@ nsresult nsWebBrowserPersist::SaveURIInt
{
loadFlags |= nsIRequest::LOAD_FROM_CACHE;
}
// Open a channel to the URI
nsCOMPtr<nsIChannel> inputChannel;
rv = NS_NewChannel(getter_AddRefs(inputChannel),
aURI,
- nsContentUtils::GetSystemPrincipal(),
+ aTriggeringPrincipal,
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
nsIContentPolicy::TYPE_OTHER,
nullptr, // aPerformanceStorage
nullptr, // aLoadGroup
static_cast<nsIInterfaceRequestor*>(this),
loadFlags);
nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(inputChannel);
@@ -1375,26 +1386,16 @@ nsresult nsWebBrowserPersist::SaveURIInt
{
nsCOMPtr<nsIEncodedChannel> encodedChannel(do_QueryInterface(inputChannel));
if (encodedChannel)
{
encodedChannel->SetApplyConversion(false);
}
}
- if (mPersistFlags & PERSIST_FLAGS_FORCE_ALLOW_COOKIES)
- {
- nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
- do_QueryInterface(inputChannel);
- if (httpChannelInternal) {
- rv = httpChannelInternal->SetThirdPartyFlags(nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- }
- }
-
// Set the referrer, post data and headers if any
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(inputChannel));
if (httpChannel)
{
// Referrer
if (aReferrer)
{
rv = httpChannel->SetReferrerWithPolicy(aReferrer, aReferrerPolicy);
--- a/dom/webbrowserpersist/nsWebBrowserPersist.h
+++ b/dom/webbrowserpersist/nsWebBrowserPersist.h
@@ -52,17 +52,18 @@ public:
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIPROGRESSEVENTSINK
// Private members
private:
virtual ~nsWebBrowserPersist();
nsresult SaveURIInternal(
- nsIURI *aURI, uint32_t aCacheKey, nsIURI *aReferrer,
+ nsIURI *aURI, nsIPrincipal* aTriggeringPrincipal,
+ uint32_t aCacheKey, nsIURI *aReferrer,
uint32_t aReferrerPolicy, nsIInputStream *aPostData,
const char *aExtraHeaders, nsIURI *aFile,
bool aCalcFileExt, bool aIsPrivate);
nsresult SaveChannelInternal(
nsIChannel *aChannel, nsIURI *aFile, bool aCalcFileExt);
nsresult SaveDocumentInternal(
nsIWebBrowserPersistDocument *aDocument,
nsIURI *aFile,
--- a/ipc/mscom/COMPtrHolder.h
+++ b/ipc/mscom/COMPtrHolder.h
@@ -157,17 +157,17 @@ struct ParamTraits<mozilla::mscom::COMPt
{
#if defined(MOZ_CONTENT_SANDBOX)
static const bool sIsStreamPreservationNeeded =
XRE_IsParentProcess() && mozilla::GetEffectiveContentSandboxLevel() >= 3;
#else
const bool sIsStreamPreservationNeeded = false;
#endif // defined(MOZ_CONTENT_SANDBOX)
- paramType::EnvType env;
+ typename paramType::EnvType env;
mozilla::mscom::ProxyStreamFlags flags = sIsStreamPreservationNeeded ?
mozilla::mscom::ProxyStreamFlags::ePreservable :
mozilla::mscom::ProxyStreamFlags::eDefault;
mozilla::mscom::ProxyStream proxyStream(_IID, aParam.Get(), &env, flags);
int bufLen;
const BYTE* buf = proxyStream.GetBuffer(bufLen);
--- a/ipc/mscom/Interceptor.cpp
+++ b/ipc/mscom/Interceptor.cpp
@@ -239,17 +239,17 @@ Interceptor::Create(STAUniquePtr<IUnknow
{
MOZ_ASSERT(aOutInterface && aTarget && aSink);
if (!aOutInterface) {
return E_INVALIDARG;
}
detail::LiveSetAutoLock lock(GetLiveSet());
- RefPtr<IWeakReference> existingWeak(std::move(GetLiveSet().Get(aTarget.get())));
+ RefPtr<IWeakReference> existingWeak(GetLiveSet().Get(aTarget.get()));
if (existingWeak) {
RefPtr<IWeakReferenceSource> existingStrong;
if (SUCCEEDED(existingWeak->ToStrongRef(getter_AddRefs(existingStrong)))) {
// QI on existingStrong may touch other threads. Since we now hold a
// strong ref on the interceptor, we may now release the lock.
lock.Unlock();
return existingStrong->QueryInterface(aInitialIid, aOutInterface);
}
@@ -886,17 +886,17 @@ Interceptor::Release()
Interceptor::DisconnectRemotesForTarget(IUnknown* aTarget)
{
MOZ_ASSERT(aTarget);
detail::LiveSetAutoLock lock(GetLiveSet());
// It is not an error if the interceptor doesn't exist, so we return
// S_FALSE instead of an error in that case.
- RefPtr<IWeakReference> existingWeak(std::move(GetLiveSet().Get(aTarget)));
+ RefPtr<IWeakReference> existingWeak(GetLiveSet().Get(aTarget));
if (!existingWeak) {
return S_FALSE;
}
RefPtr<IWeakReferenceSource> existingStrong;
if (FAILED(existingWeak->ToStrongRef(getter_AddRefs(existingStrong)))) {
return S_FALSE;
}
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2947,24 +2947,26 @@ nsIFrame::BuildDisplayListForStackingCon
if (usingSVGEffects) {
dirtyRect =
nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
visibleRect =
nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, visibleRect);
aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
}
+
+ bool needsActiveOpacityLayer = false;
// We build an opacity item if it's not going to be drawn by SVG content, or
// SVG effects. SVG effects won't handle the opacity if we want an active
// layer (for async animations), see
// nsSVGIntegrationsUtils::PaintMaskAndClipPath or
// nsSVGIntegrationsUtils::PaintFilter.
bool useOpacity = HasVisualOpacity(effectSet) &&
!nsSVGUtils::CanOptimizeOpacity(this) &&
- (!usingSVGEffects || nsDisplayOpacity::NeedsActiveLayer(aBuilder, this));
+ ((needsActiveOpacityLayer = nsDisplayOpacity::NeedsActiveLayer(aBuilder, this)) || !usingSVGEffects);
bool useBlendMode = effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
IsScrollFrameActive(aBuilder,
nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
nsLayoutUtils::SCROLLABLE_SAME_DOC |
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN));
bool useFixedPosition = disp->mPosition == NS_STYLE_POSITION_FIXED &&
(nsLayoutUtils::IsFixedPosFrameInDisplayPort(this) || BuilderHasScrolledClip(aBuilder));
@@ -3254,19 +3256,20 @@ nsIFrame::BuildDisplayListForStackingCon
* effects, wrap it up in an opacity item.
*/
if (useOpacity) {
// Don't clip nsDisplayOpacity items. We clip their descendants instead.
// The clip we would set on an element with opacity would clip
// all descendant content, but some should not be clipped.
DisplayListClipState::AutoSaveRestore opacityClipState(aBuilder);
resultList.AppendToTop(
- MakeDisplayItem<nsDisplayOpacity>(aBuilder, this, &resultList,
+ MakeDisplayItem<nsDisplayOpacity>(aBuilder, this, &resultList,
containerItemASR,
- opacityItemForEventsAndPluginsOnly));
+ opacityItemForEventsAndPluginsOnly,
+ needsActiveOpacityLayer));
if (aCreatedContainerItem) {
*aCreatedContainerItem = true;
}
}
/* If we're going to apply a transformation and don't have preserve-3d set, wrap
* everything in an nsDisplayTransform. If there's nothing in the list, don't add
* anything.
--- a/layout/painting/RetainedDisplayListBuilder.cpp
+++ b/layout/painting/RetainedDisplayListBuilder.cpp
@@ -292,16 +292,17 @@ public:
MOZ_DIAGNOSTIC_ASSERT(!mOldItems[oldIndex.val].IsUsed());
if (aNewItem->GetChildren()) {
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
if (mBuilder->MergeDisplayLists(aNewItem->GetChildren(),
oldItem->GetChildren(),
aNewItem->GetChildren(),
containerASRForChildren,
aNewItem->GetPerFrameKey())) {
+ aNewItem->InvalidateCachedChildInfo();
mResultIsModified = true;
}
UpdateASR(aNewItem, containerASRForChildren);
aNewItem->UpdateBounds(mBuilder->Builder());
}
AutoTArray<MergedListIndex, 2> directPredecessors = ProcessPredecessorsOfOldNode(oldIndex);
@@ -396,16 +397,17 @@ public:
mOldItems[aNode.val].Discard(mBuilder, std::move(aDirectPredecessors));
mResultIsModified = true;
} else {
if (item->GetChildren()) {
Maybe<const ActiveScrolledRoot*> containerASRForChildren;
nsDisplayList empty;
if (mBuilder->MergeDisplayLists(&empty, item->GetChildren(), item->GetChildren(),
containerASRForChildren, item->GetPerFrameKey())) {
+ item->InvalidateCachedChildInfo();
mResultIsModified = true;
}
UpdateASR(item, containerASRForChildren);
item->UpdateBounds(mBuilder->Builder());
}
if (item->GetType() == DisplayItemType::TYPE_SUBDOCUMENT) {
mBuilder->IncrementSubDocPresShellPaintCount(item);
}
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -6232,21 +6232,23 @@ nsresult nsDisplayWrapper::WrapListsInPl
NS_ENSURE_SUCCESS(rv, rv);
// The outlines may not be in-flow
return WrapEachDisplayItem(aBuilder, aLists.Outlines(), this);
}
nsDisplayOpacity::nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot,
- bool aForEventsAndPluginsOnly)
+ bool aForEventsAndPluginsOnly,
+ bool aNeedsActiveLayer)
: nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot, true)
, mOpacity(aFrame->StyleEffects()->mOpacity)
, mForEventsAndPluginsOnly(aForEventsAndPluginsOnly)
- , mOpacityAppliedToChildren(false)
+ , mNeedsActiveLayer(aNeedsActiveLayer)
+ , mChildOpacityState(ChildOpacityState::Unknown)
{
MOZ_COUNT_CTOR(nsDisplayOpacity);
mState.mOpacity = mOpacity;
}
#ifdef NS_BUILD_REFCNT_LOGGING
nsDisplayOpacity::~nsDisplayOpacity() {
MOZ_COUNT_DTOR(nsDisplayOpacity);
@@ -6373,24 +6375,29 @@ CollectItemsWithOpacity(nsDisplayList* a
}
return true;
}
bool
nsDisplayOpacity::ApplyOpacityToChildren(nsDisplayListBuilder* aBuilder)
{
+ if (mChildOpacityState == ChildOpacityState::Deferred) {
+ return false;
+ }
+
// Only try folding our opacity down if we have at most kMaxChildCount
// children that don't overlap and can all apply the opacity to themselves.
static const size_t kMaxChildCount = 3;
// Iterate through the child display list and copy at most kMaxChildCount
// child display item pointers to a temporary list.
AutoTArray<nsDisplayItem*, kMaxChildCount> items;
if (!CollectItemsWithOpacity(&mList, items, kMaxChildCount)) {
+ mChildOpacityState = ChildOpacityState::Deferred;
return false;
}
struct {
nsDisplayItem* item;
nsRect bounds;
} children[kMaxChildCount];
@@ -6400,43 +6407,41 @@ nsDisplayOpacity::ApplyOpacityToChildren
children[childCount].item = item;
children[childCount].bounds = item->GetBounds(aBuilder, &snap);
childCount++;
}
for (size_t i = 0; i < childCount; i++) {
for (size_t j = i+1; j < childCount; j++) {
if (children[i].bounds.Intersects(children[j].bounds)) {
+ mChildOpacityState = ChildOpacityState::Deferred;
return false;
}
}
}
for (uint32_t i = 0; i < childCount; i++) {
children[i].item->ApplyOpacity(aBuilder, mOpacity, mClipChain);
}
- mOpacityAppliedToChildren = true;
+ mChildOpacityState = ChildOpacityState::Applied;
return true;
}
bool
nsDisplayOpacity::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
{
- // ShouldFlattenAway() should be called only once during painting.
- MOZ_ASSERT(!mOpacityAppliedToChildren);
-
if (mFrame->GetPrevContinuation() || mFrame->GetNextContinuation() ||
mFrame->HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT)) {
// If we've been split, then we might need to merge, so
// don't flatten us away.
return false;
}
- if (NeedsActiveLayer(aBuilder, mFrame) || mOpacity == 0.0) {
+ if (mNeedsActiveLayer || mOpacity == 0.0) {
// If our opacity is zero then we'll discard all descendant display items
// except for layer event regions, so there's no point in doing this
// optimization (and if we do do it, then invalidations of those descendants
// might trigger repainting).
return false;
}
if (mList.IsEmpty()) {
@@ -6456,17 +6461,17 @@ nsDisplayOpacity::GetLayerState(nsDispla
// If we only created this item so that we'd get correct nsDisplayEventRegions for child
// frames, then force us to inactive to avoid unnecessary layerization changes for content
// that won't ever be painted.
if (mForEventsAndPluginsOnly) {
MOZ_ASSERT(mOpacity == 0);
return LAYER_INACTIVE;
}
- if (NeedsActiveLayer(aBuilder, mFrame)) {
+ if (mNeedsActiveLayer) {
// Returns LAYER_ACTIVE_FORCE to avoid flatterning the layer for async
// animations.
return LAYER_ACTIVE_FORCE;
}
return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, GetAnimatedGeometryRoot());
}
@@ -6644,17 +6649,17 @@ nsDisplayBlendMode::ComputeVisibility(ns
return nsDisplayWrapList::ComputeVisibility(aBuilder, &visibleUnderChildren);
}
bool
nsDisplayBlendMode::CanMerge(const nsDisplayItem* aItem) const
{
// Items for the same content element should be merged into a single
// compositing group.
- if (!HasSameTypeAndClip(aItem) || !HasSameContent(aItem)) {
+ if (!HasDifferentFrame(aItem) || !HasSameTypeAndClip(aItem) || !HasSameContent(aItem)) {
return false;
}
const nsDisplayBlendMode* item =
static_cast<const nsDisplayBlendMode*>(aItem);
if (item->mIndex != 0 || mIndex != 0) {
// Don't merge background-blend-mode items
@@ -9360,17 +9365,17 @@ CanMergeDisplayMaskFrame(nsIFrame* aFram
return true;
}
bool
nsDisplayMask::CanMerge(const nsDisplayItem* aItem) const
{
// Items for the same content element should be merged into a single
// compositing group.
- if (!HasSameTypeAndClip(aItem) || !HasSameContent(aItem)) {
+ if (!HasDifferentFrame(aItem) || !HasSameTypeAndClip(aItem) || !HasSameContent(aItem)) {
return false;
}
return CanMergeDisplayMaskFrame(mFrame) &&
CanMergeDisplayMaskFrame(aItem->Frame());
}
already_AddRefed<Layer>
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -2368,16 +2368,22 @@ public:
aInvalidRegion->Or(aGeometry->mBounds, bounds);
} else {
aInvalidRegion->Xor(aGeometry->mBounds, bounds);
}
}
}
/**
+ * This function is called when an item's list of children has been omdified
+ * by RetaineDisplayListBuilder.
+ */
+ virtual void InvalidateCachedChildInfo() {}
+
+ /**
* @param aSnap set to true if the edges of the rectangles of the opaque
* region would be snapped to device pixels when drawing
* @return a region of the item that is opaque --- that is, every pixel
* that is visible is painted with an opaque
* color. This is useful for determining when one piece
* of content completely obscures another so that we can do occlusion
* culling.
* This does not take clipping into account.
@@ -2780,16 +2786,21 @@ public:
bool BackfaceIsHidden() const { return mFrame->BackfaceIsHidden(); }
bool In3DContextAndBackfaceIsHidden()
{
return mBackfaceHidden;
}
+ bool HasDifferentFrame(const nsDisplayItem* aOther) const
+ {
+ return mFrame != aOther->mFrame;
+ }
+
bool HasSameTypeAndClip(const nsDisplayItem* aOther) const
{
return GetPerFrameKey() == aOther->GetPerFrameKey() &&
GetClipChain() == aOther->GetClipChain();
}
bool HasSameContent(const nsDisplayItem* aOther) const
{
@@ -4962,16 +4973,17 @@ public:
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
return false;
}
virtual void Merge(const nsDisplayItem* aItem) override
{
MOZ_ASSERT(CanMerge(aItem));
+ MOZ_ASSERT(Frame() != aItem->Frame());
MergeFromTrackingMergedFrames(static_cast<const nsDisplayWrapList*>(aItem));
}
virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) const override
{
aFrames->AppendElements(mMergedFrames);
}
@@ -5110,63 +5122,66 @@ protected:
* The standard display item to paint a stacking context with translucency
* set by the stacking context root frame's 'opacity' style.
*/
class nsDisplayOpacity : public nsDisplayWrapList {
public:
nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList,
const ActiveScrolledRoot* aActiveScrolledRoot,
- bool aForEventsAndPluginsOnly);
+ bool aForEventsAndPluginsOnly,
+ bool aNeedsActiveLayer);
nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
const nsDisplayOpacity& aOther)
: nsDisplayWrapList(aBuilder, aOther)
, mOpacity(aOther.mOpacity)
, mForEventsAndPluginsOnly(aOther.mForEventsAndPluginsOnly)
- , mOpacityAppliedToChildren(false)
+ , mNeedsActiveLayer(aOther.mNeedsActiveLayer)
+ , mChildOpacityState(ChildOpacityState::Unknown)
{
// We should not try to merge flattened opacities.
- MOZ_ASSERT(!aOther.mOpacityAppliedToChildren);
+ MOZ_ASSERT(aOther.mChildOpacityState != ChildOpacityState::Applied);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayOpacity();
#endif
virtual void RestoreState() override
{
nsDisplayItem::RestoreState();
mOpacity = mState.mOpacity;
- mOpacityAppliedToChildren = false;
}
virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
{
MOZ_COUNT_CTOR(nsDisplayOpacity);
return MakeDisplayItem<nsDisplayOpacity>(aBuilder, *this);
}
+ virtual void InvalidateCachedChildInfo() override { mChildOpacityState = ChildOpacityState::Unknown; }
+
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
bool* aSnap) const override;
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) override;
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aParameters) override;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) override;
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
// items for the same content element should be merged into a single
// compositing group
// aItem->GetUnderlyingFrame() returns non-null because it's nsDisplayOpacity
- return HasSameTypeAndClip(aItem) && HasSameContent(aItem);
+ return HasDifferentFrame(aItem) && HasSameTypeAndClip(aItem) && HasSameContent(aItem);
}
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
{
return new nsDisplayOpacityGeometry(this, aBuilder, mOpacity);
}
virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
@@ -5184,17 +5199,17 @@ public:
float aOpacity,
const DisplayItemClipChain* aClip) override;
virtual bool CanApplyOpacity() const override;
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
/**
* Returns true if ShouldFlattenAway() applied opacity to children.
*/
- bool OpacityAppliedToChildren() const { return mOpacityAppliedToChildren; }
+ bool OpacityAppliedToChildren() const { return mChildOpacityState == ChildOpacityState::Applied; }
static bool NeedsActiveLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
virtual void WriteDebugInfo(std::stringstream& aStream) override;
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
@@ -5204,18 +5219,31 @@ public:
nsDisplayListBuilder* aDisplayListBuilder) override;
float GetOpacity() { return mOpacity; }
private:
bool ApplyOpacityToChildren(nsDisplayListBuilder* aBuilder);
float mOpacity;
- bool mForEventsAndPluginsOnly;
- bool mOpacityAppliedToChildren;
+ bool mForEventsAndPluginsOnly : 1;
+ enum class ChildOpacityState : uint8_t {
+ // Our child list has changed since the last time ApplyOpacityToChildren was called.
+ Unknown,
+ // Our children defer opacity handling to us.
+ Deferred,
+ // Opacity is applied to our children.
+ Applied
+ };
+ bool mNeedsActiveLayer : 1;
+#ifndef __GNUC__
+ ChildOpacityState mChildOpacityState : 2;
+#else
+ ChildOpacityState mChildOpacityState;
+#endif
struct {
float mOpacity;
} mState;
};
class nsDisplayBlendMode : public nsDisplayWrapList {
public:
@@ -5376,17 +5404,17 @@ public:
const StackingContextHelper& aSc,
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) override;
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
// Items for the same content element should be merged into a single
// compositing group.
- return HasSameTypeAndClip(aItem) && HasSameContent(aItem)
+ return HasDifferentFrame(aItem) && HasSameTypeAndClip(aItem) && HasSameContent(aItem)
&& mIsForBackground == static_cast<const nsDisplayBlendContainer*>(aItem)->mIsForBackground;
}
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
{
return false;
}
virtual uint32_t GetPerFrameKey() const override {
@@ -6131,17 +6159,17 @@ public:
}
NS_DISPLAY_DECL_NAME("Filter", TYPE_FILTER)
virtual bool CanMerge(const nsDisplayItem* aItem) const override
{
// Items for the same content element should be merged into a single
// compositing group.
- return HasSameTypeAndClip(aItem) && HasSameContent(aItem);
+ return HasDifferentFrame(aItem) && HasSameTypeAndClip(aItem) && HasSameContent(aItem);
}
virtual void Merge(const nsDisplayItem* aItem) override
{
nsDisplayWrapList::Merge(aItem);
const nsDisplayFilter* other = static_cast<const nsDisplayFilter*>(aItem);
mEffectsBounds.UnionRect(mEffectsBounds,
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -85,24 +85,24 @@ printf_stderr(const char *fmt, ...)
vfprintf(fp, fmt, args);
va_end(args);
fclose(fp);
}
typedef MOZ_NORETURN_PTR void (__fastcall* BaseThreadInitThunk_func)(BOOL aIsInitialThread, void* aStartAddress, void* aThreadParam);
-static BaseThreadInitThunk_func stub_BaseThreadInitThunk = nullptr;
+static WindowsDllInterceptor::FuncHookType<BaseThreadInitThunk_func> stub_BaseThreadInitThunk;
typedef NTSTATUS (NTAPI *LdrLoadDll_func) (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle);
-static LdrLoadDll_func stub_LdrLoadDll;
+static WindowsDllInterceptor::FuncHookType<LdrLoadDll_func> stub_LdrLoadDll;
#ifdef _M_AMD64
typedef decltype(RtlInstallFunctionTableCallback)* RtlInstallFunctionTableCallback_func;
-static RtlInstallFunctionTableCallback_func stub_RtlInstallFunctionTableCallback;
+static WindowsDllInterceptor::FuncHookType<RtlInstallFunctionTableCallback_func> stub_RtlInstallFunctionTableCallback;
extern uint8_t* sMsMpegJitCodeRegionStart;
extern size_t sMsMpegJitCodeRegionSize;
BOOLEAN WINAPI patched_RtlInstallFunctionTableCallback(DWORD64 TableIdentifier,
DWORD64 BaseAddress, DWORD Length, PGET_RUNTIME_FUNCTION_CALLBACK Callback,
PVOID Context, PCWSTR OutOfProcessCallbackDll)
{
@@ -657,17 +657,18 @@ DllBlocklist_Initialize(uint32_t aInitFl
NtDllIntercept.Init("ntdll.dll");
ReentrancySentinel::InitializeStatics();
// We specifically use a detour, because there are cases where external
// code also tries to hook LdrLoadDll, and doesn't know how to relocate our
// nop space patches. (Bug 951827)
- bool ok = NtDllIntercept.AddDetour("LdrLoadDll", reinterpret_cast<intptr_t>(patched_LdrLoadDll), (void**) &stub_LdrLoadDll);
+ bool ok = stub_LdrLoadDll.SetDetour(NtDllIntercept, "LdrLoadDll",
+ &patched_LdrLoadDll);
if (!ok) {
sBlocklistInitFailed = true;
#ifdef DEBUG
printf_stderr("LdrLoadDll hook failed, no dll blocklisting active\n");
#endif
}
@@ -678,28 +679,28 @@ DllBlocklist_Initialize(uint32_t aInitFl
::LoadLibraryW(L"user32.dll");
}
Kernel32Intercept.Init("kernel32.dll");
#ifdef _M_AMD64
if (!IsWin8OrLater()) {
// The crash that this hook works around is only seen on Win7.
- Kernel32Intercept.AddHook("RtlInstallFunctionTableCallback",
- reinterpret_cast<intptr_t>(patched_RtlInstallFunctionTableCallback),
- (void**)&stub_RtlInstallFunctionTableCallback);
+ stub_RtlInstallFunctionTableCallback.Set(Kernel32Intercept,
+ "RtlInstallFunctionTableCallback",
+ &patched_RtlInstallFunctionTableCallback);
}
#endif
// Bug 1361410: WRusr.dll will overwrite our hook and cause a crash.
// Workaround: If we detect WRusr.dll, don't hook.
if (!GetModuleHandleW(L"WRusr.dll")) {
- if(!Kernel32Intercept.AddDetour("BaseThreadInitThunk",
- reinterpret_cast<intptr_t>(patched_BaseThreadInitThunk),
- (void**) &stub_BaseThreadInitThunk)) {
+ if (!stub_BaseThreadInitThunk.SetDetour(Kernel32Intercept,
+ "BaseThreadInitThunk",
+ &patched_BaseThreadInitThunk)) {
#ifdef DEBUG
printf_stderr("BaseThreadInitThunk hook failed\n");
#endif
}
}
#if defined(NIGHTLY_BUILD)
// Populate a list of thread start addresses to block.
--- a/mozglue/misc/interceptor/PatcherDetour.h
+++ b/mozglue/misc/interceptor/PatcherDetour.h
@@ -37,29 +37,29 @@ public:
WindowsDllDetourPatcher(const WindowsDllDetourPatcher&) = delete;
WindowsDllDetourPatcher(WindowsDllDetourPatcher&&) = delete;
WindowsDllDetourPatcher& operator=(const WindowsDllDetourPatcher&) = delete;
WindowsDllDetourPatcher& operator=(WindowsDllDetourPatcher&&) = delete;
void Clear()
{
- if (!mVMPolicy.ShouldUnhookUponDestruction()) {
+ if (!this->mVMPolicy.ShouldUnhookUponDestruction()) {
return;
}
#if defined(_M_IX86)
size_t nBytes = 1 + sizeof(intptr_t);
#elif defined(_M_X64)
size_t nBytes = 2 + sizeof(intptr_t);
#else
#error "Unknown processor type"
#endif
- const auto& tramps = mVMPolicy.Items();
+ const auto& tramps = this->mVMPolicy.Items();
for (auto&& tramp : tramps) {
// First we read the pointer to the interceptor instance.
Maybe<uintptr_t> instance = tramp.ReadEncodedPointer();
if (!instance) {
continue;
}
if (instance.value() != reinterpret_cast<uintptr_t>(this)) {
@@ -75,17 +75,17 @@ public:
});
// Now we read the pointer to the intercepted function.
Maybe<uintptr_t> interceptedFn = tramp.ReadEncodedPointer();
if (!interceptedFn) {
continue;
}
- WritableTargetFunction<MMPolicyT> origBytes(mVMPolicy,
+ WritableTargetFunction<MMPolicyT> origBytes(this->mVMPolicy,
interceptedFn.value(), nBytes);
if (!origBytes) {
continue;
}
Maybe<uint8_t> maybeOpcode1 = origBytes.ReadByte();
if (!maybeOpcode1) {
continue;
@@ -130,43 +130,43 @@ public:
}
#else
#error "Unknown processor type"
#endif
origBytes.Commit();
}
- mVMPolicy.Clear();
+ this->mVMPolicy.Clear();
}
void Init(int aNumHooks = 0)
{
if (Initialized()) {
return;
}
if (aNumHooks == 0) {
// Win32 allocates VM addresses at a 64KiB granularity, so by default we
// might as well utilize that entire 64KiB reservation instead of
// artifically constraining ourselves to the page size.
- aNumHooks = mVMPolicy.GetAllocGranularity() / kHookSize;
+ aNumHooks = this->mVMPolicy.GetAllocGranularity() / kHookSize;
}
- mVMPolicy.Reserve(aNumHooks);
+ this->mVMPolicy.Reserve(aNumHooks);
}
bool Initialized() const
{
- return !!mVMPolicy;
+ return !!this->mVMPolicy;
}
bool AddHook(FARPROC aTargetFn, intptr_t aHookDest, void** aOrigFunc)
{
- ReadOnlyTargetFunction<MMPolicyT> target(ResolveRedirectedAddress(aTargetFn));
+ ReadOnlyTargetFunction<MMPolicyT> target(this->ResolveRedirectedAddress(aTargetFn));
CreateTrampoline(target, aHookDest, aOrigFunc);
if (!*aOrigFunc) {
return false;
}
return true;
}
--- a/mozglue/misc/interceptor/VMSharingPolicies.h
+++ b/mozglue/misc/interceptor/VMSharingPolicies.h
@@ -29,33 +29,34 @@ public:
MOZ_ASSERT(aCount);
uint32_t bytesReserved = MMPolicy::Reserve(aCount * kChunkSize);
return !!bytesReserved;
}
Trampoline<MMPolicy> GetNextTrampoline()
{
uint32_t offset = mNextChunkIndex * kChunkSize;
- if (!MaybeCommitNextPage(offset, kChunkSize)) {
+ if (!this->MaybeCommitNextPage(offset, kChunkSize)) {
return nullptr;
}
- Trampoline<MMPolicy> result(this, GetLocalView() + offset,
- GetRemoteView() + offset, kChunkSize);
+ Trampoline<MMPolicy> result(this, this->GetLocalView() + offset,
+ this->GetRemoteView() + offset, kChunkSize);
if (!!result) {
++mNextChunkIndex;
}
return std::move(result);
}
TrampolineCollection<MMPolicy> Items() const
{
- return TrampolineCollection<MMPolicy>(*this, GetLocalView(), GetRemoteView(),
+ return TrampolineCollection<MMPolicy>(*this, this->GetLocalView(),
+ this->GetRemoteView(),
kChunkSize, mNextChunkIndex);
}
void Clear()
{
mNextChunkIndex = 0;
}
--- a/mozglue/misc/nsWindowsDllInterceptor.h
+++ b/mozglue/misc/nsWindowsDllInterceptor.h
@@ -3,20 +3,22 @@
/* 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 NS_WINDOWS_DLL_INTERCEPTOR_H_
#define NS_WINDOWS_DLL_INTERCEPTOR_H_
#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/DebugOnly.h"
-#include "mozilla/NotNull.h"
+#include "mozilla/Move.h"
+#include "mozilla/Tuple.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Types.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Vector.h"
#include "nsWindowsHelpers.h"
#include <wchar.h>
#include <windows.h>
@@ -77,26 +79,165 @@
*
* Note that this is not thread-safe. Sad day.
*
*/
namespace mozilla {
namespace interceptor {
+template <typename InterceptorT, typename FuncPtrT>
+class FuncHook final
+{
+ template <typename T>
+ struct OriginalFunctionPtrTraits;
+
+ template <typename R, typename... Args>
+ struct OriginalFunctionPtrTraits<R (*)(Args...)>
+ {
+ using ReturnType = R;
+ };
+
+#if defined(_M_IX86)
+ template <typename R, typename... Args>
+ struct OriginalFunctionPtrTraits<R (__stdcall*)(Args...)>
+ {
+ using ReturnType = R;
+ };
+
+ template <typename R, typename... Args>
+ struct OriginalFunctionPtrTraits<R (__fastcall*)(Args...)>
+ {
+ using ReturnType = R;
+ };
+#endif // defined(_M_IX86)
+
+public:
+ using ThisType = FuncHook<InterceptorT, FuncPtrT>;
+ using ReturnType = typename OriginalFunctionPtrTraits<FuncPtrT>::ReturnType;
+
+ constexpr FuncHook()
+ : mOrigFunc(nullptr)
+ , mInitOnce(INIT_ONCE_STATIC_INIT)
+ {
+ }
+
+ ~FuncHook() = default;
+
+ bool Set(InterceptorT& aInterceptor, const char* aName,
+ FuncPtrT aHookDest)
+ {
+ LPVOID addHookOk;
+ InitOnceContext ctx(this, &aInterceptor, aName, aHookDest, false);
+
+ return ::InitOnceExecuteOnce(&mInitOnce, &InitOnceCallback, &ctx,
+ &addHookOk) && addHookOk;
+ }
+
+ bool SetDetour(InterceptorT& aInterceptor, const char* aName,
+ FuncPtrT aHookDest)
+ {
+ LPVOID addHookOk;
+ InitOnceContext ctx(this, &aInterceptor, aName, aHookDest, true);
+
+ return ::InitOnceExecuteOnce(&mInitOnce, &InitOnceCallback, &ctx,
+ &addHookOk) && addHookOk;
+ }
+
+ explicit operator bool() const
+ {
+ return !!mOrigFunc;
+ }
+
+ template <typename... ArgsType>
+ ReturnType operator()(ArgsType... aArgs) const
+ {
+ return mOrigFunc(std::forward<ArgsType>(aArgs)...);
+ }
+
+ FuncPtrT GetStub() const
+ {
+ return mOrigFunc;
+ }
+
+ // One-time init stuff cannot be moved or copied
+ FuncHook(const FuncHook&) = delete;
+ FuncHook(FuncHook&&) = delete;
+ FuncHook& operator=(const FuncHook&) = delete;
+ FuncHook& operator=(FuncHook&& aOther) = delete;
+
+private:
+ struct MOZ_RAII InitOnceContext final
+ {
+ InitOnceContext(ThisType* aHook, InterceptorT* aInterceptor,
+ const char* aName, void* aHookDest, bool aForceDetour)
+ : mHook(aHook)
+ , mInterceptor(aInterceptor)
+ , mName(aName)
+ , mHookDest(aHookDest)
+ , mForceDetour(aForceDetour)
+ {
+ }
+
+ ThisType* mHook;
+ InterceptorT* mInterceptor;
+ const char* mName;
+ void* mHookDest;
+ bool mForceDetour;
+ };
+
+private:
+ bool Apply(InterceptorT* aInterceptor, const char* aName, void* aHookDest)
+ {
+ return aInterceptor->AddHook(aName, reinterpret_cast<intptr_t>(aHookDest),
+ reinterpret_cast<void**>(&mOrigFunc));
+ }
+
+ bool ApplyDetour(InterceptorT* aInterceptor, const char* aName,
+ void* aHookDest)
+ {
+ return aInterceptor->AddDetour(aName, reinterpret_cast<intptr_t>(aHookDest),
+ reinterpret_cast<void**>(&mOrigFunc));
+ }
+
+ static BOOL CALLBACK
+ InitOnceCallback(PINIT_ONCE aInitOnce, PVOID aParam, PVOID* aOutContext)
+ {
+ MOZ_ASSERT(aOutContext);
+
+ bool result;
+ auto ctx = reinterpret_cast<InitOnceContext*>(aParam);
+ if (ctx->mForceDetour) {
+ result = ctx->mHook->ApplyDetour(ctx->mInterceptor, ctx->mName,
+ ctx->mHookDest);
+ } else {
+ result = ctx->mHook->Apply(ctx->mInterceptor, ctx->mName, ctx->mHookDest);
+ }
+
+ *aOutContext = result ? reinterpret_cast<PVOID>(1U << INIT_ONCE_CTX_RESERVED_BITS) : nullptr;
+ return TRUE;
+ }
+
+private:
+ FuncPtrT mOrigFunc;
+ INIT_ONCE mInitOnce;
+};
+
enum
{
kDefaultTrampolineSize = 128
};
template <typename VMPolicy =
mozilla::interceptor::VMSharingPolicyShared<
mozilla::interceptor::MMPolicyInProcess, kDefaultTrampolineSize>>
class WindowsDllInterceptor final
{
+ typedef WindowsDllInterceptor<VMPolicy> ThisType;
+
interceptor::WindowsDllDetourPatcher<VMPolicy> mDetourPatcher;
#if defined(_M_IX86)
interceptor::WindowsDllNopSpacePatcher<typename VMPolicy::MMPolicyT> mNopSpacePatcher;
#endif // defined(_M_IX86)
HMODULE mModule;
int mNHooks;
@@ -155,16 +296,17 @@ public:
#if defined(_M_IX86)
mNopSpacePatcher.Clear();
#endif // defined(_M_IX86)
mDetourPatcher.Clear();
// NB: We intentionally leak mModule
}
+private:
/**
* Hook/detour the method aName from the DLL we set in Init so that it calls
* aHookDest instead. Returns the original method pointer in aOrigFunc
* and returns true if successful.
*
* IMPORTANT: If you use this method, please add your case to the
* TestDllInterceptor in order to detect future failures. Even if this
* succeeds now, updates to the hooked DLL could cause it to fail in
@@ -214,27 +356,34 @@ public:
FARPROC proc = ::GetProcAddress(mModule, aName);
if (!proc) {
return false;
}
return AddDetour(proc, aHookDest, aOrigFunc);
}
-private:
bool AddDetour(FARPROC aProc, intptr_t aHookDest, void** aOrigFunc)
{
MOZ_ASSERT(mModule && aProc);
if (!mDetourPatcher.Initialized()) {
mDetourPatcher.Init(mNHooks);
}
return mDetourPatcher.AddHook(aProc, aHookDest, aOrigFunc);
}
+
+public:
+ template <typename FuncPtrT>
+ using FuncHookType = FuncHook<ThisType, FuncPtrT>;
+
+private:
+ template <typename InterceptorT, typename FuncPtrT>
+ friend class FuncHook;
};
} // namespace interceptor
using WindowsDllInterceptor = interceptor::WindowsDllInterceptor<>;
using CrossProcessDllInterceptor = interceptor::WindowsDllInterceptor<
mozilla::interceptor::VMSharingPolicyUnique<
--- a/mozglue/tests/interceptor/TestDllInterceptor.cpp
+++ b/mozglue/tests/interceptor/TestDllInterceptor.cpp
@@ -5,20 +5,43 @@
#include <shlobj.h>
#include <stdio.h>
#include <commdlg.h>
#define SECURITY_WIN32
#include <security.h>
#include <wininet.h>
#include <schnlsp.h>
+#include "mozilla/TypeTraits.h"
+#include "mozilla/UniquePtr.h"
#include "mozilla/WindowsVersion.h"
#include "nsWindowsDllInterceptor.h"
#include "nsWindowsHelpers.h"
+NTSTATUS NTAPI NtFlushBuffersFile(HANDLE, PIO_STATUS_BLOCK);
+NTSTATUS NTAPI NtReadFile(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
+ PIO_STATUS_BLOCK, PVOID, ULONG,
+ PLARGE_INTEGER, PULONG);
+NTSTATUS NTAPI NtReadFileScatter(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
+ PIO_STATUS_BLOCK, PFILE_SEGMENT_ELEMENT, ULONG,
+ PLARGE_INTEGER, PULONG);
+NTSTATUS NTAPI NtWriteFile(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
+ PIO_STATUS_BLOCK, PVOID, ULONG,
+ PLARGE_INTEGER, PULONG);
+NTSTATUS NTAPI NtWriteFileGather(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
+ PIO_STATUS_BLOCK, PFILE_SEGMENT_ELEMENT, ULONG,
+ PLARGE_INTEGER, PULONG);
+NTSTATUS NTAPI NtQueryFullAttributesFile(POBJECT_ATTRIBUTES, PVOID);
+NTSTATUS NTAPI LdrLoadDll(PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle);
+NTSTATUS NTAPI LdrUnloadDll(HMODULE);
+// These pointers are disguised as PVOID to avoid pulling in obscure headers
+PVOID NTAPI LdrResolveDelayLoadedAPI(PVOID, PVOID, PVOID, PVOID, PVOID, ULONG);
+void CALLBACK ProcessCaretEvents(HWINEVENTHOOK, DWORD, HWND, LONG, LONG, DWORD, DWORD);
+void __fastcall BaseThreadInitThunk(BOOL aIsInitialThread, void* aStartAddress, void* aThreadParam);
+
using namespace mozilla;
struct payload {
UINT64 a;
UINT64 b;
UINT64 c;
bool operator==(const payload &other) const {
@@ -33,90 +56,319 @@ extern "C" __declspec(dllexport) __decls
p.a = p.b;
p.b = p.c;
p.c = tmp;
return p;
}
static bool patched_func_called = false;
-static payload (*orig_rotatePayload)(payload);
+static WindowsDllInterceptor::FuncHookType<decltype(&rotatePayload)>
+ orig_rotatePayload;
static payload
patched_rotatePayload(payload p)
{
patched_func_called = true;
return orig_rotatePayload(p);
}
-typedef bool(*HookTestFunc)(void*);
-bool CheckHook(HookTestFunc aHookTestFunc, void* aOrigFunc,
- const char* aDllName, const char* aFuncName)
+// Invoke aFunc by taking aArg's contents and using them as aFunc's arguments
+template <typename CallableT, typename... Args, typename ArgTuple = Tuple<Args...>, size_t... Indices>
+decltype(auto) Apply(CallableT&& aFunc, ArgTuple&& aArgs, std::index_sequence<Indices...>)
{
- if (aHookTestFunc(aOrigFunc)) {
+ return std::forward<CallableT>(aFunc)(Get<Indices>(std::forward<ArgTuple>(aArgs))...);
+}
+
+template <typename CallableT>
+bool TestFunction(CallableT aFunc);
+
+#define DEFINE_TEST_FUNCTION(calling_convention) \
+ template <typename R, typename... Args, typename... TestArgs> \
+ bool TestFunction(WindowsDllInterceptor::FuncHookType<R (calling_convention *)(Args...)>&& aFunc, \
+ bool (* aPred)(R), TestArgs... aArgs) \
+ { \
+ using FuncHookType = WindowsDllInterceptor::FuncHookType<R (calling_convention *)(Args...)>; \
+ using ArgTuple = Tuple<Args...>; \
+ using Indices = std::index_sequence_for<Args...>; \
+ ArgTuple fakeArgs{ std::forward<TestArgs>(aArgs)... }; \
+ return aPred(Apply(std::forward<FuncHookType>(aFunc), std::forward<ArgTuple>(fakeArgs), Indices())); \
+ } \
+ \
+ /* Specialization for functions returning void */ \
+ template <typename... Args, typename PredicateT, typename... TestArgs> \
+ bool TestFunction(WindowsDllInterceptor::FuncHookType<void (calling_convention *)(Args...)>&& aFunc, \
+ PredicateT&& aPred, TestArgs... aArgs) \
+ { \
+ using FuncHookType = WindowsDllInterceptor::FuncHookType<void (calling_convention *)(Args...)>; \
+ using ArgTuple = Tuple<Args...>; \
+ using Indices = std::index_sequence_for<Args...>; \
+ ArgTuple fakeArgs{ std::forward<TestArgs>(aArgs)... }; \
+ Apply(std::forward<FuncHookType>(aFunc), std::forward<ArgTuple>(fakeArgs), Indices()); \
+ return true; \
+ }
+
+// C++11 allows empty arguments to macros. clang works just fine. MSVC does the
+// right thing, but it also throws up warning C4003.
+#if defined(_MSC_VER) && !defined(__clang__)
+DEFINE_TEST_FUNCTION(__cdecl)
+#else
+DEFINE_TEST_FUNCTION()
+#endif
+
+#ifdef _M_IX86
+DEFINE_TEST_FUNCTION(__stdcall)
+DEFINE_TEST_FUNCTION(__fastcall)
+#endif // _M_IX86
+
+// Test the hooked function against the supplied predicate
+template <typename OrigFuncT, typename PredicateT, typename... Args>
+bool CheckHook(WindowsDllInterceptor::FuncHookType<OrigFuncT> &aOrigFunc,
+ const char* aDllName, const char* aFuncName, PredicateT&& aPred,
+ Args... aArgs)
+{
+ if (TestFunction(std::forward<WindowsDllInterceptor::FuncHookType<OrigFuncT>>(aOrigFunc), std::forward<PredicateT>(aPred), std::forward<Args>(aArgs)...)) {
printf("TEST-PASS | WindowsDllInterceptor | "
"Executed hooked function %s from %s\n", aFuncName, aDllName);
return true;
}
printf("TEST-FAILED | WindowsDllInterceptor | "
"Failed to execute hooked function %s from %s\n", aFuncName, aDllName);
return false;
}
-template <size_t N>
-bool TestHook(HookTestFunc funcTester, const char (&dll)[N], const char *func)
+// Hook the function and optionally attempt calling it
+template <typename OrigFuncT, size_t N, typename PredicateT, typename... Args>
+bool TestHook(const char (&dll)[N], const char *func, PredicateT&& aPred, Args... aArgs)
{
- void *orig_func;
+ auto orig_func(mozilla::MakeUnique<WindowsDllInterceptor::FuncHookType<OrigFuncT>>());
+
bool successful = false;
{
WindowsDllInterceptor TestIntercept;
TestIntercept.Init(dll);
- successful = TestIntercept.AddHook(func, 0, &orig_func);
+ successful = orig_func->Set(TestIntercept, func, nullptr);
}
if (successful) {
printf("TEST-PASS | WindowsDllInterceptor | Could hook %s from %s\n", func, dll);
- return CheckHook(funcTester, orig_func, dll, func);
+ if (!aPred) {
+ printf("TEST-SKIPPED | WindowsDllInterceptor | "
+ "Will not attempt to execute patched %s.\n", func);
+ return true;
+ }
+
+ return CheckHook(*orig_func, dll, func, std::forward<PredicateT>(aPred), std::forward<Args>(aArgs)...);
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to hook %s from %s\n", func, dll);
return false;
}
}
-template <size_t N>
-bool TestDetour(const char (&dll)[N], const char *func)
+// Detour the function and optionally attempt calling it
+template <typename OrigFuncT, size_t N, typename PredicateT>
+bool TestDetour(const char (&dll)[N], const char *func, PredicateT&& aPred)
{
- void *orig_func;
+ auto orig_func(mozilla::MakeUnique<WindowsDllInterceptor::FuncHookType<OrigFuncT>>());
+
bool successful = false;
{
WindowsDllInterceptor TestIntercept;
TestIntercept.Init(dll);
- successful = TestIntercept.AddDetour(func, 0, &orig_func);
+ successful = orig_func->SetDetour(TestIntercept, func, nullptr);
}
if (successful) {
printf("TEST-PASS | WindowsDllInterceptor | Could detour %s from %s\n", func, dll);
- return true;
+ if (!aPred) {
+ printf("TEST-SKIPPED | WindowsDllInterceptor | "
+ "Will not attempt to execute patched %s.\n", func);
+ return true;
+ }
+
+ return CheckHook(*orig_func, dll, func, std::forward<PredicateT>(aPred));
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to detour %s from %s\n", func, dll);
return false;
}
}
-template <size_t N>
-bool MaybeTestHook(const bool cond, HookTestFunc funcTester, const char (&dll)[N], const char* func)
+// If a function pointer's type returns void*, this template converts that type
+// to return uintptr_t instead, for the purposes of predicates.
+template <typename FuncT>
+struct SubstituteForVoidPtr
+{
+ using Type = FuncT;
+};
+
+template <typename... Args>
+struct SubstituteForVoidPtr<void* (*)(Args...)>
+{
+ using Type = uintptr_t (*)(Args...);
+};
+
+#ifdef _M_IX86
+template <typename... Args>
+struct SubstituteForVoidPtr<void* (__stdcall*)(Args...)>
+{
+ using Type = uintptr_t (__stdcall*)(Args...);
+};
+
+template <typename... Args>
+struct SubstituteForVoidPtr<void* (__fastcall*)(Args...)>
+{
+ using Type = uintptr_t (__fastcall*)(Args...);
+};
+#endif // _M_IX86
+
+// Determines the function's return type
+template <typename FuncT>
+struct ReturnType;
+
+template <typename R, typename... Args>
+struct ReturnType<R (*)(Args...)>
+{
+ using Type = R;
+};
+
+#ifdef _M_IX86
+template <typename R, typename... Args>
+struct ReturnType<R (__stdcall*)(Args...)>
+{
+ using Type = R;
+};
+
+template <typename R, typename... Args>
+struct ReturnType<R (__fastcall*)(Args...)>
+{
+ using Type = R;
+};
+#endif // _M_IX86
+
+// Predicates that may be supplied during tests
+template <typename FuncT>
+struct Predicates
+{
+ using ArgType = typename ReturnType<FuncT>::Type;
+
+ template <ArgType CompVal>
+ static bool Equals(ArgType aValue)
+ {
+ return CompVal == aValue;
+ }
+
+ template <ArgType CompVal>
+ static bool NotEquals(ArgType aValue)
+ {
+ return CompVal != aValue;
+ }
+
+ template <ArgType CompVal>
+ static bool Ignore(ArgType aValue)
+ {
+ return true;
+ }
+};
+
+// Functions that return void should be ignored, so we specialize the
+// Ignore predicate for that case. Use nullptr as the value to compare against.
+template <typename... Args>
+struct Predicates<void (*)(Args...)>
+{
+ template <nullptr_t DummyVal>
+ static bool Ignore()
+ {
+ return true;
+ }
+};
+
+#ifdef _M_IX86
+template <typename... Args>
+struct Predicates<void (__stdcall*)(Args...)>
+{
+ template <nullptr_t DummyVal>
+ static bool Ignore()
+ {
+ return true;
+ }
+};
+
+template <typename... Args>
+struct Predicates<void (__fastcall*)(Args...)>
+{
+ template <nullptr_t DummyVal>
+ static bool Ignore()
+ {
+ return true;
+ }
+};
+#endif // _M_IX86
+
+// The standard test. Hook |func|, and then try executing it with all zero
+// arguments, using |pred| and |comp| to determine whether the call successfully
+// executed. In general, you want set pred and comp such that they return true
+// when the function is returning whatever value is expected with all-zero
+// arguments.
+//
+// Note: When |func| returns void, you must supply |Ignore| and |nullptr| as the
+// |pred| and |comp| arguments, respectively.
+#define TEST_HOOK(dll, func, pred, comp) \
+ TestHook<decltype(&func)>(#dll, #func, &Predicates<decltype(&func)>::pred<comp>)
+
+// We need to special-case functions that return INVALID_HANDLE_VALUE
+// (ie, CreateFile). Our template machinery for comparing values doesn't work
+// with integer constants passed as pointers (well, it works on MSVC, but not
+// clang, because that is not standard-compliant).
+#define TEST_HOOK_FOR_INVALID_HANDLE_VALUE(dll, func) \
+ TestHook<SubstituteForVoidPtr<decltype(&func)>::Type>(#dll, #func, &Predicates<SubstituteForVoidPtr<decltype(&func)>::Type>::Equals<uintptr_t(-1)>)
+
+// This variant allows you to explicitly supply arguments to the hooked function
+// during testing. You want to provide arguments that produce the conditions that
+// induce the function to return a value that is accepted by your predicate.
+#define TEST_HOOK_PARAMS(dll, func, pred, comp, ...) \
+ TestHook<decltype(&func)>(#dll, #func, &Predicates<decltype(&func)>::pred<comp>, __VA_ARGS__)
+
+// This is for cases when we want to hook |func|, but it is unsafe to attempt
+// to execute the function in the context of a test.
+#define TEST_HOOK_SKIP_EXEC(dll, func) \
+ TestHook<decltype(&func)>(#dll, #func, reinterpret_cast<bool (*)(typename ReturnType<decltype(&func)>::Type)>(NULL))
+
+// The following three variants are identical to the previous macros,
+// however the forcibly use a Detour on 32-bit Windows. On 64-bit Windows,
+// these macros are identical to their TEST_HOOK variants.
+#define TEST_DETOUR(dll, func, pred, comp) \
+ TestDetour<decltype(&func)>(#dll, #func, &Predicates<decltype(&func)>::pred<comp>)
+
+#define TEST_DETOUR_PARAMS(dll, func, pred, comp, ...) \
+ TestDetour<decltype(&func)>(#dll, #func, &Predicates<decltype(&func)>::pred<comp>, __VA_ARGS__)
+
+#define TEST_DETOUR_SKIP_EXEC(dll, func) \
+ TestDetour<decltype(&func)>(#dll, #func, reinterpret_cast<bool (*)(typename ReturnType<decltype(&func)>::Type)>(NULL))
+
+template <typename OrigFuncT, size_t N, typename PredicateT, typename... Args>
+bool MaybeTestHook(const bool cond, const char (&dll)[N], const char *func, PredicateT&& aPred, Args... aArgs)
{
if (!cond) {
printf("TEST-SKIPPED | WindowsDllInterceptor | Skipped hook test for %s from %s\n", func, dll);
return true;
}
- return TestHook(funcTester, dll, func);
+ return TestHook<OrigFuncT>(dll, func, std::forward<PredicateT>(aPred), std::forward<Args>(aArgs)...);
}
+// Like TEST_HOOK, but the test is only executed when cond is true.
+#define MAYBE_TEST_HOOK(cond, dll, func, pred, comp) \
+ MaybeTestHook<decltype(&func)>(cond, #dll, #func, &Predicates<decltype(&func)>::pred<comp>)
+
+#define MAYBE_TEST_HOOK_PARAMS(cond, dll, func, pred, comp, ...) \
+ MaybeTestHook<decltype(&func)>(cond, #dll, #func, &Predicates<decltype(&func)>::pred<comp>, __VA_ARGS__)
+
+#define MAYBE_TEST_HOOK_SKIP_EXEC(cond, dll, func) \
+ MaybeTestHook<decltype(&func)>(cond, #dll, #func, reinterpret_cast<bool (*)(typename ReturnType<decltype(&func)>::Type)>(NULL))
+
bool ShouldTestTipTsf()
{
if (!IsWin8OrLater()) {
return false;
}
nsModuleHandle shell32(LoadLibraryW(L"shell32.dll"));
if (!shell32) {
@@ -142,465 +394,16 @@ bool ShouldTestTipTsf()
if (!LoadLibraryW(fullPath)) {
return false;
}
// Leak the module so that it's loaded for the interceptor test
return true;
}
-// These test the patched function returned by the DLL
-// interceptor. They check that the patched assembler preamble does
-// something sane. The parameter is a pointer to the patched function.
-bool TestGetWindowInfo(void* aFunc)
-{
- auto patchedGetWindowInfo =
- reinterpret_cast<decltype(&GetWindowInfo)>(aFunc);
- return patchedGetWindowInfo(0, 0) == FALSE;
-}
-
-bool TestSetWindowLongPtr(void* aFunc)
-{
- auto patchedSetWindowLongPtr =
- reinterpret_cast<decltype(&SetWindowLongPtr)>(aFunc);
- return patchedSetWindowLongPtr(0, 0, 0) == 0;
-}
-
-bool TestSetWindowLong(void* aFunc)
-{
- auto patchedSetWindowLong =
- reinterpret_cast<decltype(&SetWindowLong)>(aFunc);
- return patchedSetWindowLong(0, 0, 0) == 0;
-}
-
-bool TestTrackPopupMenu(void* aFunc)
-{
- auto patchedTrackPopupMenu =
- reinterpret_cast<decltype(&TrackPopupMenu)>(aFunc);
- return patchedTrackPopupMenu(0, 0, 0, 0, 0, 0, 0) == 0;
-}
-
-bool TestNtFlushBuffersFile(void* aFunc)
-{
- typedef NTSTATUS(WINAPI *NtFlushBuffersFileType)(HANDLE, PIO_STATUS_BLOCK);
- auto patchedNtFlushBuffersFile =
- reinterpret_cast<NtFlushBuffersFileType>(aFunc);
- patchedNtFlushBuffersFile(0, 0);
- return true;
-}
-
-bool TestNtCreateFile(void* aFunc)
-{
- auto patchedNtCreateFile =
- reinterpret_cast<decltype(&NtCreateFile)>(aFunc);
- return patchedNtCreateFile(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
-}
-
-bool TestNtReadFile(void* aFunc)
-{
- typedef NTSTATUS(WINAPI *NtReadFileType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
- PIO_STATUS_BLOCK, PVOID, ULONG,
- PLARGE_INTEGER, PULONG);
- auto patchedNtReadFile =
- reinterpret_cast<NtReadFileType>(aFunc);
- return patchedNtReadFile(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
-}
-
-bool TestNtReadFileScatter(void* aFunc)
-{
- typedef NTSTATUS(WINAPI *NtReadFileScatterType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
- PIO_STATUS_BLOCK, PFILE_SEGMENT_ELEMENT, ULONG,
- PLARGE_INTEGER, PULONG);
- auto patchedNtReadFileScatter =
- reinterpret_cast<NtReadFileScatterType>(aFunc);
- return patchedNtReadFileScatter(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
-}
-
-bool TestNtWriteFile(void* aFunc)
-{
- typedef NTSTATUS(WINAPI *NtWriteFileType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
- PIO_STATUS_BLOCK, PVOID, ULONG,
- PLARGE_INTEGER, PULONG);
- auto patchedNtWriteFile =
- reinterpret_cast<NtWriteFileType>(aFunc);
- return patchedNtWriteFile(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
-}
-
-bool TestNtWriteFileGather(void* aFunc)
-{
- typedef NTSTATUS(WINAPI *NtWriteFileGatherType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
- PIO_STATUS_BLOCK, PFILE_SEGMENT_ELEMENT, ULONG,
- PLARGE_INTEGER, PULONG);
- auto patchedNtWriteFileGather =
- reinterpret_cast<NtWriteFileGatherType>(aFunc);
- return patchedNtWriteFileGather(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
-}
-
-bool TestNtQueryFullAttributesFile(void* aFunc)
-{
- typedef NTSTATUS(WINAPI *NtQueryFullAttributesFileType)(POBJECT_ATTRIBUTES,
- PVOID);
- auto patchedNtQueryFullAttributesFile =
- reinterpret_cast<NtQueryFullAttributesFileType>(aFunc);
- return patchedNtQueryFullAttributesFile(0, 0) != 0;
-}
-
-bool TestLdrUnloadDll(void* aFunc)
-{
- typedef NTSTATUS (NTAPI *LdrUnloadDllType)(HMODULE);
- auto patchedLdrUnloadDll = reinterpret_cast<LdrUnloadDllType>(aFunc);
- return patchedLdrUnloadDll(0) != 0;
-}
-
-bool TestLdrResolveDelayLoadedAPI(void* aFunc)
-{
- // These pointers are disguised as PVOID to avoid pulling in obscure headers
- typedef PVOID (WINAPI *LdrResolveDelayLoadedAPIType)(PVOID, PVOID, PVOID,
- PVOID, PVOID, ULONG);
- auto patchedLdrResolveDelayLoadedAPI =
- reinterpret_cast<LdrResolveDelayLoadedAPIType>(aFunc);
- // No idea how to call this API. Flags==99 is just an arbitrary number that
- // doesn't crash when the other params are null.
- return patchedLdrResolveDelayLoadedAPI(0, 0, 0, 0, 0, 99) == 0;
-}
-
-#ifdef _M_AMD64
-bool TestRtlInstallFunctionTableCallback(void* aFunc)
-{
- auto patchedRtlInstallFunctionTableCallback =
- reinterpret_cast<decltype(RtlInstallFunctionTableCallback)*>(aFunc);
-
- return patchedRtlInstallFunctionTableCallback(0, 0, 0, 0, 0, 0) == FALSE;
-}
-#endif
-
-bool TestSetUnhandledExceptionFilter(void* aFunc)
-{
- auto patchedSetUnhandledExceptionFilter =
- reinterpret_cast<decltype(&SetUnhandledExceptionFilter)>(aFunc);
- // Retrieve the current filter as we set the new filter to null, then restore the current filter.
- LPTOP_LEVEL_EXCEPTION_FILTER current = patchedSetUnhandledExceptionFilter(0);
- patchedSetUnhandledExceptionFilter(current);
- return true;
-}
-
-bool TestVirtualAlloc(void* aFunc)
-{
- auto patchedVirtualAlloc =
- reinterpret_cast<decltype(&VirtualAlloc)>(aFunc);
- return patchedVirtualAlloc(0, 0, 0, 0) == 0;
-}
-
-bool TestMapViewOfFile(void* aFunc)
-{
- auto patchedMapViewOfFile =
- reinterpret_cast<decltype(&MapViewOfFile)>(aFunc);
- return patchedMapViewOfFile(0, 0, 0, 0, 0) == 0;
-}
-
-bool TestCreateDIBSection(void* aFunc)
-{
- auto patchedCreateDIBSection =
- reinterpret_cast<decltype(&CreateDIBSection)>(aFunc);
- // MSDN is wrong here. This does not return ERROR_INVALID_PARAMETER. It
- // sets the value of GetLastError to ERROR_INVALID_PARAMETER.
- // CreateDIBSection returns 0 on error.
- return patchedCreateDIBSection(0, 0, 0, 0, 0, 0) == 0;
-}
-
-bool TestCreateFileW(void* aFunc)
-{
- auto patchedCreateFileW =
- reinterpret_cast<decltype(&CreateFileW)>(aFunc);
- return patchedCreateFileW(0, 0, 0, 0, 0, 0, 0) == INVALID_HANDLE_VALUE;
-}
-
-bool TestCreateFileA(void* aFunc)
-{
- auto patchedCreateFileA =
- reinterpret_cast<decltype(&CreateFileA)>(aFunc);
-// return patchedCreateFileA(0, 0, 0, 0, 0, 0, 0) == INVALID_HANDLE_VALUE;
- printf("TEST-SKIPPED | WindowsDllInterceptor | "
- "Will not attempt to execute patched CreateFileA -- patched method is known to fail.\n");
- return true;
-}
-
-bool TestQueryDosDeviceW(void* aFunc)
-{
- auto patchedQueryDosDeviceW =
- reinterpret_cast<decltype(&QueryDosDeviceW)>(aFunc);
- return patchedQueryDosDeviceW(nullptr, nullptr, 0) == 0;
-}
-
-bool TestInSendMessageEx(void* aFunc)
-{
- auto patchedInSendMessageEx =
- reinterpret_cast<decltype(&InSendMessageEx)>(aFunc);
- patchedInSendMessageEx(0);
- return true;
-}
-
-bool TestImmGetContext(void* aFunc)
-{
- auto patchedImmGetContext =
- reinterpret_cast<decltype(&ImmGetContext)>(aFunc);
- patchedImmGetContext(0);
- return true;
-}
-
-bool TestImmGetCompositionStringW(void* aFunc)
-{
- auto patchedImmGetCompositionStringW =
- reinterpret_cast<decltype(&ImmGetCompositionStringW)>(aFunc);
- patchedImmGetCompositionStringW(0, 0, 0, 0);
- return true;
-}
-
-bool TestImmSetCandidateWindow(void* aFunc)
-{
- auto patchedImmSetCandidateWindow =
- reinterpret_cast<decltype(&ImmSetCandidateWindow)>(aFunc);
-// return patchedImmSetCandidateWindow(0, 0) == 0;
- // ImmSetCandidateWindow crashes if given bad parameters.
- printf("TEST-SKIPPED | WindowsDllInterceptor | "
- "Will not attempt to execute patched ImmSetCandidateWindow.\n");
- return true;
-}
-
-bool TestImmNotifyIME(void* aFunc)
-{
- auto patchedImmNotifyIME =
- reinterpret_cast<decltype(&ImmNotifyIME)>(aFunc);
- return patchedImmNotifyIME(0, 0, 0, 0) == 0;
-}
-
-bool TestGetSaveFileNameW(void* aFunc)
-{
- auto patchedGetSaveFileNameWType =
- reinterpret_cast<decltype(&GetSaveFileNameW)>(aFunc);
- patchedGetSaveFileNameWType(0);
- return true;
-}
-
-bool TestGetOpenFileNameW(void* aFunc)
-{
- auto patchedGetOpenFileNameWType =
- reinterpret_cast<decltype(&GetOpenFileNameW)>(aFunc);
- patchedGetOpenFileNameWType(0);
- return true;
-}
-
-bool TestGetKeyState(void* aFunc)
-{
- auto patchedGetKeyState =
- reinterpret_cast<decltype(&GetKeyState)>(aFunc);
- patchedGetKeyState(0);
- return true;
-}
-
-bool TestSendMessageTimeoutW(void* aFunc)
-{
- auto patchedSendMessageTimeoutW =
- reinterpret_cast<decltype(&SendMessageTimeoutW)>(aFunc);
- return patchedSendMessageTimeoutW(0, 0, 0, 0, 0, 0, 0) == 0;
-}
-
-bool TestProcessCaretEvents(void* aFunc)
-{
- auto patchedProcessCaretEvents =
- reinterpret_cast<WINEVENTPROC>(aFunc);
- patchedProcessCaretEvents(0, 0, 0, 0, 0, 0, 0);
- return true;
-}
-
-bool TestSetCursorPos(void* aFunc)
-{
- // SetCursorPos has some issues in automation -- see bug 1368033.
- // For that reason, we don't check the return value -- we only
- // check that the method runs without producing an exception.
- auto patchedSetCursorPos =
- reinterpret_cast<decltype(&SetCursorPos)>(aFunc);
- patchedSetCursorPos(512, 512);
- return true;
-}
-
-static DWORD sTlsIndex = 0;
-
-bool TestTlsAlloc(void* aFunc)
-{
- auto patchedTlsAlloc =
- reinterpret_cast<decltype(&TlsAlloc)>(aFunc);
- sTlsIndex = patchedTlsAlloc();
- return sTlsIndex != TLS_OUT_OF_INDEXES;
-}
-
-bool TestTlsFree(void* aFunc)
-{
- auto patchedTlsFree =
- reinterpret_cast<decltype(&TlsFree)>(aFunc);
- return sTlsIndex != 0 && patchedTlsFree(sTlsIndex);
-}
-
-bool TestCloseHandle(void* aFunc)
-{
- auto patchedCloseHandle =
- reinterpret_cast<decltype(&CloseHandle)>(aFunc);
- return patchedCloseHandle(0) == FALSE;
-}
-
-bool TestDuplicateHandle(void* aFunc)
-{
- auto patchedDuplicateHandle =
- reinterpret_cast<decltype(&DuplicateHandle)>(aFunc);
- return patchedDuplicateHandle(0, 0, 0, 0, 0, 0, 0) == FALSE;
-}
-
-bool TestPrintDlgW(void* aFunc)
-{
- auto patchedPrintDlgW =
- reinterpret_cast<decltype(&PrintDlgW)>(aFunc);
- patchedPrintDlgW(0);
- return true;
-}
-
-bool TestInternetConnectA(void* aFunc)
-{
- auto patchedInternetConnectA =
- reinterpret_cast<decltype(&InternetConnectA)>(aFunc);
- return patchedInternetConnectA(0, 0, 0, 0, 0, 0, 0, 0) == 0;
-}
-
-HINTERNET sInternet = 0;
-
-bool TestInternetOpenA(void* aFunc)
-{
- auto patchedInternetOpenA =
- reinterpret_cast<decltype(&InternetOpenA)>(aFunc);
- sInternet = patchedInternetOpenA(0, 0, 0, 0, 0);
- return sInternet != 0;
-}
-
-bool TestInternetCloseHandle(void* aFunc)
-{
- auto patchedInternetCloseHandle =
- reinterpret_cast<decltype(&InternetCloseHandle)>(aFunc);
- return patchedInternetCloseHandle(sInternet);
-}
-
-bool TestInternetQueryDataAvailable(void* aFunc)
-{
- auto patchedInternetQueryDataAvailable =
- reinterpret_cast<decltype(&InternetQueryDataAvailable)>(aFunc);
- return patchedInternetQueryDataAvailable(0, 0, 0, 0) == FALSE;
-}
-
-bool TestInternetReadFile(void* aFunc)
-{
- auto patchedInternetReadFile =
- reinterpret_cast<decltype(&InternetReadFile)>(aFunc);
- return patchedInternetReadFile(0, 0, 0, 0) == FALSE;
-}
-
-bool TestInternetWriteFile(void* aFunc)
-{
- auto patchedInternetWriteFile =
- reinterpret_cast<decltype(&InternetWriteFile)>(aFunc);
- return patchedInternetWriteFile(0, 0, 0, 0) == FALSE;
-}
-
-bool TestInternetSetOptionA(void* aFunc)
-{
- auto patchedInternetSetOptionA =
- reinterpret_cast<decltype(&InternetSetOptionA)>(aFunc);
- return patchedInternetSetOptionA(0, 0, 0, 0) == FALSE;
-}
-
-bool TestHttpAddRequestHeadersA(void* aFunc)
-{
- auto patchedHttpAddRequestHeadersA =
- reinterpret_cast<decltype(&HttpAddRequestHeadersA)>(aFunc);
- return patchedHttpAddRequestHeadersA(0, 0, 0, 0) == FALSE;
-}
-
-bool TestHttpOpenRequestA(void* aFunc)
-{
- auto patchedHttpOpenRequestA =
- reinterpret_cast<decltype(&HttpOpenRequestA)>(aFunc);
- return patchedHttpOpenRequestA(0, 0, 0, 0, 0, 0, 0, 0) == 0;
-}
-
-bool TestHttpQueryInfoA(void* aFunc)
-{
- auto patchedHttpQueryInfoA =
- reinterpret_cast<decltype(&HttpQueryInfoA)>(aFunc);
- return patchedHttpQueryInfoA(0, 0, 0, 0, 0) == FALSE;
-}
-
-bool TestHttpSendRequestA(void* aFunc)
-{
- auto patchedHttpSendRequestA =
- reinterpret_cast<decltype(&HttpSendRequestA)>(aFunc);
- return patchedHttpSendRequestA(0, 0, 0, 0, 0) == FALSE;
-}
-
-bool TestHttpSendRequestExA(void* aFunc)
-{
- auto patchedHttpSendRequestExA =
- reinterpret_cast<decltype(&HttpSendRequestExA)>(aFunc);
- return patchedHttpSendRequestExA(0, 0, 0, 0, 0) == FALSE;
-}
-
-bool TestHttpEndRequestA(void* aFunc)
-{
- auto patchedHttpEndRequestA =
- reinterpret_cast<decltype(&HttpEndRequestA)>(aFunc);
- return patchedHttpEndRequestA(0, 0, 0, 0) == FALSE;
-}
-
-bool TestInternetQueryOptionA(void* aFunc)
-{
- auto patchedInternetQueryOptionA =
- reinterpret_cast<decltype(&InternetQueryOptionA)>(aFunc);
- return patchedInternetQueryOptionA(0, 0, 0, 0) == FALSE;
-}
-
-bool TestInternetErrorDlg(void* aFunc)
-{
- auto patchedInternetErrorDlg =
- reinterpret_cast<decltype(&InternetErrorDlg)>(aFunc);
- return patchedInternetErrorDlg(0, 0, 0, 0, 0) == ERROR_INVALID_HANDLE;
-}
-
-CredHandle sCredHandle;
-
-bool TestAcquireCredentialsHandleA(void* aFunc)
-{
- auto patchedAcquireCredentialsHandleA =
- reinterpret_cast<decltype(&AcquireCredentialsHandleA)>(aFunc);
- SCHANNEL_CRED cred;
- memset(&cred, 0, sizeof(cred));
- cred.dwVersion = SCHANNEL_CRED_VERSION;
- return patchedAcquireCredentialsHandleA(0, UNISP_NAME, SECPKG_CRED_OUTBOUND,
- 0, &cred, 0, 0, &sCredHandle, 0) == S_OK;
-}
-
-bool TestQueryCredentialsAttributesA(void* aFunc)
-{
- auto patchedQueryCredentialsAttributesA =
- reinterpret_cast<decltype(&QueryCredentialsAttributesA)>(aFunc);
- return patchedQueryCredentialsAttributesA(&sCredHandle, 0, 0) == SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-bool TestFreeCredentialsHandle(void* aFunc)
-{
- auto patchedFreeCredentialsHandle =
- reinterpret_cast<decltype(&FreeCredentialsHandle)>(aFunc);
- return patchedFreeCredentialsHandle(&sCredHandle) == S_OK;
-}
-
int main()
{
LARGE_INTEGER start;
QueryPerformanceCounter(&start);
// We disable this part of the test because the code coverage instrumentation
// injects code in rotatePayload in a way that WindowsDllInterceptor doesn't
// understand.
@@ -610,17 +413,17 @@ int main()
ZeroMemory(&p0, sizeof(p0));
ZeroMemory(&p1, sizeof(p1));
p0 = rotatePayload(initial);
{
WindowsDllInterceptor ExeIntercept;
ExeIntercept.Init("TestDllInterceptor.exe");
- if (ExeIntercept.AddHook("rotatePayload", reinterpret_cast<intptr_t>(patched_rotatePayload), (void**) &orig_rotatePayload)) {
+ if (orig_rotatePayload.Set(ExeIntercept, "rotatePayload", &patched_rotatePayload)) {
printf("TEST-PASS | WindowsDllInterceptor | Hook added\n");
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to add hook\n");
return 1;
}
p1 = rotatePayload(initial);
@@ -654,95 +457,95 @@ int main()
if (p0 == p1) {
printf("TEST-PASS | WindowsDllInterceptor | Original function worked properly\n");
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Original function didn't return the right information\n");
return 1;
}
#endif
- if (TestHook(TestGetWindowInfo, "user32.dll", "GetWindowInfo") &&
+ if (TEST_HOOK(user32.dll, GetWindowInfo, Equals, FALSE) &&
#ifdef _WIN64
- TestHook(TestSetWindowLongPtr, "user32.dll", "SetWindowLongPtrA") &&
- TestHook(TestSetWindowLongPtr, "user32.dll", "SetWindowLongPtrW") &&
+ TEST_HOOK(user32.dll, SetWindowLongPtrA, Equals, 0) &&
+ TEST_HOOK(user32.dll, SetWindowLongPtrW, Equals, 0) &&
#else
- TestHook(TestSetWindowLong, "user32.dll", "SetWindowLongA") &&
- TestHook(TestSetWindowLong, "user32.dll", "SetWindowLongW") &&
+ TEST_HOOK(user32.dll, SetWindowLongA, Equals, 0) &&
+ TEST_HOOK(user32.dll, SetWindowLongW, Equals, 0) &&
#endif
- TestHook(TestTrackPopupMenu, "user32.dll", "TrackPopupMenu") &&
+ TEST_HOOK(user32.dll, TrackPopupMenu, Equals, FALSE) &&
#ifdef _M_IX86
// We keep this test to hook complex code on x86. (Bug 850957)
- TestHook(TestNtFlushBuffersFile, "ntdll.dll", "NtFlushBuffersFile") &&
+ TEST_HOOK(ntdll.dll, NtFlushBuffersFile, NotEquals, 0) &&
#endif
- TestHook(TestNtCreateFile, "ntdll.dll", "NtCreateFile") &&
- TestHook(TestNtReadFile, "ntdll.dll", "NtReadFile") &&
- TestHook(TestNtReadFileScatter, "ntdll.dll", "NtReadFileScatter") &&
- TestHook(TestNtWriteFile, "ntdll.dll", "NtWriteFile") &&
- TestHook(TestNtWriteFileGather, "ntdll.dll", "NtWriteFileGather") &&
- TestHook(TestNtQueryFullAttributesFile, "ntdll.dll", "NtQueryFullAttributesFile") &&
+ TEST_HOOK(ntdll.dll, NtCreateFile, NotEquals, 0) &&
+ TEST_HOOK(ntdll.dll, NtReadFile, NotEquals, 0) &&
+ TEST_HOOK(ntdll.dll, NtReadFileScatter, NotEquals, 0) &&
+ TEST_HOOK(ntdll.dll, NtWriteFile, NotEquals, 0) &&
+ TEST_HOOK(ntdll.dll, NtWriteFileGather, NotEquals, 0) &&
+ TEST_HOOK(ntdll.dll, NtQueryFullAttributesFile, NotEquals, 0) &&
#ifndef MOZ_ASAN
// Bug 733892: toolkit/crashreporter/nsExceptionHandler.cpp
// This fails on ASan because the ASan runtime already hooked this function
- TestHook(TestSetUnhandledExceptionFilter, "kernel32.dll", "SetUnhandledExceptionFilter") &&
+ TEST_HOOK(kernel32.dll, SetUnhandledExceptionFilter, Ignore, nullptr) &&
#endif
#ifdef _M_IX86
// Bug 670967: xpcom/base/AvailableMemoryTracker.cpp
- TestHook(TestVirtualAlloc, "kernel32.dll", "VirtualAlloc") &&
- TestHook(TestMapViewOfFile, "kernel32.dll", "MapViewOfFile") &&
- TestHook(TestCreateDIBSection, "gdi32.dll", "CreateDIBSection") &&
- TestHook(TestCreateFileW, "kernel32.dll", "CreateFileW") && // see Bug 1316415
+ TEST_HOOK(kernel32.dll, VirtualAlloc, Equals, nullptr) &&
+ TEST_HOOK(kernel32.dll, MapViewOfFile, Equals, nullptr) &&
+ TEST_HOOK(gdi32.dll, CreateDIBSection, Equals, nullptr) &&
+ TEST_HOOK_FOR_INVALID_HANDLE_VALUE(kernel32.dll, CreateFileW) &&
#endif
- TestHook(TestCreateFileA, "kernel32.dll", "CreateFileA") &&
- TestHook(TestQueryDosDeviceW, "kernelbase.dll", "QueryDosDeviceW") &&
- TestDetour("user32.dll", "CreateWindowExW") &&
- TestHook(TestInSendMessageEx, "user32.dll", "InSendMessageEx") &&
- TestHook(TestImmGetContext, "imm32.dll", "ImmGetContext") &&
- TestHook(TestImmGetCompositionStringW, "imm32.dll", "ImmGetCompositionStringW") &&
- TestHook(TestImmSetCandidateWindow, "imm32.dll", "ImmSetCandidateWindow") &&
- TestHook(TestImmNotifyIME, "imm32.dll", "ImmNotifyIME") &&
- TestHook(TestGetSaveFileNameW, "comdlg32.dll", "GetSaveFileNameW") &&
- TestHook(TestGetOpenFileNameW, "comdlg32.dll", "GetOpenFileNameW") &&
+ TEST_HOOK_FOR_INVALID_HANDLE_VALUE(kernel32.dll, CreateFileA) &&
+ TEST_HOOK(kernelbase.dll, QueryDosDeviceW, Equals, 0) &&
+ TEST_DETOUR(user32.dll, CreateWindowExW, Equals, nullptr) &&
+ TEST_HOOK(user32.dll, InSendMessageEx, Equals, ISMEX_NOSEND) &&
+ TEST_HOOK(imm32.dll, ImmGetContext, Equals, nullptr) &&
+ TEST_HOOK(imm32.dll, ImmGetCompositionStringW, Ignore, 0) &&
+ TEST_HOOK_SKIP_EXEC(imm32.dll, ImmSetCandidateWindow) &&
+ TEST_HOOK(imm32.dll, ImmNotifyIME, Equals, 0) &&
+ TEST_HOOK(comdlg32.dll, GetSaveFileNameW, Ignore, FALSE) &&
+ TEST_HOOK(comdlg32.dll, GetOpenFileNameW, Ignore, FALSE) &&
#ifdef _M_X64
- TestHook(TestGetKeyState, "user32.dll", "GetKeyState") && // see Bug 1316415
- TestHook(TestLdrUnloadDll, "ntdll.dll", "LdrUnloadDll") &&
- MaybeTestHook(IsWin8OrLater(), TestLdrResolveDelayLoadedAPI, "ntdll.dll", "LdrResolveDelayLoadedAPI") &&
- MaybeTestHook(!IsWin8OrLater(), TestRtlInstallFunctionTableCallback, "kernel32.dll", "RtlInstallFunctionTableCallback") &&
- TestHook(TestPrintDlgW, "comdlg32.dll", "PrintDlgW") &&
+ TEST_HOOK(user32.dll, GetKeyState, Ignore, 0) && // see Bug 1316415
+ TEST_HOOK(ntdll.dll, LdrUnloadDll, NotEquals, 0) &&
+ MAYBE_TEST_HOOK_SKIP_EXEC(IsWin8OrLater(), ntdll.dll, LdrResolveDelayLoadedAPI) &&
+ MAYBE_TEST_HOOK(!IsWin8OrLater(), kernel32.dll, RtlInstallFunctionTableCallback, Equals, FALSE) &&
+ TEST_HOOK(comdlg32.dll, PrintDlgW, Ignore, 0) &&
#endif
- MaybeTestHook(ShouldTestTipTsf(), TestProcessCaretEvents, "tiptsf.dll", "ProcessCaretEvents") &&
+ MAYBE_TEST_HOOK(ShouldTestTipTsf(), tiptsf.dll, ProcessCaretEvents, Ignore, nullptr) &&
#ifdef _M_IX86
- TestHook(TestSendMessageTimeoutW, "user32.dll", "SendMessageTimeoutW") &&
+ TEST_HOOK(user32.dll, SendMessageTimeoutW, Equals, 0) &&
#endif
- TestHook(TestSetCursorPos, "user32.dll", "SetCursorPos") &&
- TestHook(TestTlsAlloc, "kernel32.dll", "TlsAlloc") &&
- TestHook(TestTlsFree, "kernel32.dll", "TlsFree") &&
- TestHook(TestCloseHandle, "kernel32.dll", "CloseHandle") &&
- TestHook(TestDuplicateHandle, "kernel32.dll", "DuplicateHandle") &&
+ TEST_HOOK(user32.dll, SetCursorPos, NotEquals, FALSE) &&
+ TEST_HOOK(kernel32.dll, TlsAlloc, NotEquals, TLS_OUT_OF_INDEXES) &&
+ TEST_HOOK_PARAMS(kernel32.dll, TlsFree, Equals, FALSE, TLS_OUT_OF_INDEXES) &&
+ TEST_HOOK(kernel32.dll, CloseHandle, Equals, FALSE) &&
+ TEST_HOOK(kernel32.dll, DuplicateHandle, Equals, FALSE) &&
- TestHook(TestInternetOpenA, "wininet.dll", "InternetOpenA") &&
- TestHook(TestInternetCloseHandle, "wininet.dll", "InternetCloseHandle") &&
- TestHook(TestInternetConnectA, "wininet.dll", "InternetConnectA") &&
- TestHook(TestInternetQueryDataAvailable, "wininet.dll", "InternetQueryDataAvailable") &&
- TestHook(TestInternetReadFile, "wininet.dll", "InternetReadFile") &&
- TestHook(TestInternetWriteFile, "wininet.dll", "InternetWriteFile") &&
- TestHook(TestInternetSetOptionA, "wininet.dll", "InternetSetOptionA") &&
- TestHook(TestHttpAddRequestHeadersA, "wininet.dll", "HttpAddRequestHeadersA") &&
- TestHook(TestHttpOpenRequestA, "wininet.dll", "HttpOpenRequestA") &&
- TestHook(TestHttpQueryInfoA, "wininet.dll", "HttpQueryInfoA") &&
- TestHook(TestHttpSendRequestA, "wininet.dll", "HttpSendRequestA") &&
- TestHook(TestHttpSendRequestExA, "wininet.dll", "HttpSendRequestExA") &&
- TestHook(TestHttpEndRequestA, "wininet.dll", "HttpEndRequestA") &&
- TestHook(TestInternetQueryOptionA, "wininet.dll", "InternetQueryOptionA") &&
+ TEST_HOOK(wininet.dll, InternetOpenA, NotEquals, nullptr) &&
+ TEST_HOOK(wininet.dll, InternetCloseHandle, Equals, FALSE) &&
+ TEST_HOOK(wininet.dll, InternetConnectA, Equals, nullptr) &&
+ TEST_HOOK(wininet.dll, InternetQueryDataAvailable, Equals, FALSE) &&
+ TEST_HOOK(wininet.dll, InternetReadFile, Equals, FALSE) &&
+ TEST_HOOK(wininet.dll, InternetWriteFile, Equals, FALSE) &&
+ TEST_HOOK(wininet.dll, InternetSetOptionA, Equals, FALSE) &&
+ TEST_HOOK(wininet.dll, HttpAddRequestHeadersA, Equals, FALSE) &&
+ TEST_HOOK(wininet.dll, HttpOpenRequestA, Equals, nullptr) &&
+ TEST_HOOK(wininet.dll, HttpQueryInfoA, Equals, FALSE) &&
+ TEST_HOOK(wininet.dll, HttpSendRequestA, Equals, FALSE) &&
+ TEST_HOOK(wininet.dll, HttpSendRequestExA, Equals, FALSE) &&
+ TEST_HOOK(wininet.dll, HttpEndRequestA, Equals, FALSE) &&
+ TEST_HOOK(wininet.dll, InternetQueryOptionA, Equals, FALSE) &&
- TestHook(TestAcquireCredentialsHandleA, "sspicli.dll", "AcquireCredentialsHandleA") &&
- TestHook(TestQueryCredentialsAttributesA, "sspicli.dll", "QueryCredentialsAttributesA") &&
- TestHook(TestFreeCredentialsHandle, "sspicli.dll", "FreeCredentialsHandle") &&
+ TEST_HOOK(sspicli.dll, AcquireCredentialsHandleA, NotEquals, SEC_E_OK) &&
+ TEST_HOOK(sspicli.dll, QueryCredentialsAttributesA, NotEquals, SEC_E_OK) &&
+ TEST_HOOK(sspicli.dll, FreeCredentialsHandle, NotEquals, SEC_E_OK) &&
- TestDetour("kernel32.dll", "BaseThreadInitThunk") &&
- TestDetour("ntdll.dll", "LdrLoadDll")) {
+ TEST_DETOUR_SKIP_EXEC(kernel32.dll, BaseThreadInitThunk) &&
+ TEST_DETOUR_SKIP_EXEC(ntdll.dll, LdrLoadDll)) {
printf("TEST-PASS | WindowsDllInterceptor | all checks passed\n");
LARGE_INTEGER end, freq;
QueryPerformanceCounter(&end);
QueryPerformanceFrequency(&freq);
LARGE_INTEGER result;
--- a/mozglue/tests/interceptor/TestDllInterceptorCrossProcess.cpp
+++ b/mozglue/tests/interceptor/TestDllInterceptorCrossProcess.cpp
@@ -6,29 +6,29 @@
#include "nsWindowsDllInterceptor.h"
#include "nsWindowsHelpers.h"
#include <string>
using std::wstring;
-static void* gOrigReturnResult;
-
extern "C" __declspec(dllexport) int
ReturnResult()
{
return 2;
}
+static mozilla::CrossProcessDllInterceptor::FuncHookType<decltype(&ReturnResult)>
+ gOrigReturnResult;
+
static int
ReturnResultHook()
{
- auto origFn = reinterpret_cast<decltype(&ReturnResult)>(gOrigReturnResult);
- if (origFn() != 2) {
+ if (gOrigReturnResult() != 2) {
return 3;
}
return 0;
}
int ParentMain()
{
@@ -68,19 +68,17 @@ int ParentMain()
printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Failed to assign child process to job\n");
::TerminateProcess(childProcess.get(), 1);
return 1;
}
mozilla::CrossProcessDllInterceptor intcpt(childProcess.get());
intcpt.Init("TestDllInterceptorCrossProcess.exe");
- if (!intcpt.AddHook("ReturnResult",
- reinterpret_cast<intptr_t>(&ReturnResultHook),
- &gOrigReturnResult)) {
+ if (!gOrigReturnResult.Set(intcpt, "ReturnResult", &ReturnResultHook)) {
printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Failed to add hook\n");
return 1;
}
printf("TEST-PASS | DllInterceptorCrossProcess | Hook added\n");
// Let's save the original hook
SIZE_T bytesWritten;
--- a/python/mozboot/bin/bootstrap-msys2.vbs
+++ b/python/mozboot/bin/bootstrap-msys2.vbs
@@ -64,17 +64,17 @@ If Err.Number <> 0 Then
WScript.Quit 1
End If
On Error GoTo 0
' Install ConEmu
' Download installer
On Error Resume Next
Download "https://conemu.github.io/install2.ps1", "install2.ps1"
-conemuSettingsURI = "https://api.pub.build.mozilla.org/tooltool/sha512/9aa384ecc8025a974999e913c83064b3b797e05d19806e62ef558c8300e4c3f72967e9464ace59759f76216fc2fc66f338a1e5cdea3b9aa264529487f091d929"
+conemuSettingsURI = "https://tooltool.mozilla-releng.net/sha512/9aa384ecc8025a974999e913c83064b3b797e05d19806e62ef558c8300e4c3f72967e9464ace59759f76216fc2fc66f338a1e5cdea3b9aa264529487f091d929"
' Run installer
errorCode = shell.Run("powershell.exe -NoProfile -ExecutionPolicy Unrestricted set dst '" & conemuPath & "'; set ver 'stable'; set lnk 'Mozilla Development Shell'; set xml '" & conemuSettingsURI & "'; set run $FALSE; .\install2.ps1", 0, true)
' Delete ConEmu installer
fso.DeleteFile("install2.ps1")
If Err.Number <> 0 Then
MsgBox("Error downloading and installing ConEmu. Make sure you have internet connection and Powershell installed. If you think this is a bug, please file one in Bugzilla https://bugzilla.mozilla.org/enter_bug.cgi?product=Core&component=Build%20Config")
WScript.Quit 1
End If
--- a/security/sandbox/win/SandboxInitialization.cpp
+++ b/security/sandbox/win/SandboxInitialization.cpp
@@ -10,26 +10,27 @@
#include "nsWindowsDllInterceptor.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "mozilla/sandboxing/permissionsService.h"
namespace mozilla {
namespace sandboxing {
typedef BOOL(WINAPI* CloseHandle_func) (HANDLE hObject);
-static CloseHandle_func stub_CloseHandle = nullptr;
+static WindowsDllInterceptor::FuncHookType<CloseHandle_func> stub_CloseHandle;
typedef BOOL(WINAPI* DuplicateHandle_func)(HANDLE hSourceProcessHandle,
HANDLE hSourceHandle,
HANDLE hTargetProcessHandle,
LPHANDLE lpTargetHandle,
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwOptions);
-static DuplicateHandle_func stub_DuplicateHandle = nullptr;
+static WindowsDllInterceptor::FuncHookType<DuplicateHandle_func>
+ stub_DuplicateHandle;
static BOOL WINAPI
patched_CloseHandle(HANDLE hObject)
{
// Check all handles being closed against the sandbox's tracked handles.
base::win::OnHandleBeingClosed(hObject);
return stub_CloseHandle(hObject);
}
@@ -57,27 +58,24 @@ patched_DuplicateHandle(HANDLE hSourcePr
static WindowsDllInterceptor Kernel32Intercept;
static bool
EnableHandleCloseMonitoring()
{
Kernel32Intercept.Init("kernel32.dll");
bool hooked =
- Kernel32Intercept.AddHook("CloseHandle",
- reinterpret_cast<intptr_t>(patched_CloseHandle),
- (void**)&stub_CloseHandle);
+ stub_CloseHandle.Set(Kernel32Intercept, "CloseHandle", &patched_CloseHandle);
if (!hooked) {
return false;
}
hooked =
- Kernel32Intercept.AddHook("DuplicateHandle",
- reinterpret_cast<intptr_t>(patched_DuplicateHandle),
- (void**)&stub_DuplicateHandle);
+ stub_DuplicateHandle.Set(Kernel32Intercept, "DuplicateHandle",
+ &patched_DuplicateHandle);
if (!hooked) {
return false;
}
return true;
}
static bool
--- a/testing/mozharness/configs/android/android_hw.py
+++ b/testing/mozharness/configs/android/android_hw.py
@@ -18,13 +18,13 @@ config = {
'create-virtualenv',
'verify-device',
'install',
'run-tests',
],
# from android_common.py
"download_tooltool": True,
"download_minidump_stackwalk": True,
- "tooltool_servers": ['https://api.pub.build.mozilla.org/tooltool/'],
+ "tooltool_servers": ['https://tooltool.mozilla-releng.net/'],
# minidump_tooltool_manifest_path is relative to workspace/build/tests/
"minidump_tooltool_manifest_path": "config/tooltool-manifests/linux64/releng.manifest",
"xpcshell_extra": "--remoteTestRoot=/data/local/tests",
}
--- a/testing/mozharness/configs/repackage/win32_partner.py
+++ b/testing/mozharness/configs/repackage/win32_partner.py
@@ -24,13 +24,13 @@ config = {
"repack_id": os.environ.get("REPACK_ID"),
"download_config": download_config,
"repackage_config": repackage_config,
# ToolTool
"tooltool_manifest_src": 'browser\\config\\tooltool-manifests\\{}\\releng.manifest'.format(platform),
- 'tooltool_url': 'https://api.pub.build.mozilla.org/tooltool/',
+ 'tooltool_url': 'https://tooltool.mozilla-releng.net/',
'tooltool_cache': os.environ.get('TOOLTOOL_CACHE'),
'run_configure': False,
}
--- a/testing/mozharness/configs/repackage/win64_partner.py
+++ b/testing/mozharness/configs/repackage/win64_partner.py
@@ -24,13 +24,13 @@ config = {
"repack_id": os.environ.get("REPACK_ID"),
"download_config": download_config,
"repackage_config": repackage_config,
# ToolTool
"tooltool_manifest_src": 'browser\\config\\tooltool-manifests\\{}\\releng.manifest'.format(platform),
- 'tooltool_url': 'https://api.pub.build.mozilla.org/tooltool/',
+ 'tooltool_url': 'https://tooltool.mozilla-releng.net/',
'tooltool_cache': os.environ.get('TOOLTOOL_CACHE'),
'run_configure': False,
}
--- a/toolkit/components/browser/nsWebBrowser.cpp
+++ b/toolkit/components/browser/nsWebBrowser.cpp
@@ -981,31 +981,34 @@ NS_IMETHODIMP
nsWebBrowser::SetProgressListener(nsIWebProgressListener* aProgressListener)
{
mProgressListener = aProgressListener;
return NS_OK;
}
NS_IMETHODIMP
nsWebBrowser::SaveURI(nsIURI* aURI,
+ nsIPrincipal* aPrincipal,
uint32_t aCacheKey,
nsIURI* aReferrer,
uint32_t aReferrerPolicy,
nsIInputStream* aPostData,
const char* aExtraHeaders,
nsISupports* aFile,
nsILoadContext* aPrivacyContext)
{
return SavePrivacyAwareURI(
- aURI, aCacheKey, aReferrer, aReferrerPolicy, aPostData, aExtraHeaders,
- aFile, aPrivacyContext && aPrivacyContext->UsePrivateBrowsing());
+ aURI, aPrincipal, aCacheKey, aReferrer, aReferrerPolicy, aPostData,
+ aExtraHeaders, aFile,
+ aPrivacyContext && aPrivacyContext->UsePrivateBrowsing());
}
NS_IMETHODIMP
nsWebBrowser::SavePrivacyAwareURI(nsIURI* aURI,
+ nsIPrincipal* aPrincipal,
uint32_t aCacheKey,
nsIURI* aReferrer,
uint32_t aReferrerPolicy,
nsIInputStream* aPostData,
const char* aExtraHeaders,
nsISupports* aFile,
bool aIsPrivate)
{
@@ -1033,18 +1036,19 @@ nsWebBrowser::SavePrivacyAwareURI(nsIURI
// Create a throwaway persistence object to do the work
nsresult rv;
mPersist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
mPersist->SetProgressListener(this);
mPersist->SetPersistFlags(mPersistFlags);
mPersist->GetCurrentState(&mPersistCurrentState);
- rv = mPersist->SavePrivacyAwareURI(uri, aCacheKey, aReferrer, aReferrerPolicy,
- aPostData, aExtraHeaders, aFile, aIsPrivate);
+ rv = mPersist->SavePrivacyAwareURI(uri, aPrincipal, aCacheKey,
+ aReferrer, aReferrerPolicy, aPostData,
+ aExtraHeaders, aFile, aIsPrivate);
if (NS_FAILED(rv)) {
mPersist = nullptr;
}
return rv;
}
NS_IMETHODIMP
nsWebBrowser::SaveChannel(nsIChannel* aChannel, nsISupports* aFile)
--- a/toolkit/components/downloads/test/unit/head.js
+++ b/toolkit/components/downloads/test/unit/head.js
@@ -278,17 +278,18 @@ function promiseStartLegacyDownload(aSou
// Initialize the components so they reference each other. This will cause
// the Download object to be created and added to the public downloads.
transfer.init(sourceURI, NetUtil.newURI(targetFile), null, mimeInfo, null,
null, persist, isPrivate);
persist.progressListener = transfer;
// Start the actual download process.
persist.savePrivacyAwareURI(
- sourceURI, 0, referrer, Ci.nsIHttpChannel.REFERRER_POLICY_UNSAFE_URL,
+ sourceURI, Services.scriptSecurityManager.getSystemPrincipal(),
+ 0, referrer, Ci.nsIHttpChannel.REFERRER_POLICY_UNSAFE_URL,
null, null, targetFile, isPrivate);
}).catch(do_report_unexpected_exception);
});
}
/**
* Starts a new download using the nsIHelperAppService interface, and controls
--- a/toolkit/components/viewsource/content/viewSourceUtils.js
+++ b/toolkit/components/viewsource/content/viewSourceUtils.js
@@ -221,17 +221,21 @@ var gViewSourceUtils = {
this.viewSourceProgressListener.file = file;
var webBrowserPersist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(this.mnsIWebBrowserPersist);
// the default setting is to not decode. we need to decode.
webBrowserPersist.persistFlags = this.mnsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
webBrowserPersist.progressListener = this.viewSourceProgressListener;
let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_NO_REFERRER;
- webBrowserPersist.savePrivacyAwareURI(uri, null, null, referrerPolicy, null, null, file, data.isPrivate);
+ let ssm = Services.scriptSecurityManager;
+ let principal = ssm.createCodebasePrincipal(data.uri,
+ browser.contentPrincipal.originAttributes);
+ webBrowserPersist.savePrivacyAwareURI(uri, principal, null, null,
+ referrerPolicy, null, null, file, data.isPrivate);
let helperService = Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
.getService(Ci.nsPIExternalAppLauncher);
if (data.isPrivate) {
// register the file to be deleted when possible
helperService.deleteTemporaryPrivateFileWhenPossible(file);
} else {
// register the file to be deleted on app exit
--- a/toolkit/content/contentAreaUtils.js
+++ b/toolkit/content/contentAreaUtils.js
@@ -57,24 +57,25 @@ function forbidCPOW(arg, func, argname)
// - An image with an extension (e.g. .jpg) in its file name, using
// Context->Save Image As...
// - An image without an extension (e.g. a banner ad on cnn.com) using
// the above method.
// - A linked document using Save Link As...
// - A linked document using Alt-click Save Link As...
//
function saveURL(aURL, aFileName, aFilePickerTitleKey, aShouldBypassCache,
- aSkipPrompt, aReferrer, aSourceDocument, aIsContentWindowPrivate) {
+ aSkipPrompt, aReferrer, aSourceDocument,
+ aIsContentWindowPrivate, aPrincipal) {
forbidCPOW(aURL, "saveURL", "aURL");
forbidCPOW(aReferrer, "saveURL", "aReferrer");
// Allow aSourceDocument to be a CPOW.
internalSave(aURL, null, aFileName, null, null, aShouldBypassCache,
aFilePickerTitleKey, null, aReferrer, aSourceDocument,
- aSkipPrompt, null, aIsContentWindowPrivate);
+ aSkipPrompt, null, aIsContentWindowPrivate, aPrincipal);
}
// Just like saveURL, but will get some info off the image before
// calling internalSave
// Clientele: (Make sure you don't break any of these)
// - Context -> Save Image As...
const imgICache = Ci.imgICache;
const nsISupportsCString = Ci.nsISupportsCString;
@@ -107,17 +108,17 @@ const nsISupportsCString = Ci.nsISupport
* @param aContentDisp (string, optional)
* The content disposition of the image.
* @param aIsContentWindowPrivate (bool)
* Whether or not the containing window is in private browsing mode.
* Does not need to be provided is aDoc is passed.
*/
function saveImageURL(aURL, aFileName, aFilePickerTitleKey, aShouldBypassCache,
aSkipPrompt, aReferrer, aDoc, aContentType, aContentDisp,
- aIsContentWindowPrivate) {
+ aIsContentWindowPrivate, aPrincipal) {
forbidCPOW(aURL, "saveImageURL", "aURL");
forbidCPOW(aReferrer, "saveImageURL", "aReferrer");
if (aDoc && aIsContentWindowPrivate == undefined) {
if (Cu.isCrossProcessWrapper(aDoc)) {
Deprecated.warning("saveImageURL should not be passed document CPOWs. " +
"The caller should pass in the content type and " +
"disposition themselves",
@@ -151,17 +152,17 @@ function saveImageURL(aURL, aFileName, a
}
} catch (e) {
// Failure to get type and content-disposition off the image is non-fatal
}
}
internalSave(aURL, null, aFileName, aContentDisp, aContentType,
aShouldBypassCache, aFilePickerTitleKey, null, aReferrer,
- null, aSkipPrompt, null, aIsContentWindowPrivate);
+ aDoc, aSkipPrompt, null, aIsContentWindowPrivate, aPrincipal);
}
// This is like saveDocument, but takes any browser/frame-like element
// and saves the current document inside it,
// whether in-process or out-of-process.
function saveBrowser(aBrowser, aSkipPrompt, aOuterWindowID = 0) {
if (!aBrowser) {
throw "Must have a browser when calling saveBrowser";
@@ -326,21 +327,25 @@ XPCOMUtils.defineConstant(this, "kSaveAs
* default downloads folder without prompting.
* @param aCacheKey [optional]
* If set will be passed to saveURI. See nsIWebBrowserPersist for
* allowed values.
* @param aIsContentWindowPrivate [optional]
* This parameter is provided when the aInitiatingDocument is not a
* real document object. Stores whether aInitiatingDocument.defaultView
* was private or not.
+ * @param aPrincipal [optional]
+ * This parameter is provided when neither aDocument nor
+ * aInitiatingDocument is provided. Used to determine what level of
+ * privilege to load the URI with.
*/
function internalSave(aURL, aDocument, aDefaultFileName, aContentDisposition,
aContentType, aShouldBypassCache, aFilePickerTitleKey,
aChosenData, aReferrer, aInitiatingDocument, aSkipPrompt,
- aCacheKey, aIsContentWindowPrivate) {
+ aCacheKey, aIsContentWindowPrivate, aPrincipal) {
forbidCPOW(aURL, "internalSave", "aURL");
forbidCPOW(aReferrer, "internalSave", "aReferrer");
forbidCPOW(aCacheKey, "internalSave", "aCacheKey");
// Allow aInitiatingDocument to be a CPOW.
if (aSkipPrompt == undefined)
aSkipPrompt = false;
@@ -406,18 +411,27 @@ function internalSave(aURL, aDocument, a
let isPrivate = aIsContentWindowPrivate;
if (isPrivate === undefined) {
isPrivate = aInitiatingDocument.nodeType == 9 /* DOCUMENT_NODE */
? PrivateBrowsingUtils.isContentWindowPrivate(aInitiatingDocument.defaultView)
: aInitiatingDocument.isPrivate;
}
+ // We have to cover the cases here where we were either passed an explicit
+ // principal, or a 'real' document (with a nodePrincipal property), or an
+ // nsIWebBrowserPersistDocument which has a principal property.
+ let sourcePrincipal =
+ aPrincipal ||
+ (aDocument && (aDocument.nodePrincipal || aDocument.principal)) ||
+ (aInitiatingDocument && aInitiatingDocument.nodePrincipal);
+
var persistArgs = {
sourceURI,
+ sourcePrincipal,
sourceReferrer: aReferrer,
sourceDocument: useSaveDocument ? aDocument : null,
targetContentType: (saveAsType == kSaveAsType_Text) ? "text/plain" : null,
targetFile: file,
sourceCacheKey: aCacheKey,
sourcePostData: nonCPOWDocument ? getPostData(aDocument) : null,
bypassCache: aShouldBypassCache,
isPrivate,
@@ -458,18 +472,17 @@ function internalSave(aURL, aDocument, a
* @param persistArgs.isPrivate
* Indicates whether this is taking place in a private browsing context.
*/
function internalPersist(persistArgs) {
var persist = makeWebBrowserPersist();
// Calculate persist flags.
const nsIWBP = Ci.nsIWebBrowserPersist;
- const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
- nsIWBP.PERSIST_FLAGS_FORCE_ALLOW_COOKIES;
+ const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
if (persistArgs.bypassCache)
persist.persistFlags = flags | nsIWBP.PERSIST_FLAGS_BYPASS_CACHE;
else
persist.persistFlags = flags | nsIWBP.PERSIST_FLAGS_FROM_CACHE;
// Leave it to WebBrowserPersist to discover the encoding type (or lack thereof):
persist.persistFlags |= nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
@@ -506,16 +519,17 @@ function internalPersist(persistArgs) {
encodingFlags |= nsIWBP.ENCODE_FLAGS_ENCODE_BASIC_ENTITIES;
}
const kWrapColumn = 80;
persist.saveDocument(persistArgs.sourceDocument, targetFileURL, filesFolder,
persistArgs.targetContentType, encodingFlags, kWrapColumn);
} else {
persist.savePrivacyAwareURI(persistArgs.sourceURI,
+ persistArgs.sourcePrincipal,
persistArgs.sourceCacheKey,
persistArgs.sourceReferrer,
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
persistArgs.sourcePostData,
null,
targetFileURL,
persistArgs.isPrivate);
}
--- a/toolkit/content/tests/browser/browser_saveImageURL.js
+++ b/toolkit/content/tests/browser/browser_saveImageURL.js
@@ -31,17 +31,18 @@ add_task(async function preferred_API()
gBrowser,
url: IMAGE_PAGE,
}, async function(browser) {
let url = await ContentTask.spawn(browser, null, async function() {
let image = content.document.getElementById("image");
return image.href;
});
- saveImageURL(url, "image.jpg", null, true, false, null, null, null, null, false);
+ saveImageURL(url, "image.jpg", null, true, false, null, null, null, null,
+ false, gBrowser.contentPrincipal);
let channel = gBrowser.contentDocumentAsCPOW.docShell.currentDocumentChannel;
if (channel) {
ok(true, channel.QueryInterface(Ci.nsIHttpChannelInternal)
.channelIsForDownload);
// Throttleable is the only class flag assigned to downloads.
ok(channel.QueryInterface(Ci.nsIClassOfService).classFlags,
Ci.nsIClassOfService.Throttleable);
--- a/toolkit/crashreporter/breakpad-windows-libxul/moz.build
+++ b/toolkit/crashreporter/breakpad-windows-libxul/moz.build
@@ -1,35 +1,29 @@
# -*- 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/.
-SOURCES += [
- '../google-breakpad/src/common/windows/http_upload.cc',
-]
-
Library('google_breakpad_libxul_s')
FINAL_LIBRARY = 'xul'
for var in ('UNICODE', 'UNICODE_', 'BREAKPAD_NO_TERMINATE_THREAD'):
DEFINES[var] = True
LOCAL_INCLUDES += [
'/toolkit/crashreporter/breakpad-client',
'/toolkit/crashreporter/google-breakpad/src',
]
include('/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild')
include('/toolkit/crashreporter/breakpad-client/windows/handler/objs.mozbuild')
-include('/toolkit/crashreporter/breakpad-client/windows/sender/objs.mozbuild')
include('/toolkit/crashreporter/breakpad-client/windows/crash_generation/objs.mozbuild')
include('/toolkit/crashreporter/breakpad-client/windows/common/objs.mozbuild')
SOURCES += objs_common
SOURCES += objs_crash_generation
SOURCES += objs_handler
-SOURCES += objs_sender
SOURCES += objs_client_common
DisableStlWrapping()
--- a/toolkit/crashreporter/client/moz.build
+++ b/toolkit/crashreporter/client/moz.build
@@ -19,20 +19,30 @@ if CONFIG['OS_TARGET'] != 'Android':
USE_LIBS += [
'jsoncpp',
]
if CONFIG['OS_ARCH'] == 'WINNT':
UNIFIED_SOURCES += [
'crashreporter_win.cpp',
]
+ include('/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild')
+ include('/toolkit/crashreporter/breakpad-client/windows/sender/objs.mozbuild')
+ include('/toolkit/crashreporter/breakpad-client/windows/crash_generation/objs.mozbuild')
+ include('/toolkit/crashreporter/breakpad-client/windows/common/objs.mozbuild')
+ SOURCES += objs_common
+ SOURCES += objs_sender
+ SOURCES += objs_crash_generation
+ SOURCES += objs_client_common
+ SOURCES += [
+ '../google-breakpad/src/common/windows/http_upload.cc',
+ ]
DEFINES['UNICODE'] = True
DEFINES['_UNICODE'] = True
USE_LIBS += [
- 'google_breakpad_libxul_s',
'nss',
]
OS_LIBS += [
'comctl32',
'ole32',
'shell32',
'wininet',
'shlwapi',
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -333,17 +333,18 @@ nsTArray<nsAutoPtr<DelayedNote> >* gDela
#if defined(XP_WIN)
// the following are used to prevent other DLLs reverting the last chance
// exception handler to the windows default. Any attempt to change the
// unhandled exception filter or to reset it is ignored and our crash
// reporter is loaded instead (in case it became unloaded somehow)
typedef LPTOP_LEVEL_EXCEPTION_FILTER (WINAPI *SetUnhandledExceptionFilter_func)
(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
-static SetUnhandledExceptionFilter_func stub_SetUnhandledExceptionFilter = 0;
+static WindowsDllInterceptor::FuncHookType<SetUnhandledExceptionFilter_func>
+ stub_SetUnhandledExceptionFilter;
static LPTOP_LEVEL_EXCEPTION_FILTER previousUnhandledExceptionFilter = nullptr;
static WindowsDllInterceptor gKernel32Intercept;
static bool gBlockUnhandledExceptionFilter = true;
static LPTOP_LEVEL_EXCEPTION_FILTER GetUnhandledExceptionFilter()
{
// Set a dummy value to get the current filter, then restore
LPTOP_LEVEL_EXCEPTION_FILTER current = SetUnhandledExceptionFilter(nullptr);
@@ -1634,19 +1635,19 @@ nsresult SetExceptionHandler(nsIFile* aX
#ifdef _WIN64
// Tell JS about the new filter before we disable SetUnhandledExceptionFilter
SetJitExceptionHandler();
#endif
// protect the crash reporter from being unloaded
gBlockUnhandledExceptionFilter = true;
gKernel32Intercept.Init("kernel32.dll");
- bool ok = gKernel32Intercept.AddHook("SetUnhandledExceptionFilter",
- reinterpret_cast<intptr_t>(patched_SetUnhandledExceptionFilter),
- (void**) &stub_SetUnhandledExceptionFilter);
+ bool ok = stub_SetUnhandledExceptionFilter.Set(gKernel32Intercept,
+ "SetUnhandledExceptionFilter",
+ &patched_SetUnhandledExceptionFilter);
#ifdef DEBUG
if (!ok)
printf_stderr ("SetUnhandledExceptionFilter hook failed; crash reporter is vulnerable.\n");
#endif
#endif
// store application start time
--- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -966,17 +966,18 @@ function _persistImage(sourceURL, localF
Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
Ci.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION |
(PERSIST_BYPASS_CACHE ?
Ci.nsIWebBrowserPersist.PERSIST_FLAGS_BYPASS_CACHE :
Ci.nsIWebBrowserPersist.PERSIST_FLAGS_FROM_CACHE);
persist.progressListener = new _persistProgressListener(successCallback);
- persist.saveURI(sourceURI, 0,
+ let sourcePrincipal = Services.scriptSecurityManager.createCodebasePrincipal(sourceURI, {});
+ persist.saveURI(sourceURI, sourcePrincipal, 0,
null, Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
null, null, targetURI, null);
}
function _persistProgressListener(successCallback) {
this.onLocationChange = function() {};
this.onProgressChange = function() {};
this.onStatusChange = function() {};
--- a/tools/lint/eslint/eslint-plugin-mozilla/update.sh
+++ b/tools/lint/eslint/eslint-plugin-mozilla/update.sh
@@ -1,25 +1,25 @@
#!/bin/sh
# Script to regenerate the npm packages used for eslint-plugin-mozilla by the builders.
# Requires
# Force the scripts working directory to be projdir/tools/lint/eslint/eslint-plugin-mozilla.
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR
-echo "To complete this script you will need the following tokens from https://api.pub.build.mozilla.org/tokenauth/"
+echo "To complete this script you will need the following tokens from https://mozilla-releng.net/tokens"
echo " - tooltool.upload.public"
echo " - tooltool.download.public"
echo ""
read -p "Are these tokens visible at the above URL (y/n)?" choice
case "$choice" in
y|Y )
echo ""
- echo "1. Go to https://api.pub.build.mozilla.org/"
+ echo "1. Go to https://mozilla-releng.net"
echo "2. Log in using your Mozilla LDAP account."
echo "3. Click on \"Tokens.\""
echo "4. Issue a user token with the permissions tooltool.upload.public and tooltool.download.public."
echo ""
echo "When you click issue you will be presented with a long string. Paste the string into a temporary file called ~/.tooltool-token."
echo ""
read -rsp $'Press any key to continue...\n' -n 1
;;
@@ -44,18 +44,18 @@ rm package-lock.json
echo "Installing modules for eslint-plugin-mozilla..."
npm install
echo "Creating eslint-plugin-mozilla.tar.gz..."
tar cvz -f eslint-plugin-mozilla.tar.gz node_modules
echo "Adding eslint-plugin-mozilla.tar.gz to tooltool..."
rm -f manifest.tt
-../../../../python/mozbuild/mozbuild/action/tooltool.py add --visibility public --unpack eslint-plugin-mozilla.tar.gz --url="https://api.pub.build.mozilla.org/tooltool/"
+../../../../python/mozbuild/mozbuild/action/tooltool.py add --visibility public --unpack eslint-plugin-mozilla.tar.gz --url="https://tooltool.mozilla-releng.net/"
echo "Uploading eslint-plugin-mozilla.tar.gz to tooltool..."
-../../../../python/mozbuild/mozbuild/action/tooltool.py upload --authentication-file=~/.tooltool-token --message "node_modules folder update for tools/lint/eslint/eslint-plugin-mozilla" --url="https://api.pub.build.mozilla.org/tooltool/"
+../../../../python/mozbuild/mozbuild/action/tooltool.py upload --authentication-file=~/.tooltool-token --message "node_modules folder update for tools/lint/eslint/eslint-plugin-mozilla" --url="https://tooltool.mozilla-releng.net/"
echo "Cleaning up..."
rm eslint-plugin-mozilla.tar.gz
echo ""
echo "Update complete, please commit and check in your changes."
--- a/tools/lint/eslint/update.sh
+++ b/tools/lint/eslint/update.sh
@@ -1,25 +1,25 @@
#!/bin/sh
# Script to regenerate the npm packages used for ESLint by the builders.
# Requires
# Force the scripts working directory to be projdir/tools/lint/eslint.
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR
-echo "To complete this script you will need the following tokens from https://api.pub.build.mozilla.org/tokenauth/"
+echo "To complete this script you will need the following tokens from https://mozilla-releng.net/tokens"
echo " - tooltool.upload.public"
echo " - tooltool.download.public"
echo ""
read -p "Are these tokens visible at the above URL (y/n)?" choice
case "$choice" in
y|Y )
echo ""
- echo "1. Go to https://api.pub.build.mozilla.org/"
+ echo "1. Go to https://mozilla-releng.net"
echo "2. Log in using your Mozilla LDAP account."
echo "3. Click on \"Tokens.\""
echo "4. Issue a user token with the permissions tooltool.upload.public and tooltool.download.public."
echo ""
echo "When you click issue you will be presented with a long string. Paste the string into a temporary file called ~/.tooltool-token."
echo ""
read -rsp $'Press any key to continue...\n' -n 1
;;
@@ -51,20 +51,20 @@ echo "Installing eslint and external plu
# access to make changes.
npm install
echo "Creating eslint.tar.gz..."
tar cvz --exclude=eslint-plugin-mozilla --exclude=eslint-plugin-spidermonkey-js -f eslint.tar.gz node_modules
echo "Adding eslint.tar.gz to tooltool..."
rm tools/lint/eslint/manifest.tt
-./python/mozbuild/mozbuild/action/tooltool.py add --visibility public --unpack eslint.tar.gz --url="https://api.pub.build.mozilla.org/tooltool/"
+./python/mozbuild/mozbuild/action/tooltool.py add --visibility public --unpack eslint.tar.gz --url="https://tooltool.mozilla-releng.net/"
echo "Uploading eslint.tar.gz to tooltool..."
-./python/mozbuild/mozbuild/action/tooltool.py upload --authentication-file=~/.tooltool-token --message "node_modules folder update for tools/lint/eslint" --url="https://api.pub.build.mozilla.org/tooltool/"
+./python/mozbuild/mozbuild/action/tooltool.py upload --authentication-file=~/.tooltool-token --message "node_modules folder update for tools/lint/eslint" --url="https://tooltool.mozilla-releng.net/"
echo "Cleaning up..."
mv manifest.tt tools/lint/eslint/manifest.tt
rm eslint.tar.gz
cd $DIR
echo ""
--- a/tools/profiler/core/platform-win32.cpp
+++ b/tools/profiler/core/platform-win32.cpp
@@ -298,32 +298,34 @@ Registers::SyncPopulate()
PopulateRegsFromContext(*this, &context);
}
#endif
#if defined(GP_PLAT_amd64_windows)
static WindowsDllInterceptor NtDllIntercept;
typedef NTSTATUS (NTAPI *LdrUnloadDll_func)(HMODULE module);
-static LdrUnloadDll_func stub_LdrUnloadDll;
+static WindowsDllInterceptor::FuncHookType<LdrUnloadDll_func>
+ stub_LdrUnloadDll;
static NTSTATUS NTAPI
patched_LdrUnloadDll(HMODULE module)
{
// Prevent the stack walker from suspending this thread when LdrUnloadDll
// holds the RtlLookupFunctionEntry lock.
AutoSuppressStackWalking suppress;
return stub_LdrUnloadDll(module);
}
// These pointers are disguised as PVOID to avoid pulling in obscure headers
typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase,
PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
PVOID ThunkAddress, ULONG Flags);
-static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI;
+static WindowsDllInterceptor::FuncHookType<LdrResolveDelayLoadedAPI_func>
+ stub_LdrResolveDelayLoadedAPI;
static PVOID WINAPI
patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
PVOID ThunkAddress, ULONG Flags)
{
// Prevent the stack walker from suspending this thread when
// LdrResolveDelayLoadAPI holds the RtlLookupFunctionEntry lock.
@@ -331,26 +333,18 @@ patched_LdrResolveDelayLoadedAPI(PVOID P
return stub_LdrResolveDelayLoadedAPI(ParentModuleBase, DelayloadDescriptor,
FailureDllHook, FailureSystemHook,
ThunkAddress, Flags);
}
void
InitializeWin64ProfilerHooks()
{
- static bool initialized = false;
- if (initialized) {
- return;
- }
- initialized = true;
-
NtDllIntercept.Init("ntdll.dll");
- NtDllIntercept.AddHook("LdrUnloadDll",
- reinterpret_cast<intptr_t>(patched_LdrUnloadDll),
- (void**)&stub_LdrUnloadDll);
+ stub_LdrUnloadDll.Set(NtDllIntercept, "LdrUnloadDll", &patched_LdrUnloadDll);
if (IsWin8OrLater()) { // LdrResolveDelayLoadedAPI was introduced in Win8
- NtDllIntercept.AddHook("LdrResolveDelayLoadedAPI",
- reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI),
- (void**)&stub_LdrResolveDelayLoadedAPI);
+ stub_LdrResolveDelayLoadedAPI.Set(NtDllIntercept,
+ "LdrResolveDelayLoadedAPI",
+ &patched_LdrResolveDelayLoadedAPI);
}
}
#endif // defined(GP_PLAT_amd64_windows)
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -347,19 +347,16 @@ static bool gWindowsVisible
// True if we have sent a notification that we are suspending/sleeping.
static bool gIsSleepMode = false;
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
// General purpose user32.dll hook object
static WindowsDllInterceptor sUser32Intercept;
-// AddHook success checks
-static mozilla::Maybe<bool> sHookedGetWindowInfo;
-
// 2 pixel offset for eTransparencyBorderlessGlass which equals the size of
// the default window border Windows paints. Glass will be extended inward
// this distance to remove the border.
static const int32_t kGlassMarginAdjustment = 2;
// When the client area is extended out into the default window frame area,
// this is the minimum amount of space along the edge of resizable windows
// we will always display a resize cursor in, regardless of the underlying
@@ -456,27 +453,27 @@ private:
::GetCurrentThreadId());
MOZ_ASSERT(mHook);
// On touchscreen devices, tiptsf.dll will have been loaded when STA COM was
// first initialized.
if (!IsWin10OrLater() && GetModuleHandle(L"tiptsf.dll") &&
!sProcessCaretEventsStub) {
sTipTsfInterceptor.Init("tiptsf.dll");
- DebugOnly<bool> ok = sTipTsfInterceptor.AddHook("ProcessCaretEvents",
- reinterpret_cast<intptr_t>(&ProcessCaretEventsHook),
- (void**) &sProcessCaretEventsStub);
+ DebugOnly<bool> ok = sProcessCaretEventsStub.Set(sTipTsfInterceptor,
+ "ProcessCaretEvents",
+ &ProcessCaretEventsHook);
MOZ_ASSERT(ok);
}
if (!sSendMessageTimeoutWStub) {
sUser32Intercept.Init("user32.dll");
- DebugOnly<bool> hooked = sUser32Intercept.AddHook("SendMessageTimeoutW",
- reinterpret_cast<intptr_t>(&SendMessageTimeoutWHook),
- (void**) &sSendMessageTimeoutWStub);
+ DebugOnly<bool> hooked = sSendMessageTimeoutWStub.Set(sUser32Intercept,
+ "SendMessageTimeoutW",
+ &SendMessageTimeoutWHook);
MOZ_ASSERT(hooked);
}
}
class MOZ_RAII A11yInstantiationBlocker
{
public:
A11yInstantiationBlocker()
@@ -551,28 +548,32 @@ private:
// off to DefWindowProc to accomplish this.
*aMsgResult = static_cast<DWORD_PTR>(::DefWindowProcW(aHwnd, aMsgCode,
aWParam, aLParam));
return static_cast<LRESULT>(TRUE);
}
static WindowsDllInterceptor sTipTsfInterceptor;
- static WINEVENTPROC sProcessCaretEventsStub;
- static decltype(&SendMessageTimeoutW) sSendMessageTimeoutWStub;
+ static WindowsDllInterceptor::FuncHookType<WINEVENTPROC>
+ sProcessCaretEventsStub;
+ static WindowsDllInterceptor::FuncHookType<decltype(&SendMessageTimeoutW)>
+ sSendMessageTimeoutWStub;
static StaticAutoPtr<TIPMessageHandler> sInstance;
HHOOK mHook;
UINT mMessages[7];
uint32_t mA11yBlockCount;
};
WindowsDllInterceptor TIPMessageHandler::sTipTsfInterceptor;
-WINEVENTPROC TIPMessageHandler::sProcessCaretEventsStub;
-decltype(&SendMessageTimeoutW) TIPMessageHandler::sSendMessageTimeoutWStub;
+WindowsDllInterceptor::FuncHookType<WINEVENTPROC>
+ TIPMessageHandler::sProcessCaretEventsStub;
+WindowsDllInterceptor::FuncHookType<decltype(&SendMessageTimeoutW)>
+ TIPMessageHandler::sSendMessageTimeoutWStub;
StaticAutoPtr<TIPMessageHandler> TIPMessageHandler::sInstance;
} // namespace mozilla
#endif // defined(ACCESSIBILITY)
/**************************************************************
**************************************************************
@@ -2467,17 +2468,17 @@ nsWindow::ResetLayout()
Invalidate();
}
// Internally track the caption status via a window property. Required
// due to our internal handling of WM_NCACTIVATE when custom client
// margins are set.
static const wchar_t kManageWindowInfoProperty[] = L"ManageWindowInfoProperty";
typedef BOOL (WINAPI *GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
-static GetWindowInfoPtr sGetWindowInfoPtrStub = nullptr;
+static WindowsDllInterceptor::FuncHookType<GetWindowInfoPtr> sGetWindowInfoPtrStub;
BOOL WINAPI
GetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi)
{
if (!sGetWindowInfoPtrStub) {
NS_ASSERTION(FALSE, "Something is horribly wrong in GetWindowInfoHook!");
return FALSE;
}
@@ -2495,28 +2496,25 @@ GetWindowInfoHook(HWND hWnd, PWINDOWINFO
}
void
nsWindow::UpdateGetWindowInfoCaptionStatus(bool aActiveCaption)
{
if (!mWnd)
return;
- if (sHookedGetWindowInfo.isNothing()) {
- sUser32Intercept.Init("user32.dll");
- sHookedGetWindowInfo =
- Some(sUser32Intercept.AddHook("GetWindowInfo",
- reinterpret_cast<intptr_t>(GetWindowInfoHook),
- (void**) &sGetWindowInfoPtrStub));
- if (!sHookedGetWindowInfo.value()) {
- return;
- }
- }
+ sUser32Intercept.Init("user32.dll");
+ sGetWindowInfoPtrStub.Set(sUser32Intercept, "GetWindowInfo",
+ &GetWindowInfoHook);
+ if (!sGetWindowInfoPtrStub) {
+ return;
+ }
+
// Update our internally tracked caption status
- SetPropW(mWnd, kManageWindowInfoProperty,
+ SetPropW(mWnd, kManageWindowInfoProperty,
reinterpret_cast<HANDLE>(static_cast<INT_PTR>(aActiveCaption) + 1));
}
/**
* Called when the window layout changes: full screen mode transitions,
* theme changes, and composition changes. Calculates the new non-client
* margins and fires off a frame changed event, which triggers an nc calc
* size windows event, kicking the changes in.
--- a/xpcom/base/AvailableMemoryTracker.cpp
+++ b/xpcom/base/AvailableMemoryTracker.cpp
@@ -79,26 +79,24 @@ bool sHooksActive = false;
// Alas, we'd like to use mozilla::TimeStamp, but we can't, because it acquires
// a lock!
volatile bool sUnderMemoryPressure = false;
volatile PRIntervalTime sLastLowMemoryNotificationTime;
// These are function pointers to the functions we wrap in Init().
-void* (WINAPI* sVirtualAllocOrig)(LPVOID aAddress, SIZE_T aSize,
- DWORD aAllocationType, DWORD aProtect);
+static WindowsDllInterceptor::FuncHookType<decltype(&VirtualAlloc)>
+ sVirtualAllocOrig;
-void* (WINAPI* sMapViewOfFileOrig)(HANDLE aFileMappingObject,
- DWORD aDesiredAccess, DWORD aFileOffsetHigh,
- DWORD aFileOffsetLow, SIZE_T aNumBytesToMap);
+static WindowsDllInterceptor::FuncHookType<decltype(&MapViewOfFile)>
+ sMapViewOfFileOrig;
-HBITMAP(WINAPI* sCreateDIBSectionOrig)(HDC aDC, const BITMAPINFO* aBitmapInfo,
- UINT aUsage, VOID** aBits,
- HANDLE aSection, DWORD aOffset);
+static WindowsDllInterceptor::FuncHookType<decltype(&CreateDIBSection)>
+ sCreateDIBSectionOrig;
/**
* Fire a memory pressure event if we were not under memory pressure yet, or
* fire an ongoing one if it's been long enough since the last one we
* fired.
*/
bool
MaybeScheduleMemoryPressureEvent()
@@ -640,27 +638,22 @@ Init()
#if defined(XP_WIN) && !defined(HAVE_64BIT_BUILD)
// Don't register the hooks if we're a build instrumented for PGO: If we're
// an instrumented build, the compiler adds function calls all over the place
// which may call VirtualAlloc; this makes it hard to prevent
// VirtualAllocHook from reentering itself.
if (!PR_GetEnv("MOZ_PGO_INSTRUMENTED")) {
sKernel32Intercept.Init("Kernel32.dll");
- sKernel32Intercept.AddHook("VirtualAlloc",
- reinterpret_cast<intptr_t>(VirtualAllocHook),
- reinterpret_cast<void**>(&sVirtualAllocOrig));
- sKernel32Intercept.AddHook("MapViewOfFile",
- reinterpret_cast<intptr_t>(MapViewOfFileHook),
- reinterpret_cast<void**>(&sMapViewOfFileOrig));
+ sVirtualAllocOrig.Set(sKernel32Intercept, "VirtualAlloc", &VirtualAllocHook);
+ sMapViewOfFileOrig.Set(sKernel32Intercept, "MapViewOfFile", &MapViewOfFileHook);
sGdi32Intercept.Init("Gdi32.dll");
- sGdi32Intercept.AddHook("CreateDIBSection",
- reinterpret_cast<intptr_t>(CreateDIBSectionHook),
- reinterpret_cast<void**>(&sCreateDIBSectionOrig));
+ sCreateDIBSectionOrig.Set(sGdi32Intercept, "CreateDIBSection",
+ &CreateDIBSectionHook);
}
sInitialized = true;
#endif // defined(XP_WIN) && !defined(HAVE_64BIT_BUILD)
}
} // namespace AvailableMemoryTracker
} // namespace mozilla
--- a/xpcom/build/PoisonIOInterposerWin.cpp
+++ b/xpcom/build/PoisonIOInterposerWin.cpp
@@ -204,23 +204,30 @@ WinIOAutoObservation::Filename(nsAString
mHasQueriedFilename = true;
aFilename = mFilename;
}
/*************************** IO Interposing Methods ***************************/
// Function pointers to original functions
-static NtCreateFileFn gOriginalNtCreateFile;
-static NtReadFileFn gOriginalNtReadFile;
-static NtReadFileScatterFn gOriginalNtReadFileScatter;
-static NtWriteFileFn gOriginalNtWriteFile;
-static NtWriteFileGatherFn gOriginalNtWriteFileGather;
-static NtFlushBuffersFileFn gOriginalNtFlushBuffersFile;
-static NtQueryFullAttributesFileFn gOriginalNtQueryFullAttributesFile;
+static WindowsDllInterceptor::FuncHookType<NtCreateFileFn>
+ gOriginalNtCreateFile;
+static WindowsDllInterceptor::FuncHookType<NtReadFileFn>
+ gOriginalNtReadFile;
+static WindowsDllInterceptor::FuncHookType<NtReadFileScatterFn>
+ gOriginalNtReadFileScatter;
+static WindowsDllInterceptor::FuncHookType<NtWriteFileFn>
+ gOriginalNtWriteFile;
+static WindowsDllInterceptor::FuncHookType<NtWriteFileGatherFn>
+ gOriginalNtWriteFileGather;
+static WindowsDllInterceptor::FuncHookType<NtFlushBuffersFileFn>
+ gOriginalNtFlushBuffersFile;
+static WindowsDllInterceptor::FuncHookType<NtQueryFullAttributesFileFn>
+ gOriginalNtQueryFullAttributesFile;
static NTSTATUS NTAPI
InterposedNtCreateFile(PHANDLE aFileHandle,
ACCESS_MASK aDesiredAccess,
POBJECT_ATTRIBUTES aObjectAttributes,
PIO_STATUS_BLOCK aIoStatusBlock,
PLARGE_INTEGER aAllocationSize,
ULONG aFileAttributes,
@@ -443,44 +450,31 @@ InitPoisonIOInterposer()
// at any moment, so the instance needs to persist longer than the scope
// of this functions.
static DebugFdRegistry registry;
ReplaceMalloc::InitDebugFd(registry);
#endif
// Initialize dll interceptor and add hooks
sNtDllInterceptor.Init("ntdll.dll");
- sNtDllInterceptor.AddHook(
- "NtCreateFile",
- reinterpret_cast<intptr_t>(InterposedNtCreateFile),
- reinterpret_cast<void**>(&gOriginalNtCreateFile));
- sNtDllInterceptor.AddHook(
- "NtReadFile",
- reinterpret_cast<intptr_t>(InterposedNtReadFile),
- reinterpret_cast<void**>(&gOriginalNtReadFile));
- sNtDllInterceptor.AddHook(
- "NtReadFileScatter",
- reinterpret_cast<intptr_t>(InterposedNtReadFileScatter),
- reinterpret_cast<void**>(&gOriginalNtReadFileScatter));
- sNtDllInterceptor.AddHook(
- "NtWriteFile",
- reinterpret_cast<intptr_t>(InterposedNtWriteFile),
- reinterpret_cast<void**>(&gOriginalNtWriteFile));
- sNtDllInterceptor.AddHook(
- "NtWriteFileGather",
- reinterpret_cast<intptr_t>(InterposedNtWriteFileGather),
- reinterpret_cast<void**>(&gOriginalNtWriteFileGather));
- sNtDllInterceptor.AddHook(
- "NtFlushBuffersFile",
- reinterpret_cast<intptr_t>(InterposedNtFlushBuffersFile),
- reinterpret_cast<void**>(&gOriginalNtFlushBuffersFile));
- sNtDllInterceptor.AddHook(
- "NtQueryFullAttributesFile",
- reinterpret_cast<intptr_t>(InterposedNtQueryFullAttributesFile),
- reinterpret_cast<void**>(&gOriginalNtQueryFullAttributesFile));
+ gOriginalNtCreateFile.Set(sNtDllInterceptor, "NtCreateFile",
+ &InterposedNtCreateFile);
+ gOriginalNtReadFile.Set(sNtDllInterceptor, "NtReadFile",
+ &InterposedNtReadFile);
+ gOriginalNtReadFileScatter.Set(sNtDllInterceptor, "NtReadFileScatter",
+ &InterposedNtReadFileScatter);
+ gOriginalNtWriteFile.Set(sNtDllInterceptor, "NtWriteFile",
+ &InterposedNtWriteFile);
+ gOriginalNtWriteFileGather.Set(sNtDllInterceptor, "NtWriteFileGather",
+ &InterposedNtWriteFileGather);
+ gOriginalNtFlushBuffersFile.Set(sNtDllInterceptor, "NtFlushBuffersFile",
+ &InterposedNtFlushBuffersFile);
+ gOriginalNtQueryFullAttributesFile.Set(sNtDllInterceptor,
+ "NtQueryFullAttributesFile",
+ &InterposedNtQueryFullAttributesFile);
}
void
ClearPoisonIOInterposer()
{
MOZ_ASSERT(false);
if (sIOPoisoned) {
// Destroy the DLL interceptor