merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2017-02-17 13:24:55 +01:00
Родитель 16f8dd152a 8ad9541ad3
Коммит afe4d4b240
195 изменённых файлов: 4918 добавлений и 3920 удалений

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

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Touch clobber again because of bug 1336456
Touching clobber for Telemetry IPC refactor in bug 1339749.

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

@ -152,7 +152,7 @@ DocAccessibleParent::RecvHideEvent(const uint64_t& aRootID,
if (mShutdown)
return IPC_OK();
MOZ_DIAGNOSTIC_ASSERT(CheckDocTree());
MOZ_ASSERT(CheckDocTree());
// We shouldn't actually need this because mAccessibles shouldn't have an
// entry for the document itself, but it doesn't hurt to be explicit.
@ -587,8 +587,10 @@ DocAccessibleParent::SetCOMProxy(const RefPtr<IAccessible>& aCOMProxy)
}
}
}
Unused << SendParentCOMProxy(holder, reinterpret_cast<uintptr_t>(
mEmulatedWindowHandle), hWndAccHolder);
Unused << SendEmulatedWindow(reinterpret_cast<uintptr_t>(mEmulatedWindowHandle),
hWndAccHolder);
Unused << SendParentCOMProxy(holder);
}
void

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

@ -46,19 +46,11 @@ DocAccessibleChild::Shutdown()
}
ipc::IPCResult
DocAccessibleChild::RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy,
const WindowsHandle& aEmulatedWindowHandle,
const IAccessibleHolder& aEmulatedWindowCOMProxy)
DocAccessibleChild::RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy)
{
MOZ_ASSERT(!mParentProxy && !aParentCOMProxy.IsNull());
mParentProxy.reset(const_cast<IAccessibleHolder&>(aParentCOMProxy).Release());
SetConstructedInParentProcess();
mEmulatedWindowHandle = reinterpret_cast<HWND>(aEmulatedWindowHandle);
if (!aEmulatedWindowCOMProxy.IsNull()) {
MOZ_ASSERT(!mEmulatedWindowProxy);
mEmulatedWindowProxy.reset(
const_cast<IAccessibleHolder&>(aEmulatedWindowCOMProxy).Release());
}
for (uint32_t i = 0, l = mDeferredEvents.Length(); i < l; ++i) {
mDeferredEvents[i]->Dispatch();
@ -69,6 +61,20 @@ DocAccessibleChild::RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy,
return IPC_OK();
}
ipc::IPCResult
DocAccessibleChild::RecvEmulatedWindow(const WindowsHandle& aEmulatedWindowHandle,
const IAccessibleHolder& aEmulatedWindowCOMProxy)
{
mEmulatedWindowHandle = reinterpret_cast<HWND>(aEmulatedWindowHandle);
if (!aEmulatedWindowCOMProxy.IsNull()) {
MOZ_ASSERT(!mEmulatedWindowProxy);
mEmulatedWindowProxy.reset(
const_cast<IAccessibleHolder&>(aEmulatedWindowCOMProxy).Release());
}
return IPC_OK();
}
void
DocAccessibleChild::PushDeferredEvent(UniquePtr<DeferredEvent> aEvent)
{

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

@ -28,9 +28,10 @@ public:
virtual void Shutdown() override;
virtual ipc::IPCResult
RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy,
const WindowsHandle& aEmulatedWindowHandle,
const IAccessibleHolder& aEmulatedWindowCOMProxy) override;
RecvParentCOMProxy(const IAccessibleHolder& aParentCOMProxy) override;
virtual ipc::IPCResult
RecvEmulatedWindow(const WindowsHandle& aEmulatedWindowHandle,
const IAccessibleHolder& aEmulatedWindowCOMProxy) override;
HWND GetEmulatedWindowHandle() const { return mEmulatedWindowHandle; }
IAccessible* GetEmulatedWindowIAccessible() const { return mEmulatedWindowProxy.get(); }

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

@ -66,8 +66,8 @@ parent:
returns (IAccessibleHolder aPluginCOMProxy);
child:
async ParentCOMProxy(IAccessibleHolder aParentCOMProxy,
WindowsHandle aEmulatedWindowHandle,
async ParentCOMProxy(IAccessibleHolder aParentCOMProxy);
async EmulatedWindow(WindowsHandle aEmulatedWindowHandle,
IAccessibleHolder aEmulatedWindowCOMProxy);
async __delete__();

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

@ -6,6 +6,7 @@
hidden="true"
orient="vertical"
noautofocus="true"
followanchor="false"
role="alert"/>
<popupnotification id="webRTC-shareDevices-notification" hidden="true">

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

@ -204,23 +204,24 @@
# define _LARGEFILE_SOURCE 1
#endif
/* The GCC_VERSION, CLANG_VERSION, and MSVC_VERSION macros are used to
/* The GCC_VERSION and MSVC_VERSION macros are used to
** conditionally include optimizations for each of these compilers. A
** value of 0 means that compiler is not being used. The
** SQLITE_DISABLE_INTRINSIC macro means do not use any compiler-specific
** optimizations, and hence set all compiler macros to 0
**
** There was once also a CLANG_VERSION macro. However, we learn that the
** version numbers in clang are for "marketing" only and are inconsistent
** and unreliable. Fortunately, all versions of clang also recognize the
** gcc version numbers and have reasonable settings for gcc version numbers,
** so the GCC_VERSION macro will be set to a correct non-zero value even
** when compiling with clang.
*/
#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
#else
# define GCC_VERSION 0
#endif
#if defined(__clang__) && !defined(_WIN32) && !defined(SQLITE_DISABLE_INTRINSIC)
# define CLANG_VERSION \
(__clang_major__*1000000+__clang_minor__*1000+__clang_patchlevel__)
#else
# define CLANG_VERSION 0
#endif
#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC)
# define MSVC_VERSION _MSC_VER
#else
@ -28697,7 +28698,7 @@ SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
u32 x;
memcpy(&x,p,4);
return x;
#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
u32 x;
memcpy(&x,p,4);
return __builtin_bswap32(x);
@ -28713,7 +28714,7 @@ SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
#if SQLITE_BYTEORDER==4321
memcpy(p,&v,4);
#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
u32 x = __builtin_bswap32(v);
memcpy(p,&x,4);
#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
@ -28832,7 +28833,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
** overflow, leave *pA unchanged and return 1.
*/
SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
#if GCC_VERSION>=5004000 || CLANG_VERSION>=4000000
#if GCC_VERSION>=5004000
return __builtin_add_overflow(*pA, iB, pA);
#else
i64 iA = *pA;
@ -28852,7 +28853,7 @@ SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
#endif
}
SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
#if GCC_VERSION>=5004000 || CLANG_VERSION>=4000000
#if GCC_VERSION>=5004000
return __builtin_sub_overflow(*pA, iB, pA);
#else
testcase( iB==SMALLEST_INT64+1 );
@ -28867,7 +28868,7 @@ SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
#endif
}
SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
#if GCC_VERSION>=5004000 || CLANG_VERSION>=4000000
#if GCC_VERSION>=5004000
return __builtin_mul_overflow(*pA, iB, pA);
#else
i64 iA = *pA;
@ -163304,7 +163305,11 @@ struct RtreeMatchArg {
# define MIN(x,y) ((x) > (y) ? (y) : (x))
#endif
/* What version of GCC is being used. 0 means GCC is not being used */
/* What version of GCC is being used. 0 means GCC is not being used .
** Note that the GCC_VERSION macro will also be set correctly when using
** clang, since clang works hard to be gcc compatible. So the gcc
** optimizations will also work when compiling with clang.
*/
#ifndef GCC_VERSION
#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
@ -163313,16 +163318,6 @@ struct RtreeMatchArg {
#endif
#endif
/* What version of CLANG is being used. 0 means CLANG is not being used */
#ifndef CLANG_VERSION
#if defined(__clang__) && !defined(_WIN32) && !defined(SQLITE_DISABLE_INTRINSIC)
# define CLANG_VERSION \
(__clang_major__*1000000+__clang_minor__*1000+__clang_patchlevel__)
#else
# define CLANG_VERSION 0
#endif
#endif
/* The testcase() macro should already be defined in the amalgamation. If
** it is not, make it a no-op.
*/
@ -163373,7 +163368,7 @@ static void readCoord(u8 *p, RtreeCoord *pCoord){
assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */
#if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
pCoord->u = _byteswap_ulong(*(u32*)p);
#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
pCoord->u = __builtin_bswap32(*(u32*)p);
#elif SQLITE_BYTEORDER==4321
pCoord->u = *(u32*)p;
@ -163391,7 +163386,7 @@ static i64 readInt64(u8 *p){
u64 x;
memcpy(&x, p, 8);
return (i64)_byteswap_uint64(x);
#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
u64 x;
memcpy(&x, p, 8);
return (i64)__builtin_bswap64(x);
@ -163427,7 +163422,7 @@ static int writeCoord(u8 *p, RtreeCoord *pCoord){
assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */
assert( sizeof(RtreeCoord)==4 );
assert( sizeof(u32)==4 );
#if SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
i = __builtin_bswap32(pCoord->u);
memcpy(p, &i, 4);
#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
@ -163446,7 +163441,7 @@ static int writeCoord(u8 *p, RtreeCoord *pCoord){
return 4;
}
static int writeInt64(u8 *p, i64 i){
#if SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
i = (i64)__builtin_bswap64((u64)i);
memcpy(p, &i, 8);
#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
@ -164002,7 +163997,7 @@ static int rtreeEof(sqlite3_vtab_cursor *cur){
c.u = _byteswap_ulong(*(u32*)a); \
r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \
}
#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000)
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
#define RTREE_DECODE_COORD(eInt, a, r) { \
RtreeCoord c; /* Coordinate decoded */ \
c.u = __builtin_bswap32(*(u32*)a); \

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

@ -460,4 +460,4 @@ skip-if = e10s && debug
[browser_dbg_WorkerActor.attachThread.js]
skip-if = e10s && debug
[browser_dbg_split-console-keypress.js]
skip-if = e10s && (debug || os == "linux") # Bug 1214439
skip-if = (debug || os == "linux") # Bug 1214439

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

@ -161,7 +161,7 @@ const Message = createClass({
let notesNodes;
if (notes) {
notes.map(note => dom.span(
notesNodes = notes.map(note => dom.span(
{ className: "message-flex-body error-note" },
dom.span({ className: "message-body devtools-monospace" },
"note: " + note.messageBody

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

@ -11,6 +11,7 @@
#include "nsCExternalHandlerService.h"
#include "mozilla/UniquePtr.h"
#include "nsIInputStream.h"
using namespace mozilla;
using namespace mozilla::dom;

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

@ -9,7 +9,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/BaseBlobImpl.h"
#include "ArchiveReader.h"
@ -21,7 +21,7 @@ BEGIN_ARCHIVEREADER_NAMESPACE
/**
* ArchiveZipBlobImpl to BlobImpl
*/
class ArchiveZipBlobImpl : public BlobImplBase
class ArchiveZipBlobImpl : public BaseBlobImpl
{
public:
NS_DECL_ISUPPORTS_INHERITED
@ -31,7 +31,7 @@ public:
uint64_t aLength,
ZipCentral& aCentral,
BlobImpl* aBlobImpl)
: BlobImplBase(aName, aContentType, aLength),
: BaseBlobImpl(aName, aContentType, aLength),
mCentral(aCentral),
mBlobImpl(aBlobImpl),
mFilename(aName)
@ -45,7 +45,7 @@ public:
uint64_t aLength,
ZipCentral& aCentral,
BlobImpl* aBlobImpl)
: BlobImplBase(aContentType, aStart, aLength),
: BaseBlobImpl(aContentType, aStart, aLength),
mCentral(aCentral),
mBlobImpl(aBlobImpl),
mFilename(aName)

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

@ -829,6 +829,10 @@ AudioChannelService::GetAudioChannelVolume(mozIDOMWindowProxy* aWindow,
MOZ_ASSERT(NS_IsMainThread());
auto* window = nsPIDOMWindowOuter::From(aWindow)->GetScriptableTop();
if (!window) {
*aVolume = 0.f;
return NS_ERROR_FAILURE;
}
*aVolume = GetAudioChannelVolume(window, (AudioChannel)aAudioChannel);
return NS_OK;
}
@ -859,6 +863,9 @@ AudioChannelService::SetAudioChannelVolume(mozIDOMWindowProxy* aWindow,
MOZ_ASSERT(NS_IsMainThread());
auto* window = nsPIDOMWindowOuter::From(aWindow)->GetScriptableTop();
if (!window) {
return NS_ERROR_FAILURE;
}
SetAudioChannelVolume(window, (AudioChannel)aAudioChannel, aVolume);
return NS_OK;
}
@ -883,6 +890,10 @@ AudioChannelService::GetAudioChannelMuted(mozIDOMWindowProxy* aWindow,
MOZ_ASSERT(NS_IsMainThread());
auto* window = nsPIDOMWindowOuter::From(aWindow)->GetScriptableTop();
if (!window) {
*aMuted = false;
return NS_ERROR_FAILURE;
}
*aMuted = GetAudioChannelMuted(window, (AudioChannel)aAudioChannel);
return NS_OK;
}
@ -918,6 +929,9 @@ AudioChannelService::SetAudioChannelMuted(mozIDOMWindowProxy* aWindow,
MOZ_ASSERT(NS_IsMainThread());
auto* window = nsPIDOMWindowOuter::From(aWindow)->GetScriptableTop();
if (!window) {
return NS_ERROR_FAILURE;
}
SetAudioChannelMuted(window, (AudioChannel)aAudioChannel, aMuted);
return NS_OK;
}
@ -942,6 +956,10 @@ AudioChannelService::IsAudioChannelActive(mozIDOMWindowProxy* aWindow,
MOZ_ASSERT(NS_IsMainThread());
auto* window = nsPIDOMWindowOuter::From(aWindow)->GetScriptableTop();
if (!window) {
*aActive = false;
return NS_ERROR_FAILURE;
}
*aActive = IsAudioChannelActive(window, (AudioChannel)aAudioChannel);
return NS_OK;
}
@ -952,6 +970,9 @@ AudioChannelService::IsWindowActive(nsPIDOMWindowOuter* aWindow)
MOZ_ASSERT(NS_IsMainThread());
auto* window = nsPIDOMWindowOuter::From(aWindow)->GetScriptableTop();
if (!window) {
return false;
}
AudioChannelWindow* winData = GetOrCreateWindowData(window);
return !winData->mAudibleAgents.IsEmpty();
}

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

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
window.onload = function(){
let x = document.getElementsByTagName("iframe")[0];
let w = window.open();
let o = window.frames[0];
x.remove();
o.requestIdleCallback(function(){});
w.close();
};
</script>
</head>
<body>
<iframe></iframe>
</body>
</html>

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

@ -1 +1,2 @@
load 1223734.html
load 1339930.html

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

@ -42,6 +42,7 @@
#include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/DOMTypes.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/dom/HTMLTemplateElement.h"
#include "mozilla/dom/HTMLContentElement.h"
@ -7876,12 +7877,21 @@ nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
continue;
}
blobImpl = new BlobImplFile(file);
ErrorResult rv;
blobImpl = new FileBlobImpl(file);
IgnoredErrorResult rv;
// Ensure that file data is cached no that the content process
// has this data available to it when passed over:
blobImpl->GetSize(rv);
if (NS_WARN_IF(rv.Failed())) {
continue;
}
blobImpl->GetLastModified(rv);
if (NS_WARN_IF(rv.Failed())) {
continue;
}
} else {
if (aInSyncMessage) {
// Can't do anything.

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

@ -20,6 +20,7 @@
#include "nsNetUtil.h"
#include "nsScriptLoader.h"
#include "nsFrameLoader.h"
#include "nsIInputStream.h"
#include "nsIXULRuntime.h"
#include "nsIScriptError.h"
#include "nsIConsoleService.h"

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

@ -395,6 +395,7 @@ GK_ATOM(floor, "floor")
GK_ATOM(flowlength, "flowlength")
GK_ATOM(focus, "focus")
GK_ATOM(focused, "focused")
GK_ATOM(followanchor, "followanchor")
GK_ATOM(following, "following")
GK_ATOM(followingSibling, "following-sibling")
GK_ATOM(font, "font")

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

@ -4189,7 +4189,13 @@ nsPIDOMWindowInner::IsPlayingAudio()
if (!acs) {
return false;
}
return acs->IsWindowActive(GetOuterWindow());
auto outer = GetOuterWindow();
if (!outer) {
// We've been unlinked and are about to die. Not a good time to pretend to
// be playing audio.
return false;
}
return acs->IsWindowActive(outer);
}
mozilla::dom::TimeoutManager&
@ -14320,6 +14326,18 @@ nsPIDOMWindowOuter::SetLargeAllocStatus(LargeAllocStatus aStatus)
mLargeAllocStatus = aStatus;
}
bool
nsPIDOMWindowOuter::IsTopLevelWindow()
{
return nsGlobalWindow::Cast(this)->IsTopLevelWindow();
}
bool
nsPIDOMWindowOuter::HadOriginalOpener() const
{
return nsGlobalWindow::Cast(this)->HadOriginalOpener();
}
void
nsGlobalWindow::ReportLargeAllocStatus()
{

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

@ -292,6 +292,10 @@ public:
return static_cast<nsGlobalWindow*>(
reinterpret_cast<nsPIDOMWindow<nsISupports>*>(aPIWin));
}
static const nsGlobalWindow* Cast(const nsPIDOMWindowOuter* aPIWin) {
return static_cast<const nsGlobalWindow*>(
reinterpret_cast<const nsPIDOMWindow<nsISupports>*>(aPIWin));
}
static nsGlobalWindow* Cast(mozIDOMWindowProxy* aWin) {
return Cast(nsPIDOMWindowOuter::From(aWin));
}

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

@ -1631,7 +1631,7 @@ nsJSContext::EndCycleCollectionCallback(CycleCollectorResults &aResults)
gcMsg.AssignLiteral(", forced a GC");
}
NS_NAMED_MULTILINE_LITERAL_STRING(kFmt,
NS_NAMED_LITERAL_STRING(kFmt,
u"CC(T+%.1f)[%s-%i] max pause: %lums, total time: %lums, slices: %lu, suspected: %lu, visited: %lu RCed and %lu%s GCed, collected: %lu RCed and %lu GCed (%lu|%lu|%lu waiting for GC)%s\n"
u"ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, max sync: %lu ms, removed: %lu");
nsString msg;
@ -1663,7 +1663,7 @@ nsJSContext::EndCycleCollectionCallback(CycleCollectorResults &aResults)
}
if (sPostGCEventsToObserver) {
NS_NAMED_MULTILINE_LITERAL_STRING(kJSONFmt,
NS_NAMED_LITERAL_STRING(kJSONFmt,
u"{ \"timestamp\": %llu, "
u"\"duration\": %lu, "
u"\"max_slice_pause\": %lu, "

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

@ -974,6 +974,9 @@ public:
float GetDevicePixelRatio(mozilla::dom::CallerType aCallerType);
void SetLargeAllocStatus(mozilla::dom::LargeAllocStatus aStatus);
bool IsTopLevelWindow();
bool HadOriginalOpener() const;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindowOuter, NS_PIDOMWINDOWOUTER_IID)

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

@ -107,10 +107,6 @@ DOMInterfaces = {
'nativeType': 'mozilla::dom::AudioContext',
},
'Blob': {
'headerFile': 'mozilla/dom/File.h',
},
'BatteryManager': {
'nativeType': 'mozilla::dom::battery::BatteryManager',
'headerFile': 'BatteryManager.h'

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

@ -8,7 +8,7 @@
#include "nsIMIMEService.h"
#include "nsCExternalHandlerService.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "ContentParent.h"
#include "nsProxyRelease.h"
@ -281,7 +281,7 @@ DeviceStorageRequestParent::PostBlobSuccessEvent::CancelableRun() {
nsString fullPath;
mFile->GetFullPath(fullPath);
RefPtr<BlobImpl> blob =
new BlobImplFile(fullPath, mime, mLength, mFile->mFile,
new FileBlobImpl(fullPath, mime, mLength, mFile->mFile,
mLastModificationDate);
ContentParent* cp = static_cast<ContentParent*>(mParent->Manager());

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

@ -15,6 +15,7 @@
#include "mozilla/dom/DeviceStorageFileSystem.h"
#include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h"
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/PBrowserChild.h"
@ -34,6 +35,7 @@
#include "nsServiceManagerUtils.h"
#include "nsIFile.h"
#include "nsIDirectoryEnumerator.h"
#include "nsIInputStream.h"
#include "nsNetUtil.h"
#include "nsIOutputStream.h"
#include "nsCycleCollectionParticipant.h"
@ -3995,9 +3997,9 @@ DeviceStorageRequestManager::Resolve(uint32_t aId, DeviceStorageFile* aFile,
MOZ_ASSERT(aFile->mLength != UINT64_MAX);
MOZ_ASSERT(aFile->mLastModifiedDate != UINT64_MAX);
RefPtr<BlobImpl> blobImpl = new BlobImplFile(fullPath, aFile->mMimeType,
aFile->mLength, aFile->mFile,
aFile->mLastModifiedDate);
RefPtr<BlobImpl> blobImpl = new FileBlobImpl(fullPath, aFile->mMimeType,
aFile->mLength, aFile->mFile,
aFile->mLastModifiedDate);
/* File should start out as mutable by default but we should turn
that off if it wasn't requested. */

156
dom/file/BaseBlobImpl.cpp Normal file
Просмотреть файл

@ -0,0 +1,156 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/BaseBlobImpl.h"
#include "prtime.h"
namespace mozilla {
namespace dom {
void
BaseBlobImpl::GetName(nsAString& aName) const
{
MOZ_ASSERT(mIsFile, "Should only be called on files");
aName = mName;
}
void
BaseBlobImpl::GetDOMPath(nsAString& aPath) const
{
MOZ_ASSERT(mIsFile, "Should only be called on files");
aPath = mPath;
}
void
BaseBlobImpl::SetDOMPath(const nsAString& aPath)
{
MOZ_ASSERT(mIsFile, "Should only be called on files");
mPath = aPath;
}
void
BaseBlobImpl::GetMozFullPath(nsAString& aFileName,
SystemCallerGuarantee /* unused */,
ErrorResult& aRv) const
{
MOZ_ASSERT(mIsFile, "Should only be called on files");
GetMozFullPathInternal(aFileName, aRv);
}
void
BaseBlobImpl::GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const
{
if (!mIsFile) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
aFileName.Truncate();
}
void
BaseBlobImpl::GetType(nsAString& aType)
{
aType = mContentType;
}
int64_t
BaseBlobImpl::GetLastModified(ErrorResult& aRv)
{
MOZ_ASSERT(mIsFile, "Should only be called on files");
if (IsDateUnknown()) {
mLastModificationDate = PR_Now();
}
return mLastModificationDate / PR_USEC_PER_MSEC;
}
void
BaseBlobImpl::SetLastModified(int64_t aLastModified)
{
mLastModificationDate = aLastModified * PR_USEC_PER_MSEC;
}
int64_t
BaseBlobImpl::GetFileId()
{
return -1;
}
nsresult
BaseBlobImpl::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
nsACString& aContentType, nsACString& aCharset)
{
MOZ_ASSERT(aContentLength);
ErrorResult rv;
nsCOMPtr<nsIInputStream> stream;
GetInternalStream(getter_AddRefs(stream), rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
*aContentLength = GetSize(rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
nsAutoString contentType;
GetType(contentType);
if (contentType.IsEmpty()) {
aContentType.SetIsVoid(true);
} else {
CopyUTF16toUTF8(contentType, aContentType);
}
aCharset.Truncate();
stream.forget(aBody);
return NS_OK;
}
nsresult
BaseBlobImpl::GetMutable(bool* aMutable) const
{
*aMutable = !mImmutable;
return NS_OK;
}
nsresult
BaseBlobImpl::SetMutable(bool aMutable)
{
nsresult rv = NS_OK;
NS_ENSURE_ARG(!mImmutable || !aMutable);
if (!mImmutable && !aMutable) {
// Force the content type and size to be cached
nsAutoString dummyString;
GetType(dummyString);
ErrorResult error;
GetSize(error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
mImmutable = !aMutable;
return rv;
}
/* static */ uint64_t
BaseBlobImpl::NextSerialNumber()
{
static Atomic<uint64_t> nextSerialNumber;
return nextSerialNumber++;
}
} // namespace dom
} // namespace mozilla

191
dom/file/BaseBlobImpl.h Normal file
Просмотреть файл

@ -0,0 +1,191 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_BaseBlobImpl_h
#define mozilla_dom_BaseBlobImpl_h
#include "mozilla/dom/BlobImpl.h"
namespace mozilla {
namespace dom {
class BaseBlobImpl : public BlobImpl
{
public:
BaseBlobImpl(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, int64_t aLastModifiedDate)
: mIsFile(true)
, mImmutable(false)
, mContentType(aContentType)
, mName(aName)
, mStart(0)
, mLength(aLength)
, mLastModificationDate(aLastModifiedDate)
, mSerialNumber(NextSerialNumber())
{
// Ensure non-null mContentType by default
mContentType.SetIsVoid(false);
}
BaseBlobImpl(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength)
: mIsFile(true)
, mImmutable(false)
, mContentType(aContentType)
, mName(aName)
, mStart(0)
, mLength(aLength)
, mLastModificationDate(INT64_MAX)
, mSerialNumber(NextSerialNumber())
{
// Ensure non-null mContentType by default
mContentType.SetIsVoid(false);
}
BaseBlobImpl(const nsAString& aContentType, uint64_t aLength)
: mIsFile(false)
, mImmutable(false)
, mContentType(aContentType)
, mStart(0)
, mLength(aLength)
, mLastModificationDate(INT64_MAX)
, mSerialNumber(NextSerialNumber())
{
// Ensure non-null mContentType by default
mContentType.SetIsVoid(false);
}
BaseBlobImpl(const nsAString& aContentType, uint64_t aStart,
uint64_t aLength)
: mIsFile(false)
, mImmutable(false)
, mContentType(aContentType)
, mStart(aStart)
, mLength(aLength)
, mLastModificationDate(INT64_MAX)
, mSerialNumber(NextSerialNumber())
{
MOZ_ASSERT(aLength != UINT64_MAX, "Must know length when creating slice");
// Ensure non-null mContentType by default
mContentType.SetIsVoid(false);
}
virtual void GetName(nsAString& aName) const override;
virtual void GetDOMPath(nsAString& aName) const override;
virtual void SetDOMPath(const nsAString& aName) override;
virtual int64_t GetLastModified(ErrorResult& aRv) override;
virtual void SetLastModified(int64_t aLastModified) override;
virtual void GetMozFullPath(nsAString& aName,
SystemCallerGuarantee /* unused */,
ErrorResult& aRv) const override;
virtual void GetMozFullPathInternal(nsAString& aFileName,
ErrorResult& aRv) const override;
virtual uint64_t GetSize(ErrorResult& aRv) override
{
return mLength;
}
virtual void GetType(nsAString& aType) override;
virtual uint64_t GetSerialNumber() const override { return mSerialNumber; }
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override
{
return nullptr;
}
virtual const nsTArray<RefPtr<BlobImpl>>*
GetSubBlobImpls() const override
{
return nullptr;
}
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
}
virtual int64_t GetFileId() override;
virtual nsresult GetSendInfo(nsIInputStream** aBody,
uint64_t* aContentLength,
nsACString& aContentType,
nsACString& aCharset) override;
virtual nsresult GetMutable(bool* aMutable) const override;
virtual nsresult SetMutable(bool aMutable) override;
virtual void
SetLazyData(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, int64_t aLastModifiedDate) override
{
mName = aName;
mContentType = aContentType;
mLength = aLength;
mLastModificationDate = aLastModifiedDate;
mIsFile = !aName.IsVoid();
}
virtual bool IsMemoryFile() const override
{
return false;
}
virtual bool IsDateUnknown() const override
{
return mIsFile && mLastModificationDate == INT64_MAX;
}
virtual bool IsFile() const override
{
return mIsFile;
}
virtual bool IsSizeUnknown() const override
{
return mLength == UINT64_MAX;
}
protected:
virtual ~BaseBlobImpl() {}
/**
* Returns a new, effectively-unique serial number. This should be used
* by implementations to obtain a serial number for GetSerialNumber().
* The implementation is thread safe.
*/
static uint64_t NextSerialNumber();
bool mIsFile;
bool mImmutable;
nsString mContentType;
nsString mName;
nsString mPath; // The path relative to a directory chosen by the user
uint64_t mStart;
uint64_t mLength;
int64_t mLastModificationDate;
const uint64_t mSerialNumber;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_BaseBlobImpl_h

294
dom/file/Blob.cpp Normal file
Просмотреть файл

@ -0,0 +1,294 @@
/* -*- 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 "Blob.h"
#include "File.h"
#include "MemoryBlobImpl.h"
#include "mozilla/dom/BlobBinding.h"
#include "MultipartBlobImpl.h"
#include "ipc/nsIRemoteBlob.h"
#include "nsIInputStream.h"
#include "nsPIDOMWindow.h"
#include "TemporaryBlobImpl.h"
#include "StreamBlobImpl.h"
#include "StringBlobImpl.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(Blob)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Blob)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Blob)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Blob)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Blob)
// This class should not receive any nsIRemoteBlob QI!
MOZ_ASSERT(!aIID.Equals(NS_GET_IID(nsIRemoteBlob)));
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMBlob)
NS_INTERFACE_MAP_ENTRY(nsIDOMBlob)
NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
NS_INTERFACE_MAP_ENTRY(nsIMutable)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(Blob)
NS_IMPL_CYCLE_COLLECTING_RELEASE(Blob)
void
Blob::MakeValidBlobType(nsAString& aType)
{
char16_t* iter = aType.BeginWriting();
char16_t* end = aType.EndWriting();
for ( ; iter != end; ++iter) {
char16_t c = *iter;
if (c < 0x20 || c > 0x7E) {
// Non-ASCII char, bail out.
aType.Truncate();
return;
}
if (c >= 'A' && c <= 'Z') {
*iter = c + ('a' - 'A');
}
}
}
/* static */ Blob*
Blob::Create(nsISupports* aParent, BlobImpl* aImpl)
{
MOZ_ASSERT(aImpl);
return aImpl->IsFile() ? new File(aParent, aImpl)
: new Blob(aParent, aImpl);
}
/* static */ already_AddRefed<Blob>
Blob::CreateStringBlob(nsISupports* aParent, const nsACString& aData,
const nsAString& aContentType)
{
RefPtr<BlobImpl> blobImpl = StringBlobImpl::Create(aData, aContentType);
RefPtr<Blob> blob = Blob::Create(aParent, blobImpl);
MOZ_ASSERT(!blob->mImpl->IsFile());
return blob.forget();
}
/* static */ already_AddRefed<Blob>
Blob::CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer,
uint64_t aLength, const nsAString& aContentType)
{
RefPtr<Blob> blob = Blob::Create(aParent,
new MemoryBlobImpl(aMemoryBuffer, aLength, aContentType));
MOZ_ASSERT(!blob->mImpl->IsFile());
return blob.forget();
}
/* static */ already_AddRefed<Blob>
Blob::CreateTemporaryBlob(nsISupports* aParent, PRFileDesc* aFD,
uint64_t aStartPos, uint64_t aLength,
const nsAString& aContentType)
{
RefPtr<Blob> blob = Blob::Create(aParent,
new TemporaryBlobImpl(aFD, aStartPos, aLength, aContentType));
MOZ_ASSERT(!blob->mImpl->IsFile());
return blob.forget();
}
Blob::Blob(nsISupports* aParent, BlobImpl* aImpl)
: mImpl(aImpl)
, mParent(aParent)
{
MOZ_ASSERT(mImpl);
#ifdef DEBUG
{
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aParent);
if (win) {
MOZ_ASSERT(win->IsInnerWindow());
}
}
#endif
}
Blob::~Blob()
{}
bool
Blob::IsFile() const
{
return mImpl->IsFile();
}
const nsTArray<RefPtr<BlobImpl>>*
Blob::GetSubBlobImpls() const
{
return mImpl->GetSubBlobImpls();
}
already_AddRefed<File>
Blob::ToFile()
{
if (!mImpl->IsFile()) {
return nullptr;
}
RefPtr<File> file;
if (HasFileInterface()) {
file = static_cast<File*>(this);
} else {
file = new File(mParent, mImpl);
}
return file.forget();
}
already_AddRefed<File>
Blob::ToFile(const nsAString& aName, ErrorResult& aRv) const
{
AutoTArray<RefPtr<BlobImpl>, 1> blobImpls({mImpl});
nsAutoString contentType;
mImpl->GetType(contentType);
RefPtr<MultipartBlobImpl> impl =
MultipartBlobImpl::Create(Move(blobImpls), aName, contentType, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
RefPtr<File> file = new File(mParent, impl);
return file.forget();
}
already_AddRefed<Blob>
Blob::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType,
ErrorResult& aRv)
{
RefPtr<BlobImpl> impl = mImpl->CreateSlice(aStart, aLength,
aContentType, aRv);
if (aRv.Failed()) {
return nullptr;
}
RefPtr<Blob> blob = Blob::Create(mParent, impl);
return blob.forget();
}
uint64_t
Blob::GetSize(ErrorResult& aRv)
{
return mImpl->GetSize(aRv);
}
void
Blob::GetType(nsAString &aType)
{
mImpl->GetType(aType);
}
already_AddRefed<Blob>
Blob::Slice(const Optional<int64_t>& aStart,
const Optional<int64_t>& aEnd,
const nsAString& aContentType,
ErrorResult& aRv)
{
RefPtr<BlobImpl> impl =
mImpl->Slice(aStart, aEnd, aContentType, aRv);
if (aRv.Failed()) {
return nullptr;
}
RefPtr<Blob> blob = Blob::Create(mParent, impl);
return blob.forget();
}
NS_IMETHODIMP
Blob::GetSendInfo(nsIInputStream** aBody,
uint64_t* aContentLength,
nsACString& aContentType,
nsACString& aCharset)
{
return mImpl->GetSendInfo(aBody, aContentLength, aContentType, aCharset);
}
NS_IMETHODIMP
Blob::GetMutable(bool* aMutable)
{
return mImpl->GetMutable(aMutable);
}
NS_IMETHODIMP
Blob::SetMutable(bool aMutable)
{
return mImpl->SetMutable(aMutable);
}
JSObject*
Blob::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return BlobBinding::Wrap(aCx, this, aGivenProto);
}
/* static */ already_AddRefed<Blob>
Blob::Constructor(const GlobalObject& aGlobal,
const Optional<Sequence<BlobPart>>& aData,
const BlobPropertyBag& aBag,
ErrorResult& aRv)
{
RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl();
if (aData.WasPassed()) {
nsAutoString type(aBag.mType);
MakeValidBlobType(type);
impl->InitializeBlob(aGlobal.Context(), aData.Value(), type,
aBag.mEndings == EndingTypes::Native, aRv);
} else {
impl->InitializeBlob(aRv);
}
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
MOZ_ASSERT(!impl->IsFile());
RefPtr<Blob> blob = Blob::Create(aGlobal.GetAsSupports(), impl);
return blob.forget();
}
int64_t
Blob::GetFileId()
{
return mImpl->GetFileId();
}
bool
Blob::IsMemoryFile() const
{
return mImpl->IsMemoryFile();
}
void
Blob::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
{
mImpl->GetInternalStream(aStream, aRv);
}
} // namespace dom
} // namespace mozilla

153
dom/file/Blob.h Normal file
Просмотреть файл

@ -0,0 +1,153 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_Blob_h
#define mozilla_dom_Blob_h
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/BlobImpl.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
#include "nsIDOMBlob.h"
#include "nsIMutable.h"
#include "nsIXMLHttpRequest.h"
#include "nsWrapperCache.h"
#include "nsWeakReference.h"
class nsIInputStream;
namespace mozilla {
namespace dom {
struct BlobPropertyBag;
class File;
class OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString;
class Blob : public nsIDOMBlob
, public nsIXHRSendable
, public nsIMutable
, public nsSupportsWeakReference
, public nsWrapperCache
{
public:
NS_DECL_NSIDOMBLOB
NS_DECL_NSIXHRSENDABLE
NS_DECL_NSIMUTABLE
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIDOMBlob)
typedef OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString BlobPart;
// This creates a Blob or a File based on the type of BlobImpl.
static Blob*
Create(nsISupports* aParent, BlobImpl* aImpl);
static already_AddRefed<Blob>
CreateStringBlob(nsISupports* aParent, const nsACString& aData,
const nsAString& aContentType);
// The returned Blob takes ownership of aMemoryBuffer. aMemoryBuffer will be
// freed by free so it must be allocated by malloc or something
// compatible with it.
static already_AddRefed<Blob>
CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
const nsAString& aContentType);
static already_AddRefed<Blob>
CreateTemporaryBlob(nsISupports* aParent, PRFileDesc* aFD,
uint64_t aStartPos, uint64_t aLength,
const nsAString& aContentType);
BlobImpl* Impl() const
{
return mImpl;
}
bool IsFile() const;
const nsTArray<RefPtr<BlobImpl>>* GetSubBlobImpls() const;
// This method returns null if this Blob is not a File; it returns
// the same object in case this Blob already implements the File interface;
// otherwise it returns a new File object with the same BlobImpl.
already_AddRefed<File> ToFile();
// This method creates a new File object with the given name and the same
// BlobImpl.
already_AddRefed<File> ToFile(const nsAString& aName,
ErrorResult& aRv) const;
already_AddRefed<Blob>
CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
ErrorResult& aRv);
void
GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv);
int64_t
GetFileId();
// A utility function that enforces the spec constraints on the type of a
// blob: no codepoints outside the ASCII range (otherwise type becomes empty)
// and lowercase ASCII only. We can't just use our existing nsContentUtils
// ASCII-related helpers because we need the "outside ASCII range" check, and
// we can't use NS_IsAscii because its definition of "ASCII" (chars all <=
// 0x7E) differs from the file API definition (which excludes control chars).
static void
MakeValidBlobType(nsAString& aType);
// WebIDL methods
nsISupports* GetParentObject() const
{
return mParent;
}
bool
IsMemoryFile() const;
// Blob constructor
static already_AddRefed<Blob>
Constructor(const GlobalObject& aGlobal,
const Optional<Sequence<BlobPart>>& aData,
const BlobPropertyBag& aBag,
ErrorResult& aRv);
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
uint64_t GetSize(ErrorResult& aRv);
void GetType(nsAString& aType);
already_AddRefed<Blob> Slice(const Optional<int64_t>& aStart,
const Optional<int64_t>& aEnd,
const nsAString& aContentType,
ErrorResult& aRv);
protected:
// File constructor should never be used directly. Use Blob::Create instead.
Blob(nsISupports* aParent, BlobImpl* aImpl);
virtual ~Blob();
virtual bool HasFileInterface() const { return false; }
// The member is the real backend implementation of this File/Blob.
// It's thread-safe and not CC-able and it's the only element that is moved
// between threads.
// Note: we should not store any other state in this class!
RefPtr<BlobImpl> mImpl;
private:
nsCOMPtr<nsISupports> mParent;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_Blob_h

76
dom/file/BlobImpl.cpp Normal file
Просмотреть файл

@ -0,0 +1,76 @@
/* -*- 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 "BlobImpl.h"
#include "File.h"
#include "mozilla/CheckedInt.h"
namespace mozilla {
namespace dom {
// Makes sure that aStart and aEnd is less then or equal to aSize and greater
// than 0
static void
ParseSize(int64_t aSize, int64_t& aStart, int64_t& aEnd)
{
CheckedInt64 newStartOffset = aStart;
if (aStart < -aSize) {
newStartOffset = 0;
}
else if (aStart < 0) {
newStartOffset += aSize;
}
else if (aStart > aSize) {
newStartOffset = aSize;
}
CheckedInt64 newEndOffset = aEnd;
if (aEnd < -aSize) {
newEndOffset = 0;
}
else if (aEnd < 0) {
newEndOffset += aSize;
}
else if (aEnd > aSize) {
newEndOffset = aSize;
}
if (!newStartOffset.isValid() || !newEndOffset.isValid() ||
newStartOffset.value() >= newEndOffset.value()) {
aStart = aEnd = 0;
}
else {
aStart = newStartOffset.value();
aEnd = newEndOffset.value();
}
}
already_AddRefed<BlobImpl>
BlobImpl::Slice(const Optional<int64_t>& aStart,
const Optional<int64_t>& aEnd,
const nsAString& aContentType,
ErrorResult& aRv)
{
// Truncate aStart and aEnd so that we stay within this file.
uint64_t thisLength = GetSize(aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
int64_t start = aStart.WasPassed() ? aStart.Value() : 0;
int64_t end = aEnd.WasPassed() ? aEnd.Value() : (int64_t)thisLength;
ParseSize((int64_t)thisLength, start, end);
nsAutoString type(aContentType);
Blob::MakeValidBlobType(type);
return CreateSlice((uint64_t)start, (uint64_t)(end - start), type, aRv);
}
NS_IMPL_ISUPPORTS(BlobImpl, BlobImpl)
} // namespace dom
} // namespace mozilla

122
dom/file/BlobImpl.h Normal file
Просмотреть файл

@ -0,0 +1,122 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_BlobImpl_h
#define mozilla_dom_BlobImpl_h
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/ErrorResult.h"
#include "nsISupportsImpl.h"
#include "nsString.h"
#define BLOBIMPL_IID \
{ 0xbccb3275, 0x6778, 0x4ac5, \
{ 0xaf, 0x03, 0x90, 0xed, 0x37, 0xad, 0xdf, 0x5d } }
class nsIInputStream;
namespace mozilla {
namespace dom {
// This is the abstract class for any File backend. It must be nsISupports
// because this class must be ref-counted and it has to work with IPC.
class BlobImpl : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(BLOBIMPL_IID)
NS_DECL_THREADSAFE_ISUPPORTS
BlobImpl() {}
virtual void GetName(nsAString& aName) const = 0;
virtual void GetDOMPath(nsAString& aName) const = 0;
virtual void SetDOMPath(const nsAString& aName) = 0;
virtual int64_t GetLastModified(ErrorResult& aRv) = 0;
virtual void SetLastModified(int64_t aLastModified) = 0;
virtual void GetMozFullPath(nsAString& aName,
SystemCallerGuarantee /* unused */,
ErrorResult& aRv) const = 0;
virtual void GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const = 0;
virtual uint64_t GetSize(ErrorResult& aRv) = 0;
virtual void GetType(nsAString& aType) = 0;
/**
* An effectively-unique serial number identifying this instance of FileImpl.
*
* Implementations should obtain a serial number from
* FileImplBase::NextSerialNumber().
*/
virtual uint64_t GetSerialNumber() const = 0;
already_AddRefed<BlobImpl>
Slice(const Optional<int64_t>& aStart, const Optional<int64_t>& aEnd,
const nsAString& aContentType, ErrorResult& aRv);
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) = 0;
virtual const nsTArray<RefPtr<BlobImpl>>*
GetSubBlobImpls() const = 0;
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) = 0;
virtual int64_t GetFileId() = 0;
virtual nsresult GetSendInfo(nsIInputStream** aBody,
uint64_t* aContentLength,
nsACString& aContentType,
nsACString& aCharset) = 0;
virtual nsresult GetMutable(bool* aMutable) const = 0;
virtual nsresult SetMutable(bool aMutable) = 0;
virtual void SetLazyData(const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength,
int64_t aLastModifiedDate) = 0;
virtual bool IsMemoryFile() const = 0;
virtual bool IsSizeUnknown() const = 0;
virtual bool IsDateUnknown() const = 0;
virtual bool IsFile() const = 0;
// Returns true if the BlobImpl is backed by an nsIFile and the underlying
// file is a directory.
virtual bool IsDirectory() const
{
return false;
}
// True if this implementation can be sent to other threads.
virtual bool MayBeClonedToOtherThreads() const
{
return true;
}
protected:
virtual ~BlobImpl() {}
};
NS_DEFINE_STATIC_IID_ACCESSOR(BlobImpl, BLOBIMPL_IID)
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_BlobImpl_h

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

@ -7,6 +7,7 @@
#include "mozilla/dom/BlobSet.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/dom/File.h"
#include "MemoryBlobImpl.h"
#include "MultipartBlobImpl.h"
namespace mozilla {
@ -27,7 +28,7 @@ BlobSet::AppendVoidPtr(const void* aData, uint32_t aLength)
memcpy((char*)data, aData, aLength);
RefPtr<BlobImpl> blobImpl = new BlobImplMemory(data, aLength, EmptyString());
RefPtr<BlobImpl> blobImpl = new MemoryBlobImpl(data, aLength, EmptyString());
mBlobImpls.AppendElement(blobImpl);
return NS_OK;

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

@ -0,0 +1,47 @@
/* -*- 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 "EmptyBlobImpl.h"
#include "nsStringStream.h"
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS_INHERITED0(EmptyBlobImpl, BlobImpl)
already_AddRefed<BlobImpl>
EmptyBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType,
ErrorResult& aRv)
{
MOZ_ASSERT(!aStart && !aLength);
RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
DebugOnly<bool> isMutable;
MOZ_ASSERT(NS_SUCCEEDED(impl->GetMutable(&isMutable)));
MOZ_ASSERT(!isMutable);
return impl.forget();
}
void
EmptyBlobImpl::GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv)
{
if (NS_WARN_IF(!aStream)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsresult rv = NS_NewCStringInputStream(aStream, EmptyCString());
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return;
}
}
} // namespace dom
} // namespace mozilla

53
dom/file/EmptyBlobImpl.h Normal file
Просмотреть файл

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_EmptyBlobImpl_h
#define mozilla_dom_EmptyBlobImpl_h
#include "BaseBlobImpl.h"
namespace mozilla {
namespace dom {
class EmptyBlobImpl final : public BaseBlobImpl
{
public:
NS_DECL_ISUPPORTS_INHERITED
explicit EmptyBlobImpl(const nsAString& aContentType)
: BaseBlobImpl(aContentType, 0 /* aLength */)
{
mImmutable = true;
}
EmptyBlobImpl(const nsAString& aName,
const nsAString& aContentType,
int64_t aLastModifiedDate)
: BaseBlobImpl(aName, aContentType, 0, aLastModifiedDate)
{
mImmutable = true;
}
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
virtual bool IsMemoryFile() const override
{
return true;
}
private:
~EmptyBlobImpl() {}
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_EmptyBlobImpl_h

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -7,154 +7,18 @@
#ifndef mozilla_dom_File_h
#define mozilla_dom_File_h
#include "mozilla/Attributes.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/GuardObjects.h"
#include "mozilla/LinkedList.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/Blob.h"
#include "mozilla/dom/Date.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
#include "nsIDOMBlob.h"
#include "nsIFile.h"
#include "nsIMemoryReporter.h"
#include "nsIMutable.h"
#include "nsIXMLHttpRequest.h"
#include "nsString.h"
#include "nsTemporaryFileInputStream.h"
#include "nsWrapperCache.h"
#include "nsWeakReference.h"
class nsIFile;
class nsIInputStream;
#define BLOBIMPL_IID \
{ 0xbccb3275, 0x6778, 0x4ac5, \
{ 0xaf, 0x03, 0x90, 0xed, 0x37, 0xad, 0xdf, 0x5d } }
namespace mozilla {
namespace dom {
struct BlobPropertyBag;
struct ChromeFilePropertyBag;
struct FilePropertyBag;
class BlobImpl;
class File;
class OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString;
class Promise;
class Blob : public nsIDOMBlob
, public nsIXHRSendable
, public nsIMutable
, public nsSupportsWeakReference
, public nsWrapperCache
{
public:
NS_DECL_NSIDOMBLOB
NS_DECL_NSIXHRSENDABLE
NS_DECL_NSIMUTABLE
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIDOMBlob)
typedef OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString BlobPart;
// This creates a Blob or a File based on the type of BlobImpl.
static Blob*
Create(nsISupports* aParent, BlobImpl* aImpl);
static already_AddRefed<Blob>
CreateStringBlob(nsISupports* aParent, const nsACString& aData,
const nsAString& aContentType);
// The returned Blob takes ownership of aMemoryBuffer. aMemoryBuffer will be
// freed by free so it must be allocated by malloc or something
// compatible with it.
static already_AddRefed<Blob>
CreateMemoryBlob(nsISupports* aParent, void* aMemoryBuffer, uint64_t aLength,
const nsAString& aContentType);
static already_AddRefed<Blob>
CreateTemporaryBlob(nsISupports* aParent, PRFileDesc* aFD,
uint64_t aStartPos, uint64_t aLength,
const nsAString& aContentType);
BlobImpl* Impl() const
{
return mImpl;
}
bool IsFile() const;
const nsTArray<RefPtr<BlobImpl>>* GetSubBlobImpls() const;
// This method returns null if this Blob is not a File; it returns
// the same object in case this Blob already implements the File interface;
// otherwise it returns a new File object with the same BlobImpl.
already_AddRefed<File> ToFile();
// This method creates a new File object with the given name and the same
// BlobImpl.
already_AddRefed<File> ToFile(const nsAString& aName,
ErrorResult& aRv) const;
already_AddRefed<Blob>
CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType,
ErrorResult& aRv);
void
GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv);
int64_t
GetFileId();
// WebIDL methods
nsISupports* GetParentObject() const
{
return mParent;
}
bool
IsMemoryFile() const;
// Blob constructor
static already_AddRefed<Blob>
Constructor(const GlobalObject& aGlobal,
const Optional<Sequence<BlobPart>>& aData,
const BlobPropertyBag& aBag,
ErrorResult& aRv);
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
uint64_t GetSize(ErrorResult& aRv);
void GetType(nsAString& aType);
already_AddRefed<Blob> Slice(const Optional<int64_t>& aStart,
const Optional<int64_t>& aEnd,
const nsAString& aContentType,
ErrorResult& aRv);
protected:
// File constructor should never be used directly. Use Blob::Create instead.
Blob(nsISupports* aParent, BlobImpl* aImpl);
virtual ~Blob() {};
virtual bool HasFileInterface() const { return false; }
// The member is the real backend implementation of this File/Blob.
// It's thread-safe and not CC-able and it's the only element that is moved
// between threads.
// Note: we should not store any other state in this class!
RefPtr<BlobImpl> mImpl;
private:
nsCOMPtr<nsISupports> mParent;
};
class File final : public Blob
{
friend class Blob;
@ -240,617 +104,7 @@ private:
// File constructor should never be used directly. Use Blob::Create or
// File::Create.
File(nsISupports* aParent, BlobImpl* aImpl);
~File() {};
};
// This is the abstract class for any File backend. It must be nsISupports
// because this class must be ref-counted and it has to work with IPC.
class BlobImpl : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(BLOBIMPL_IID)
NS_DECL_THREADSAFE_ISUPPORTS
BlobImpl() {}
virtual void GetName(nsAString& aName) const = 0;
virtual void GetDOMPath(nsAString& aName) const = 0;
virtual void SetDOMPath(const nsAString& aName) = 0;
virtual int64_t GetLastModified(ErrorResult& aRv) = 0;
virtual void SetLastModified(int64_t aLastModified) = 0;
virtual void GetMozFullPath(nsAString& aName,
SystemCallerGuarantee /* unused */,
ErrorResult& aRv) const = 0;
virtual void GetMozFullPathInternal(nsAString& aFileName, ErrorResult& aRv) const = 0;
virtual uint64_t GetSize(ErrorResult& aRv) = 0;
virtual void GetType(nsAString& aType) = 0;
/**
* An effectively-unique serial number identifying this instance of FileImpl.
*
* Implementations should obtain a serial number from
* FileImplBase::NextSerialNumber().
*/
virtual uint64_t GetSerialNumber() const = 0;
already_AddRefed<BlobImpl>
Slice(const Optional<int64_t>& aStart, const Optional<int64_t>& aEnd,
const nsAString& aContentType, ErrorResult& aRv);
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) = 0;
virtual const nsTArray<RefPtr<BlobImpl>>*
GetSubBlobImpls() const = 0;
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) = 0;
virtual int64_t GetFileId() = 0;
virtual nsresult GetSendInfo(nsIInputStream** aBody,
uint64_t* aContentLength,
nsACString& aContentType,
nsACString& aCharset) = 0;
virtual nsresult GetMutable(bool* aMutable) const = 0;
virtual nsresult SetMutable(bool aMutable) = 0;
virtual void SetLazyData(const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength,
int64_t aLastModifiedDate) = 0;
virtual bool IsMemoryFile() const = 0;
virtual bool IsSizeUnknown() const = 0;
virtual bool IsDateUnknown() const = 0;
virtual bool IsFile() const = 0;
// Returns true if the BlobImpl is backed by an nsIFile and the underlying
// file is a directory.
virtual bool IsDirectory() const
{
return false;
}
// True if this implementation can be sent to other threads.
virtual bool MayBeClonedToOtherThreads() const
{
return true;
}
protected:
virtual ~BlobImpl() {}
};
NS_DEFINE_STATIC_IID_ACCESSOR(BlobImpl, BLOBIMPL_IID)
class BlobImplBase : public BlobImpl
{
public:
BlobImplBase(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, int64_t aLastModifiedDate)
: mIsFile(true)
, mImmutable(false)
, mContentType(aContentType)
, mName(aName)
, mStart(0)
, mLength(aLength)
, mLastModificationDate(aLastModifiedDate)
, mSerialNumber(NextSerialNumber())
{
// Ensure non-null mContentType by default
mContentType.SetIsVoid(false);
}
BlobImplBase(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength)
: mIsFile(true)
, mImmutable(false)
, mContentType(aContentType)
, mName(aName)
, mStart(0)
, mLength(aLength)
, mLastModificationDate(INT64_MAX)
, mSerialNumber(NextSerialNumber())
{
// Ensure non-null mContentType by default
mContentType.SetIsVoid(false);
}
BlobImplBase(const nsAString& aContentType, uint64_t aLength)
: mIsFile(false)
, mImmutable(false)
, mContentType(aContentType)
, mStart(0)
, mLength(aLength)
, mLastModificationDate(INT64_MAX)
, mSerialNumber(NextSerialNumber())
{
// Ensure non-null mContentType by default
mContentType.SetIsVoid(false);
}
BlobImplBase(const nsAString& aContentType, uint64_t aStart,
uint64_t aLength)
: mIsFile(false)
, mImmutable(false)
, mContentType(aContentType)
, mStart(aStart)
, mLength(aLength)
, mLastModificationDate(INT64_MAX)
, mSerialNumber(NextSerialNumber())
{
MOZ_ASSERT(aLength != UINT64_MAX, "Must know length when creating slice");
// Ensure non-null mContentType by default
mContentType.SetIsVoid(false);
}
virtual void GetName(nsAString& aName) const override;
virtual void GetDOMPath(nsAString& aName) const override;
virtual void SetDOMPath(const nsAString& aName) override;
virtual int64_t GetLastModified(ErrorResult& aRv) override;
virtual void SetLastModified(int64_t aLastModified) override;
virtual void GetMozFullPath(nsAString& aName,
SystemCallerGuarantee /* unused */,
ErrorResult& aRv) const override;
virtual void GetMozFullPathInternal(nsAString& aFileName,
ErrorResult& aRv) const override;
virtual uint64_t GetSize(ErrorResult& aRv) override
{
return mLength;
}
virtual void GetType(nsAString& aType) override;
virtual uint64_t GetSerialNumber() const override { return mSerialNumber; }
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override
{
return nullptr;
}
virtual const nsTArray<RefPtr<BlobImpl>>*
GetSubBlobImpls() const override
{
return nullptr;
}
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
}
virtual int64_t GetFileId() override;
virtual nsresult GetSendInfo(nsIInputStream** aBody,
uint64_t* aContentLength,
nsACString& aContentType,
nsACString& aCharset) override;
virtual nsresult GetMutable(bool* aMutable) const override;
virtual nsresult SetMutable(bool aMutable) override;
virtual void
SetLazyData(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, int64_t aLastModifiedDate) override
{
mName = aName;
mContentType = aContentType;
mLength = aLength;
mLastModificationDate = aLastModifiedDate;
mIsFile = !aName.IsVoid();
}
virtual bool IsMemoryFile() const override
{
return false;
}
virtual bool IsDateUnknown() const override
{
return mIsFile && mLastModificationDate == INT64_MAX;
}
virtual bool IsFile() const override
{
return mIsFile;
}
virtual bool IsSizeUnknown() const override
{
return mLength == UINT64_MAX;
}
protected:
virtual ~BlobImplBase() {}
/**
* Returns a new, effectively-unique serial number. This should be used
* by implementations to obtain a serial number for GetSerialNumber().
* The implementation is thread safe.
*/
static uint64_t NextSerialNumber();
bool mIsFile;
bool mImmutable;
nsString mContentType;
nsString mName;
nsString mPath; // The path relative to a directory chosen by the user
uint64_t mStart;
uint64_t mLength;
int64_t mLastModificationDate;
const uint64_t mSerialNumber;
};
class BlobImplString final : public BlobImplBase
, public nsIMemoryReporter
{
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIMEMORYREPORTER
static already_AddRefed<BlobImplString>
Create(const nsACString& aData, const nsAString& aContentType);
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
private:
BlobImplString(const nsACString& aData, const nsAString& aContentType);
~BlobImplString();
nsCString mData;
};
/**
* This class may be used off the main thread, and in particular, its
* constructor and destructor may not run on the same thread. Be careful!
*/
class BlobImplMemory final : public BlobImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
BlobImplMemory(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
const nsAString& aContentType, int64_t aLastModifiedDate)
: BlobImplBase(aName, aContentType, aLength, aLastModifiedDate)
, mDataOwner(new DataOwner(aMemoryBuffer, aLength))
{
MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
}
BlobImplMemory(void* aMemoryBuffer, uint64_t aLength,
const nsAString& aContentType)
: BlobImplBase(aContentType, aLength)
, mDataOwner(new DataOwner(aMemoryBuffer, aLength))
{
MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
}
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
virtual bool IsMemoryFile() const override
{
return true;
}
class DataOwner final : public mozilla::LinkedListElement<DataOwner>
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner)
DataOwner(void* aMemoryBuffer, uint64_t aLength)
: mData(aMemoryBuffer)
, mLength(aLength)
{
mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
if (!sDataOwners) {
sDataOwners = new mozilla::LinkedList<DataOwner>();
EnsureMemoryReporterRegistered();
}
sDataOwners->insertBack(this);
}
private:
// Private destructor, to discourage deletion outside of Release():
~DataOwner() {
mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
remove();
if (sDataOwners->isEmpty()) {
// Free the linked list if it's empty.
sDataOwners = nullptr;
}
free(mData);
}
public:
static void EnsureMemoryReporterRegistered();
// sDataOwners and sMemoryReporterRegistered may only be accessed while
// holding sDataOwnerMutex! You also must hold the mutex while touching
// elements of the linked list that DataOwner inherits from.
static mozilla::StaticMutex sDataOwnerMutex;
static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
static bool sMemoryReporterRegistered;
void* mData;
uint64_t mLength;
};
private:
// Create slice
BlobImplMemory(const BlobImplMemory* aOther, uint64_t aStart,
uint64_t aLength, const nsAString& aContentType)
: BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
, mDataOwner(aOther->mDataOwner)
{
MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
mImmutable = aOther->mImmutable;
}
~BlobImplMemory() {}
// Used when backed by a memory store
RefPtr<DataOwner> mDataOwner;
};
class BlobImplTemporaryBlob final : public BlobImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
BlobImplTemporaryBlob(PRFileDesc* aFD, uint64_t aStartPos,
uint64_t aLength, const nsAString& aContentType)
: BlobImplBase(aContentType, aLength)
, mStartPos(aStartPos)
{
mFileDescOwner = new nsTemporaryFileInputStream::FileDescOwner(aFD);
}
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
private:
BlobImplTemporaryBlob(const BlobImplTemporaryBlob* aOther,
uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
: BlobImplBase(aContentType, aLength)
, mStartPos(aStart)
, mFileDescOwner(aOther->mFileDescOwner)
{}
~BlobImplTemporaryBlob() {}
uint64_t mStartPos;
RefPtr<nsTemporaryFileInputStream::FileDescOwner> mFileDescOwner;
};
class BlobImplFile : public BlobImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
// Create as a file
explicit BlobImplFile(nsIFile* aFile)
: BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
, mFile(aFile)
, mWholeFile(true)
{
MOZ_ASSERT(mFile, "must have file");
// Lazily get the content type and size
mContentType.SetIsVoid(true);
mFile->GetLeafName(mName);
}
// Create as a file
BlobImplFile(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile)
: BlobImplBase(aName, aContentType, aLength, UINT64_MAX)
, mFile(aFile)
, mWholeFile(true)
{
MOZ_ASSERT(mFile, "must have file");
}
BlobImplFile(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile,
int64_t aLastModificationDate)
: BlobImplBase(aName, aContentType, aLength, aLastModificationDate)
, mFile(aFile)
, mWholeFile(true)
{
MOZ_ASSERT(mFile, "must have file");
}
// Create as a file with custom name
BlobImplFile(nsIFile* aFile, const nsAString& aName,
const nsAString& aContentType)
: BlobImplBase(aName, aContentType, UINT64_MAX, INT64_MAX)
, mFile(aFile)
, mWholeFile(true)
{
MOZ_ASSERT(mFile, "must have file");
if (aContentType.IsEmpty()) {
// Lazily get the content type and size
mContentType.SetIsVoid(true);
}
}
// Overrides
virtual uint64_t GetSize(ErrorResult& aRv) override;
virtual void GetType(nsAString& aType) override;
virtual int64_t GetLastModified(ErrorResult& aRv) override;
virtual void SetLastModified(int64_t aLastModified) override;
virtual void GetMozFullPathInternal(nsAString& aFullPath,
ErrorResult& aRv) const override;
virtual void GetInternalStream(nsIInputStream** aInputStream,
ErrorResult& aRv) override;
virtual bool IsDirectory() const override;
// We always have size and date for this kind of blob.
virtual bool IsSizeUnknown() const override { return false; }
virtual bool IsDateUnknown() const override { return false; }
protected:
virtual ~BlobImplFile() = default;
private:
// Create slice
BlobImplFile(const BlobImplFile* aOther, uint64_t aStart,
uint64_t aLength, const nsAString& aContentType)
: BlobImplBase(aContentType, aOther->mStart + aStart, aLength)
, mFile(aOther->mFile)
, mWholeFile(false)
{
MOZ_ASSERT(mFile, "must have file");
mImmutable = aOther->mImmutable;
}
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
nsCOMPtr<nsIFile> mFile;
bool mWholeFile;
};
class EmptyBlobImpl final : public BlobImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
explicit EmptyBlobImpl(const nsAString& aContentType)
: BlobImplBase(aContentType, 0 /* aLength */)
{
mImmutable = true;
}
EmptyBlobImpl(const nsAString& aName,
const nsAString& aContentType,
int64_t aLastModifiedDate)
: BlobImplBase(aName, aContentType, 0, aLastModifiedDate)
{
mImmutable = true;
}
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
virtual bool IsMemoryFile() const override
{
return true;
}
private:
~EmptyBlobImpl() {}
};
class BlobImplStream final : public BlobImplBase
, public nsIMemoryReporter
{
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIMEMORYREPORTER
static already_AddRefed<BlobImplStream>
Create(nsIInputStream* aInputStream,
const nsAString& aContentType,
uint64_t aLength);
static already_AddRefed<BlobImplStream>
Create(nsIInputStream* aInputStream,
const nsAString& aName,
const nsAString& aContentType,
int64_t aLastModifiedDate,
uint64_t aLength);
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
virtual bool IsMemoryFile() const override
{
return true;
}
private:
BlobImplStream(nsIInputStream* aInputStream,
const nsAString& aContentType,
uint64_t aLength);
BlobImplStream(nsIInputStream* aInputStream,
const nsAString& aName,
const nsAString& aContentType,
int64_t aLastModifiedDate,
uint64_t aLength);
BlobImplStream(BlobImplStream* aOther,
const nsAString& aContentType,
uint64_t aStart,
uint64_t aLength);
~BlobImplStream();
void MaybeRegisterMemoryReporter();
nsCOMPtr<nsIInputStream> mInputStream;
~File();
};
} // namespace dom

254
dom/file/FileBlobImpl.cpp Normal file
Просмотреть файл

@ -0,0 +1,254 @@
/* -*- 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 "FileBlobImpl.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerRunnable.h"
#include "nsCExternalHandlerService.h"
#include "nsIFile.h"
#include "nsIFileStreams.h"
#include "nsIMIMEService.h"
#include "nsNetUtil.h"
#include "nsStreamUtils.h"
#include "SlicedInputStream.h"
namespace mozilla {
namespace dom {
using namespace workers;
NS_IMPL_ISUPPORTS_INHERITED0(FileBlobImpl, BlobImpl)
FileBlobImpl::FileBlobImpl(nsIFile* aFile)
: BaseBlobImpl(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
, mFile(aFile)
, mWholeFile(true)
{
MOZ_ASSERT(mFile, "must have file");
// Lazily get the content type and size
mContentType.SetIsVoid(true);
mFile->GetLeafName(mName);
}
FileBlobImpl::FileBlobImpl(const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile)
: BaseBlobImpl(aName, aContentType, aLength, UINT64_MAX)
, mFile(aFile)
, mWholeFile(true)
{
MOZ_ASSERT(mFile, "must have file");
}
FileBlobImpl::FileBlobImpl(const nsAString& aName,
const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile,
int64_t aLastModificationDate)
: BaseBlobImpl(aName, aContentType, aLength, aLastModificationDate)
, mFile(aFile)
, mWholeFile(true)
{
MOZ_ASSERT(mFile, "must have file");
}
FileBlobImpl::FileBlobImpl(nsIFile* aFile, const nsAString& aName,
const nsAString& aContentType)
: BaseBlobImpl(aName, aContentType, UINT64_MAX, INT64_MAX)
, mFile(aFile)
, mWholeFile(true)
{
MOZ_ASSERT(mFile, "must have file");
if (aContentType.IsEmpty()) {
// Lazily get the content type and size
mContentType.SetIsVoid(true);
}
}
FileBlobImpl::FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart,
uint64_t aLength, const nsAString& aContentType)
: BaseBlobImpl(aContentType, aOther->mStart + aStart, aLength)
, mFile(aOther->mFile)
, mWholeFile(false)
{
MOZ_ASSERT(mFile, "must have file");
mImmutable = aOther->mImmutable;
}
already_AddRefed<BlobImpl>
FileBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType,
ErrorResult& aRv)
{
RefPtr<BlobImpl> impl =
new FileBlobImpl(this, aStart, aLength, aContentType);
return impl.forget();
}
void
FileBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
ErrorResult& aRv) const
{
MOZ_ASSERT(mIsFile, "Should only be called on files");
aRv = mFile->GetPath(aFilename);
}
uint64_t
FileBlobImpl::GetSize(ErrorResult& aRv)
{
if (BaseBlobImpl::IsSizeUnknown()) {
MOZ_ASSERT(mWholeFile,
"Should only use lazy size when using the whole file");
int64_t fileSize;
aRv = mFile->GetFileSize(&fileSize);
if (NS_WARN_IF(aRv.Failed())) {
return 0;
}
if (fileSize < 0) {
aRv.Throw(NS_ERROR_FAILURE);
return 0;
}
mLength = fileSize;
}
return mLength;
}
namespace {
class GetTypeRunnable final : public WorkerMainThreadRunnable
{
public:
GetTypeRunnable(WorkerPrivate* aWorkerPrivate,
BlobImpl* aBlobImpl)
: WorkerMainThreadRunnable(aWorkerPrivate,
NS_LITERAL_CSTRING("FileBlobImpl :: GetType"))
, mBlobImpl(aBlobImpl)
{
MOZ_ASSERT(aBlobImpl);
aWorkerPrivate->AssertIsOnWorkerThread();
}
bool
MainThreadRun() override
{
MOZ_ASSERT(NS_IsMainThread());
nsAutoString type;
mBlobImpl->GetType(type);
return true;
}
private:
~GetTypeRunnable() = default;
RefPtr<BlobImpl> mBlobImpl;
};
} // anonymous namespace
void
FileBlobImpl::GetType(nsAString& aType)
{
aType.Truncate();
if (mContentType.IsVoid()) {
MOZ_ASSERT(mWholeFile,
"Should only use lazy ContentType when using the whole file");
if (!NS_IsMainThread()) {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
if (!workerPrivate) {
// I have no idea in which thread this method is called. We cannot
// return any valid value.
return;
}
RefPtr<GetTypeRunnable> runnable =
new GetTypeRunnable(workerPrivate, this);
ErrorResult rv;
runnable->Dispatch(Terminating, rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
}
return;
}
nsresult rv;
nsCOMPtr<nsIMIMEService> mimeService =
do_GetService(NS_MIMESERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsAutoCString mimeType;
rv = mimeService->GetTypeFromFile(mFile, mimeType);
if (NS_FAILED(rv)) {
mimeType.Truncate();
}
AppendUTF8toUTF16(mimeType, mContentType);
mContentType.SetIsVoid(false);
}
aType = mContentType;
}
int64_t
FileBlobImpl::GetLastModified(ErrorResult& aRv)
{
MOZ_ASSERT(mIsFile, "Should only be called on files");
if (BaseBlobImpl::IsDateUnknown()) {
PRTime msecs;
aRv = mFile->GetLastModifiedTime(&msecs);
if (NS_WARN_IF(aRv.Failed())) {
return 0;
}
mLastModificationDate = msecs;
}
return mLastModificationDate;
}
void
FileBlobImpl::SetLastModified(int64_t aLastModified)
{
MOZ_CRASH("SetLastModified of a real file is not allowed!");
}
const uint32_t sFileStreamFlags =
nsIFileInputStream::CLOSE_ON_EOF |
nsIFileInputStream::REOPEN_ON_REWIND |
nsIFileInputStream::DEFER_OPEN |
nsIFileInputStream::SHARE_DELETE;
void
FileBlobImpl::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
{
if (mWholeFile) {
aRv = NS_NewLocalFileInputStream(aStream, mFile, -1, -1, sFileStreamFlags);
return;
}
aRv = NS_NewPartialLocalFileInputStream(aStream, mFile, mStart, mLength,
-1, -1, sFileStreamFlags);
}
bool
FileBlobImpl::IsDirectory() const
{
bool isDirectory = false;
if (mFile) {
mFile->IsDirectory(&isDirectory);
}
return isDirectory;
}
} // namespace dom
} // namespace mozilla

72
dom/file/FileBlobImpl.h Normal file
Просмотреть файл

@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_FileBlobImpl_h
#define mozilla_dom_FileBlobImpl_h
#include "mozilla/dom/BaseBlobImpl.h"
class nsIFile;
namespace mozilla {
namespace dom {
class FileBlobImpl : public BaseBlobImpl
{
public:
NS_DECL_ISUPPORTS_INHERITED
// Create as a file
explicit FileBlobImpl(nsIFile* aFile);
// Create as a file
FileBlobImpl(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile);
FileBlobImpl(const nsAString& aName, const nsAString& aContentType,
uint64_t aLength, nsIFile* aFile,
int64_t aLastModificationDate);
// Create as a file with custom name
FileBlobImpl(nsIFile* aFile, const nsAString& aName,
const nsAString& aContentType);
// Overrides
virtual uint64_t GetSize(ErrorResult& aRv) override;
virtual void GetType(nsAString& aType) override;
virtual int64_t GetLastModified(ErrorResult& aRv) override;
virtual void SetLastModified(int64_t aLastModified) override;
virtual void GetMozFullPathInternal(nsAString& aFullPath,
ErrorResult& aRv) const override;
virtual void GetInternalStream(nsIInputStream** aInputStream,
ErrorResult& aRv) override;
virtual bool IsDirectory() const override;
// We always have size and date for this kind of blob.
virtual bool IsSizeUnknown() const override { return false; }
virtual bool IsDateUnknown() const override { return false; }
protected:
virtual ~FileBlobImpl() = default;
private:
// Create slice
FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart,
uint64_t aLength, const nsAString& aContentType);
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
nsCOMPtr<nsIFile> mFile;
bool mWholeFile;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_FileBlobImpl_h

217
dom/file/MemoryBlobImpl.cpp Normal file
Просмотреть файл

@ -0,0 +1,217 @@
/* -*- 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 "MemoryBlobImpl.h"
#include "mozilla/SHA1.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsPrintfCString.h"
namespace mozilla {
namespace dom {
// XXXkhuey the input stream that we pass out of a File
// can outlive the actual File object. Thus, we must
// ensure that the buffer underlying the stream we get
// from NS_NewByteInputStream is held alive as long as the
// stream is. We do that by passing back this class instead.
class DataOwnerAdapter final : public nsIInputStream,
public nsISeekableStream,
public nsIIPCSerializableInputStream
{
typedef MemoryBlobImpl::DataOwner DataOwner;
public:
static nsresult Create(DataOwner* aDataOwner,
uint32_t aStart,
uint32_t aLength,
nsIInputStream** _retval);
NS_DECL_THREADSAFE_ISUPPORTS
// These are mandatory.
NS_FORWARD_NSIINPUTSTREAM(mStream->)
NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
// This is optional. We use a conditional QI to keep it from being called
// if the underlying stream doesn't support it.
NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
private:
~DataOwnerAdapter() {}
DataOwnerAdapter(DataOwner* aDataOwner,
nsIInputStream* aStream)
: mDataOwner(aDataOwner), mStream(aStream),
mSeekableStream(do_QueryInterface(aStream)),
mSerializableInputStream(do_QueryInterface(aStream))
{
MOZ_ASSERT(mSeekableStream, "Somebody gave us the wrong stream!");
}
RefPtr<DataOwner> mDataOwner;
nsCOMPtr<nsIInputStream> mStream;
nsCOMPtr<nsISeekableStream> mSeekableStream;
nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
};
NS_IMPL_ADDREF(DataOwnerAdapter)
NS_IMPL_RELEASE(DataOwnerAdapter)
NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
mSerializableInputStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
uint32_t aStart,
uint32_t aLength,
nsIInputStream** _retval)
{
nsresult rv;
MOZ_ASSERT(aDataOwner, "Uh ...");
nsCOMPtr<nsIInputStream> stream;
rv = NS_NewByteInputStream(getter_AddRefs(stream),
static_cast<const char*>(aDataOwner->mData) +
aStart,
(int32_t)aLength,
NS_ASSIGNMENT_DEPEND);
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*_retval = new DataOwnerAdapter(aDataOwner, stream));
return NS_OK;
}
NS_IMPL_ISUPPORTS_INHERITED0(MemoryBlobImpl, BlobImpl)
already_AddRefed<BlobImpl>
MemoryBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType,
ErrorResult& aRv)
{
RefPtr<BlobImpl> impl =
new MemoryBlobImpl(this, aStart, aLength, aContentType);
return impl.forget();
}
void
MemoryBlobImpl::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
{
if (mLength > INT32_MAX) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
aRv = DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
}
/* static */ StaticMutex
MemoryBlobImpl::DataOwner::sDataOwnerMutex;
/* static */ StaticAutoPtr<LinkedList<MemoryBlobImpl::DataOwner>>
MemoryBlobImpl::DataOwner::sDataOwners;
/* static */ bool
MemoryBlobImpl::DataOwner::sMemoryReporterRegistered = false;
MOZ_DEFINE_MALLOC_SIZE_OF(MemoryFileDataOwnerMallocSizeOf)
class MemoryBlobImplDataOwnerMemoryReporter final
: public nsIMemoryReporter
{
~MemoryBlobImplDataOwnerMemoryReporter() {}
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize) override
{
typedef MemoryBlobImpl::DataOwner DataOwner;
StaticMutexAutoLock lock(DataOwner::sDataOwnerMutex);
if (!DataOwner::sDataOwners) {
return NS_OK;
}
const size_t LARGE_OBJECT_MIN_SIZE = 8 * 1024;
size_t smallObjectsTotal = 0;
for (DataOwner *owner = DataOwner::sDataOwners->getFirst();
owner; owner = owner->getNext()) {
size_t size = MemoryFileDataOwnerMallocSizeOf(owner->mData);
if (size < LARGE_OBJECT_MIN_SIZE) {
smallObjectsTotal += size;
} else {
SHA1Sum sha1;
sha1.update(owner->mData, owner->mLength);
uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long.
sha1.finish(digest);
nsAutoCString digestString;
for (size_t i = 0; i < sizeof(digest); i++) {
digestString.AppendPrintf("%02x", digest[i]);
}
aHandleReport->Callback(
/* process */ NS_LITERAL_CSTRING(""),
nsPrintfCString(
"explicit/dom/memory-file-data/large/file(length=%llu, sha1=%s)",
owner->mLength, aAnonymize ? "<anonymized>" : digestString.get()),
KIND_HEAP, UNITS_BYTES, size,
nsPrintfCString(
"Memory used to back a memory file of length %llu bytes. The file "
"has a sha1 of %s.\n\n"
"Note that the allocator may round up a memory file's length -- "
"that is, an N-byte memory file may take up more than N bytes of "
"memory.",
owner->mLength, digestString.get()),
aData);
}
}
if (smallObjectsTotal > 0) {
aHandleReport->Callback(
/* process */ NS_LITERAL_CSTRING(""),
NS_LITERAL_CSTRING("explicit/dom/memory-file-data/small"),
KIND_HEAP, UNITS_BYTES, smallObjectsTotal,
nsPrintfCString(
"Memory used to back small memory files (i.e. those taking up less "
"than %zu bytes of memory each).\n\n"
"Note that the allocator may round up a memory file's length -- "
"that is, an N-byte memory file may take up more than N bytes of "
"memory.", LARGE_OBJECT_MIN_SIZE),
aData);
}
return NS_OK;
}
};
NS_IMPL_ISUPPORTS(MemoryBlobImplDataOwnerMemoryReporter, nsIMemoryReporter)
/* static */ void
MemoryBlobImpl::DataOwner::EnsureMemoryReporterRegistered()
{
sDataOwnerMutex.AssertCurrentThreadOwns();
if (sMemoryReporterRegistered) {
return;
}
RegisterStrongMemoryReporter(new MemoryBlobImplDataOwnerMemoryReporter());
sMemoryReporterRegistered = true;
}
} // namespace dom
} // namespace mozilla

117
dom/file/MemoryBlobImpl.h Normal file
Просмотреть файл

@ -0,0 +1,117 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_MemoryBlobImpl_h
#define mozilla_dom_MemoryBlobImpl_h
#include "mozilla/dom/BaseBlobImpl.h"
#include "mozilla/LinkedList.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "nsIMemoryReporter.h"
namespace mozilla {
namespace dom {
class MemoryBlobImpl final : public BaseBlobImpl
{
public:
NS_DECL_ISUPPORTS_INHERITED
MemoryBlobImpl(void* aMemoryBuffer, uint64_t aLength, const nsAString& aName,
const nsAString& aContentType, int64_t aLastModifiedDate)
: BaseBlobImpl(aName, aContentType, aLength, aLastModifiedDate)
, mDataOwner(new DataOwner(aMemoryBuffer, aLength))
{
MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
}
MemoryBlobImpl(void* aMemoryBuffer, uint64_t aLength,
const nsAString& aContentType)
: BaseBlobImpl(aContentType, aLength)
, mDataOwner(new DataOwner(aMemoryBuffer, aLength))
{
MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
}
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
virtual bool IsMemoryFile() const override
{
return true;
}
class DataOwner final : public mozilla::LinkedListElement<DataOwner>
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner)
DataOwner(void* aMemoryBuffer, uint64_t aLength)
: mData(aMemoryBuffer)
, mLength(aLength)
{
mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
if (!sDataOwners) {
sDataOwners = new mozilla::LinkedList<DataOwner>();
EnsureMemoryReporterRegistered();
}
sDataOwners->insertBack(this);
}
private:
// Private destructor, to discourage deletion outside of Release():
~DataOwner() {
mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
remove();
if (sDataOwners->isEmpty()) {
// Free the linked list if it's empty.
sDataOwners = nullptr;
}
free(mData);
}
public:
static void EnsureMemoryReporterRegistered();
// sDataOwners and sMemoryReporterRegistered may only be accessed while
// holding sDataOwnerMutex! You also must hold the mutex while touching
// elements of the linked list that DataOwner inherits from.
static mozilla::StaticMutex sDataOwnerMutex;
static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
static bool sMemoryReporterRegistered;
void* mData;
uint64_t mLength;
};
private:
// Create slice
MemoryBlobImpl(const MemoryBlobImpl* aOther, uint64_t aStart,
uint64_t aLength, const nsAString& aContentType)
: BaseBlobImpl(aContentType, aOther->mStart + aStart, aLength)
, mDataOwner(aOther->mDataOwner)
{
MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data");
mImmutable = aOther->mImmutable;
}
~MemoryBlobImpl() {}
// Used when backed by a memory store
RefPtr<DataOwner> mDataOwner;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_MemoryBlobImpl_h

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

@ -280,13 +280,13 @@ MultipartBlobImpl::GetMozFullPathInternal(nsAString& aFilename,
ErrorResult& aRv) const
{
if (!mIsFromNsIFile || mBlobImpls.Length() == 0) {
BlobImplBase::GetMozFullPathInternal(aFilename, aRv);
BaseBlobImpl::GetMozFullPathInternal(aFilename, aRv);
return;
}
BlobImpl* blobImpl = mBlobImpls.ElementAt(0).get();
if (!blobImpl) {
BlobImplBase::GetMozFullPathInternal(aFilename, aRv);
BaseBlobImpl::GetMozFullPathInternal(aFilename, aRv);
return;
}
@ -313,7 +313,7 @@ MultipartBlobImpl::SetMutable(bool aMutable)
}
}
rv = BlobImplBase::SetMutable(aMutable);
rv = BaseBlobImpl::SetMutable(aMutable);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

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

@ -8,20 +8,14 @@
#define mozilla_dom_MultipartBlobImpl_h
#include "mozilla/Attributes.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/Move.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/FileBinding.h"
#include <algorithm>
#include "nsPIDOMWindow.h"
#include "mozilla/dom/BaseBlobImpl.h"
namespace mozilla {
namespace dom {
class MultipartBlobImpl final : public BlobImplBase
class MultipartBlobImpl final : public BaseBlobImpl
{
public:
NS_DECL_ISUPPORTS_INHERITED
@ -41,14 +35,14 @@ public:
// Create as a file to be later initialized
explicit MultipartBlobImpl(const nsAString& aName)
: BlobImplBase(aName, EmptyString(), UINT64_MAX),
: BaseBlobImpl(aName, EmptyString(), UINT64_MAX),
mIsFromNsIFile(false)
{
}
// Create as a blob to be later initialized
MultipartBlobImpl()
: BlobImplBase(EmptyString(), UINT64_MAX),
: BaseBlobImpl(EmptyString(), UINT64_MAX),
mIsFromNsIFile(false)
{
}
@ -103,7 +97,7 @@ protected:
MultipartBlobImpl(nsTArray<RefPtr<BlobImpl>>&& aBlobImpls,
const nsAString& aName,
const nsAString& aContentType)
: BlobImplBase(aName, aContentType, UINT64_MAX),
: BaseBlobImpl(aName, aContentType, UINT64_MAX),
mBlobImpls(Move(aBlobImpls)),
mIsFromNsIFile(false)
{
@ -111,7 +105,7 @@ protected:
MultipartBlobImpl(nsTArray<RefPtr<BlobImpl>>&& aBlobImpls,
const nsAString& aContentType)
: BlobImplBase(aContentType, UINT64_MAX),
: BaseBlobImpl(aContentType, UINT64_MAX),
mBlobImpls(Move(aBlobImpls)),
mIsFromNsIFile(false)
{

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

@ -4,9 +4,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/MutableBlobStorage.h"
#include "MutableBlobStorage.h"
#include "MemoryBlobImpl.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/dom/File.h"
#include "mozilla/Preferences.h"
#include "File.h"
#include "nsAnonymousTemporaryFile.h"
#include "nsNetCID.h"
#include "nsProxyRelease.h"
@ -406,10 +408,10 @@ MutableBlobStorage::GetBlobWhenReady(nsISupports* aParent,
RefPtr<BlobImpl> blobImpl;
if (mData) {
blobImpl = new BlobImplMemory(mData, mDataLen,
blobImpl = new MemoryBlobImpl(mData, mDataLen,
NS_ConvertUTF8toUTF16(aContentType));
mData = nullptr; // The BlobImplMemory takes ownership of the buffer
mData = nullptr; // The MemoryBlobImpl takes ownership of the buffer
mDataLen = 0;
mDataBufferLen = 0;
} else {

139
dom/file/StreamBlobImpl.cpp Normal file
Просмотреть файл

@ -0,0 +1,139 @@
/* -*- 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 "StreamBlobImpl.h"
#include "nsStringStream.h"
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS_INHERITED(StreamBlobImpl, BlobImpl, nsIMemoryReporter)
/* static */ already_AddRefed<StreamBlobImpl>
StreamBlobImpl::Create(nsIInputStream* aInputStream,
const nsAString& aContentType,
uint64_t aLength)
{
RefPtr<StreamBlobImpl> blobImplStream =
new StreamBlobImpl(aInputStream, aContentType, aLength);
blobImplStream->MaybeRegisterMemoryReporter();
return blobImplStream.forget();
}
/* static */ already_AddRefed<StreamBlobImpl>
StreamBlobImpl::Create(nsIInputStream* aInputStream,
const nsAString& aName,
const nsAString& aContentType,
int64_t aLastModifiedDate,
uint64_t aLength)
{
RefPtr<StreamBlobImpl> blobImplStream =
new StreamBlobImpl(aInputStream, aName, aContentType, aLastModifiedDate,
aLength);
blobImplStream->MaybeRegisterMemoryReporter();
return blobImplStream.forget();
}
StreamBlobImpl::StreamBlobImpl(nsIInputStream* aInputStream,
const nsAString& aContentType,
uint64_t aLength)
: BaseBlobImpl(aContentType, aLength)
, mInputStream(aInputStream)
{
mImmutable = true;
}
StreamBlobImpl::StreamBlobImpl(StreamBlobImpl* aOther,
const nsAString& aContentType,
uint64_t aStart, uint64_t aLength)
: BaseBlobImpl(aContentType, aOther->mStart + aStart, aLength)
, mInputStream(new SlicedInputStream(aOther->mInputStream, aStart, aLength))
{
mImmutable = true;
}
StreamBlobImpl::StreamBlobImpl(nsIInputStream* aInputStream,
const nsAString& aName,
const nsAString& aContentType,
int64_t aLastModifiedDate,
uint64_t aLength)
: BaseBlobImpl(aName, aContentType, aLength, aLastModifiedDate)
, mInputStream(aInputStream)
{
mImmutable = true;
}
StreamBlobImpl::~StreamBlobImpl()
{
UnregisterWeakMemoryReporter(this);
}
void
StreamBlobImpl::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
{
nsCOMPtr<nsIInputStream> clonedStream;
nsCOMPtr<nsIInputStream> replacementStream;
aRv = NS_CloneInputStream(mInputStream, getter_AddRefs(clonedStream),
getter_AddRefs(replacementStream));
if (NS_WARN_IF(aRv.Failed())) {
return;
}
if (replacementStream) {
mInputStream = replacementStream.forget();
}
clonedStream.forget(aStream);
}
already_AddRefed<BlobImpl>
StreamBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv)
{
if (!aLength) {
RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
return impl.forget();
}
RefPtr<BlobImpl> impl =
new StreamBlobImpl(this, aContentType, aStart, aLength);
return impl.forget();
}
void
StreamBlobImpl::MaybeRegisterMemoryReporter()
{
// We report only stringInputStream.
nsCOMPtr<nsIStringInputStream> stringInputStream =
do_QueryInterface(mInputStream);
if (!stringInputStream) {
return;
}
RegisterWeakMemoryReporter(this);
}
NS_IMETHODIMP
StreamBlobImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize)
{
nsCOMPtr<nsIStringInputStream> stringInputStream =
do_QueryInterface(mInputStream);
if (!stringInputStream) {
return NS_OK;
}
MOZ_COLLECT_REPORT(
"explicit/dom/memory-file-data/stream", KIND_HEAP, UNITS_BYTES,
stringInputStream->SizeOfIncludingThis(MallocSizeOf),
"Memory used to back a File/Blob based on an input stream.");
return NS_OK;
}
} // namespace dom
} // namespace mozilla

75
dom/file/StreamBlobImpl.h Normal file
Просмотреть файл

@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_StreamBlobImpl_h
#define mozilla_dom_StreamBlobImpl_h
#include "BaseBlobImpl.h"
#include "nsIMemoryReporter.h"
namespace mozilla {
namespace dom {
class StreamBlobImpl final : public BaseBlobImpl
, public nsIMemoryReporter
{
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIMEMORYREPORTER
static already_AddRefed<StreamBlobImpl>
Create(nsIInputStream* aInputStream,
const nsAString& aContentType,
uint64_t aLength);
static already_AddRefed<StreamBlobImpl>
Create(nsIInputStream* aInputStream,
const nsAString& aName,
const nsAString& aContentType,
int64_t aLastModifiedDate,
uint64_t aLength);
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
virtual bool IsMemoryFile() const override
{
return true;
}
private:
StreamBlobImpl(nsIInputStream* aInputStream,
const nsAString& aContentType,
uint64_t aLength);
StreamBlobImpl(nsIInputStream* aInputStream,
const nsAString& aName,
const nsAString& aContentType,
int64_t aLastModifiedDate,
uint64_t aLength);
StreamBlobImpl(StreamBlobImpl* aOther,
const nsAString& aContentType,
uint64_t aStart,
uint64_t aLength);
~StreamBlobImpl();
void MaybeRegisterMemoryReporter();
nsCOMPtr<nsIInputStream> mInputStream;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_StreamBlobImpl_h

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

@ -0,0 +1,64 @@
/* -*- 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 "StreamBlobImpl.h"
#include "nsStringStream.h"
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS_INHERITED(StringBlobImpl, BlobImpl, nsIMemoryReporter)
/* static */ already_AddRefed<StringBlobImpl>
StringBlobImpl::Create(const nsACString& aData, const nsAString& aContentType)
{
RefPtr<StringBlobImpl> blobImpl = new StringBlobImpl(aData, aContentType);
RegisterWeakMemoryReporter(blobImpl);
return blobImpl.forget();
}
StringBlobImpl::StringBlobImpl(const nsACString& aData,
const nsAString& aContentType)
: BaseBlobImpl(aContentType, aData.Length())
, mData(aData)
{
}
StringBlobImpl::~StringBlobImpl()
{
UnregisterWeakMemoryReporter(this);
}
already_AddRefed<BlobImpl>
StringBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType,
ErrorResult& aRv)
{
RefPtr<BlobImpl> impl =
new StringBlobImpl(Substring(mData, aStart, aLength),
aContentType);
return impl.forget();
}
void
StringBlobImpl::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
{
aRv = NS_NewCStringInputStream(aStream, mData);
}
NS_IMETHODIMP
StringBlobImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize)
{
MOZ_COLLECT_REPORT(
"explicit/dom/memory-file-data/string", KIND_HEAP, UNITS_BYTES,
mData.SizeOfExcludingThisIfUnshared(MallocSizeOf),
"Memory used to back a File/Blob based on a string.");
return NS_OK;
}
} // namespace dom
} // namespace mozilla

46
dom/file/StringBlobImpl.h Normal file
Просмотреть файл

@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_StringBlobImpl_h
#define mozilla_dom_StringBlobImpl_h
#include "BaseBlobImpl.h"
#include "nsIMemoryReporter.h"
namespace mozilla {
namespace dom {
class StringBlobImpl final : public BaseBlobImpl
, public nsIMemoryReporter
{
MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIMEMORYREPORTER
static already_AddRefed<StringBlobImpl>
Create(const nsACString& aData, const nsAString& aContentType);
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
private:
StringBlobImpl(const nsACString& aData, const nsAString& aContentType);
~StringBlobImpl();
nsCString mData;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_StringBlobImpl_h

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

@ -0,0 +1,58 @@
/* -*- 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 "TemporaryBlobImpl.h"
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS_INHERITED0(TemporaryBlobImpl, BlobImpl)
TemporaryBlobImpl::TemporaryBlobImpl(PRFileDesc* aFD, uint64_t aStartPos,
uint64_t aLength,
const nsAString& aContentType)
: BaseBlobImpl(aContentType, aLength)
, mStartPos(aStartPos)
{
mFileDescOwner = new nsTemporaryFileInputStream::FileDescOwner(aFD);
}
TemporaryBlobImpl::TemporaryBlobImpl(const TemporaryBlobImpl* aOther,
uint64_t aStart, uint64_t aLength,
const nsAString& aContentType)
: BaseBlobImpl(aContentType, aLength)
, mStartPos(aStart)
, mFileDescOwner(aOther->mFileDescOwner)
{}
already_AddRefed<BlobImpl>
TemporaryBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType,
ErrorResult& aRv)
{
if (aStart + aLength > mLength) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
RefPtr<BlobImpl> impl =
new TemporaryBlobImpl(this, aStart + mStartPos,
aLength, aContentType);
return impl.forget();
}
void
TemporaryBlobImpl::GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv)
{
nsCOMPtr<nsIInputStream> stream =
new nsTemporaryFileInputStream(mFileDescOwner, mStartPos,
mStartPos + mLength);
stream.forget(aStream);
}
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,45 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_TemporaryBlobImpl_h
#define mozilla_dom_TemporaryBlobImpl_h
#include "BaseBlobImpl.h"
#include "nsTemporaryFileInputStream.h"
namespace mozilla {
namespace dom {
class TemporaryBlobImpl final : public BaseBlobImpl
{
public:
NS_DECL_ISUPPORTS_INHERITED
TemporaryBlobImpl(PRFileDesc* aFD, uint64_t aStartPos,
uint64_t aLength, const nsAString& aContentType);
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
private:
TemporaryBlobImpl(const TemporaryBlobImpl* aOther,
uint64_t aStart, uint64_t aLength,
const nsAString& aContentType);
~TemporaryBlobImpl() = default;
uint64_t mStartPos;
RefPtr<nsTemporaryFileInputStream::FileDescOwner> mFileDescOwner;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_TemporaryBlobImpl_h

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

@ -10,6 +10,7 @@
#include "BackgroundParent.h"
#include "ContentChild.h"
#include "ContentParent.h"
#include "EmptyBlobImpl.h"
#include "FileDescriptorSetChild.h"
#include "jsapi.h"
#include "mozilla/Assertions.h"
@ -18,7 +19,7 @@
#include "mozilla/Monitor.h"
#include "mozilla/Mutex.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/BaseBlobImpl.h"
#include "mozilla/dom/nsIContentParent.h"
#include "mozilla/dom/nsIContentChild.h"
#include "mozilla/dom/PBlobStreamChild.h"
@ -46,6 +47,7 @@
#include "nsStringStream.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
#include "StreamBlobImpl.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
@ -658,7 +660,7 @@ CreateBlobImpl(const BlobDataStream& aStream,
if (!aMetadata.mHasRecursed && aMetadata.IsFile()) {
if (length) {
blobImpl =
BlobImplStream::Create(inputStream,
StreamBlobImpl::Create(inputStream,
aMetadata.mName,
aMetadata.mContentType,
aMetadata.mLastModifiedDate,
@ -671,7 +673,7 @@ CreateBlobImpl(const BlobDataStream& aStream,
}
} else if (length) {
blobImpl =
BlobImplStream::Create(inputStream, aMetadata.mContentType,
StreamBlobImpl::Create(inputStream, aMetadata.mContentType,
length);
} else {
blobImpl = new EmptyBlobImpl(aMetadata.mContentType);
@ -1786,7 +1788,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(BlobParent::OpenStreamRunnable, Runnable)
******************************************************************************/
class BlobChild::RemoteBlobImpl
: public BlobImplBase
: public BaseBlobImpl
, public nsIRemoteBlob
{
protected:
@ -2180,7 +2182,7 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
int64_t aModDate,
BlobImplIsDirectory aIsDirectory,
bool aIsSameProcessBlob)
: BlobImplBase(aName, aContentType, aLength, aModDate)
: BaseBlobImpl(aName, aContentType, aLength, aModDate)
, mWorkerPrivate(nullptr)
, mMutex("BlobChild::RemoteBlobImpl::mMutex")
, mIsSlice(false), mIsDirectory(aIsDirectory == eDirectory)
@ -2204,7 +2206,7 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
const nsAString& aContentType,
uint64_t aLength,
bool aIsSameProcessBlob)
: BlobImplBase(aContentType, aLength)
: BaseBlobImpl(aContentType, aLength)
, mWorkerPrivate(nullptr)
, mMutex("BlobChild::RemoteBlobImpl::mMutex")
, mIsSlice(false), mIsDirectory(false)
@ -2222,7 +2224,7 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor,
BlobChild::
RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor)
: BlobImplBase(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
: BaseBlobImpl(EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX)
, mWorkerPrivate(nullptr)
, mMutex("BlobChild::RemoteBlobImpl::mMutex")
, mIsSlice(false), mIsDirectory(false)
@ -2232,7 +2234,7 @@ RemoteBlobImpl::RemoteBlobImpl(BlobChild* aActor)
BlobChild::
RemoteBlobImpl::RemoteBlobImpl(const nsAString& aContentType, uint64_t aLength)
: BlobImplBase(aContentType, aLength)
: BaseBlobImpl(aContentType, aLength)
, mActor(nullptr)
, mWorkerPrivate(nullptr)
, mMutex("BlobChild::RemoteBlobImpl::mMutex")
@ -2478,7 +2480,7 @@ RemoteBlobImpl::SetMutable(bool aMutable)
AsSlice()->EnsureActorWasCreated();
}
nsresult rv = BlobImplBase::SetMutable(aMutable);
nsresult rv = BaseBlobImpl::SetMutable(aMutable);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

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

@ -19,27 +19,41 @@ EXPORTS += [
]
EXPORTS.mozilla.dom += [
'BaseBlobImpl.h',
'Blob.h',
'BlobImpl.h',
'BlobSet.h',
'File.h',
'FileBlobImpl.h',
'FileCreatorHelper.h',
'FileList.h',
'FileReader.h',
'MemoryBlobImpl.h',
'MultipartBlobImpl.h',
'MutableBlobStorage.h',
'MutableBlobStreamListener.h',
]
UNIFIED_SOURCES += [
'BaseBlobImpl.cpp',
'Blob.cpp',
'BlobImpl.cpp',
'BlobSet.cpp',
'EmptyBlobImpl.cpp',
'File.cpp',
'FileBlobImpl.cpp',
'FileCreatorHelper.cpp',
'FileList.cpp',
'FileReader.cpp',
'MemoryBlobImpl.cpp',
'MultipartBlobImpl.cpp',
'MutableBlobStorage.cpp',
'MutableBlobStreamListener.cpp',
'nsHostObjectProtocolHandler.cpp',
'nsHostObjectURI.cpp',
'StreamBlobImpl.cpp',
'StringBlobImpl.cpp',
'TemporaryBlobImpl.cpp',
]
LOCAL_INCLUDES += [

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

@ -10,7 +10,7 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/Exceptions.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/BlobImpl.h"
#include "mozilla/dom/ipc/BlobChild.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/dom/MediaSource.h"

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

@ -9,7 +9,7 @@
#include <algorithm>
#include "mozilla/Preferences.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "mozilla/dom/FileSystemBase.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/PFileSystemParams.h"
@ -20,6 +20,7 @@
#include "mozilla/ipc/PBackgroundChild.h"
#include "nsIFile.h"
#include "nsNetUtil.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsStringGlue.h"
@ -232,7 +233,7 @@ CreateFileTaskParent::GetSuccessRequestResult(ErrorResult& aRv) const
{
AssertIsOnBackgroundThread();
RefPtr<BlobImpl> blobImpl = new BlobImplFile(mTargetPath);
RefPtr<BlobImpl> blobImpl = new FileBlobImpl(mTargetPath);
BlobParent* blobParent =
BlobParent::GetOrCreate(mRequestParent->Manager(), blobImpl);
return FileSystemFileResponse(blobParent, nullptr);

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

@ -8,7 +8,7 @@
#include "HTMLSplitOnSpacesTokenizer.h"
#include "js/Value.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "mozilla/dom/FileSystemBase.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/PFileSystemParams.h"
@ -239,7 +239,7 @@ GetDirectoryListingTaskParent::GetSuccessRequestResult(ErrorResult& aRv) const
}
FileSystemDirectoryListingResponseFile fileData;
RefPtr<BlobImpl> blobImpl = new BlobImplFile(path);
RefPtr<BlobImpl> blobImpl = new FileBlobImpl(path);
nsAutoString filePath;
filePath.Assign(mDOMPath);

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

@ -7,7 +7,7 @@
#include "GetFileOrDirectoryTask.h"
#include "js/Value.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "mozilla/dom/FileSystemBase.h"
#include "mozilla/dom/FileSystemUtils.h"
#include "mozilla/dom/PFileSystemParams.h"
@ -214,7 +214,7 @@ GetFileOrDirectoryTaskParent::GetSuccessRequestResult(ErrorResult& aRv) const
return FileSystemDirectoryResponse(path);
}
RefPtr<BlobImpl> blobImpl = new BlobImplFile(mTargetPath);
RefPtr<BlobImpl> blobImpl = new FileBlobImpl(mTargetPath);
BlobParent* blobParent =
BlobParent::GetOrCreate(mRequestParent->Manager(), blobImpl);
return FileSystemFileResponse(blobParent, nullptr);

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

@ -7,6 +7,7 @@
#include "GetFilesHelper.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "nsProxyRelease.h"
namespace mozilla {
@ -383,7 +384,7 @@ GetFilesHelperBase::ExploreDirectory(const nsAString& aDOMPath, nsIFile* aFile)
domPath.Append(leafName);
if (isFile) {
RefPtr<BlobImpl> blobImpl = new BlobImplFile(currFile);
RefPtr<BlobImpl> blobImpl = new FileBlobImpl(currFile);
blobImpl->SetDOMPath(domPath);
if (!mTargetBlobImplArray.AppendElement(blobImpl, fallible)) {

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

@ -372,6 +372,17 @@ nsGenericHTMLFrameElement::MapScrollingAttribute(const nsAttrValue* aValue)
return mappedValue;
}
static bool
PrincipalAllowsBrowserFrame(nsIPrincipal* aPrincipal)
{
nsCOMPtr<nsIPermissionManager> permMgr = mozilla::services::GetPermissionManager();
NS_ENSURE_TRUE(permMgr, false);
uint32_t permission = nsIPermissionManager::DENY_ACTION;
nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, "browser", &permission);
NS_ENSURE_SUCCESS(rv, false);
return permission == nsIPermissionManager::ALLOW_ACTION;
}
/* virtual */ nsresult
nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
@ -401,6 +412,11 @@ nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}
}
if (aName == nsGkAtoms::mozbrowser && aNameSpaceID == kNameSpaceID_None) {
mReallyIsBrowser = !!aValue && BrowserFramesEnabled() &&
PrincipalAllowsBrowserFrame(NodePrincipal());
}
return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
aNotify);
}
@ -486,28 +502,7 @@ nsGenericHTMLFrameElement::BrowserFramesEnabled()
/* [infallible] */ nsresult
nsGenericHTMLFrameElement::GetReallyIsBrowser(bool *aOut)
{
*aOut = false;
// Fail if browser frames are globally disabled.
if (!nsGenericHTMLFrameElement::BrowserFramesEnabled()) {
return NS_OK;
}
// Fail if this frame doesn't have the mozbrowser attribute.
if (!GetBoolAttr(nsGkAtoms::mozbrowser)) {
return NS_OK;
}
// Fail if the node principal isn't trusted.
nsIPrincipal *principal = NodePrincipal();
nsCOMPtr<nsIPermissionManager> permMgr =
services::GetPermissionManager();
NS_ENSURE_TRUE(permMgr, NS_OK);
uint32_t permission = nsIPermissionManager::DENY_ACTION;
nsresult rv = permMgr->TestPermissionFromPrincipal(principal, "browser", &permission);
NS_ENSURE_SUCCESS(rv, NS_OK);
*aOut = permission == nsIPermissionManager::ALLOW_ACTION;
*aOut = mReallyIsBrowser;
return NS_OK;
}

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

@ -36,6 +36,7 @@ public:
, mIsPrerendered(false)
, mBrowserFrameListenersRegistered(false)
, mFrameLoaderCreationDisallowed(false)
, mReallyIsBrowser(false)
{
}
@ -125,6 +126,7 @@ protected:
bool mIsPrerendered;
bool mBrowserFrameListenersRegistered;
bool mFrameLoaderCreationDisallowed;
bool mReallyIsBrowser;
// This flag is only used by <iframe>. See HTMLIFrameElement::
// FullscreenFlag() for details. It is placed here so that we

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

@ -34,6 +34,7 @@
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/dom/filehandle/ActorsParent.h"
@ -9086,14 +9087,14 @@ private:
};
class BlobImplStoredFile final
: public BlobImplFile
: public FileBlobImpl
{
RefPtr<FileInfo> mFileInfo;
const bool mSnapshot;
public:
BlobImplStoredFile(nsIFile* aFile, FileInfo* aFileInfo, bool aSnapshot)
: BlobImplFile(aFile)
: FileBlobImpl(aFile)
, mFileInfo(aFileInfo)
, mSnapshot(aSnapshot)
{
@ -17633,7 +17634,7 @@ FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage)
******************************************************************************/
NS_IMPL_ISUPPORTS_INHERITED(BlobImplStoredFile,
BlobImplFile,
FileBlobImpl,
BlobImplStoredFile)
/*******************************************************************************

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

@ -34,6 +34,7 @@
#include "mozilla/dom/IDBMutableFileBinding.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/IDBObjectStoreBinding.h"
#include "mozilla/dom/MemoryBlobImpl.h"
#include "mozilla/dom/StructuredCloneHolder.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
@ -363,11 +364,11 @@ StructuredCloneWriteCallback(JSContext* aCx,
compiledSize);
RefPtr<BlobImpl> blobImpl =
new BlobImplMemory(bytecode.release(), bytecodeSize, EmptyString());
new MemoryBlobImpl(bytecode.release(), bytecodeSize, EmptyString());
RefPtr<Blob> bytecodeBlob = Blob::Create(nullptr, blobImpl);
blobImpl =
new BlobImplMemory(compiled.release(), compiledSize, EmptyString());
new MemoryBlobImpl(compiled.release(), compiledSize, EmptyString());
RefPtr<Blob> compiledBlob = Blob::Create(nullptr, blobImpl);
if (cloneWriteInfo->mFiles.Length() + 1 > size_t(UINT32_MAX)) {

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

@ -10,7 +10,6 @@
#include "ContentChild.h"
#include "CrashReporterChild.h"
#include "GeckoProfiler.h"
#include "TabChild.h"
#include "HandlerServiceChild.h"
@ -33,7 +32,6 @@
#include "mozilla/dom/FlyWebPublishedServerIPC.h"
#include "mozilla/dom/GetFilesHelper.h"
#include "mozilla/dom/MemoryReportRequest.h"
#include "mozilla/dom/PCrashReporterChild.h"
#include "mozilla/dom/ProcessGlobal.h"
#include "mozilla/dom/PushNotifier.h"
#include "mozilla/dom/StorageIPC.h"
@ -205,6 +203,9 @@
#ifdef MOZ_WIDGET_GTK
#include "nsAppRunner.h"
#endif
#ifdef MOZ_CRASHREPORTER
#include "mozilla/ipc/CrashReporterClient.h"
#endif
using namespace mozilla;
@ -587,8 +588,7 @@ ContentChild::Init(MessageLoop* aIOLoop,
#endif
#ifdef MOZ_CRASHREPORTER
SendPCrashReporterConstructor(CrashReporter::CurrentThreadId(),
XRE_GetProcessType());
CrashReporterClient::InitSingleton(this);
#endif
mID = aChildID;
@ -1625,24 +1625,6 @@ ContentChild::RecvNotifyEmptyHTTPCache()
return IPC_OK();
}
PCrashReporterChild*
ContentChild::AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id,
const uint32_t& processType)
{
#ifdef MOZ_CRASHREPORTER
return new CrashReporterChild();
#else
return nullptr;
#endif
}
bool
ContentChild::DeallocPCrashReporterChild(PCrashReporterChild* crashreporter)
{
delete crashreporter;
return true;
}
PHalChild*
ContentChild::AllocPHalChild()
{
@ -2037,6 +2019,9 @@ ContentChild::ActorDestroy(ActorDestroyReason why)
}
mIsAlive = false;
# ifdef MOZ_CRASHREPORTER
CrashReporterClient::DestroySingleton();
# endif
XRE_ShutdownChildProcess();
#endif // NS_FREE_PERMANENT_DATA
}
@ -2062,14 +2047,8 @@ ContentChild::ProcessingError(Result aCode, const char* aReason)
}
#if defined(MOZ_CRASHREPORTER) && !defined(MOZ_B2G)
if (PCrashReporterChild* c = LoneManagedOrNullAsserts(ManagedPCrashReporterChild())) {
CrashReporterChild* crashReporter =
static_cast<CrashReporterChild*>(c);
nsDependentCString reason(aReason);
crashReporter->SendAnnotateCrashReport(
NS_LITERAL_CSTRING("ipc_channel_error"),
reason);
}
nsDependentCString reason(aReason);
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ipc_channel_error"), reason);
#endif
MOZ_CRASH("Content child abort due to IPC error");
}

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

@ -188,13 +188,6 @@ public:
virtual bool DeallocPBlobChild(PBlobChild* aActor) override;
virtual PCrashReporterChild*
AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id,
const uint32_t& processType) override;
virtual bool
DeallocPCrashReporterChild(PCrashReporterChild*) override;
virtual PHalChild* AllocPHalChild() override;
virtual bool DeallocPHalChild(PHalChild*) override;

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

@ -25,7 +25,6 @@
#include "mozilla/a11y/PDocAccessible.h"
#include "AudioChannelService.h"
#include "CrashReporterParent.h"
#include "DeviceStorageStatics.h"
#include "GMPServiceParent.h"
#include "HandlerServiceParent.h"
@ -95,6 +94,7 @@
#include "mozilla/Services.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TelemetryIPC.h"
#include "mozilla/WebBrowserPersistDocumentParent.h"
#include "mozilla/Unused.h"
#include "nsAnonymousTemporaryFile.h"
@ -247,6 +247,7 @@
#ifdef MOZ_CRASHREPORTER
#include "nsThread.h"
#include "mozilla/ipc/CrashReporterHost.h"
#endif
#ifdef ACCESSIBILITY
@ -1592,17 +1593,17 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
// There's a window in which child processes can crash
// after IPC is established, but before a crash reporter
// is created.
if (PCrashReporterParent* p = LoneManagedOrNullAsserts(ManagedPCrashReporterParent())) {
CrashReporterParent* crashReporter =
static_cast<CrashReporterParent*>(p);
if (mCrashReporter) {
// if mCreatedPairedMinidumps is true, we've already generated
// parent/child dumps for dekstop crashes.
// parent/child dumps for desktop crashes.
if (!mCreatedPairedMinidumps) {
crashReporter->GenerateCrashReport(this, nullptr);
mCrashReporter->GenerateCrashReport(OtherPid());
}
nsAutoString dumpID(crashReporter->ChildDumpID());
nsAutoString dumpID;
if (mCrashReporter->HasMinidump()) {
dumpID = mCrashReporter->MinidumpID();
}
props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
}
#endif
@ -2816,25 +2817,28 @@ ContentParent::KillHard(const char* aReason)
// We're about to kill the child process associated with this content.
// Something has gone wrong to get us here, so we generate a minidump
// of the parent and child for submission to the crash server.
if (PCrashReporterParent* p = LoneManagedOrNullAsserts(ManagedPCrashReporterParent())) {
CrashReporterParent* crashReporter =
static_cast<CrashReporterParent*>(p);
if (mCrashReporter) {
// GeneratePairedMinidump creates two minidumps for us - the main
// one is for the content process we're about to kill, and the other
// one is for the main browser process. That second one is the extra
// minidump tagging along, so we have to tell the crash reporter that
// it exists and is being appended.
nsAutoCString additionalDumps("browser");
crashReporter->AnnotateCrashReport(
mCrashReporter->AddNote(
NS_LITERAL_CSTRING("additional_minidumps"),
additionalDumps);
nsDependentCString reason(aReason);
crashReporter->AnnotateCrashReport(
mCrashReporter->AddNote(
NS_LITERAL_CSTRING("ipc_channel_error"),
reason);
// Generate the report and insert into the queue for submittal.
mCreatedPairedMinidumps = crashReporter->GenerateCompleteMinidump(this);
if (mCrashReporter->GenerateMinidumpAndPair(this,
nullptr,
NS_LITERAL_CSTRING("browser")))
{
mCreatedPairedMinidumps = mCrashReporter->FinalizeCrashReport();
}
Telemetry::Accumulate(Telemetry::SUBPROCESS_KILL_HARD, reason, 1);
}
@ -2873,33 +2877,18 @@ ContentParent::FriendlyName(nsAString& aName, bool aAnonymize)
}
}
PCrashReporterParent*
ContentParent::AllocPCrashReporterParent(const NativeThreadId& tid,
const uint32_t& processType)
mozilla::ipc::IPCResult
ContentParent::RecvInitCrashReporter(Shmem&& aShmem, const NativeThreadId& aThreadId)
{
#ifdef MOZ_CRASHREPORTER
return new CrashReporterParent();
#else
return nullptr;
mCrashReporter = MakeUnique<CrashReporterHost>(
GeckoProcessType_Content,
aShmem,
aThreadId);
#endif
}
mozilla::ipc::IPCResult
ContentParent::RecvPCrashReporterConstructor(PCrashReporterParent* actor,
const NativeThreadId& tid,
const uint32_t& processType)
{
static_cast<CrashReporterParent*>(actor)->SetChildData(tid, processType);
return IPC_OK();
}
bool
ContentParent::DeallocPCrashReporterParent(PCrashReporterParent* crashreporter)
{
delete crashreporter;
return true;
}
hal_sandbox::PHalParent*
ContentParent::AllocPHalParent()
{
@ -4888,18 +4877,18 @@ ContentParent::ForceTabPaint(TabParent* aTabParent, uint64_t aLayerObserverEpoch
}
mozilla::ipc::IPCResult
ContentParent::RecvAccumulateChildHistogram(
ContentParent::RecvAccumulateChildHistograms(
InfallibleTArray<Accumulation>&& aAccumulations)
{
Telemetry::AccumulateChild(GeckoProcessType_Content, aAccumulations);
TelemetryIPC::AccumulateChildHistograms(GeckoProcessType_Content, aAccumulations);
return IPC_OK();
}
mozilla::ipc::IPCResult
ContentParent::RecvAccumulateChildKeyedHistogram(
ContentParent::RecvAccumulateChildKeyedHistograms(
InfallibleTArray<KeyedAccumulation>&& aAccumulations)
{
Telemetry::AccumulateChildKeyed(GeckoProcessType_Content, aAccumulations);
TelemetryIPC::AccumulateChildKeyedHistograms(GeckoProcessType_Content, aAccumulations);
return IPC_OK();
}
@ -4907,7 +4896,7 @@ mozilla::ipc::IPCResult
ContentParent::RecvUpdateChildScalars(
InfallibleTArray<ScalarAction>&& aScalarActions)
{
Telemetry::UpdateChildScalars(GeckoProcessType_Content, aScalarActions);
TelemetryIPC::UpdateChildScalars(GeckoProcessType_Content, aScalarActions);
return IPC_OK();
}
@ -4915,7 +4904,7 @@ mozilla::ipc::IPCResult
ContentParent::RecvUpdateChildKeyedScalars(
InfallibleTArray<KeyedScalarAction>&& aScalarActions)
{
Telemetry::UpdateChildKeyedScalars(GeckoProcessType_Content, aScalarActions);
TelemetryIPC::UpdateChildKeyedScalars(GeckoProcessType_Content, aScalarActions);
return IPC_OK();
}

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

@ -74,6 +74,7 @@ class OptionalURIParams;
class PFileDescriptorSetParent;
class URIParams;
class TestShellParent;
class CrashReporterHost;
} // namespace ipc
namespace jsipc {
@ -402,14 +403,8 @@ public:
virtual void OnChannelError() override;
virtual PCrashReporterParent*
AllocPCrashReporterParent(const NativeThreadId& tid,
const uint32_t& processType) override;
virtual mozilla::ipc::IPCResult
RecvPCrashReporterConstructor(PCrashReporterParent* actor,
const NativeThreadId& tid,
const uint32_t& processType) override;
RecvInitCrashReporter(Shmem&& aShmem, const NativeThreadId& aThreadId) override;
virtual PNeckoParent* AllocPNeckoParent() override;
@ -796,9 +791,6 @@ private:
RecvPBlobConstructor(PBlobParent* aActor,
const BlobConstructorParams& params) override;
virtual bool
DeallocPCrashReporterParent(PCrashReporterParent* crashreporter) override;
virtual mozilla::ipc::IPCResult RecvNSSU2FTokenIsCompatibleVersion(const nsString& aVersion,
bool* aIsCompatible) override;
@ -1113,9 +1105,9 @@ private:
const int64_t& aLastModified,
const bool& aIsFromNsIFile) override;
virtual mozilla::ipc::IPCResult RecvAccumulateChildHistogram(
virtual mozilla::ipc::IPCResult RecvAccumulateChildHistograms(
InfallibleTArray<Accumulation>&& aAccumulations) override;
virtual mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistogram(
virtual mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistograms(
InfallibleTArray<KeyedAccumulation>&& aAccumulations) override;
virtual mozilla::ipc::IPCResult RecvUpdateChildScalars(
InfallibleTArray<ScalarAction>&& aScalarActions) override;
@ -1175,8 +1167,6 @@ private:
bool mShutdownPending;
bool mIPCOpen;
friend class CrashReporterParent;
RefPtr<nsConsoleService> mConsoleService;
nsConsoleService* GetConsoleService();
@ -1213,6 +1203,9 @@ private:
nsRefPtrHashtable<nsIDHashKey, GetFilesHelper> mGetFilesPendingRequests;
nsTArray<nsCString> mBlobURLs;
#ifdef MOZ_CRASHREPORTER
UniquePtr<mozilla::ipc::CrashReporterHost> mCrashReporter;
#endif
};
} // namespace dom

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

@ -17,20 +17,7 @@ namespace dom {
PCrashReporterChild*
CrashReporterChild::GetCrashReporter()
{
const ManagedContainer<PCrashReporterChild>* reporters = nullptr;
switch (XRE_GetProcessType()) {
case GeckoProcessType_Content: {
ContentChild* child = ContentChild::GetSingleton();
reporters = &child->ManagedPCrashReporterChild();
break;
}
default:
break;
}
if (!reporters) {
return nullptr;
}
return LoneManagedOrNullAsserts(*reporters);
return nullptr;
}
} // namespace dom

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

@ -12,7 +12,7 @@
#include "nsIFile.h"
#include "nsISimpleEnumerator.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileBlobImpl.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/TabParent.h"
@ -105,7 +105,7 @@ FilePickerParent::IORunnable::Run()
continue;
}
RefPtr<BlobImpl> blobImpl = new BlobImplFile(mFiles[i]);
RefPtr<BlobImpl> blobImpl = new FileBlobImpl(mFiles[i]);
ErrorResult error;
blobImpl->GetSize(error);

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

@ -11,7 +11,6 @@ include protocol PCompositorBridge;
include protocol PContentBridge;
include protocol PContentPermissionRequest;
include protocol PCycleCollectWithLogs;
include protocol PCrashReporter;
include protocol PPSMContentDownloader;
include protocol PExternalHelperApp;
include protocol PHandlerService;
@ -383,7 +382,6 @@ nested(upto inside_cpow) sync protocol PContent
manages PBlob;
manages PBrowser;
manages PContentPermissionRequest;
manages PCrashReporter;
manages PCycleCollectWithLogs;
manages PDeviceStorageRequest;
manages PPSMContentDownloader;
@ -746,7 +744,7 @@ parent:
async PRemoteSpellcheckEngine();
async PDeviceStorageRequest(DeviceStorageParams params);
sync PCrashReporter(NativeThreadId tid, uint32_t processType);
async InitCrashReporter(Shmem shmem, NativeThreadId tid);
/**
* Is this token compatible with the provided version?
@ -1181,8 +1179,8 @@ parent:
/**
* Messages for communicating child Telemetry to the parent process
*/
async AccumulateChildHistogram(Accumulation[] accumulations);
async AccumulateChildKeyedHistogram(KeyedAccumulation[] accumulations);
async AccumulateChildHistograms(Accumulation[] accumulations);
async AccumulateChildKeyedHistograms(KeyedAccumulation[] accumulations);
async UpdateChildScalars(ScalarAction[] updates);
async UpdateChildKeyedScalars(KeyedScalarAction[] updates);

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

@ -20,7 +20,6 @@ struct Mapping {
};
async protocol PCrashReporter {
manager PContent;
parent:
async AnnotateCrashReport(nsCString key, nsCString data);
async AppendAppNotes(nsCString data);

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

@ -6,37 +6,202 @@
* and to access the manifest data (including icons).
*
* TODO:
* - Persist installed manifest data to disk and keep track of which
* origins have installed applications
* - Trigger appropriate app installed events
*/
"use strict";
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cc = Components.classes;
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const { ManifestObtainer } =
Cu.import('resource://gre/modules/ManifestObtainer.jsm', {});
Cu.import("resource://gre/modules/ManifestObtainer.jsm", {});
const { ManifestIcons } =
Cu.import('resource://gre/modules/ManifestIcons.jsm', {});
Cu.import("resource://gre/modules/ManifestIcons.jsm", {});
function Manifest(browser) {
this.browser = browser;
this.data = null;
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "JSONFile",
"resource://gre/modules/JSONFile.jsm");
/**
* Generates an hash for the given string.
*
* @note The generated hash is returned in base64 form. Mind the fact base64
* is case-sensitive if you are going to reuse this code.
*/
function generateHash(aString) {
const cryptoHash = Cc["@mozilla.org/security/hash;1"]
.createInstance(Ci.nsICryptoHash);
cryptoHash.init(Ci.nsICryptoHash.MD5);
const stringStream = Cc["@mozilla.org/io/string-input-stream;1"]
.createInstance(Ci.nsIStringInputStream);
stringStream.data = aString;
cryptoHash.updateFromStream(stringStream, -1);
// base64 allows the '/' char, but we can't use it for filenames.
return cryptoHash.finish(true).replace(/\//g, "-");
}
Manifest.prototype.install = Task.async(function* () {
this.data = yield ManifestObtainer.browserObtainManifest(this.browser);
});
Manifest.prototype.icon = Task.async(function* (expectedSize) {
return yield ManifestIcons.browserFetchIcon(this.browser, this.data, expectedSize);
});
Manifest.prototype.name = function () {
return this.data.short_name || this.data.short_url;
/**
* Trims the query paramters from a url
*/
function stripQuery(url) {
return url.split("?")[0];
}
this.EXPORTED_SYMBOLS = ["Manifest"]; // jshint ignore:line
// Folder in which we store the manifest files
const MANIFESTS_DIR = OS.Path.join(OS.Constants.Path.profileDir, "manifests");
// We maintain a list of scopes for installed webmanifests so we can determine
// whether a given url is within the scope of a previously installed manifest
const MANIFESTS_FILE = "manifest-scopes.json";
/**
* Manifest object
*/
class Manifest {
constructor(browser, manifestUrl) {
this._manifestUrl = manifestUrl;
// The key for this is the manifests URL that is required to be unique.
// However arbitrary urls are not safe file paths so lets hash it.
const fileName = generateHash(manifestUrl) + ".json";
this._path = OS.Path.join(MANIFESTS_DIR, fileName);
this._browser = browser;
}
async initialise() {
this._store = new JSONFile({path: this._path});
await this._store.load();
}
async install() {
const manifestData = await ManifestObtainer.browserObtainManifest(this._browser);
this._store.data = {
installed: true,
manifest: manifestData
};
Manifests.manifestInstalled(this);
this._store.saveSoon();
}
async icon(expectedSize) {
return await ManifestIcons
.browserFetchIcon(this._browser, this._store.data.manifest, expectedSize);
}
get scope() {
const scope = this._store.data.manifest.scope ||
this._store.data.manifest.start_url;
return stripQuery(scope);
}
get name() {
return this._store.data.manifest.short_name ||
this._store.data.manifest.short_url;
}
get url() {
return this._manifestUrl;
}
get installed() {
return this._store.data && this._store.data.installed || false;
}
get start_url() {
return this._store.data.manifest.start_url;
}
}
/*
* Manifests maintains the list of installed manifests
*/
var Manifests = {
async initialise () {
if (this.started) {
return this.started;
}
this.started = (async function() {
// Make sure the manifests have the folder needed to save into
await OS.File.makeDir(MANIFESTS_DIR, {ignoreExisting: true});
// Ensure any existing scope data we have about manifests is loaded
this._path = OS.Path.join(OS.Constants.Path.profileDir, MANIFESTS_FILE);
this._store = new JSONFile({path: this._path});
await this._store.load();
// If we dont have any existing data, initialise empty
if (!this._store.data.hasOwnProperty("scopes")) {
this._store.data.scopes = new Map();
}
// Cache the Manifest objects creates as they are references to files
// and we do not want multiple file handles
this.manifestObjs = {};
}).bind(this)();
return this.started;
},
// When a manifest is installed, we save its scope so we can determine if
// fiture visits fall within this manifests scope
manifestInstalled(manifest) {
this._store.data.scopes[manifest.scope] = manifest.url;
this._store.saveSoon();
},
// Given a url, find if it is within an installed manifests scope and if so
// return that manifests url
findManifestUrl(url) {
for (let scope in this._store.data.scopes) {
if (url.startsWith(scope)) {
return this._store.data.scopes[scope];
}
}
return null;
},
// Get the manifest given a url, or if not look for a manifest that is
// tied to the current page
async getManifest(browser, manifestUrl) {
// Ensure we have all started up
await this.initialise();
// If the client does not already know its manifestUrl, we take the
// url of the client and see if it matches the scope of any installed
// manifests
if (!manifestUrl) {
const url = stripQuery(browser.currentURI.spec);
manifestUrl = this.findManifestUrl(url);
}
// No matches so no manifest
if (manifestUrl === null) {
return null;
}
// If we have already created this manifest return cached
if (manifestUrl in this.manifestObjs) {
return this.manifestObjs[manifestUrl];
}
// Otherwise create a new manifest object
this.manifestObjs[manifestUrl] = new Manifest(browser, manifestUrl);
await this.manifestObjs[manifestUrl].initialise();
return this.manifestObjs[manifestUrl];
}
};
this.EXPORTED_SYMBOLS = ["Manifests"]; // jshint ignore:line

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

@ -6,6 +6,7 @@ support-files =
resource.sjs
red-50.png
blue-150.png
[browser_Manifest_install.js]
[browser_ManifestFinder_browserHasManifestLink.js]
[browser_ManifestIcons_browserFetchIcon.js]
[browser_ManifestObtainer_obtain.js]

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

@ -0,0 +1,49 @@
//Used by JSHint:
/*global Cu, BrowserTestUtils, ok, add_task, gBrowser */
"use strict";
const { Manifests } = Cu.import("resource://gre/modules/Manifest.jsm", {});
const defaultURL = new URL("http://example.org/browser/dom/manifest/test/resource.sjs");
defaultURL.searchParams.set("Content-Type", "application/manifest+json");
const manifest = JSON.stringify({short_name: "hello World", scope: "/browser/"});
const manifestUrl = `${defaultURL}&body=${manifest}`;
function makeTestURL(manifest) {
const url = new URL(defaultURL);
const body = `<link rel="manifest" href='${manifestUrl}'>`;
url.searchParams.set("Content-Type", "text/html; charset=utf-8");
url.searchParams.set("body", encodeURIComponent(body));
return url.href;
}
add_task(function*() {
const tabOptions = {gBrowser, url: makeTestURL(manifest)};
yield BrowserTestUtils.withNewTab(tabOptions, function*(browser) {
let manifest = yield Manifests.getManifest(browser, manifestUrl);
is(manifest.installed, false, "We havent installed this manifest yet");
yield manifest.install(browser);
is(manifest.name, "hello World", "Manifest has correct name");
is(manifest.installed, true, "Manifest is installed");
is(manifest.url, manifestUrl, "has correct url");
manifest = yield Manifests.getManifest(browser, manifestUrl);
is(manifest.installed, true, "New instances are installed");
manifest = yield Manifests.getManifest(browser);
is(manifest.installed, true, "Will find manifest without being given url");
let foundManifest = Manifests.findManifestUrl("http://example.org/browser/dom/");
is(foundManifest, manifestUrl, "Finds manifests within scope");
foundManifest = Manifests.findManifestUrl("http://example.org/");
is(foundManifest, null, "Does not find manifests outside scope");
});
});

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

@ -73,8 +73,9 @@ transferSimulcastProperties: function(offer_sdp, answer_sdp) {
o_rids.forEach((o_rid) => {
new_answer_sdp = new_answer_sdp + o_rid.replace(/send/, "recv") + "\r\n";
});
ok(offer_sdp.includes("a=extmap:1/sendonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id"), "Offer contains RID RTP header extension");
new_answer_sdp = new_answer_sdp + "a=extmap:1/recvonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\n";
var extmap_id = offer_sdp.match("a=extmap:([0-9+])/sendonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id");
ok(extmap_id != null, "Offer contains RID RTP header extension");
new_answer_sdp = new_answer_sdp + "a=extmap:" + extmap_id[1] + "/recvonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\r\n";
return new_answer_sdp;
},

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

@ -26,7 +26,10 @@
runNetworkTest(() =>
pushPrefs(['media.peerconnection.simulcast', true],
['media.peerconnection.video.min_bitrate_estimate', 100*1000]).then(() => {
// 180Kbps was determined empirically, set well-higher than
// the 80Kbps+overhead needed for the two simulcast streams.
// 100Kbps was apparently too low.
['media.peerconnection.video.min_bitrate_estimate', 180*1000]).then(() => {
SimpleTest.requestCompleteLog();
var helper;

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

@ -12,10 +12,12 @@
#endif
#include "mozilla/ArrayUtils.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/BlobSet.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/DOMString.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileBinding.h"
#include "mozilla/dom/FileCreatorHelper.h"
#include "mozilla/dom/FetchUtil.h"
#include "mozilla/dom/FormData.h"

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

@ -31461,7 +31461,7 @@ inventiveness/M
inventor/MS
inventory/DSMG
inverse/SMY
invert/SMDG
invert/SMDGR
invest/ASDGL
investigate/GNVDSX
investigation/M

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

@ -32,8 +32,6 @@
#include <string>
#endif
#include "gfxPrefs.h"
struct _cairo_surface;
typedef _cairo_surface cairo_surface_t;
@ -720,13 +718,7 @@ public:
typedef void (*FontDescriptorOutput)(const uint8_t* aData, uint32_t aLength, Float aFontSize, void* aBaton);
virtual FontType GetType() const = 0;
virtual AntialiasMode GetDefaultAAMode() {
if (gfxPrefs::DisableAllTextAA()) {
return AntialiasMode::NONE;
}
return AntialiasMode::DEFAULT;
}
virtual AntialiasMode GetDefaultAAMode();
/** This allows getting a path that describes the outline of a set of glyphs.
* A target is passed in so that the guarantee is made the returned path

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

@ -5,6 +5,8 @@
#include "ScaledFontBase.h"
#include "gfxPrefs.h"
#ifdef USE_SKIA
#include "PathSkia.h"
#include "skia/include/core/SkPaint.h"
@ -24,6 +26,16 @@ using namespace std;
namespace mozilla {
namespace gfx {
AntialiasMode
ScaledFont::GetDefaultAAMode()
{
if (gfxPrefs::DisableAllTextAA()) {
return AntialiasMode::NONE;
}
return AntialiasMode::DEFAULT;
}
ScaledFontBase::~ScaledFontBase()
{
#ifdef USE_SKIA
@ -253,7 +265,7 @@ ScaledFontBase::SetCairoScaledFont(cairo_scaled_font_t* font)
if (font == mScaledFont)
return;
if (mScaledFont)
cairo_scaled_font_destroy(mScaledFont);

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

@ -73,9 +73,6 @@ LOCAL_INCLUDES += [
if CONFIG['MOZ_USE_PTHREADS']:
DEFINES['HAVE_PTHREAD_SETSPECIFIC'] = True
if CONFIG['_MSC_VER']:
DEFINES['PIXMAN_USE_XP_DLL_TLS_WORKAROUND'] = True
DEFINES['PACKAGE'] = 'mozpixman'
DEFINES['_USE_MATH_DEFINES'] = True

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

@ -10,6 +10,7 @@
#include "GPUProcessHost.h"
#include "GPUProcessManager.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TelemetryIPC.h"
#include "mozilla/dom/CheckerboardReportService.h"
#include "mozilla/dom/MemoryReportRequest.h"
#include "mozilla/gfx/gfxVars.h"
@ -144,30 +145,30 @@ GPUChild::RecvNotifyUiObservers(const nsCString& aTopic)
}
mozilla::ipc::IPCResult
GPUChild::RecvAccumulateChildHistogram(InfallibleTArray<Accumulation>&& aAccumulations)
GPUChild::RecvAccumulateChildHistograms(InfallibleTArray<Accumulation>&& aAccumulations)
{
Telemetry::AccumulateChild(GeckoProcessType_GPU, aAccumulations);
TelemetryIPC::AccumulateChildHistograms(GeckoProcessType_GPU, aAccumulations);
return IPC_OK();
}
mozilla::ipc::IPCResult
GPUChild::RecvAccumulateChildKeyedHistogram(InfallibleTArray<KeyedAccumulation>&& aAccumulations)
GPUChild::RecvAccumulateChildKeyedHistograms(InfallibleTArray<KeyedAccumulation>&& aAccumulations)
{
Telemetry::AccumulateChildKeyed(GeckoProcessType_GPU, aAccumulations);
TelemetryIPC::AccumulateChildKeyedHistograms(GeckoProcessType_GPU, aAccumulations);
return IPC_OK();
}
mozilla::ipc::IPCResult
GPUChild::RecvUpdateChildScalars(InfallibleTArray<ScalarAction>&& aScalarActions)
{
Telemetry::UpdateChildScalars(GeckoProcessType_GPU, aScalarActions);
TelemetryIPC::UpdateChildScalars(GeckoProcessType_GPU, aScalarActions);
return IPC_OK();
}
mozilla::ipc::IPCResult
GPUChild::RecvUpdateChildKeyedScalars(InfallibleTArray<KeyedScalarAction>&& aScalarActions)
{
Telemetry::UpdateChildKeyedScalars(GeckoProcessType_GPU, aScalarActions);
TelemetryIPC::UpdateChildKeyedScalars(GeckoProcessType_GPU, aScalarActions);
return IPC_OK();
}

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

@ -43,8 +43,8 @@ public:
mozilla::ipc::IPCResult RecvInitComplete(const GPUDeviceData& aData) override;
mozilla::ipc::IPCResult RecvReportCheckerboard(const uint32_t& aSeverity, const nsCString& aLog) override;
mozilla::ipc::IPCResult RecvInitCrashReporter(Shmem&& shmem, const NativeThreadId& aThreadId) override;
mozilla::ipc::IPCResult RecvAccumulateChildHistogram(InfallibleTArray<Accumulation>&& aAccumulations) override;
mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistogram(InfallibleTArray<KeyedAccumulation>&& aAccumulations) override;
mozilla::ipc::IPCResult RecvAccumulateChildHistograms(InfallibleTArray<Accumulation>&& aAccumulations) override;
mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistograms(InfallibleTArray<KeyedAccumulation>&& aAccumulations) override;
mozilla::ipc::IPCResult RecvUpdateChildScalars(InfallibleTArray<ScalarAction>&& aScalarActions) override;
mozilla::ipc::IPCResult RecvUpdateChildKeyedScalars(InfallibleTArray<KeyedScalarAction>&& aScalarActions) override;
void ActorDestroy(ActorDestroyReason aWhy) override;

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

@ -110,8 +110,8 @@ child:
async NotifyUiObservers(nsCString aTopic);
// Messages for reporting telemetry to the UI process.
async AccumulateChildHistogram(Accumulation[] accumulations);
async AccumulateChildKeyedHistogram(KeyedAccumulation[] accumulations);
async AccumulateChildHistograms(Accumulation[] accumulations);
async AccumulateChildKeyedHistograms(KeyedAccumulation[] accumulations);
async UpdateChildScalars(ScalarAction[] actions);
async UpdateChildKeyedScalars(KeyedScalarAction[] actions);

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

@ -383,6 +383,7 @@ private:
DECL_GFX_PREF(Once, "gfx.direct2d.force-enabled", Direct2DForceEnabled, bool, false);
DECL_GFX_PREF(Live, "gfx.direct3d11.reuse-decoder-device", Direct3D11ReuseDecoderDevice, int32_t, -1);
DECL_GFX_PREF(Live, "gfx.direct3d11.allow-intel-mutex", Direct3D11AllowIntelMutex, bool, true);
DECL_GFX_PREF(Live, "gfx.downloadable_fonts.otl_validation", ValidateOTLTables, bool, true);
DECL_GFX_PREF(Live, "gfx.draw-color-bars", CompositorDrawColorBars, bool, false);
DECL_GFX_PREF(Once, "gfx.e10s.hide-plugins-for-scroll", HidePluginsForScroll, bool, true);
DECL_GFX_PREF(Live, "gfx.layerscope.enabled", LayerScopeEnabled, bool, false);

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

@ -7,6 +7,7 @@
#include "gfxUserFontSet.h"
#include "gfxPlatform.h"
#include "gfxPrefs.h"
#include "nsContentPolicyUtils.h"
#include "nsUnicharUtils.h"
#include "nsNetUtil.h"
@ -176,17 +177,19 @@ gfxUserFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeeds
class gfxOTSContext : public ots::OTSContext {
public:
explicit gfxOTSContext(gfxUserFontEntry* aUserFontEntry)
: mUserFontEntry(aUserFontEntry) {}
: mUserFontEntry(aUserFontEntry)
{
// Whether to apply OTS validation to OpenType Layout tables
mCheckOTLTables = gfxPrefs::ValidateOTLTables();
}
virtual ots::TableAction GetTableAction(uint32_t aTag) override {
// Preserve Graphite, color glyph and SVG tables
if (
#ifdef RELEASE_OR_BETA // For Beta/Release, also allow OT Layout tables through
// unchecked, and rely on harfbuzz to handle them safely.
aTag == TRUETYPE_TAG('G', 'D', 'E', 'F') ||
aTag == TRUETYPE_TAG('G', 'P', 'O', 'S') ||
aTag == TRUETYPE_TAG('G', 'S', 'U', 'B') ||
#endif
// Preserve Graphite, color glyph and SVG tables,
// and possibly OTL tables (depending on pref)
if ((!mCheckOTLTables &&
(aTag == TRUETYPE_TAG('G', 'D', 'E', 'F') ||
aTag == TRUETYPE_TAG('G', 'P', 'O', 'S') ||
aTag == TRUETYPE_TAG('G', 'S', 'U', 'B'))) ||
aTag == TRUETYPE_TAG('S', 'i', 'l', 'f') ||
aTag == TRUETYPE_TAG('S', 'i', 'l', 'l') ||
aTag == TRUETYPE_TAG('G', 'l', 'o', 'c') ||
@ -225,6 +228,7 @@ public:
private:
gfxUserFontEntry* mUserFontEntry;
nsTHashtable<nsCStringHashKey> mWarningsIssued;
bool mCheckOTLTables;
};
// Call the OTS library to sanitize an sfnt before attempting to use it.

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

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

@ -507,7 +507,7 @@ bool Pickle::WriteBytes(const void* data, uint32_t data_len, uint32_t alignment)
}
bool Pickle::WriteString(const std::string& value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
std::string v(value);
Singleton<mozilla::ipc::Faulty>::get()->FuzzString(v);
if (!WriteInt(static_cast<int>(v.size())))
@ -523,7 +523,7 @@ bool Pickle::WriteString(const std::string& value) {
}
bool Pickle::WriteWString(const std::wstring& value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
std::wstring v(value);
Singleton<mozilla::ipc::Faulty>::get()->FuzzWString(v);
if (!WriteInt(static_cast<int>(v.size())))
@ -541,7 +541,7 @@ bool Pickle::WriteWString(const std::wstring& value) {
}
bool Pickle::WriteData(const char* data, uint32_t length) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
std::string v(data, length);
Singleton<mozilla::ipc::Faulty>::get()->FuzzData(v, v.size());
return WriteInt(v.size()) && WriteBytes(v.data(), v.size());

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

@ -17,7 +17,7 @@
#include "mozilla/BufferList.h"
#include "mozilla/mozalloc.h"
#ifdef MOZ_FAULTY
#ifdef FUZZING
#include "base/singleton.h"
#include "mozilla/ipc/Faulty.h"
#endif
@ -134,25 +134,25 @@ class Pickle {
// Pickle, it is important to read them in the order in which they were added
// to the Pickle.
bool WriteBool(bool value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzBool(&value);
#endif
return WriteInt(value ? 1 : 0);
}
bool WriteInt16(int16_t value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzInt16(&value);
#endif
return WriteBytes(&value, sizeof(value));
}
bool WriteUInt16(uint16_t value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzUInt16(&value);
#endif
return WriteBytes(&value, sizeof(value));
}
bool WriteInt(int value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzInt(&value);
#endif
return WriteBytes(&value, sizeof(value));
@ -160,7 +160,7 @@ class Pickle {
bool WriteLong(long value) {
// Always written as a 64-bit value since the size for this type can
// differ between architectures.
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzLong(&value);
#endif
return WriteInt64(int64_t(value));
@ -168,7 +168,7 @@ class Pickle {
bool WriteULong(unsigned long value) {
// Always written as a 64-bit value since the size for this type can
// differ between architectures.
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzULong(&value);
#endif
return WriteUInt64(uint64_t(value));
@ -176,37 +176,37 @@ class Pickle {
bool WriteSize(size_t value) {
// Always written as a 64-bit value since the size for this type can
// differ between architectures.
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzSize(&value);
#endif
return WriteUInt64(uint64_t(value));
}
bool WriteInt32(int32_t value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzInt(&value);
#endif
return WriteBytes(&value, sizeof(value));
}
bool WriteUInt32(uint32_t value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzUInt32(&value);
#endif
return WriteBytes(&value, sizeof(value));
}
bool WriteInt64(int64_t value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzInt64(&value);
#endif
return WriteBytes(&value, sizeof(value));
}
bool WriteUInt64(uint64_t value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzUInt64(&value);
#endif
return WriteBytes(&value, sizeof(value));
}
bool WriteDouble(double value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzDouble(&value);
#endif
return WriteBytes(&value, sizeof(value));
@ -217,7 +217,7 @@ class Pickle {
return WriteInt64(int64_t(value));
}
bool WriteUnsignedChar(unsigned char value) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->FuzzUChar(&value);
#endif
return WriteBytes(&value, sizeof(value));

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

@ -35,7 +35,7 @@
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/UniquePtr.h"
#ifdef MOZ_FAULTY
#ifdef FUZZING
#include "mozilla/ipc/Faulty.h"
#endif
@ -583,7 +583,7 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() {
// Write out all the messages we can till the write blocks or there are no
// more outgoing messages.
while (!output_queue_.empty()) {
#ifdef MOZ_FAULTY
#ifdef FUZZING
Singleton<mozilla::ipc::Faulty>::get()->MaybeCollectAndClosePipe(pipe_);
#endif
Message* msg = output_queue_.front();

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

@ -3,17 +3,19 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ipc/Faulty.h"
#include <cerrno>
#include <climits>
#include <cmath>
#include <prinrval.h>
#include "nsXULAppAPI.h"
#include <unistd.h>
#include "base/string_util.h"
#include "chrome/common/ipc_message.h"
#include "chrome/common/ipc_channel.h"
#include "prenv.h"
#include "mozilla/ipc/Faulty.h"
#include "mozilla/TypeTraits.h"
#include <cmath>
#include <climits>
#include "nsXULAppAPI.h"
#include "prenv.h"
namespace mozilla {
namespace ipc {

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

@ -20,6 +20,7 @@
#include "nsMultiplexInputStream.h"
#include "nsNetCID.h"
#include "nsStringStream.h"
#include "nsTemporaryFileInputStream.h"
#include "nsXULAppAPI.h"
using namespace mozilla::dom;

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

@ -421,7 +421,7 @@ LoggingEnabled()
inline bool
LoggingEnabledFor(const char *aTopLevelProtocol)
{
#if defined(DEBUG)
#if defined(DEBUG) || defined(FUZZING)
const char *filter = PR_GetEnv("MOZ_IPC_MESSAGE_LOG");
if (!filter) {
return false;

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

@ -45,7 +45,7 @@ EXPORTS.mozilla.ipc += [
'WindowsMessageLoop.h',
]
if CONFIG['MOZ_FAULTY'] == '1':
if CONFIG['FUZZING'] == '1':
EXPORTS.mozilla.ipc += ['Faulty.h']
SOURCES += ['Faulty.cpp']

51
ipc/mscom/Aggregation.h Normal file
Просмотреть файл

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_mscom_Aggregation_h
#define mozilla_mscom_Aggregation_h
#include "mozilla/Attributes.h"
namespace mozilla {
namespace mscom {
/**
* This is used for stabilizing a COM object's reference count during
* construction when that object aggregates other objects. Since the aggregated
* object(s) may AddRef() or Release(), we need to artifically boost the
* refcount to prevent premature destruction. Note that we increment/decrement
* instead of AddRef()/Release() in this class because we want to adjust the
* refcount without causing any other side effects (like object destruction).
*/
template <typename RefCntT>
class MOZ_RAII StabilizedRefCount
{
public:
explicit StabilizedRefCount(RefCntT& aRefCnt)
: mRefCnt(aRefCnt)
{
++aRefCnt;
}
~StabilizedRefCount()
{
--mRefCnt;
}
StabilizedRefCount(const StabilizedRefCount&) = delete;
StabilizedRefCount(StabilizedRefCount&&) = delete;
StabilizedRefCount& operator=(const StabilizedRefCount&) = delete;
StabilizedRefCount& operator=(StabilizedRefCount&&) = delete;
private:
RefCntT& mRefCnt;
};
} // namespace mscom
} // namespace mozilla
#endif // mozilla_mscom_Aggregation_h

299
ipc/mscom/AsyncInvoker.h Normal file
Просмотреть файл

@ -0,0 +1,299 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_mscom_AsyncInvoker_h
#define mozilla_mscom_AsyncInvoker_h
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Move.h"
#include "mozilla/mscom/Aggregation.h"
#include "mozilla/mscom/Utils.h"
#include "mozilla/Mutex.h"
#include "nsISupportsImpl.h"
#include <objidl.h>
#include <windows.h>
namespace mozilla {
namespace mscom {
namespace detail {
template <typename AsyncInterface>
class ForgettableAsyncCall : public ISynchronize
{
public:
explicit ForgettableAsyncCall(ICallFactory* aCallFactory)
: mRefCnt(0)
, mAsyncCall(nullptr)
{
StabilizedRefCount<Atomic<ULONG>> stabilizer(mRefCnt);
HRESULT hr =
aCallFactory->CreateCall(__uuidof(AsyncInterface), this,
IID_IUnknown, getter_AddRefs(mInnerUnk));
if (FAILED(hr)) {
return;
}
hr = mInnerUnk->QueryInterface(__uuidof(AsyncInterface),
reinterpret_cast<void**>(&mAsyncCall));
if (SUCCEEDED(hr)) {
// Don't hang onto a ref. Because mAsyncCall is aggregated, its refcount
// is this->mRefCnt, so we'd create a cycle!
mAsyncCall->Release();
}
}
AsyncInterface* GetInterface() const
{
return mAsyncCall;
}
// IUnknown
STDMETHODIMP QueryInterface(REFIID aIid, void** aOutInterface) override
{
if (aIid == IID_IUnknown || aIid == IID_ISynchronize) {
RefPtr<ISynchronize> ptr(this);
ptr.forget(aOutInterface);
return S_OK;
}
return mInnerUnk->QueryInterface(aIid, aOutInterface);
}
STDMETHODIMP_(ULONG) AddRef() override
{
ULONG result = ++mRefCnt;
NS_LOG_ADDREF(this, result, "ForgettableAsyncCall", sizeof(*this));
return result;
}
STDMETHODIMP_(ULONG) Release() override
{
ULONG result = --mRefCnt;
NS_LOG_RELEASE(this, result, "ForgettableAsyncCall");
if (!result) {
delete this;
}
return result;
}
// ISynchronize
STDMETHODIMP Wait(DWORD aFlags, DWORD aTimeoutMilliseconds) override
{
return E_NOTIMPL;
}
STDMETHODIMP Signal() override
{
// Even though this function is a no-op, we must return S_OK as opposed to
// E_NOTIMPL or else COM will consider the async call to have failed.
return S_OK;
}
STDMETHODIMP Reset() override
{
// Even though this function is a no-op, we must return S_OK as opposed to
// E_NOTIMPL or else COM will consider the async call to have failed.
return S_OK;
}
protected:
virtual ~ForgettableAsyncCall() {}
private:
Atomic<ULONG> mRefCnt;
RefPtr<IUnknown> mInnerUnk;
AsyncInterface* mAsyncCall; // weak reference
};
template <typename AsyncInterface>
class WaitableAsyncCall : public ForgettableAsyncCall<AsyncInterface>
{
public:
explicit WaitableAsyncCall(ICallFactory* aCallFactory)
: ForgettableAsyncCall(aCallFactory)
, mEvent(::CreateEventW(nullptr, FALSE, FALSE, nullptr))
{
}
STDMETHODIMP Wait(DWORD aFlags, DWORD aTimeoutMilliseconds) override
{
const DWORD waitStart = aTimeoutMilliseconds == INFINITE ? 0 :
::GetTickCount();
DWORD flags = aFlags;
if (XRE_IsContentProcess() && NS_IsMainThread()) {
flags |= COWAIT_ALERTABLE;
}
HRESULT hr;
DWORD signaledIdx;
DWORD elapsed = 0;
while (true) {
if (aTimeoutMilliseconds != INFINITE) {
elapsed = ::GetTickCount() - waitStart;
}
if (elapsed >= aTimeoutMilliseconds) {
return RPC_S_CALLPENDING;
}
::SetLastError(ERROR_SUCCESS);
hr = ::CoWaitForMultipleHandles(flags, aTimeoutMilliseconds - elapsed, 1,
&mEvent, &signaledIdx);
if (hr == RPC_S_CALLPENDING || FAILED(hr)) {
return hr;
}
if (hr == S_OK && signaledIdx == 0) {
return hr;
}
}
}
STDMETHODIMP Signal() override
{
if (!::SetEvent(mEvent)) {
return HRESULT_FROM_WIN32(::GetLastError());
}
return S_OK;
}
protected:
~WaitableAsyncCall()
{
if (mEvent) {
::CloseHandle(mEvent);
}
}
private:
HANDLE mEvent;
};
template <typename AsyncInterface>
class FireAndForgetInvoker
{
protected:
typedef ForgettableAsyncCall<AsyncInterface> AsyncCallType;
RefPtr<ForgettableAsyncCall<AsyncInterface>> mAsyncCall;
};
template <typename AsyncInterface>
class WaitableInvoker
{
public:
HRESULT Wait(DWORD aTimeout = INFINITE) const
{
if (!mAsyncCall) {
return E_POINTER;
}
return mAsyncCall->Wait(0, aTimeout);
}
protected:
typedef WaitableAsyncCall<AsyncInterface> AsyncCallType;
RefPtr<WaitableAsyncCall<AsyncInterface>> mAsyncCall;
};
} // namespace detail
/**
* This class is intended for "fire-and-forget" asynchronous invocations of COM
* interfaces. This requires that an interface be annotated with the
* |async_uuid| attribute in midl.
*
* For example, let us suppose we have some IDL as such:
* [object, uuid(...), async_uuid(...)]
* interface IFoo : IUnknown
* {
* HRESULT Bar(long baz);
* }
*
* Then, given an IFoo, we may construct an AsyncInvoker<AsyncIFoo>:
*
* IFoo* foo = ...;
* AsyncInvoker<AsyncIFoo> myInvoker(foo);
* HRESULT hr = myInvoker->Begin_Bar(7);
*
* Alternatively you may use the ASYNC_INVOKER_FOR macro, which automatically
* derives the name of the asynchronous interface from the name of the
* synchronous interface:
*
* ASYNC_INVOKER_FOR(IFoo) myInvoker(foo);
*
* This class may also be used when a synchronous COM call must be made that
* might reenter the content process. In this case, use the WaitableAsyncInvoker
* variant, or the WAITABLE_ASYNC_INVOKER_FOR macro:
*
* WAITABLE_ASYNC_INVOKER_FOR(Ifoo) myInvoker(foo);
* myInvoker->Begin_Bar(7);
* myInvoker.Wait(); // <-- Wait for the COM call to complete.
*
* In general you should avoid using the waitable version, but in some corner
* cases it is absolutely necessary in order to preserve correctness while
* avoiding deadlock.
*/
template <typename AsyncInterface,
template <typename Iface> class WaitPolicy = detail::FireAndForgetInvoker>
class MOZ_RAII AsyncInvoker final : public WaitPolicy<AsyncInterface>
{
public:
/**
* @param aSyncProxy The COM object on which to invoke the asynchronous event.
* This object must be a proxy to the synchronous variant of
* AsyncInterface.
*/
explicit AsyncInvoker(IUnknown* aSyncProxy)
{
MOZ_ASSERT(aSyncProxy);
MOZ_ASSERT(IsProxy(aSyncProxy));
RefPtr<ICallFactory> callFactory;
if (FAILED(aSyncProxy->QueryInterface(IID_ICallFactory,
getter_AddRefs(callFactory)))) {
return;
}
mAsyncCall = new AsyncCallType(callFactory);
}
explicit operator bool() const
{
return mAsyncCall && mAsyncCall->GetInterface();
}
AsyncInterface* operator->() const
{
return mAsyncCall->GetInterface();
}
AsyncInvoker(const AsyncInvoker& aOther) = delete;
AsyncInvoker(AsyncInvoker&& aOther) = delete;
AsyncInvoker& operator=(const AsyncInvoker& aOther) = delete;
AsyncInvoker& operator=(AsyncInvoker&& aOther) = delete;
};
template <typename AsyncInterface>
using WaitableAsyncInvoker = AsyncInvoker<AsyncInterface, detail::WaitableInvoker>;
} // namespace mscom
} // namespace mozilla
#define ASYNC_INVOKER_FOR(SyncIface) \
mozilla::mscom::AsyncInvoker<Async##SyncIface>
#define WAITABLE_ASYNC_INVOKER_FOR(SyncIface) \
mozilla::mscom::WaitableAsyncInvoker<Async##SyncIface>
#endif // mozilla_mscom_AsyncInvoker_h

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

@ -5,6 +5,8 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS.mozilla.mscom += [
'Aggregation.h',
'AsyncInvoker.h',
'COMApartmentRegion.h',
'COMPtrHolder.h',
'EnsureMTA.h',

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

@ -36,9 +36,7 @@
# include "jit/PerfSpewer.h"
#endif
#include "vm/MatchPairs.h"
#ifdef MOZ_VTUNE
# include "vtune/VTuneWrapper.h"
#endif
#include "vtune/VTuneWrapper.h"
#include "jit/MacroAssembler-inl.h"

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

@ -1003,9 +1003,7 @@ BaselineCacheIRCompiler::emitStoreTypedObjectScalarProperty()
masm.addPtr(offsetAddr, scratch1);
Address dest(scratch1, 0);
BaselineStoreToTypedArray(cx_, masm, type, val, dest, scratch2,
failure->label(), failure->label());
BaselineStoreToTypedArray(cx_, masm, type, val, dest, scratch2, failure->label());
return true;
}
@ -1198,6 +1196,52 @@ BaselineCacheIRCompiler::emitStoreDenseElementHole()
return true;
}
bool
BaselineCacheIRCompiler::emitStoreTypedElement()
{
Register obj = allocator.useRegister(masm, reader.objOperandId());
Register index = allocator.useRegister(masm, reader.int32OperandId());
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
TypedThingLayout layout = reader.typedThingLayout();
Scalar::Type type = reader.scalarType();
bool handleOOB = reader.readBool();
AutoScratchRegister scratch1(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
return false;
// Bounds check.
Label done;
LoadTypedThingLength(masm, layout, obj, scratch1);
masm.branch32(Assembler::BelowOrEqual, scratch1, index, handleOOB ? &done : failure->label());
// Load the elements vector.
LoadTypedThingData(masm, layout, obj, scratch1);
BaseIndex dest(scratch1, index, ScaleFromElemWidth(Scalar::byteSize(type)));
// Use ICStubReg as second scratch register. TODO: consider doing the RHS
// type check/conversion as a separate IR instruction so we can simplify
// this.
Register scratch2 = ICStubReg;
masm.push(scratch2);
Label fail;
BaselineStoreToTypedArray(cx_, masm, type, val, dest, scratch2, &fail);
masm.pop(scratch2);
masm.jump(&done);
masm.bind(&fail);
masm.pop(scratch2);
masm.jump(failure->label());
masm.bind(&done);
return true;
}
bool
BaselineCacheIRCompiler::emitStoreUnboxedArrayElement()
{

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

@ -28,6 +28,7 @@
#include "vm/EnvironmentObject.h"
#include "vm/Interpreter.h"
#include "vm/TraceLogging.h"
#include "vtune/VTuneWrapper.h"
#include "jsscriptinlines.h"
@ -35,9 +36,6 @@
#include "jit/MacroAssembler-inl.h"
#include "vm/Interpreter-inl.h"
#include "vm/NativeObject-inl.h"
#ifdef MOZ_VTUNE
# include "vtune/VTuneWrapper.h"
#endif
using namespace js;
using namespace js::jit;

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

@ -903,38 +903,6 @@ LoadTypedThingLength(MacroAssembler& masm, TypedThingLayout layout, Register obj
}
}
static bool
TypedArraySetElemStubExists(ICSetElem_Fallback* stub, HandleObject obj, bool expectOOB)
{
for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
if (!iter->isSetElem_TypedArray())
continue;
ICSetElem_TypedArray* taStub = iter->toSetElem_TypedArray();
if (obj->maybeShape() == taStub->shape() && taStub->expectOutOfBounds() == expectOOB)
return true;
}
return false;
}
static bool
RemoveExistingTypedArraySetElemStub(JSContext* cx, ICSetElem_Fallback* stub, HandleObject obj)
{
for (ICStubIterator iter = stub->beginChain(); !iter.atEnd(); iter++) {
if (!iter->isSetElem_TypedArray())
continue;
if (obj->maybeShape() != iter->toSetElem_TypedArray()->shape())
continue;
// TypedArraySetElem stubs are only removed using this procedure if
// being replaced with one that expects out of bounds index.
MOZ_ASSERT(!iter->toSetElem_TypedArray()->expectOutOfBounds());
iter.unlink(cx);
return true;
}
return false;
}
static bool
DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_, Value* stack,
HandleValue objv, HandleValue index, HandleValue rhs)
@ -994,6 +962,9 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
newStub->toCacheIR_Updated()->notePreliminaryObject();
else if (gen.shouldUnlinkPreliminaryObjectStubs())
StripPreliminaryObjectStubs(cx, stub);
if (gen.attachedTypedArrayOOBStub())
stub->noteHasTypedArrayOOB();
}
}
}
@ -1057,55 +1028,6 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
}
}
if ((obj->is<TypedArrayObject>() || IsPrimitiveArrayTypedObject(obj)) &&
index.isNumber() &&
rhs.isNumber())
{
if (!cx->runtime()->jitSupportsFloatingPoint &&
(TypedThingRequiresFloatingPoint(obj) || index.isDouble()))
{
return true;
}
bool expectOutOfBounds;
double idx = index.toNumber();
if (obj->is<TypedArrayObject>()) {
expectOutOfBounds = (idx < 0 || idx >= double(obj->as<TypedArrayObject>().length()));
} else {
// Typed objects throw on out of bounds accesses. Don't attach
// a stub in this case.
if (idx < 0 || idx >= double(obj->as<TypedObject>().length()))
return true;
expectOutOfBounds = false;
// Don't attach stubs if the underlying storage for typed objects
// in the compartment could be detached, as the stub will always
// bail out.
if (cx->compartment()->detachedTypedObjects)
return true;
}
if (!TypedArraySetElemStubExists(stub, obj, expectOutOfBounds)) {
// Remove any existing TypedArraySetElemStub that doesn't handle out-of-bounds
if (expectOutOfBounds)
RemoveExistingTypedArraySetElemStub(cx, stub, obj);
Shape* shape = obj->maybeShape();
Scalar::Type type = TypedThingElementType(obj);
JitSpew(JitSpew_BaselineIC,
" Generating SetElem_TypedArray stub (shape=%p, type=%u, oob=%s)",
shape, type, expectOutOfBounds ? "yes" : "no");
ICSetElem_TypedArray::Compiler compiler(cx, shape, type, expectOutOfBounds);
ICStub* typedArrayStub = compiler.getStub(compiler.getStubSpace(outerScript));
if (!typedArrayStub)
return false;
stub->addNewStub(typedArrayStub);
return true;
}
}
return true;
}
@ -1153,13 +1075,13 @@ ICSetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
}
void
BaselineScript::noteArrayWriteHole(uint32_t pcOffset)
BaselineScript::noteHasDenseAdd(uint32_t pcOffset)
{
ICEntry& entry = icEntryFromPCOffset(pcOffset);
ICFallbackStub* stub = entry.fallbackStub();
if (stub->isSetElem_Fallback())
stub->toSetElem_Fallback()->noteArrayWriteHole();
stub->toSetElem_Fallback()->noteHasDenseAdd();
}
void
@ -1173,15 +1095,11 @@ EmitUnboxedPreBarrierForBaseline(MacroAssembler &masm, const BaseIndex& address,
MOZ_ASSERT(!UnboxedTypeNeedsPreBarrier(type));
}
//
// SetElem_TypedArray
//
template <typename S, typename T>
template <typename T>
void
BaselineStoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type, const S& value,
const T& dest, Register scratch, Label* failure,
Label* failureModifiedScratch)
BaselineStoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type,
const ValueOperand& value, const T& dest, Register scratch,
Label* failure)
{
Label done;
@ -1231,7 +1149,7 @@ BaselineStoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type
if (cx->runtime()->jitSupportsFloatingPoint) {
masm.branchTestDouble(Assembler::NotEqual, value, failure);
masm.unboxDouble(value, FloatReg0);
masm.branchTruncateDoubleMaybeModUint32(FloatReg0, scratch, failureModifiedScratch);
masm.branchTruncateDoubleMaybeModUint32(FloatReg0, scratch, failure);
masm.jump(&isInt32);
} else {
masm.jump(failure);
@ -1244,98 +1162,12 @@ BaselineStoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type
template void
BaselineStoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type,
const ValueOperand& value, const Address& dest, Register scratch,
Label* failure, Label* failureModifiedScratch);
Label* failure);
template void
BaselineStoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type,
const Address& value, const BaseIndex& dest, Register scratch,
Label* failure, Label* failureModifiedScratch);
bool
ICSetElem_TypedArray::Compiler::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
Label failure;
if (layout_ != Layout_TypedArray)
CheckForTypedObjectWithDetachedStorage(cx, masm, &failure);
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
Register scratchReg = regs.takeAny();
// Unbox R0 and shape guard.
Register obj = masm.extractObject(R0, ExtractTemp0);
masm.loadPtr(Address(ICStubReg, ICSetElem_TypedArray::offsetOfShape()), scratchReg);
masm.branchTestObjShape(Assembler::NotEqual, obj, scratchReg, &failure);
// Ensure the index is an integer.
if (cx->runtime()->jitSupportsFloatingPoint) {
Label isInt32;
masm.branchTestInt32(Assembler::Equal, R1, &isInt32);
{
// If the index is a double, try to convert it to int32. It's okay
// to convert -0 to 0: the shape check ensures the object is a typed
// array so the difference is not observable.
masm.branchTestDouble(Assembler::NotEqual, R1, &failure);
masm.unboxDouble(R1, FloatReg0);
masm.convertDoubleToInt32(FloatReg0, scratchReg, &failure, /* negZeroCheck = */false);
masm.tagValue(JSVAL_TYPE_INT32, scratchReg, R1);
}
masm.bind(&isInt32);
} else {
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
}
// Unbox key.
Register key = masm.extractInt32(R1, ExtractTemp1);
// Bounds check.
Label oobWrite;
LoadTypedThingLength(masm, layout_, obj, scratchReg);
masm.branch32(Assembler::BelowOrEqual, scratchReg, key,
expectOutOfBounds_ ? &oobWrite : &failure);
// Load the elements vector.
LoadTypedThingData(masm, layout_, obj, scratchReg);
BaseIndex dest(scratchReg, key, ScaleFromElemWidth(Scalar::byteSize(type_)));
Address value(masm.getStackPointer(), ICStackValueOffset);
// We need a second scratch register. It's okay to clobber the type tag of
// R0 or R1, as long as it's restored before jumping to the next stub.
regs = availableGeneralRegs(0);
regs.takeUnchecked(obj);
regs.takeUnchecked(key);
regs.take(scratchReg);
Register secondScratch = regs.takeAny();
Label failureModifiedSecondScratch;
BaselineStoreToTypedArray(cx, masm, type_, value, dest,
secondScratch, &failure, &failureModifiedSecondScratch);
EmitReturnFromIC(masm);
if (failureModifiedSecondScratch.used()) {
// Writing to secondScratch may have clobbered R0 or R1, restore them
// first.
masm.bind(&failureModifiedSecondScratch);
masm.tagValue(JSVAL_TYPE_OBJECT, obj, R0);
masm.tagValue(JSVAL_TYPE_INT32, key, R1);
}
// Failure case - jump to next stub
masm.bind(&failure);
EmitStubGuardFailure(masm);
if (expectOutOfBounds_) {
MOZ_ASSERT(layout_ == Layout_TypedArray);
masm.bind(&oobWrite);
EmitReturnFromIC(masm);
}
return true;
}
const ValueOperand& value, const BaseIndex& dest, Register scratch,
Label* failure);
//
// In_Fallback
@ -4674,17 +4506,6 @@ ICTypeUpdate_ObjectGroup::ICTypeUpdate_ObjectGroup(JitCode* stubCode, ObjectGrou
group_(group)
{ }
ICSetElem_TypedArray::ICSetElem_TypedArray(JitCode* stubCode, Shape* shape, Scalar::Type type,
bool expectOutOfBounds)
: ICStub(SetElem_TypedArray, stubCode),
shape_(shape)
{
extra_ = uint8_t(type);
MOZ_ASSERT(extra_ == type);
extra_ |= (static_cast<uint16_t>(expectOutOfBounds) << 8);
}
ICGetIntrinsic_Constant::ICGetIntrinsic_Constant(JitCode* stubCode, const Value& value)
: ICStub(GetIntrinsic_Constant, stubCode),
value_(value)

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

@ -431,15 +431,17 @@ class ICSetElem_Fallback : public ICFallbackStub
: ICFallbackStub(ICStub::SetElem_Fallback, stubCode)
{ }
static const size_t HasDenseAddFlag = 0x1;
static const size_t HasTypedArrayOOBFlag = 0x2;
public:
static const uint32_t MAX_OPTIMIZED_STUBS = 8;
void noteArrayWriteHole() {
extra_ = 1;
}
bool hasArrayWriteHole() const {
return extra_;
}
void noteHasDenseAdd() { extra_ |= HasDenseAddFlag; }
bool hasDenseAdd() const { return extra_ & HasDenseAddFlag; }
void noteHasTypedArrayOOB() { extra_ |= HasTypedArrayOOBFlag; }
bool hasTypedArrayOOB() const { return extra_ & HasTypedArrayOOBFlag; }
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
@ -457,67 +459,6 @@ class ICSetElem_Fallback : public ICFallbackStub
};
};
// Accesses scalar elements of a typed array or typed object.
class ICSetElem_TypedArray : public ICStub
{
friend class ICStubSpace;
protected: // Protected to silence Clang warning.
GCPtrShape shape_;
ICSetElem_TypedArray(JitCode* stubCode, Shape* shape, Scalar::Type type,
bool expectOutOfBounds);
public:
Scalar::Type type() const {
return (Scalar::Type) (extra_ & 0xff);
}
bool expectOutOfBounds() const {
return (extra_ >> 8) & 1;
}
static size_t offsetOfShape() {
return offsetof(ICSetElem_TypedArray, shape_);
}
GCPtrShape& shape() {
return shape_;
}
class Compiler : public ICStubCompiler {
RootedShape shape_;
Scalar::Type type_;
TypedThingLayout layout_;
bool expectOutOfBounds_;
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
virtual int32_t getKey() const {
return static_cast<int32_t>(engine_) |
(static_cast<int32_t>(kind) << 1) |
(static_cast<int32_t>(type_) << 17) |
(static_cast<int32_t>(layout_) << 25) |
(static_cast<int32_t>(expectOutOfBounds_) << 29);
}
public:
Compiler(JSContext* cx, Shape* shape, Scalar::Type type, bool expectOutOfBounds)
: ICStubCompiler(cx, ICStub::SetElem_TypedArray, Engine::Baseline),
shape_(cx, shape),
type_(type),
layout_(GetTypedThingLayout(shape->getObjectClass())),
expectOutOfBounds_(expectOutOfBounds)
{}
ICStub* getStub(ICStubSpace* space) {
return newStub<ICSetElem_TypedArray>(space, getStubCode(), shape_, type_,
expectOutOfBounds_);
}
};
};
// In
// JSOP_IN
class ICIn_Fallback : public ICFallbackStub
@ -1775,12 +1716,11 @@ void EmitUnboxedPreBarrierForBaseline(MacroAssembler &masm, const BaseIndex& add
// Write an arbitrary value to a typed array or typed object address at dest.
// If the value could not be converted to the appropriate format, jump to
// failure or failureModifiedScratch.
template <typename S, typename T>
void
BaselineStoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type, const S& value,
const T& dest, Register scratch, Label* failure,
Label* failureModifiedScratch);
// failure.
template <typename T>
void BaselineStoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type,
const ValueOperand& value, const T& dest, Register scratch,
Label* failure);
} // namespace jit
} // namespace js

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

@ -49,9 +49,7 @@ namespace jit {
_(Call_IsSuspendedStarGenerator) \
\
_(GetElem_Fallback) \
\
_(SetElem_Fallback) \
_(SetElem_TypedArray) \
\
_(In_Fallback) \
\

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

@ -30,7 +30,7 @@ SetElemICInspector::sawOOBDenseWrite() const
// Check for a write hole bit on the SetElem_Fallback stub.
ICStub* stub = icEntry_->fallbackStub();
if (stub->isSetElem_Fallback())
return stub->toSetElem_Fallback()->hasArrayWriteHole();
return stub->toSetElem_Fallback()->hasDenseAdd();
return false;
}
@ -41,27 +41,10 @@ SetElemICInspector::sawOOBTypedArrayWrite() const
if (!icEntry_)
return false;
// Check for SetElem_TypedArray stubs with expectOutOfBounds set.
for (ICStub* stub = icEntry_->firstStub(); stub; stub = stub->next()) {
if (!stub->isSetElem_TypedArray())
continue;
if (stub->toSetElem_TypedArray()->expectOutOfBounds())
return true;
}
return false;
}
ICStub* stub = icEntry_->fallbackStub();
if (stub->isSetElem_Fallback())
return stub->toSetElem_Fallback()->hasTypedArrayOOB();
bool
SetElemICInspector::sawTypedArrayWrite() const
{
if (!icEntry_)
return false;
// Check for a SetElem_TypedArray stub.
for (ICStub* stub = icEntry_->firstStub(); stub; stub = stub->next()) {
if (stub->isSetElem_TypedArray())
return true;
}
return false;
}

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