mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
520d6b7062
- Don't upgrade gfx features after device resets. (bug 1183910 part 5, r=mattwoodrow) (e53d0f91f) - Use the same graphics device parameters across processes. (bug 1183910 part 7, r=mattwoodrow) (083ae4f15) - Rename DriverInitCrashDetection to DriverCrashGuard. (bug 1190281 part 2, r=mattwoodrow) (9bd189d09) - Make DriverCrashGuard initialization lazy. (bug 1190281 part 3, r=mattwoodrow) (6821dc386) - Pull D3D11 logic out of DriverCrashGuard. (bug 1190281 part 4, r=mattwoodrow) (e499a0079) - Move telemetry recording into D3D11LayersCrashGuard. (bug 1190281 part 5, r=mattwoodrow) (b50a4c2b4) - Factor prefs out of DriverCrashGuard. (bug 1190281 part 6, r=mattwoodrow) (a3a1166ab) - Bug 1170939 - Close PBontentBridge when receving shut dwon message, r=khuey (5473d07f0) - Allow DriverCrashGuard to be used in content processes. (bug 1190281 part 7, r=mattwoodrow) (c9eaf8315) - Add a crash guard for DXVA2D3D9. (bug 1190281 part 8, r=mattwoodrow) (eceff5212) - Add driver crash guards to WebGL (bug 1190281 part 9, r=jgilbert,mattwoodrow) (c362b60c6) - Fix bogus assert in DriverCrashGuard. (bug 1190281 followup, r=mattwoodrow) (d4a7145bd) - Bug 968923 - part 5b - add nsIDOMWindowUtils::forceUseCounterFlush; r=bz (138d30251) - Bug 968923 - part 5c - add tests for use counters; r=bz (0c4b745e0) - Bug 554186 - Part 1: Unimplement NPN_Status API. r=josh (8759dad40) - Bug 554186 - Part 2: Remove unused nsPluginInstanceOwner::ShowNativeContextMenu(). r=josh (ad2ac0c4d) - Bug 1174913 - anchor and area mochitests. r=bz (ab2c58a34) - Bug 959992. Go back to not treating properties that the named properties object exposes as enumerable. r=peterv (0adeeb910) - Bug 1154974 (Part 1) - Give blobs serial numbers. r=bent (4602ca2cd) - Bug 1154974 (Part 2) - Merge image cache entries for blobs URIs with the same underlying blob. r=baku (3b64b409e) - Bug 1173314 - Make GetMozFullPath and GetMozFullPathInternal const. r=sicking (f8eaabb1e) - Bug 1167389 - Make FileList::mParent a smart pointer, and declare it to the cycle collector. r=ehsan (d1217e547) - Bug 1173390 - Remove the majority of the old directory picker implementation to prepare for the new implementation under bug 1164310. r=baku (750049972) - Bug 1164310, part 1 - Make the code for bypassing mobile security checks more general so that it can be used on non-mobile. r=baku (0486fb5ff) - Bug 1164310, part 2 - Implement an abstraction for a rooted filesystem for non-mobile devices. r=baku (f1d906bd6) - Bug 1164310, part 3 - Allow the DirState of blobs to be set explicitly. r=baku (13d832700) - Bug 1164310, part 4 - Implement the new HTMLInputElement API including the new Promise returning GetFilesAndDirectories. r=baku (d0f93ec19) - Bug 1164310, part 5 - Implement new anonymous content and layout pieces for directory picking via input elements. r=tnikkel (ac5a00781) - Bug 1164310, part 6 - Implement the new Promise returning DataTransfer.getFilesAndDirectories() API. r=baku (375fba953) - Bug 1164310 - Follow-up: Fix build bustage with --disable-accessibility. r=me (da0e6745b) - Bug 1164310, part 7 - Touch CLOBBER since bug 1177844 isn't fixed yet. r=me (5fa829742) - Bug 1185381 - Make FileList clonable - patch 1 - move code into FileList.h/.cpp, r=smaug (b85483178) - Bug 1185381 - Make FileList clonable - patch 2 - rename FILEIMPL_IID to BLOBIMPL_IID, r=smaug (0f920cd05) - Bug 1185360 - PostMessageEvent should not have a different behavior if the main principal subsumes the destination one., r=smaug (070ab034b) - Bug 1185381 - Make FileList clonable - patch 3 - FileListClonedData implementation, r=smaug (f4f082d18) - Bug 1185381 - Make FileList clonable - patch 4 - tests, r=smaug (fb3637313)
410 lines
14 KiB
C++
410 lines
14 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "PostMessageEvent.h"
|
|
|
|
#include "MessageEvent.h"
|
|
#include "mozilla/dom/BlobBinding.h"
|
|
#include "mozilla/dom/FileList.h"
|
|
#include "mozilla/dom/FileListBinding.h"
|
|
#include "mozilla/dom/MessagePort.h"
|
|
#include "mozilla/dom/MessagePortBinding.h"
|
|
#include "mozilla/dom/PMessagePort.h"
|
|
#include "mozilla/dom/StructuredCloneTags.h"
|
|
#include "mozilla/EventDispatcher.h"
|
|
#include "nsGlobalWindow.h"
|
|
#include "nsIPresShell.h"
|
|
#include "nsIPrincipal.h"
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
|
|
namespace {
|
|
|
|
struct StructuredCloneInfo
|
|
{
|
|
PostMessageEvent* event;
|
|
nsPIDOMWindow* window;
|
|
|
|
// This hashtable contains the transferred ports - used to avoid duplicates.
|
|
nsTArray<nsRefPtr<MessagePortBase>> transferredPorts;
|
|
|
|
// This array is populated when the ports are cloned.
|
|
nsTArray<nsRefPtr<MessagePortBase>> clonedPorts;
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
const JSStructuredCloneCallbacks PostMessageEvent::sPostMessageCallbacks = {
|
|
PostMessageEvent::ReadStructuredClone,
|
|
PostMessageEvent::WriteStructuredClone,
|
|
nullptr,
|
|
PostMessageEvent::ReadTransferStructuredClone,
|
|
PostMessageEvent::TransferStructuredClone,
|
|
PostMessageEvent::FreeTransferStructuredClone
|
|
};
|
|
|
|
/* static */ JSObject*
|
|
PostMessageEvent::ReadStructuredClone(JSContext* cx,
|
|
JSStructuredCloneReader* reader,
|
|
uint32_t tag,
|
|
uint32_t data,
|
|
void* closure)
|
|
{
|
|
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
|
|
NS_ASSERTION(scInfo, "Must have scInfo!");
|
|
|
|
if (tag == SCTAG_DOM_BLOB) {
|
|
NS_ASSERTION(!data, "Data should be empty");
|
|
|
|
// What we get back from the reader is a BlobImpl.
|
|
// From that we create a new File.
|
|
BlobImpl* blobImpl;
|
|
if (JS_ReadBytes(reader, &blobImpl, sizeof(blobImpl))) {
|
|
MOZ_ASSERT(blobImpl);
|
|
|
|
// nsRefPtr<File> needs to go out of scope before toObjectOrNull() is
|
|
// called because the static analysis thinks dereferencing XPCOM objects
|
|
// can GC (because in some cases it can!), and a return statement with a
|
|
// JSObject* type means that JSObject* is on the stack as a raw pointer
|
|
// while destructors are running.
|
|
JS::Rooted<JS::Value> val(cx);
|
|
{
|
|
nsRefPtr<Blob> blob = Blob::Create(scInfo->window, blobImpl);
|
|
if (!ToJSValue(cx, blob, &val)) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
return &val.toObject();
|
|
}
|
|
}
|
|
|
|
if (tag == SCTAG_DOM_FILELIST) {
|
|
NS_ASSERTION(!data, "Data should be empty");
|
|
|
|
// What we get back from the reader is a FileListClonedData.
|
|
// From that we create a new FileList.
|
|
FileListClonedData* fileListClonedData;
|
|
if (JS_ReadBytes(reader, &fileListClonedData, sizeof(fileListClonedData))) {
|
|
MOZ_ASSERT(fileListClonedData);
|
|
|
|
// nsRefPtr<FileList> needs to go out of scope before toObjectOrNull() is
|
|
// called because the static analysis thinks dereferencing XPCOM objects
|
|
// can GC (because in some cases it can!), and a return statement with a
|
|
// JSObject* type means that JSObject* is on the stack as a raw pointer
|
|
// while destructors are running.
|
|
JS::Rooted<JS::Value> val(cx);
|
|
{
|
|
nsRefPtr<FileList> fileList =
|
|
FileList::Create(scInfo->window, fileListClonedData);
|
|
if (!fileList || !ToJSValue(cx, fileList, &val)) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
return &val.toObject();
|
|
}
|
|
}
|
|
|
|
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
|
js::GetContextStructuredCloneCallbacks(cx);
|
|
|
|
if (runtimeCallbacks) {
|
|
return runtimeCallbacks->read(cx, reader, tag, data, nullptr);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/* static */ bool
|
|
PostMessageEvent::WriteStructuredClone(JSContext* cx,
|
|
JSStructuredCloneWriter* writer,
|
|
JS::Handle<JSObject*> obj,
|
|
void *closure)
|
|
{
|
|
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
|
|
NS_ASSERTION(scInfo, "Must have scInfo!");
|
|
|
|
// See if this is a File/Blob object.
|
|
{
|
|
Blob* blob = nullptr;
|
|
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, obj, blob))) {
|
|
BlobImpl* blobImpl = blob->Impl();
|
|
if (JS_WriteUint32Pair(writer, SCTAG_DOM_BLOB, 0) &&
|
|
JS_WriteBytes(writer, &blobImpl, sizeof(blobImpl))) {
|
|
scInfo->event->StoreISupports(blobImpl);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// See if this is a FileList object.
|
|
{
|
|
FileList* fileList = nullptr;
|
|
if (NS_SUCCEEDED(UNWRAP_OBJECT(FileList, obj, fileList))) {
|
|
nsRefPtr<FileListClonedData> fileListClonedData =
|
|
fileList->CreateClonedData();
|
|
MOZ_ASSERT(fileListClonedData);
|
|
FileListClonedData* ptr = fileListClonedData.get();
|
|
if (JS_WriteUint32Pair(writer, SCTAG_DOM_FILELIST, 0) &&
|
|
JS_WriteBytes(writer, &ptr, sizeof(ptr))) {
|
|
scInfo->event->StoreISupports(fileListClonedData);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
const JSStructuredCloneCallbacks* runtimeCallbacks =
|
|
js::GetContextStructuredCloneCallbacks(cx);
|
|
|
|
if (runtimeCallbacks) {
|
|
return runtimeCallbacks->write(cx, writer, obj, nullptr);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* static */ bool
|
|
PostMessageEvent::ReadTransferStructuredClone(JSContext* aCx,
|
|
JSStructuredCloneReader* reader,
|
|
uint32_t tag, void* aData,
|
|
uint64_t aExtraData,
|
|
void* aClosure,
|
|
JS::MutableHandle<JSObject*> returnObject)
|
|
{
|
|
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
|
|
NS_ASSERTION(scInfo, "Must have scInfo!");
|
|
|
|
if (tag == SCTAG_DOM_MAP_MESSAGEPORT) {
|
|
MOZ_ASSERT(!aData);
|
|
// aExtraData is the index of this port identifier.
|
|
ErrorResult rv;
|
|
nsRefPtr<MessagePort> port =
|
|
MessagePort::Create(scInfo->window,
|
|
scInfo->event->GetPortIdentifier(aExtraData),
|
|
rv);
|
|
if (NS_WARN_IF(rv.Failed())) {
|
|
return false;
|
|
}
|
|
|
|
scInfo->clonedPorts.AppendElement(port);
|
|
|
|
JS::Rooted<JS::Value> value(aCx);
|
|
if (!GetOrCreateDOMReflector(aCx, port, &value)) {
|
|
JS_ClearPendingException(aCx);
|
|
return false;
|
|
}
|
|
|
|
returnObject.set(&value.toObject());
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* static */ bool
|
|
PostMessageEvent::TransferStructuredClone(JSContext* aCx,
|
|
JS::Handle<JSObject*> aObj,
|
|
void* aClosure,
|
|
uint32_t* aTag,
|
|
JS::TransferableOwnership* aOwnership,
|
|
void** aContent,
|
|
uint64_t* aExtraData)
|
|
{
|
|
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
|
|
NS_ASSERTION(scInfo, "Must have scInfo!");
|
|
|
|
MessagePortBase* port = nullptr;
|
|
nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
if (scInfo->transferredPorts.Contains(port)) {
|
|
// No duplicates.
|
|
return false;
|
|
}
|
|
|
|
// We use aExtraData to store the index of this new port identifier.
|
|
MessagePortIdentifier* identifier =
|
|
scInfo->event->NewPortIdentifier(aExtraData);
|
|
|
|
if (!port->CloneAndDisentangle(*identifier)) {
|
|
return false;
|
|
}
|
|
|
|
scInfo->transferredPorts.AppendElement(port);
|
|
|
|
*aTag = SCTAG_DOM_MAP_MESSAGEPORT;
|
|
*aOwnership = JS::SCTAG_TMO_CUSTOM;
|
|
*aContent = nullptr;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* static */ void
|
|
PostMessageEvent::FreeTransferStructuredClone(uint32_t aTag,
|
|
JS::TransferableOwnership aOwnership,
|
|
void *aContent,
|
|
uint64_t aExtraData,
|
|
void* aClosure)
|
|
{
|
|
if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
|
|
MOZ_ASSERT(aClosure);
|
|
MOZ_ASSERT(!aContent);
|
|
|
|
StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
|
|
MessagePort::ForceClose(scInfo->event->GetPortIdentifier(aExtraData));
|
|
}
|
|
}
|
|
|
|
PostMessageEvent::PostMessageEvent(nsGlobalWindow* aSource,
|
|
const nsAString& aCallerOrigin,
|
|
nsGlobalWindow* aTargetWindow,
|
|
nsIPrincipal* aProvidedPrincipal,
|
|
bool aTrustedCaller)
|
|
: mSource(aSource),
|
|
mCallerOrigin(aCallerOrigin),
|
|
mTargetWindow(aTargetWindow),
|
|
mProvidedPrincipal(aProvidedPrincipal),
|
|
mTrustedCaller(aTrustedCaller)
|
|
{
|
|
MOZ_COUNT_CTOR(PostMessageEvent);
|
|
}
|
|
|
|
PostMessageEvent::~PostMessageEvent()
|
|
{
|
|
MOZ_COUNT_DTOR(PostMessageEvent);
|
|
}
|
|
|
|
const MessagePortIdentifier&
|
|
PostMessageEvent::GetPortIdentifier(uint64_t aId)
|
|
{
|
|
MOZ_ASSERT(aId < mPortIdentifiers.Length());
|
|
return mPortIdentifiers[aId];
|
|
}
|
|
|
|
MessagePortIdentifier*
|
|
PostMessageEvent::NewPortIdentifier(uint64_t* aPosition)
|
|
{
|
|
*aPosition = mPortIdentifiers.Length();
|
|
return mPortIdentifiers.AppendElement();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
PostMessageEvent::Run()
|
|
{
|
|
MOZ_ASSERT(mTargetWindow->IsOuterWindow(),
|
|
"should have been passed an outer window!");
|
|
MOZ_ASSERT(!mSource || mSource->IsOuterWindow(),
|
|
"should have been passed an outer window!");
|
|
|
|
AutoJSAPI jsapi;
|
|
jsapi.Init();
|
|
JSContext* cx = jsapi.cx();
|
|
|
|
// If we bailed before this point we're going to leak mMessage, but
|
|
// that's probably better than crashing.
|
|
|
|
nsRefPtr<nsGlobalWindow> targetWindow;
|
|
if (mTargetWindow->IsClosedOrClosing() ||
|
|
!(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) ||
|
|
targetWindow->IsClosedOrClosing())
|
|
return NS_OK;
|
|
|
|
MOZ_ASSERT(targetWindow->IsInnerWindow(),
|
|
"we ordered an inner window!");
|
|
JSAutoCompartment ac(cx, targetWindow->GetWrapperPreserveColor());
|
|
|
|
// Ensure that any origin which might have been provided is the origin of this
|
|
// window's document. Note that we do this *now* instead of when postMessage
|
|
// is called because the target window might have been navigated to a
|
|
// different location between then and now. If this check happened when
|
|
// postMessage was called, it would be fairly easy for a malicious webpage to
|
|
// intercept messages intended for another site by carefully timing navigation
|
|
// of the target window so it changed location after postMessage but before
|
|
// now.
|
|
if (mProvidedPrincipal) {
|
|
// Get the target's origin either from its principal or, in the case the
|
|
// principal doesn't carry a URI (e.g. the system principal), the target's
|
|
// document.
|
|
nsIPrincipal* targetPrin = targetWindow->GetPrincipal();
|
|
if (NS_WARN_IF(!targetPrin))
|
|
return NS_OK;
|
|
|
|
// Note: This is contrary to the spec with respect to file: URLs, which
|
|
// the spec groups into a single origin, but given we intentionally
|
|
// don't do that in other places it seems better to hold the line for
|
|
// now. Long-term, we want HTML5 to address this so that we can
|
|
// be compliant while being safer.
|
|
if (!targetPrin->Equals(mProvidedPrincipal)) {
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
// Deserialize the structured clone data
|
|
JS::Rooted<JS::Value> messageData(cx);
|
|
StructuredCloneInfo scInfo;
|
|
scInfo.event = this;
|
|
scInfo.window = targetWindow;
|
|
|
|
if (!mBuffer.read(cx, &messageData, &sPostMessageCallbacks, &scInfo)) {
|
|
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
|
}
|
|
|
|
// Create the event
|
|
nsCOMPtr<mozilla::dom::EventTarget> eventTarget =
|
|
do_QueryInterface(static_cast<nsPIDOMWindow*>(targetWindow.get()));
|
|
nsRefPtr<MessageEvent> event =
|
|
new MessageEvent(eventTarget, nullptr, nullptr);
|
|
|
|
event->InitMessageEvent(NS_LITERAL_STRING("message"), false /*non-bubbling */,
|
|
false /*cancelable */, messageData, mCallerOrigin,
|
|
EmptyString(), mSource);
|
|
|
|
event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()),
|
|
scInfo.clonedPorts));
|
|
|
|
// We can't simply call dispatchEvent on the window because doing so ends
|
|
// up flipping the trusted bit on the event, and we don't want that to
|
|
// happen because then untrusted content can call postMessage on a chrome
|
|
// window if it can get a reference to it.
|
|
|
|
nsIPresShell *shell = targetWindow->GetExtantDoc()->GetShell();
|
|
nsRefPtr<nsPresContext> presContext;
|
|
if (shell)
|
|
presContext = shell->GetPresContext();
|
|
|
|
event->SetTrusted(mTrustedCaller);
|
|
WidgetEvent* internalEvent = event->GetInternalNSEvent();
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
EventDispatcher::Dispatch(static_cast<nsPIDOMWindow*>(mTargetWindow),
|
|
presContext,
|
|
internalEvent,
|
|
static_cast<dom::Event*>(event.get()),
|
|
&status);
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
PostMessageEvent::Write(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|
JS::Handle<JS::Value> aTransfer, nsPIDOMWindow* aWindow)
|
|
{
|
|
// We *must* clone the data here, or the JS::Value could be modified
|
|
// by script
|
|
StructuredCloneInfo scInfo;
|
|
scInfo.event = this;
|
|
scInfo.window = aWindow;
|
|
|
|
return mBuffer.write(aCx, aMessage, aTransfer, &sPostMessageCallbacks,
|
|
&scInfo);
|
|
}
|
|
|
|
} // dom namespace
|
|
} // mozilla namespace
|