#416: M1374047 M1365413 M1369913 M1371424 M1346590 M1376087 M1322896 M1354796 M1365333 M1373970 M1355168

This commit is contained in:
Cameron Kaiser 2017-07-16 17:51:39 -07:00
parent 687ba7579f
commit 1bc1dd390d
11 changed files with 120 additions and 26 deletions

View File

@ -11317,6 +11317,21 @@ nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel, nsISupports* aOwner,
(void)AddToSessionHistory(aURI, aChannel, aOwner, aCloneSHChildren, (void)AddToSessionHistory(aURI, aChannel, aOwner, aCloneSHChildren,
getter_AddRefs(mLSHE)); getter_AddRefs(mLSHE));
} }
} else if (mSessionHistory && mLSHE && mURIResultedInDocument) {
// Even if we don't add anything to SHistory, ensure the current index
// points to the same SHEntry as our mLSHE.
int32_t index = 0;
mSessionHistory->GetRequestedIndex(&index);
if (index == -1) {
mSessionHistory->GetIndex(&index);
}
nsCOMPtr<nsISHEntry> currentSH;
mSessionHistory->GetEntryAtIndex(index, false, getter_AddRefs(currentSH));
if (currentSH != mLSHE) {
nsCOMPtr<nsISHistoryInternal> shPrivate =
do_QueryInterface(mSessionHistory);
shPrivate->ReplaceEntry(index, mLSHE);
}
} }
// If this is a POST request, we do not want to include this in global // If this is a POST request, we do not want to include this in global

View File

@ -209,6 +209,7 @@
#include "nsINode.h" #include "nsINode.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsIDocument.h" #include "nsIDocument.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "mozilla/dom/Element.h" #include "mozilla/dom/Element.h"
#include "nsIDOMHTMLDocument.h" #include "nsIDOMHTMLDocument.h"
@ -441,6 +442,7 @@ class nsTextNodeDirectionalityMap
public: public:
explicit nsTextNodeDirectionalityMap(nsINode* aTextNode) explicit nsTextNodeDirectionalityMap(nsINode* aTextNode)
: mElementToBeRemoved(nullptr)
{ {
MOZ_ASSERT(aTextNode, "Null text node"); MOZ_ASSERT(aTextNode, "Null text node");
MOZ_COUNT_CTOR(nsTextNodeDirectionalityMap); MOZ_COUNT_CTOR(nsTextNodeDirectionalityMap);
@ -454,11 +456,28 @@ public:
MOZ_COUNT_DTOR(nsTextNodeDirectionalityMap); MOZ_COUNT_DTOR(nsTextNodeDirectionalityMap);
} }
static void
nsTextNodeDirectionalityMapPropertyDestructor(void* aObject,
nsIAtom* aProperty,
void* aPropertyValue,
void* aData)
{
nsTextNode* textNode =
static_cast<nsTextNode*>(aPropertyValue);
nsTextNodeDirectionalityMap* map = GetDirectionalityMap(textNode);
if (map) {
map->RemoveEntryForProperty(static_cast<Element*>(aObject));
}
NS_RELEASE(textNode);
}
void AddEntry(nsINode* aTextNode, Element* aElement) void AddEntry(nsINode* aTextNode, Element* aElement)
{ {
if (!mElements.Contains(aElement)) { if (!mElements.Contains(aElement)) {
mElements.Put(aElement); mElements.Put(aElement);
aElement->SetProperty(nsGkAtoms::dirAutoSetBy, aTextNode); NS_ADDREF(aTextNode);
aElement->SetProperty(nsGkAtoms::dirAutoSetBy, aTextNode,
nsTextNodeDirectionalityMapPropertyDestructor);
aElement->SetHasDirAutoSet(); aElement->SetHasDirAutoSet();
} }
} }
@ -470,11 +489,21 @@ public:
mElements.Remove(aElement); mElements.Remove(aElement);
aElement->ClearHasDirAutoSet(); aElement->ClearHasDirAutoSet();
aElement->UnsetProperty(nsGkAtoms::dirAutoSetBy); aElement->DeleteProperty(nsGkAtoms::dirAutoSetBy);
}
void RemoveEntryForProperty(Element* aElement)
{
if (mElementToBeRemoved != aElement) {
mElements.Remove(aElement);
}
aElement->ClearHasDirAutoSet();
} }
private: private:
nsCheapSet<nsPtrHashKey<Element> > mElements; nsCheapSet<nsPtrHashKey<Element>> mElements;
// Only used for comparison.
Element* mElementToBeRemoved;
static nsTextNodeDirectionalityMap* GetDirectionalityMap(nsINode* aTextNode) static nsTextNodeDirectionalityMap* GetDirectionalityMap(nsINode* aTextNode)
{ {
@ -498,18 +527,29 @@ private:
return OpNext; return OpNext;
} }
struct nsTextNodeDirectionalityMapAndElement
{
nsTextNodeDirectionalityMap* mMap;
nsCOMPtr<nsINode> mNode;
};
static nsCheapSetOperator ResetNodeDirection(nsPtrHashKey<Element>* aEntry, void* aData) static nsCheapSetOperator ResetNodeDirection(nsPtrHashKey<Element>* aEntry, void* aData)
{ {
MOZ_ASSERT(aEntry->GetKey()->IsElement(), "Must be an Element"); MOZ_ASSERT(aEntry->GetKey()->IsElement(), "Must be an Element");
// run the downward propagation algorithm // run the downward propagation algorithm
// and remove the text node from the map // and remove the text node from the map
nsINode* oldTextNode = static_cast<Element*>(aData); nsTextNodeDirectionalityMapAndElement* data =
static_cast<nsTextNodeDirectionalityMapAndElement*>(aData);
nsINode* oldTextNode = data->mNode;
Element* rootNode = aEntry->GetKey(); Element* rootNode = aEntry->GetKey();
nsINode* newTextNode = nullptr; nsINode* newTextNode = nullptr;
if (rootNode->GetParentNode() && rootNode->HasDirAuto()) { if (rootNode->GetParentNode() && rootNode->HasDirAuto()) {
newTextNode = WalkDescendantsSetDirectionFromText(rootNode, true, newTextNode = WalkDescendantsSetDirectionFromText(rootNode, true,
oldTextNode); oldTextNode);
} }
AutoRestore<Element*> restore(data->mMap->mElementToBeRemoved);
data->mMap->mElementToBeRemoved = rootNode;
if (newTextNode) { if (newTextNode) {
nsINode* oldDirAutoSetBy = nsINode* oldDirAutoSetBy =
static_cast<nsTextNode*>(rootNode->GetProperty(nsGkAtoms::dirAutoSetBy)); static_cast<nsTextNode*>(rootNode->GetProperty(nsGkAtoms::dirAutoSetBy));
@ -520,7 +560,7 @@ private:
nsTextNodeDirectionalityMap::AddEntryToMap(newTextNode, rootNode); nsTextNodeDirectionalityMap::AddEntryToMap(newTextNode, rootNode);
} else { } else {
rootNode->ClearHasDirAutoSet(); rootNode->ClearHasDirAutoSet();
rootNode->UnsetProperty(nsGkAtoms::dirAutoSetBy); rootNode->DeleteProperty(nsGkAtoms::dirAutoSetBy);
} }
return OpRemove; return OpRemove;
} }
@ -529,7 +569,7 @@ private:
{ {
Element* rootNode = aEntry->GetKey(); Element* rootNode = aEntry->GetKey();
rootNode->ClearHasDirAutoSet(); rootNode->ClearHasDirAutoSet();
rootNode->UnsetProperty(nsGkAtoms::dirAutoSetBy); rootNode->DeleteProperty(nsGkAtoms::dirAutoSetBy);
return OpRemove; return OpRemove;
} }
@ -541,11 +581,13 @@ public:
void ResetAutoDirection(nsINode* aTextNode) void ResetAutoDirection(nsINode* aTextNode)
{ {
mElements.EnumerateEntries(ResetNodeDirection, aTextNode); nsTextNodeDirectionalityMapAndElement data = { this, aTextNode };
mElements.EnumerateEntries(ResetNodeDirection, &data);
} }
void EnsureMapIsClear(nsINode* aTextNode) void EnsureMapIsClear(nsINode* aTextNode)
{ {
AutoRestore<Element*> restore(mElementToBeRemoved);
DebugOnly<uint32_t> clearedEntries = DebugOnly<uint32_t> clearedEntries =
mElements.EnumerateEntries(ClearEntry, aTextNode); mElements.EnumerateEntries(ClearEntry, aTextNode);
MOZ_ASSERT(clearedEntries == 0, "Map should be empty already"); MOZ_ASSERT(clearedEntries == 0, "Map should be empty already");
@ -581,7 +623,8 @@ public:
{ {
MOZ_ASSERT(aTextNode->HasTextNodeDirectionalityMap(), MOZ_ASSERT(aTextNode->HasTextNodeDirectionalityMap(),
"Map missing in ResetTextNodeDirection"); "Map missing in ResetTextNodeDirection");
GetDirectionalityMap(aTextNode)->ResetAutoDirection(aChangedTextNode); RefPtr<nsTextNode> textNode = aTextNode;
GetDirectionalityMap(textNode)->ResetAutoDirection(aChangedTextNode);
} }
static void EnsureMapIsClearFor(nsINode* aTextNode) static void EnsureMapIsClearFor(nsINode* aTextNode)

View File

@ -3102,6 +3102,7 @@ static nsIAtom** sPropertiesToTraverseAndUnlink[] =
&nsGkAtoms::itemprop, &nsGkAtoms::itemprop,
&nsGkAtoms::sandbox, &nsGkAtoms::sandbox,
&nsGkAtoms::sizes, &nsGkAtoms::sizes,
&nsGkAtoms::dirAutoSetBy,
nullptr nullptr
}; };

View File

@ -10,6 +10,7 @@
#include "jsapi.h" #include "jsapi.h"
#include "jsfriendapi.h" #include "jsfriendapi.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/DOMEventTargetHelper.h" #include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/net/WebSocketChannel.h" #include "mozilla/net/WebSocketChannel.h"
#include "mozilla/dom/File.h" #include "mozilla/dom/File.h"
@ -610,6 +611,10 @@ WebSocketImpl::Disconnect()
AssertIsOnTargetThread(); AssertIsOnTargetThread();
// DontKeepAliveAnyMore() and DisconnectInternal() can release the object. So
// hold a reference to this until the end of the method.
RefPtr<WebSocketImpl> kungfuDeathGrip = this;
// Disconnect can be called from some control event (such as Notify() of // Disconnect can be called from some control event (such as Notify() of
// WorkerFeature). This will be schedulated before any other sync/async // WorkerFeature). This will be schedulated before any other sync/async
// runnable. In order to prevent some double Disconnect() calls, we use this // runnable. In order to prevent some double Disconnect() calls, we use this
@ -631,10 +636,6 @@ WebSocketImpl::Disconnect()
rv.SuppressException(); rv.SuppressException();
} }
// DontKeepAliveAnyMore() can release the object. So hold a reference to this
// until the end of the method.
RefPtr<WebSocketImpl> kungfuDeathGrip = this;
NS_ReleaseOnMainThread(mChannel); NS_ReleaseOnMainThread(mChannel);
NS_ReleaseOnMainThread(static_cast<nsIWebSocketEventService*>(mService.forget().take())); NS_ReleaseOnMainThread(static_cast<nsIWebSocketEventService*>(mService.forget().take()));
@ -2380,7 +2381,14 @@ WebSocket::Send(nsIInputStream* aMsgStream,
} }
// Always increment outgoing buffer len, even if closed // Always increment outgoing buffer len, even if closed
mOutgoingBufferedAmount += aMsgLength; CheckedUint32 size = mOutgoingBufferedAmount;
size += aMsgLength;
if (MOZ_UNLIKELY(!size.isValid())) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
mOutgoingBufferedAmount = size.value();
if (readyState == CLOSING || if (readyState == CLOSING ||
readyState == CLOSED) { readyState == CLOSED) {

View File

@ -148,15 +148,22 @@ nsImageLoadingContent::Notify(imgIRequest* aRequest,
} }
{ {
nsAutoScriptBlocker scriptBlocker; // Calling Notify on observers can modify the list of observers so make
// a local copy.
nsAutoTArray<nsCOMPtr<imgINotificationObserver>, 2> observers;
for (ImageObserver* observer = &mObserverList, *next; observer; for (ImageObserver* observer = &mObserverList, *next; observer;
observer = next) { observer = next) {
next = observer->mNext; next = observer->mNext;
if (observer->mObserver) { if (observer->mObserver) {
observer->mObserver->Notify(aRequest, aType, aData); observers.AppendElement(observer->mObserver);
} }
} }
nsAutoScriptBlocker scriptBlocker;
for (auto& observer : observers) {
observer->Notify(aRequest, aType, aData);
}
} }
if (aType == imgINotificationObserver::SIZE_AVAILABLE) { if (aType == imgINotificationObserver::SIZE_AVAILABLE) {

View File

@ -44,11 +44,13 @@ protected:
public: public:
inline void TraceSelf(JSTracer* trc) inline void TraceSelf(JSTracer* trc)
{ {
// XXX: Until we implement something like bug 1235598 (and its successor
// bug 1238786), we need these null checks.
if (mTypedObj) { if (mTypedObj) {
JS_CallUnbarrieredObjectTracer(trc, &mTypedObj, "TypedArray.mTypedObj"); JS_CallUnbarrieredObjectTracer(trc, &mTypedObj, "TypedArray.mTypedObj");
} }
if (mWrappedObj) { if (mWrappedObj) {
JS_CallUnbarrieredObjectTracer(trc, &mTypedObj, "TypedArray.mWrappedObj"); JS_CallUnbarrieredObjectTracer(trc, &mWrappedObj, "TypedArray.mWrappedObj");
} }
} }

View File

@ -4822,7 +4822,17 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
return; return;
} }
// Flush layout updates
if (!(flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH)) {
nsContentUtils::FlushLayoutForTree(&window);
}
EnsureTarget(); EnsureTarget();
if (!IsTargetValid()) {
return;
}
// We can't allow web apps to call this until we fix at least the // We can't allow web apps to call this until we fix at least the
// following potential security issues: // following potential security issues:
// -- rendering cross-domain IFRAMEs and then extracting the results // -- rendering cross-domain IFRAMEs and then extracting the results
@ -4836,11 +4846,6 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
return; return;
} }
// Flush layout updates
if (!(flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH)) {
nsContentUtils::FlushLayoutForTree(&window);
}
RefPtr<nsPresContext> presContext; RefPtr<nsPresContext> presContext;
nsIDocShell* docshell = window.GetDocShell(); nsIDocShell* docshell = window.GetDocShell();
if (docshell) { if (docshell) {

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ImageBitmap.h" #include "mozilla/dom/ImageBitmap.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/dom/ImageBitmapBinding.h" #include "mozilla/dom/ImageBitmapBinding.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
#include "mozilla/dom/StructuredCloneTags.h" #include "mozilla/dom/StructuredCloneTags.h"
@ -132,10 +133,14 @@ CropAndCopyDataSourceSurface(DataSourceSurface* aSurface, const IntRect& aCropRe
+ surfPortion.x * bytesPerPixel; + surfPortion.x * bytesPerPixel;
uint8_t* dstBufferPtr = dstMap.GetData() + dest.y * dstMap.GetStride() uint8_t* dstBufferPtr = dstMap.GetData() + dest.y * dstMap.GetStride()
+ dest.x * bytesPerPixel; + dest.x * bytesPerPixel;
const uint32_t copiedBytesPerRaw = surfPortion.width * bytesPerPixel; CheckedInt<uint32_t> copiedBytesPerRaw =
CheckedInt<uint32_t>(surfPortion.width) * bytesPerPixel;
if (MOZ_UNLIKELY(!copiedBytesPerRaw.isValid())) {
return nullptr;
}
for (int i = 0; i < surfPortion.height; ++i) { for (int i = 0; i < surfPortion.height; ++i) {
memcpy(dstBufferPtr, srcBufferPtr, copiedBytesPerRaw); memcpy(dstBufferPtr, srcBufferPtr, copiedBytesPerRaw.value());
srcBufferPtr += srcMap.GetStride(); srcBufferPtr += srcMap.GetStride();
dstBufferPtr += dstMap.GetStride(); dstBufferPtr += dstMap.GetStride();
} }

View File

@ -3328,6 +3328,10 @@ nsDisplayLayerEventRegions::AddFrame(nsDisplayListBuilder* aBuilder,
if (borderBoxHasRoundedCorners || if (borderBoxHasRoundedCorners ||
(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) { (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) {
mMaybeHitRegion.Or(mMaybeHitRegion, borderBox); mMaybeHitRegion.Or(mMaybeHitRegion, borderBox);
// Avoid quadratic performance as a result of the region growing to include
// an arbitrarily large number of rects, which can happen on some pages.
mMaybeHitRegion.SimplifyOutward(8);
} else { } else {
mHitRegion.Or(mHitRegion, borderBox); mHitRegion.Or(mHitRegion, borderBox);
} }

View File

@ -897,6 +897,10 @@ nsAtomicFileOutputStream::DoOpen()
nsCOMPtr<nsIFile> file; nsCOMPtr<nsIFile> file;
file.swap(mOpenParams.localFile); file.swap(mOpenParams.localFile);
if(MOZ_UNLIKELY(!file)) {
return NS_ERROR_NOT_INITIALIZED;
}
nsresult rv = file->Exists(&mTargetFileExists); nsresult rv = file->Exists(&mTargetFileExists);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_ERROR("Can't tell if target file exists"); NS_ERROR("Can't tell if target file exists");

View File

@ -2831,9 +2831,9 @@ nsHttpConnectionMgr::TimeoutTickCB(const nsACString &key,
LOG(("Force timeout of half open to %s after %.2fms.\n", LOG(("Force timeout of half open to %s after %.2fms.\n",
ent->mConnInfo->HashKey().get(), delta)); ent->mConnInfo->HashKey().get(), delta));
if (half->SocketTransport()) if (half->SocketTransport())
half->SocketTransport()->Close(NS_ERROR_ABORT); half->SocketTransport()->Close(NS_ERROR_NET_TIMEOUT);
if (half->BackupTransport()) if (half->BackupTransport())
half->BackupTransport()->Close(NS_ERROR_ABORT); half->BackupTransport()->Close(NS_ERROR_NET_TIMEOUT);
} }
// If this half open hangs around for 5 seconds after we've closed() it // If this half open hangs around for 5 seconds after we've closed() it