cherry-picked mozilla upstream changes:

bug1355414, bug1313977, bug1357366, bug1362889, bug1152353, bug1345893, bug1343172, bug1352348, bug1356843, bug1354308, bug1355340, bug1360574, bug1358776, bug1304566, bug1334097, bug1338574
This commit is contained in:
2018-06-17 23:48:50 +08:00
parent 9c67dd6ab1
commit 58895ea9e5
66 changed files with 876 additions and 239 deletions
+4
View File
@@ -978,6 +978,10 @@ RemoteInputStream::SetStream(nsIInputStream* aStream)
nsresult
RemoteInputStream::BlockAndWaitForStream()
{
if (mStream) {
return NS_OK;
}
if (IsOnOwningThread()) {
if (NS_IsMainThread()) {
NS_WARNING("Blocking the main thread is not supported!");
+9 -1
View File
@@ -89,9 +89,17 @@ FileSystemSecurity::ContentProcessHasAccessTo(ContentParentId aId,
MOZ_ASSERT(NS_IsMainThread());
AssertIsInMainProcess();
if (FindInReadable(NS_LITERAL_STRING(".."), aPath)) {
#if defined(XP_WIN)
if (StringBeginsWith(aPath, NS_LITERAL_STRING("..\\")) ||
FindInReadable(NS_LITERAL_STRING("\\..\\"), aPath)) {
return false;
}
#elif defined(XP_UNIX)
if (StringBeginsWith(aPath, NS_LITERAL_STRING("../")) ||
FindInReadable(NS_LITERAL_STRING("/../"), aPath)) {
return false;
}
#endif
nsTArray<nsString>* paths;
if (!mPaths.Get(aId, &paths)) {
@@ -28,7 +28,7 @@ addMessageListener("entries.open", function (e) {
dir1.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o700);
var file2 = dir1.clone();
file2.append('bar.txt');
file2.append('bar..txt'); // Note the double ..
file2.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o600);
var dir2 = dir1.clone();
+4 -4
View File
@@ -176,9 +176,9 @@ function test_directoryEntry_getFile_simple() {
}
function test_directoryEntry_getFile_deep() {
directoryEntry.getFile("subdir/bar.txt", {},
directoryEntry.getFile("subdir/bar..txt", {},
function(e) {
is(e.name, "bar.txt", "We have the right FileEntry.");
is(e.name, "bar..txt", "We have the right FileEntry.");
test_getParent(e, directoryEntry, /* nested */ true);
}, function(e) {
ok(false, "This should not happen.");
@@ -316,9 +316,9 @@ function test_root_getFile_simple() {
}
function test_root_getFile_deep() {
fileEntry.filesystem.root.getFile(directoryEntry.name + "/subdir/bar.txt", {},
fileEntry.filesystem.root.getFile(directoryEntry.name + "/subdir/bar..txt", {},
function(e) {
is(e.name, "bar.txt", "We have the right FileEntry.");
is(e.name, "bar..txt", "We have the right FileEntry.");
next();
}, function(e) {
ok(false, "This should not happen.");
+1 -8
View File
@@ -74,14 +74,7 @@ MediaShutdownManager::InitStatics()
sInstance, NS_LITERAL_STRING(__FILE__), __LINE__,
NS_LITERAL_STRING("MediaShutdownManager shutdown"));
if (NS_FAILED(rv)) {
// Leak the buffer on the heap to make sure that it lives long enough,
// as MOZ_CRASH_ANNOTATE expects the pointer passed to it to live to
// the end of the program.
const size_t CAPACITY = 256;
auto buf = new char[CAPACITY];
snprintf(buf, CAPACITY, "Failed to add shutdown blocker! rv=%x", uint32_t(rv));
MOZ_CRASH_ANNOTATE(buf);
MOZ_REALLY_CRASH();
MOZ_CRASH_UNSAFE_PRINTF("Failed to add shutdown blocker! rv=%x", uint32_t(rv));
}
}
+1 -1
View File
@@ -75,7 +75,7 @@ private:
char buf[sizeof(randomName) * 2 + 4];
PL_strncpy(buf, "CN=", 3);
for (size_t i = 0; i < sizeof(randomName); ++i) {
snprintf(&buf[i * 2 + 3], 2, "%.2x", randomName[i]);
snprintf(&buf[i * 2 + 3], 3, "%.2x", randomName[i]);
}
buf[sizeof(buf) - 1] = '\0';
+12
View File
@@ -2458,6 +2458,18 @@ ShutdownObserver::Observe(nsISupports* aSubject,
MOZ_ASSERT(!strcmp(aTopic, PROFILE_BEFORE_CHANGE_QM_OBSERVER_ID));
MOZ_ASSERT(gInstance);
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (NS_WARN_IF(!observerService)) {
return NS_ERROR_FAILURE;
}
// Unregister ourselves from the observer service first to make sure the
// nested event loop below will not cause re-entrancy issues.
Unused <<
observerService->RemoveObserver(this,
PROFILE_BEFORE_CHANGE_QM_OBSERVER_ID);
QuotaManagerService* qms = QuotaManagerService::Get();
MOZ_ASSERT(qms);
+1 -1
View File
@@ -226,7 +226,7 @@ nsXMLFragmentContentSink::CloseElement(nsIContent* aContent)
{
// don't do fancy stuff in nsXMLContentSink
if (mPreventScriptExecution &&
(aContent->IsHTMLElement(nsGkAtoms::script),
(aContent->IsHTMLElement(nsGkAtoms::script) ||
aContent->IsSVGElement(nsGkAtoms::script))) {
nsCOMPtr<nsIScriptElement> sele = do_QueryInterface(aContent);
NS_ASSERTION(sele, "script did QI correctly!");
+4
View File
@@ -644,6 +644,10 @@ nsEditorSpellCheck::DeleteSuggestedWordList()
NS_IMETHODIMP
nsEditorSpellCheck::UpdateCurrentDictionary(nsIEditorSpellCheckCallback* aCallback)
{
if (NS_WARN_IF(!mSpellChecker)) {
return NS_ERROR_NOT_INITIALIZED;
}
nsresult rv;
RefPtr<nsEditorSpellCheck> kungFuDeathGrip = this;
@@ -157,6 +157,8 @@ public:
*/
virtual void NotifyFlushComplete() = 0;
virtual void NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId) = 0;
virtual void UpdateOverscrollVelocity(float aX, float aY, bool aIsRootContent) {}
virtual void UpdateOverscrollOffset(float aX, float aY, bool aIsRootContent) {}
virtual void SetScrollingRootContent(bool isRootContent) {}
+17 -6
View File
@@ -53,10 +53,12 @@ typedef mozilla::gfx::Point Point;
typedef mozilla::gfx::Point4D Point4D;
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
typedef CompositorBridgeParent::LayerTreeState LayerTreeState;
float APZCTreeManager::sDPI = 160.0;
struct APZCTreeManager::TreeBuildingState {
TreeBuildingState(const CompositorBridgeParent::LayerTreeState* const aLayerTreeState,
TreeBuildingState(const LayerTreeState* const aLayerTreeState,
bool aIsFirstPaint, uint64_t aOriginatingLayersId,
APZTestData* aTestData, uint32_t aPaintSequence)
: mLayerTreeState(aLayerTreeState)
@@ -67,7 +69,7 @@ struct APZCTreeManager::TreeBuildingState {
}
// State that doesn't change as we recurse in the tree building
const CompositorBridgeParent::LayerTreeState* const mLayerTreeState;
const LayerTreeState* const mLayerTreeState;
const bool mIsFirstPaint;
const uint64_t mOriginatingLayersId;
const APZPaintLogHelper mPaintLogger;
@@ -226,13 +228,13 @@ APZCTreeManager::UpdateHitTestingTree(uint64_t aRootLayerTreeId,
// the layers id that originated this update.
APZTestData* testData = nullptr;
if (gfxPrefs::APZTestLoggingEnabled()) {
if (CompositorBridgeParent::LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aOriginatingLayersId)) {
if (LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aOriginatingLayersId)) {
testData = &state->mApzTestData;
testData->StartNewPaint(aPaintSequenceNumber);
}
}
const CompositorBridgeParent::LayerTreeState* treeState =
const LayerTreeState* treeState =
CompositorBridgeParent::GetIndirectShadowTree(aRootLayerTreeId);
MOZ_ASSERT(treeState);
TreeBuildingState state(treeState, aIsFirstPaint, aOriginatingLayersId,
@@ -439,6 +441,7 @@ APZCTreeManager::StartScrollbarDrag(const ScrollableLayerGuid& aGuid,
RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
if (!apzc) {
NotifyScrollbarDragRejected(aGuid);
return;
}
@@ -446,6 +449,14 @@ APZCTreeManager::StartScrollbarDrag(const ScrollableLayerGuid& aGuid,
mInputQueue->ConfirmDragBlock(inputBlockId, apzc, aDragMetrics);
}
void
APZCTreeManager::NotifyScrollbarDragRejected(const ScrollableLayerGuid& aGuid) const
{
const LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aGuid.mLayersId);
MOZ_ASSERT(state && state->mController);
state->mController->NotifyAsyncScrollbarDragRejected(aGuid.mScrollId);
}
HitTestingTreeNode*
APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
const FrameMetrics& aMetrics,
@@ -462,7 +473,7 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
needsApzc = false;
}
const CompositorBridgeParent::LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
const LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
if (!(state && state->mController.get())) {
needsApzc = false;
}
@@ -690,7 +701,7 @@ APZCTreeManager::FlushApzRepaints(uint64_t aLayersId)
// ensure any pending paints were flushed. Now, paints are flushed
// immediately, so it is safe to simply send a notification now.
APZCTM_LOG("Flushing repaints for layers id %" PRIu64, aLayersId);
const CompositorBridgeParent::LayerTreeState* state =
const LayerTreeState* state =
CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
MOZ_ASSERT(state && state->mController);
state->mController->DispatchToRepaintThread(NewRunnableMethod(
+2
View File
@@ -477,6 +477,8 @@ private:
void PrintAPZCInfo(const LayerMetricsWrapper& aLayer,
const AsyncPanZoomController* apzc);
void NotifyScrollbarDragRejected(const ScrollableLayerGuid& aGuid) const;
protected:
/* The input queue where input events are held until we know enough to
* figure out where they're going. Protected so gtests can access it.
@@ -49,6 +49,7 @@ protected:
while (mcc->RunThroughDelayedTasks());
apzc->Destroy();
tm->ClearTree();
tm->ClearContentController();
}
void MakeApzcWaitForMainThread()
@@ -29,6 +29,7 @@ protected:
virtual void TearDown() {
while (mcc->RunThroughDelayedTasks());
manager->ClearTree();
manager->ClearContentController();
}
/**
@@ -91,6 +91,7 @@ public:
}
MOCK_METHOD3(NotifyAPZStateChange, void(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg));
MOCK_METHOD0(NotifyFlushComplete, void());
MOCK_METHOD1(NotifyAsyncScrollbarDragRejected, void(const FrameMetrics::ViewID&));
};
class MockContentControllerDelayed : public MockContentController {
@@ -174,6 +175,10 @@ public:
return mInputQueue;
}
void ClearContentController() {
mcc = nullptr;
}
protected:
AsyncPanZoomController* NewAPZCInstance(uint64_t aLayersId,
GoannaContentController* aController) override;
@@ -918,6 +918,15 @@ APZCCallbackHelper::IsScrollInProgress(nsIScrollableFrame* aFrame)
|| aFrame->LastSmoothScrollOrigin();
}
/* static */ void
APZCCallbackHelper::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
{
MOZ_ASSERT(NS_IsMainThread());
if (nsIScrollableFrame* scrollFrame = nsLayoutUtils::FindScrollableFrameFor(aScrollId)) {
scrollFrame->AsyncScrollbarDragRejected();
}
}
/* static */ void
APZCCallbackHelper::NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
LayoutDeviceCoord aSpanChange,
+2
View File
@@ -164,6 +164,8 @@ public:
/* Notify content that the repaint flush is complete. */
static void NotifyFlushComplete(nsIPresShell* aShell);
static void NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId);
/* Temporarily ignore the Displayport for better paint performance. If at
* all possible, pass in a presShell if you have one at the call site, we
* use it to trigger a repaint once suppression is disabled. Without that
@@ -274,3 +274,16 @@ ChromeProcessController::NotifyFlushComplete()
APZCCallbackHelper::NotifyFlushComplete(GetPresShell());
}
void
ChromeProcessController::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
{
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(NewRunnableMethod<FrameMetrics::ViewID>(this,
&ChromeProcessController::NotifyAsyncScrollbarDragRejected,
aScrollId));
return;
}
APZCCallbackHelper::NotifyAsyncScrollbarDragRejected(aScrollId);
}
@@ -63,6 +63,7 @@ public:
virtual void NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
const nsString& aEvent) override;
virtual void NotifyFlushComplete() override;
virtual void NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId) override;
private:
nsCOMPtr<nsIWidget> mWidget;
RefPtr<APZEventState> mAPZEventState;
@@ -85,6 +85,12 @@ ContentProcessController::NotifyFlushComplete()
}
}
void
ContentProcessController::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
{
APZCCallbackHelper::NotifyAsyncScrollbarDragRejected(aScrollId);
}
void
ContentProcessController::PostDelayedTask(already_AddRefed<Runnable> aRunnable, int aDelayMs)
{
@@ -62,6 +62,8 @@ public:
void NotifyFlushComplete() override;
void NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId) override;
void PostDelayedTask(already_AddRefed<Runnable> aRunnable, int aDelayMs) override;
bool IsRepaintThread() override;
+7
View File
@@ -85,6 +85,13 @@ APZChild::RecvNotifyFlushComplete()
return IPC_OK();
}
mozilla::ipc::IPCResult
APZChild::RecvNotifyAsyncScrollbarDragRejected(const ViewID& aScrollId)
{
mController->NotifyAsyncScrollbarDragRejected(aScrollId);
return IPC_OK();
}
mozilla::ipc::IPCResult
APZChild::RecvDestroy()
{
+2
View File
@@ -42,6 +42,8 @@ public:
mozilla::ipc::IPCResult RecvNotifyFlushComplete() override;
mozilla::ipc::IPCResult RecvNotifyAsyncScrollbarDragRejected(const ViewID& aScrollId) override;
mozilla::ipc::IPCResult RecvDestroy() override;
private:
+2
View File
@@ -64,6 +64,8 @@ child:
async NotifyFlushComplete();
async NotifyAsyncScrollbarDragRejected(ViewID aScrollId);
async Destroy();
};
@@ -244,6 +244,21 @@ RemoteContentController::NotifyFlushComplete()
}
}
void
RemoteContentController::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
{
if (MessageLoop::current() != mCompositorThread) {
// We have to send messages from the compositor thread
mCompositorThread->PostTask(NewRunnableMethod<FrameMetrics::ViewID>(this,
&RemoteContentController::NotifyAsyncScrollbarDragRejected, aScrollId));
return;
}
if (mCanSend) {
Unused << SendNotifyAsyncScrollbarDragRejected(aScrollId);
}
}
void
RemoteContentController::ActorDestroy(ActorDestroyReason aWhy)
{
+2
View File
@@ -74,6 +74,8 @@ public:
virtual void NotifyFlushComplete() override;
virtual void NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual void Destroy() override;
+1 -1
View File
@@ -300,7 +300,7 @@ bool SkBitmapProcState::chooseScanlineProcs(bool trivialMatrix, bool clampClamp)
return false;
}
#if !defined(SK_ARM_HAS_NEON)
#if !defined(SK_ARM_HAS_NEON) || defined(SK_ARM_HAS_OPTIONAL_NEON)
static const SampleProc32 gSkBitmapProcStateSample32[] = {
S32_opaque_D32_nofilter_DXDY,
S32_alpha_D32_nofilter_DXDY,
@@ -56,7 +56,7 @@ extern const SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs_neon[];
#endif // defined(SK_ARM_HAS_NEON)
// Compile non-neon code path if needed
#if !defined(SK_ARM_HAS_NEON)
#if !defined(SK_ARM_HAS_NEON) || defined(SK_ARM_HAS_OPTIONAL_NEON)
#define MAKENAME(suffix) ClampX_ClampY ## suffix
#define TILEX_PROCF(fx, max) SkClampMax((fx) >> 16, max)
#define TILEY_PROCF(fy, max) SkClampMax((fy) >> 16, max)
+1 -3
View File
@@ -136,9 +136,7 @@ BackgroundChildImpl::ProcessingError(Result aCode, const char* aReason)
MOZ_CRASH("Unknown error code!");
}
// This is just MOZ_CRASH() un-inlined so that we can pass the result code as
// a string. MOZ_CRASH() only supports string literals at the moment.
MOZ_ReportCrash(abortMessage.get(), __FILE__, __LINE__); MOZ_REALLY_CRASH();
MOZ_CRASH_UNSAFE_PRINTF("%s: %s", abortMessage.get(), aReason);
}
void
+62 -50
View File
@@ -1802,6 +1802,50 @@ MessageChannel::DispatchAsyncMessage(const Message& aMsg)
MaybeHandleError(rv, aMsg, "DispatchAsyncMessage");
}
bool
MessageChannel::ShouldDeferInterruptMessage(const Message& aMsg, size_t aStackDepth)
{
AssertWorkerThread();
// We may or may not own the lock in this function, so don't access any
// channel state.
IPC_ASSERT(aMsg.is_interrupt() && !aMsg.is_reply(), "wrong message type");
// Race detection: see the long comment near mRemoteStackDepthGuess in
// MessageChannel.h. "Remote" stack depth means our side, and "local" means
// the other side.
if (aMsg.interrupt_remote_stack_depth_guess() == RemoteViewOfStackDepth(aStackDepth)) {
return false;
}
// Interrupt in-calls have raced. The winner, if there is one, gets to defer
// processing of the other side's in-call.
bool defer;
const char* winner;
const MessageInfo parentMsgInfo =
(mSide == ChildSide) ? MessageInfo(aMsg) : mInterruptStack.top();
const MessageInfo childMsgInfo =
(mSide == ChildSide) ? mInterruptStack.top() : MessageInfo(aMsg);
switch (mListener->MediateInterruptRace(parentMsgInfo, childMsgInfo))
{
case RIPChildWins:
winner = "child";
defer = (mSide == ChildSide);
break;
case RIPParentWins:
winner = "parent";
defer = (mSide != ChildSide);
break;
case RIPError:
MOZ_CRASH("NYI: 'Error' Interrupt race policy");
default:
MOZ_CRASH("not reached");
}
return defer;
}
void
MessageChannel::DispatchInterruptMessage(Message&& aMsg, size_t stackDepth)
{
@@ -1810,56 +1854,18 @@ MessageChannel::DispatchInterruptMessage(Message&& aMsg, size_t stackDepth)
IPC_ASSERT(aMsg.is_interrupt() && !aMsg.is_reply(), "wrong message type");
// Race detection: see the long comment near mRemoteStackDepthGuess in
// MessageChannel.h. "Remote" stack depth means our side, and "local" means
// the other side.
if (aMsg.interrupt_remote_stack_depth_guess() != RemoteViewOfStackDepth(stackDepth)) {
// Interrupt in-calls have raced. The winner, if there is one, gets to defer
// processing of the other side's in-call.
bool defer;
const char* winner;
const MessageInfo parentMsgInfo =
(mSide == ChildSide) ? MessageInfo(aMsg) : mInterruptStack.top();
const MessageInfo childMsgInfo =
(mSide == ChildSide) ? mInterruptStack.top() : MessageInfo(aMsg);
switch (mListener->MediateInterruptRace(parentMsgInfo, childMsgInfo))
{
case RIPChildWins:
winner = "child";
defer = (mSide == ChildSide);
break;
case RIPParentWins:
winner = "parent";
defer = (mSide != ChildSide);
break;
case RIPError:
MOZ_CRASH("NYI: 'Error' Interrupt race policy");
return;
default:
MOZ_CRASH("not reached");
return;
}
if (LoggingEnabled()) {
printf_stderr(" (%s: %s won, so we're%sdeferring)\n",
(mSide == ChildSide) ? "child" : "parent",
winner,
defer ? " " : " not ");
}
if (defer) {
// We now know the other side's stack has one more frame
// than we thought.
++mRemoteStackDepthGuess; // decremented in MaybeProcessDeferred()
mDeferred.push(Move(aMsg));
return;
}
// We "lost" and need to process the other side's in-call. Don't need
// to fix up the mRemoteStackDepthGuess here, because we're just about
// to increment it in DispatchCall(), which will make it correct again.
if (ShouldDeferInterruptMessage(aMsg, stackDepth)) {
// We now know the other side's stack has one more frame
// than we thought.
++mRemoteStackDepthGuess; // decremented in MaybeProcessDeferred()
mDeferred.push(Move(aMsg));
return;
}
// If we "lost" a race and need to process the other side's in-call, we
// don't need to fix up the mRemoteStackDepthGuess here, because we're just
// about to increment it, which will make it correct again.
#ifdef OS_WIN
SyncStackFrame frame(this, true);
#endif
@@ -1895,12 +1901,18 @@ MessageChannel::MaybeUndeferIncall()
size_t stackDepth = InterruptStackDepth();
Message& deferred = mDeferred.top();
// the other side can only *under*-estimate our actual stack depth
IPC_ASSERT(mDeferred.top().interrupt_remote_stack_depth_guess() <= stackDepth,
IPC_ASSERT(deferred.interrupt_remote_stack_depth_guess() <= stackDepth,
"fatal logic error");
if (ShouldDeferInterruptMessage(deferred, stackDepth)) {
return;
}
// maybe time to process this message
Message call(Move(mDeferred.top()));
Message call(Move(deferred));
mDeferred.pop();
// fix up fudge factor we added to account for race
+1
View File
@@ -419,6 +419,7 @@ class MessageChannel : HasResultCodes
bool WasTransactionCanceled(int transaction);
bool ShouldDeferMessage(const Message& aMsg);
bool ShouldDeferInterruptMessage(const Message& aMsg, size_t aStackDepth);
void OnMessageReceivedFromLink(Message&& aMsg);
void OnChannelErrorFromLink();
+6 -16
View File
@@ -843,10 +843,6 @@ DeallocateMappedContent(void* p, size_t length)
#error "Memory mapping functions are not defined for your OS."
#endif
#ifdef XP_WIN
static char sCrashReason[256];
#endif
void
ProtectPages(void* p, size_t size)
{
@@ -856,10 +852,8 @@ ProtectPages(void* p, size_t size)
#if defined(XP_WIN)
DWORD oldProtect;
if (!VirtualProtect(p, size, PAGE_NOACCESS, &oldProtect)) {
SprintfLiteral(sCrashReason,
"MOZ_CRASH(VirtualProtect(PAGE_NOACCESS) failed! Error code: %u)", GetLastError());
MOZ_CRASH_ANNOTATE(sCrashReason);
MOZ_REALLY_CRASH();
MOZ_CRASH_UNSAFE_PRINTF("VirtualProtect(PAGE_NOACCESS) failed! Error code: %u",
GetLastError());
}
MOZ_ASSERT(oldProtect == PAGE_READWRITE);
#else // assume Unix
@@ -877,10 +871,8 @@ MakePagesReadOnly(void* p, size_t size)
#if defined(XP_WIN)
DWORD oldProtect;
if (!VirtualProtect(p, size, PAGE_READONLY, &oldProtect)) {
SprintfLiteral(sCrashReason,
"MOZ_CRASH(VirtualProtect(PAGE_READONLY) failed! Error code: %u)", GetLastError());
MOZ_CRASH_ANNOTATE(sCrashReason);
MOZ_REALLY_CRASH();
MOZ_CRASH_UNSAFE_PRINTF("VirtualProtect(PAGE_READONLY) failed! Error code: %u",
GetLastError());
}
MOZ_ASSERT(oldProtect == PAGE_READWRITE);
#else // assume Unix
@@ -898,10 +890,8 @@ UnprotectPages(void* p, size_t size)
#if defined(XP_WIN)
DWORD oldProtect;
if (!VirtualProtect(p, size, PAGE_READWRITE, &oldProtect)) {
SprintfLiteral(sCrashReason,
"MOZ_CRASH(VirtualProtect(PAGE_READWRITE) failed! Error code: %u)", GetLastError());
MOZ_CRASH_ANNOTATE(sCrashReason);
MOZ_REALLY_CRASH();
MOZ_CRASH_UNSAFE_PRINTF("VirtualProtect(PAGE_READWRITE) failed! Error code: %u",
GetLastError());
}
MOZ_ASSERT(oldProtect == PAGE_NOACCESS || oldProtect == PAGE_READONLY);
#else // assume Unix
+1 -1
View File
@@ -3689,7 +3689,7 @@ js::MaybeAnalyzeBeforeCreatingLargeArray(ExclusiveContext* cx, HandleObjectGroup
ShouldUpdateTypes::Update);
MOZ_ASSERT(result.value == DenseElementResult::Success);
}
objects->maybeAnalyze(cx, group, /* forceAnalyze = */ true);
objects->maybeAnalyze(cx, group, /* force = */ true);
}
}
return true;
+3 -2
View File
@@ -3105,9 +3105,10 @@ Crash(JSContext* cx, unsigned argc, Value* vp)
char* utf8chars = JS_EncodeStringToUTF8(cx, message);
if (!utf8chars)
return false;
#ifndef DEBUG
MOZ_ReportCrash(utf8chars, __FILE__, __LINE__);
MOZ_CRASH_ANNOTATE("MOZ_CRASH(dynamic)");
MOZ_REALLY_CRASH();
#endif
MOZ_CRASH_UNSAFE_OOL(utf8chars);
}
static bool
+28
View File
@@ -63,6 +63,7 @@
#include "ScrollSnap.h"
#include "UnitTransforms.h"
#include "nsPluginFrame.h"
#include "nsSliderFrame.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include <mozilla/layers/AxisPhysicsModel.h>
#include <mozilla/layers/AxisPhysicsMSDModel.h>
@@ -6245,3 +6246,30 @@ ScrollFrameHelper::DragScroll(WidgetEvent* aEvent)
return willScroll;
}
static void
AsyncScrollbarDragRejected(nsIFrame* aScrollbar)
{
if (!aScrollbar) {
return;
}
for (nsIFrame::ChildListIterator childLists(aScrollbar);
!childLists.IsDone();
childLists.Next()) {
for (nsIFrame* frame : childLists.CurrentList()) {
if (nsSliderFrame* sliderFrame = do_QueryFrame(frame)) {
sliderFrame->AsyncScrollbarDragRejected();
}
}
}
}
void
ScrollFrameHelper::AsyncScrollbarDragRejected()
{
// We don't get told which scrollbar requested the async drag,
// so we notify both.
::AsyncScrollbarDragRejected(mHScrollbarBox);
::AsyncScrollbarDragRejected(mVScrollbarBox);
}
+10
View File
@@ -462,6 +462,8 @@ public:
bool DragScroll(WidgetEvent* aEvent);
void AsyncScrollbarDragRejected();
// owning references to the nsIAnonymousContentCreator-built content
nsCOMPtr<nsIContent> mHScrollbarContent;
nsCOMPtr<nsIContent> mVScrollbarContent;
@@ -1045,6 +1047,10 @@ public:
return mHelper.DragScroll(aEvent);
}
virtual void AsyncScrollbarDragRejected() override {
return mHelper.AsyncScrollbarDragRejected();
}
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
@@ -1478,6 +1484,10 @@ public:
return mHelper.DragScroll(aEvent);
}
virtual void AsyncScrollbarDragRejected() override {
return mHelper.AsyncScrollbarDragRejected();
}
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
+2
View File
@@ -483,6 +483,8 @@ public:
* caller should look for an ancestor to scroll.
*/
virtual bool DragScroll(mozilla::WidgetEvent* aEvent) = 0;
virtual void AsyncScrollbarDragRejected() = 0;
};
#endif
+51 -20
View File
@@ -991,36 +991,36 @@ ScrollFrameWillBuildScrollInfoLayer(nsIFrame* aScrollFrame)
return false;
}
bool
void
nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent)
{
if (!aEvent->mFlags.mHandledByAPZ) {
return false;
return;
}
if (!gfxPlatform::GetPlatform()->SupportsApzDragInput()) {
return false;
return;
}
nsContainerFrame* scrollFrame = GetScrollbar()->GetParent();
if (!scrollFrame) {
return false;
return;
}
nsIContent* scrollableContent = scrollFrame->GetContent();
if (!scrollableContent) {
return false;
return;
}
nsIScrollableFrame* scrollFrameAsScrollable = do_QueryFrame(scrollFrame);
if (!scrollFrameAsScrollable) {
return false;
return;
}
// APZ dragging requires the scrollbar to be layerized, which doesn't
// happen for scroll info layers.
if (ScrollFrameWillBuildScrollInfoLayer(scrollFrame)) {
return false;
return;
}
mozilla::layers::FrameMetrics::ViewID scrollTargetId;
@@ -1028,7 +1028,7 @@ nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent)
bool hasAPZView = hasID && (scrollTargetId != layers::FrameMetrics::NULL_SCROLL_ID);
if (!hasAPZView) {
return false;
return;
}
nsIFrame* scrollbarBox = GetScrollbar();
@@ -1053,9 +1053,15 @@ nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent)
AsyncDragMetrics::VERTICAL);
if (!nsLayoutUtils::HasDisplayPort(scrollableContent)) {
return false;
return;
}
// It's important to set this before calling nsIWidget::StartAsyncScrollbarDrag(),
// because in some configurations, that can call AsyncScrollbarDragRejected()
// synchronously, which clears the flag (and we want it to stay cleared in
// that case).
mScrollingWithAPZ = true;
// When we start an APZ drag, we wont get mouse events for the drag.
// APZ will consume them all and only notify us of the new scroll position.
bool waitForRefresh = InputAPZContext::HavePendingLayerization();
@@ -1067,7 +1073,6 @@ nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent)
if (!waitForRefresh) {
widget->StartAsyncScrollbarDrag(dragMetrics);
}
return true;
}
nsresult
@@ -1137,16 +1142,15 @@ nsSliderFrame::StartDrag(nsIDOMEvent* aEvent)
mDragStart = pos - mThumbStart;
mScrollingWithAPZ = StartAPZDrag(event);
mScrollingWithAPZ = false;
StartAPZDrag(event); // sets mScrollingWithAPZ=true if appropriate
#ifdef DEBUG_SLIDER
printf("Pressed mDragStart=%d\n",mDragStart);
#endif
if (!mScrollingWithAPZ && !mSuppressionActive) {
MOZ_ASSERT(PresContext()->PresShell());
APZCCallbackHelper::SuppressDisplayport(true, PresContext()->PresShell());
mSuppressionActive = true;
if (!mScrollingWithAPZ) {
SuppressDisplayport();
}
return NS_OK;
@@ -1160,11 +1164,7 @@ nsSliderFrame::StopDrag()
mScrollingWithAPZ = false;
if (mSuppressionActive) {
MOZ_ASSERT(PresContext()->PresShell());
APZCCallbackHelper::SuppressDisplayport(false, PresContext()->PresShell());
mSuppressionActive = false;
}
UnsuppressDisplayport();
#ifdef MOZ_WIDGET_GTK
nsIFrame* thumbFrame = mFrames.FirstChild();
@@ -1536,5 +1536,36 @@ nsSliderFrame::GetThumbRatio() const
return mRatio / mozilla::AppUnitsPerCSSPixel();
}
void
nsSliderFrame::AsyncScrollbarDragRejected()
{
mScrollingWithAPZ = false;
// Only suppress the displayport if we're still dragging the thumb.
// Otherwise, no one will unsuppress it.
if (isDraggingThumb()) {
SuppressDisplayport();
}
}
void
nsSliderFrame::SuppressDisplayport()
{
if (!mSuppressionActive) {
MOZ_ASSERT(PresContext()->PresShell());
APZCCallbackHelper::SuppressDisplayport(true, PresContext()->PresShell());
mSuppressionActive = true;
}
}
void
nsSliderFrame::UnsuppressDisplayport()
{
if (mSuppressionActive) {
MOZ_ASSERT(PresContext()->PresShell());
APZCCallbackHelper::SuppressDisplayport(false, PresContext()->PresShell());
mSuppressionActive = false;
}
}
NS_IMPL_ISUPPORTS(nsSliderMediator,
nsIDOMEventListener)
+9 -1
View File
@@ -100,7 +100,7 @@ public:
nsresult StartDrag(nsIDOMEvent* aEvent);
nsresult StopDrag();
bool StartAPZDrag(WidgetGUIEvent* aEvent);
void StartAPZDrag(mozilla::WidgetGUIEvent* aEvent);
static int32_t GetCurrentPosition(nsIContent* content);
static int32_t GetMinPosition(nsIContent* content);
@@ -137,6 +137,11 @@ public:
// scrolled frame.
float GetThumbRatio() const;
// Notify the slider frame than an async scrollbar drag requested in
// StartAPZDrag() was rejected by APZ, and the slider frame should
// fall back to main-thread dragging.
void AsyncScrollbarDragRejected();
private:
bool GetScrollToClick();
@@ -158,6 +163,9 @@ private:
void RemoveListener();
bool isDraggingThumb();
void SuppressDisplayport();
void UnsuppressDisplayport();
void StartRepeat() {
nsRepeatService::GetInstance()->Start(Notify, this);
}
+3
View File
@@ -21,4 +21,7 @@ USE_LIBS += [
'memory',
]
# The memory library defines this, so it's needed here too.
DEFINES['IMPL_MFBT'] = True
DISABLE_STL_WRAPPING = True
+52 -3
View File
@@ -3,7 +3,12 @@
* 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/Types.h"
#include "mozilla/Assertions.h"
#include "mozilla/Atomics.h"
#include <stdarg.h>
MOZ_BEGIN_EXTERN_C
/*
* The crash reason is defined as a global variable here rather than in the
@@ -11,7 +16,51 @@
* JS that don't link with the crash reporter directly. This value will only
* be consumed if the crash reporter is used by the target application.
*/
MFBT_DATA const char* gMozCrashReason = nullptr;
#ifndef DEBUG
MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void
MOZ_CrashOOL(int aLine, const char* aReason)
#else
MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void
MOZ_CrashOOL(const char* aFilename, int aLine, const char* aReason)
#endif
{
#ifdef DEBUG
MOZ_ReportCrash(aReason, aFilename, aLine);
#endif
MOZ_CRASH_ANNOTATE(aReason);
MOZ_REALLY_CRASH(aLine);
}
static char sPrintfCrashReason[sPrintfCrashReasonSize] = {};
static mozilla::Atomic<bool> sCrashing(false);
#ifndef DEBUG
MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(2, 3) void
MOZ_CrashPrintf(int aLine, const char* aFormat, ...)
#else
MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(3, 4) void
MOZ_CrashPrintf(const char* aFilename, int aLine, const char* aFormat, ...)
#endif
{
if (!sCrashing.compareExchange(false, true)) {
// In the unlikely event of a race condition, skip
// setting the crash reason and just crash safely.
MOZ_REALLY_CRASH(aLine);
}
va_list aArgs;
va_start(aArgs, aFormat);
int ret = vsnprintf(sPrintfCrashReason, sPrintfCrashReasonSize,
aFormat, aArgs);
va_end(aArgs);
MOZ_RELEASE_ASSERT(ret >= 0 && size_t(ret) < sPrintfCrashReasonSize,
"Could not write the explanation string to the supplied buffer!");
#ifdef DEBUG
MOZ_ReportCrash(sPrintfCrashReason, aFilename, aLine);
#endif
MOZ_CRASH_ANNOTATE(sPrintfCrashReason);
MOZ_REALLY_CRASH(aLine);
}
MOZ_BEGIN_EXTERN_C
MOZ_EXPORT const char* gMozCrashReason = nullptr;
MOZ_END_EXTERN_C
+62 -10
View File
@@ -214,22 +214,22 @@ static MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void MOZ_NoReturn(int aLine)
TerminateProcess(GetCurrentProcess(), 3);
}
# define MOZ_REALLY_CRASH() \
# define MOZ_REALLY_CRASH(line) \
do { \
__debugbreak(); \
MOZ_NoReturn(__LINE__); \
MOZ_NoReturn(line); \
} while (0)
#else
# ifdef __cplusplus
# define MOZ_REALLY_CRASH() \
# define MOZ_REALLY_CRASH(line) \
do { \
*((volatile int*) NULL) = __LINE__; \
*((volatile int*) NULL) = line; \
::abort(); \
} while (0)
# else
# define MOZ_REALLY_CRASH() \
# define MOZ_REALLY_CRASH(line) \
do { \
*((volatile int*) NULL) = __LINE__; \
*((volatile int*) NULL) = line; \
abort(); \
} while (0)
# endif
@@ -260,17 +260,69 @@ static MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void MOZ_NoReturn(int aLine)
# define MOZ_CRASH(...) \
do { \
MOZ_CRASH_ANNOTATE("MOZ_CRASH(" __VA_ARGS__ ")"); \
MOZ_REALLY_CRASH(); \
MOZ_REALLY_CRASH(__LINE__); \
} while (0)
#else
# define MOZ_CRASH(...) \
do { \
MOZ_ReportCrash("" __VA_ARGS__, __FILE__, __LINE__); \
MOZ_CRASH_ANNOTATE("MOZ_CRASH(" __VA_ARGS__ ")"); \
MOZ_REALLY_CRASH(); \
MOZ_REALLY_CRASH(__LINE__); \
} while (0)
#endif
/*
* MOZ_CRASH_UNSAFE_OOL(explanation-string) can be used if the explanation
* string cannot be a string literal (but no other processing needs to be done
* on it). A regular MOZ_CRASH() is preferred wherever possible, as passing
* arbitrary strings from a potentially compromised process is not without risk.
* If the string being passed is the result of a printf-style function,
* consider using MOZ_CRASH_UNSAFE_PRINTF instead.
*/
#ifndef DEBUG
MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void
MOZ_CrashOOL(int aLine, const char* aReason);
# define MOZ_CRASH_UNSAFE_OOL(reason) MOZ_CrashOOL(__LINE__, reason)
#else
MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void
MOZ_CrashOOL(const char* aFilename, int aLine, const char* aReason);
# define MOZ_CRASH_UNSAFE_OOL(reason) MOZ_CrashOOL(__FILE__, __LINE__, reason)
#endif
static const size_t sPrintfMaxArgs = 4;
static const size_t sPrintfCrashReasonSize = 1024;
#ifndef DEBUG
MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(2, 3) void
MOZ_CrashPrintf(int aLine, const char* aFormat, ...);
# define MOZ_CALL_CRASH_PRINTF(format, ...) \
MOZ_CrashPrintf(__LINE__, format, __VA_ARGS__)
#else
MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(3, 4) void
MOZ_CrashPrintf(const char* aFilename, int aLine, const char* aFormat, ...);
# define MOZ_CALL_CRASH_PRINTF(format, ...) \
MOZ_CrashPrintf(__FILE__, __LINE__, format, __VA_ARGS__)
#endif
/*
* MOZ_CRASH_UNSAFE_PRINTF(format, arg1 [, args]) can be used when more
* information is desired than a string literal can supply. The caller provides
* a printf-style format string, which must be a string literal and between
* 1 and 4 additional arguments. A regular MOZ_CRASH() is preferred wherever
* possible, as passing arbitrary strings to printf from a potentially
* compromised process is not without risk.
*/
#define MOZ_CRASH_UNSAFE_PRINTF(format, ...) \
do { \
MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
static_assert( \
MOZ_PASTE_PREFIX_AND_ARG_COUNT(, __VA_ARGS__) <= sPrintfMaxArgs, \
"Only up to 4 additional arguments are allowed!"); \
static_assert(sizeof(format) <= sPrintfCrashReasonSize, \
"The supplied format string is too long!"); \
MOZ_CALL_CRASH_PRINTF("" format, __VA_ARGS__); \
} while (0)
MOZ_END_EXTERN_C
/*
@@ -366,7 +418,7 @@ struct AssertionConditionType
if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \
MOZ_REPORT_ASSERTION_FAILURE(#expr, __FILE__, __LINE__); \
MOZ_CRASH_ANNOTATE("MOZ_RELEASE_ASSERT(" #expr ")"); \
MOZ_REALLY_CRASH(); \
MOZ_REALLY_CRASH(__LINE__); \
} \
} while (0)
/* Now the two-argument form. */
@@ -376,7 +428,7 @@ struct AssertionConditionType
if (MOZ_UNLIKELY(!MOZ_CHECK_ASSERT_ASSIGNMENT(expr))) { \
MOZ_REPORT_ASSERTION_FAILURE(#expr " (" explain ")", __FILE__, __LINE__); \
MOZ_CRASH_ANNOTATE("MOZ_RELEASE_ASSERT(" #expr ") (" explain ")"); \
MOZ_REALLY_CRASH(); \
MOZ_REALLY_CRASH(__LINE__); \
} \
} while (0)
+1 -2
View File
@@ -148,8 +148,7 @@ static MOZ_COLD
void CrashWithReason(const char * reason)
{
#ifndef RELEASE_OR_BETA
MOZ_CRASH_ANNOTATE(reason);
MOZ_REALLY_CRASH();
MOZ_CRASH_UNSAFE_OOL(reason);
#endif
}
+46 -19
View File
@@ -5660,25 +5660,6 @@ NS_IMETHODIMP nsHttpChannel::CloseStickyConnection()
return NS_OK;
}
NS_IMETHODIMP nsHttpChannel::ForceNoSpdy()
{
LOG(("nsHttpChannel::ForceNoSpdy this=%p", this));
MOZ_ASSERT(mTransaction);
if (!mTransaction) {
return NS_ERROR_UNEXPECTED;
}
mAllowSpdy = 0;
mCaps |= NS_HTTP_DISALLOW_SPDY;
if (!(mTransaction->Caps() & NS_HTTP_DISALLOW_SPDY)) {
mTransaction->DisableSpdy();
}
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsHttpChannel::nsISupports
//-----------------------------------------------------------------------------
@@ -6062,6 +6043,52 @@ nsHttpChannel::BeginConnect()
SetLoadGroupUserAgentOverride();
// Check if request was cancelled during on-modify-request or on-useragent.
if (mCanceled) {
return mStatus;
}
if (mSuspendCount) {
LOG(("Waiting until resume BeginConnect [this=%p]\n", this));
MOZ_ASSERT(!mCallOnResume);
mCallOnResume = &nsHttpChannel::HandleBeginConnectContinue;
return NS_OK;
}
return BeginConnectContinue();
}
void
nsHttpChannel::HandleBeginConnectContinue()
{
NS_PRECONDITION(!mCallOnResume, "How did that happen?");
nsresult rv;
if (mSuspendCount) {
LOG(("Waiting until resume BeginConnect [this=%p]\n", this));
mCallOnResume = &nsHttpChannel::HandleBeginConnectContinue;
return;
}
LOG(("nsHttpChannel::HandleBeginConnectContinue [this=%p]\n", this));
rv = BeginConnectContinue();
if (NS_FAILED(rv)) {
CloseCacheEntry(false);
Unused << AsyncAbort(rv);
}
}
nsresult
nsHttpChannel::BeginConnectContinue()
{
nsresult rv;
// Check if request was cancelled during suspend AFTER on-modify-request or
// on-useragent.
if (mCanceled) {
return mStatus;
}
// Check to see if we should redirect this channel elsewhere by
// nsIHttpChannel.redirectTo API request
if (mAPIRedirectToURI) {
+2 -1
View File
@@ -111,7 +111,6 @@ public:
NS_IMETHOD OnAuthAvailable() override;
NS_IMETHOD OnAuthCancelled(bool userCancel) override;
NS_IMETHOD CloseStickyConnection() override;
NS_IMETHOD ForceNoSpdy() override;
// Functions we implement from nsIHttpAuthenticableChannel but are
// declared in HttpBaseChannel must be implemented in this class. We
// just call the HttpBaseChannel:: impls.
@@ -284,6 +283,8 @@ private:
bool RequestIsConditional();
nsresult BeginConnect();
void HandleBeginConnectContinue();
MOZ_MUST_USE nsresult BeginConnectContinue();
nsresult ContinueBeginConnectWithResult();
void ContinueBeginConnect();
nsresult Connect();
@@ -820,10 +820,6 @@ nsHttpChannelAuthProvider::GetCredentialsForChallenge(const char *challenge,
}
mConnectionBased = !!(authFlags & nsIHttpAuthenticator::CONNECTION_BASED);
if (mConnectionBased) {
rv = mAuthChannel->ForceNoSpdy();
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
if (identityInvalid) {
if (entry) {
@@ -2031,11 +2031,6 @@ nsHttpTransaction::CheckForStickyAuthScheme()
MOZ_ASSERT(mResponseHead);
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
if (mClosed) {
LOG((" closed, not checking"));
return;
}
CheckForStickyAuthSchemeAt(nsHttp::WWW_Authenticate);
CheckForStickyAuthSchemeAt(nsHttp::Proxy_Authenticate);
}
+1 -2
View File
@@ -134,8 +134,6 @@ public:
void DispatchedAsBlocking();
void RemoveDispatchedAsBlocking();
void DisableSpdy() override;
nsHttpTransaction *QueryHttpTransaction() override { return this; }
Http2PushedStream *GetPushedStream() { return mPushedStream; }
@@ -203,6 +201,7 @@ private:
bool ResponseTimeoutEnabled() const final;
void DisableSpdy() override;
void ReuseConnectionOnRestartOK(bool reuseOk) override { mReuseOnRestart = reuseOk; }
// Called right after we parsed the response head. Checks for connection based
@@ -112,10 +112,4 @@ interface nsIHttpAuthenticableChannel : nsIProxiedChannel
* the same connection.
*/
void closeStickyConnection();
/**
* Tells the channel to not use SPDY-like protocols, since this will be
* using connection-oriented auth.
*/
void forceNoSpdy();
};
@@ -0,0 +1,175 @@
// This file tests async handling of a channel suspended in http-on-modify-request.
var CC = Components.Constructor;
Cu.import("resource://testing-common/httpd.js");
Cu.import("resource://gre/modules/NetUtil.jsm");
var obs = Cc["@mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
var ios = Cc["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
// baseUrl is always the initial connection attempt and is handled by
// failResponseHandler since every test expects that request will either be
// redirected or cancelled.
var baseUrl;
function failResponseHandler(metadata, response)
{
var text = "failure response";
response.setHeader("Content-Type", "text/plain", false);
response.bodyOutputStream.write(text, text.length);
do_check_true(false, "Received request when we shouldn't.");
}
function successResponseHandler(metadata, response)
{
var text = "success response";
response.setHeader("Content-Type", "text/plain", false);
response.bodyOutputStream.write(text, text.length);
do_check_true(true, "Received expected request.");
}
function onModifyListener(callback) {
obs.addObserver({
observe: function(subject, topic, data) {
var obs = Cc["@mozilla.org/observer-service;1"].getService();
obs = obs.QueryInterface(Ci.nsIObserverService);
obs.removeObserver(this, "http-on-modify-request");
callback(subject.QueryInterface(Ci.nsIHttpChannel));
}
}, "http-on-modify-request", false);
}
function startChannelRequest(baseUrl, flags, expectedResponse=null) {
var chan = NetUtil.newChannel({
uri: baseUrl,
loadUsingSystemPrincipal: true
});
chan.asyncOpen2(new ChannelListener((request, data, context) => {
if (expectedResponse) {
do_check_eq(data, expectedResponse);
} else {
do_check_true(!!!data, "no response");
}
do_execute_soon(run_next_test)
}, null, flags));
}
add_test(function testSimpleRedirect() {
onModifyListener(chan => {
chan.redirectTo(ios.newURI(`${baseUrl}/success`));
});
startChannelRequest(baseUrl, undefined, "success response");
});
add_test(function testSimpleCancel() {
onModifyListener(chan => {
chan.cancel(Cr.NS_BINDING_ABORTED);
});
startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
});
add_test(function testSimpleCancelRedirect() {
onModifyListener(chan => {
chan.redirectTo(ios.newURI(`${baseUrl}/fail`));
chan.cancel(Cr.NS_BINDING_ABORTED);
});
startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
});
// Test a request that will get redirected asynchronously. baseUrl should
// not be requested, we should receive the request for the redirectedUrl.
add_test(function testAsyncRedirect() {
onModifyListener(chan => {
// Suspend the channel then yield to make this async.
chan.suspend();
Promise.resolve().then(() => {
chan.redirectTo(ios.newURI(`${baseUrl}/success`));
chan.resume();
});
});
startChannelRequest(baseUrl, undefined, "success response");
});
add_test(function testSyncRedirect() {
onModifyListener(chan => {
chan.suspend();
chan.redirectTo(ios.newURI(`${baseUrl}/success`));
Promise.resolve().then(() => {
chan.resume();
});
});
startChannelRequest(baseUrl, undefined, "success response");
});
add_test(function testAsyncCancel() {
onModifyListener(chan => {
// Suspend the channel then yield to make this async.
chan.suspend();
Promise.resolve().then(() => {
chan.cancel(Cr.NS_BINDING_ABORTED);
chan.resume();
});
});
startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
});
add_test(function testSyncCancel() {
onModifyListener(chan => {
chan.suspend();
chan.cancel(Cr.NS_BINDING_ABORTED);
Promise.resolve().then(() => {
chan.resume();
});
});
startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
});
// Test request that will get redirected and cancelled asynchronously,
// ensure no connection is made.
add_test(function testAsyncCancelRedirect() {
onModifyListener(chan => {
// Suspend the channel then yield to make this async.
chan.suspend();
Promise.resolve().then(() => {
chan.cancel(Cr.NS_BINDING_ABORTED);
chan.redirectTo(ios.newURI(`${baseUrl}/fail`));
chan.resume();
});
});
startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
});
// Test a request that will get cancelled synchronously, ensure async redirect
// is not made.
add_test(function testSyncCancelRedirect() {
onModifyListener(chan => {
chan.suspend();
chan.cancel(Cr.NS_BINDING_ABORTED);
Promise.resolve().then(() => {
chan.redirectTo(ios.newURI(`${baseUrl}/fail`));
chan.resume();
});
});
startChannelRequest(baseUrl, CL_EXPECT_FAILURE);
});
function run_test() {
var httpServer = new HttpServer();
httpServer.registerPathHandler("/", failResponseHandler);
httpServer.registerPathHandler("/fail", failResponseHandler);
httpServer.registerPathHandler("/success", successResponseHandler);
httpServer.start(-1);
baseUrl = `http://localhost:${httpServer.identity.primaryPort}`;
run_next_test();
do_register_cleanup(function(){
httpServer.stop(() => {});
});
}
+1
View File
@@ -359,6 +359,7 @@ skip-if = os == "android"
[test_1073747.js]
[test_safeoutputstream_append.js]
[test_suspend_channel_before_connect.js]
[test_suspend_channel_on_modified.js]
[test_inhibit_caching.js]
[test_dns_disable_ipv4.js]
[test_dns_disable_ipv6.js]
+44 -6
View File
@@ -598,27 +598,49 @@ Database::BackupAndReplaceDatabaseFile(nsCOMPtr<mozIStorageService>& aStorage)
profDir, getter_AddRefs(backup));
}
// If anything fails from this point on, we have a stale connection or
// database file, and there's not much more we can do.
// The only thing we can try to do is to replace the database on the next
// start, and enforce a crash, so it gets reported to us.
// Close database connection if open.
if (mMainConn) {
// If there's any not finalized statement or this fails for any reason
// we won't be able to remove the database.
rv = mMainConn->Close();
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_SUCCESS(rv, ForceCrashAndReplaceDatabase(
NS_LITERAL_CSTRING("Unable to close the corrupt database.")));
}
// Remove the broken database.
rv = databaseFile->Remove(false);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
return ForceCrashAndReplaceDatabase(
NS_LITERAL_CSTRING("Unable to remove the corrupt database file."));
}
// Create a new database file.
// Use an unshared connection, it will consume more memory but avoid shared
// cache contentions across threads.
rv = aStorage->OpenUnsharedDatabase(databaseFile, getter_AddRefs(mMainConn));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_SUCCESS(rv, ForceCrashAndReplaceDatabase(
NS_LITERAL_CSTRING("Unable to open a new database connection.")));
return NS_OK;
}
nsresult
Database::ForceCrashAndReplaceDatabase(const nsCString& aReason)
{
Preferences::SetBool(PREF_FORCE_DATABASE_REPLACEMENT, true);
// Ensure that prefs get saved, or we could crash before storing them.
nsIPrefService* prefService = Preferences::GetService();
if (prefService && NS_SUCCEEDED(prefService->SavePrefFile(nullptr))) {
// We could force an application restart here, but we'd like to get these
// cases reported to us, so let's force a crash instead.
MOZ_CRASH_UNSAFE_OOL(aReason.get());
}
return NS_ERROR_FAILURE;
}
nsresult
Database::InitSchema(bool* aDatabaseMigrated)
{
@@ -1896,7 +1918,23 @@ Database::MigrateV35Up() {
MOZ_ASSERT(NS_IsMainThread());
int64_t mobileRootId = CreateMobileRoot();
if (mobileRootId <= 0) return NS_ERROR_FAILURE;
if (mobileRootId <= 0) {
// Either the schema is broken or there isn't any root. The latter can
// happen if a consumer, for example Thunderbird, never used bookmarks.
// If there are no roots, this migration should not run.
nsCOMPtr<mozIStorageStatement> checkRootsStmt;
nsresult rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT id FROM moz_bookmarks WHERE parent = 0"
), getter_AddRefs(checkRootsStmt));
NS_ENSURE_SUCCESS(rv, rv);
mozStorageStatementScoper scoper(checkRootsStmt);
bool hasResult = false;
rv = checkRootsStmt->ExecuteStep(&hasResult);
if (NS_SUCCEEDED(rv) && !hasResult) {
return NS_OK;
}
return NS_ERROR_FAILURE;
}
// At this point, we should have no more than two folders with the mobile
// bookmarks anno: the new root, and the old folder if one exists. If, for
+6
View File
@@ -224,6 +224,12 @@ protected:
*/
nsresult BackupAndReplaceDatabaseFile(nsCOMPtr<mozIStorageService>& aStorage);
/**
* This should be used as a last resort in case the database is corrupt and
* there's no way to fix it in-place.
*/
nsresult ForceCrashAndReplaceDatabase(const nsCString& aReason);
/**
* Initializes the database. This performs any necessary migrations for the
* database. All migration is done inside a transaction that is rolled back
@@ -0,0 +1,21 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(function* setup() {
yield setupPlacesDatabase("places_v34.sqlite");
// Setup database contents to be migrated.
let path = OS.Path.join(OS.Constants.Path.profileDir, DB_FILENAME);
let db = yield Sqlite.openConnection({ path });
// Remove all the roots.
yield db.execute("DELETE FROM moz_bookmarks");
yield db.close();
});
add_task(function* database_is_valid() {
// Accessing the database for the first time triggers migration.
Assert.equal(PlacesUtils.history.databaseStatus,
PlacesUtils.history.DATABASE_STATUS_UPGRADED);
let db = yield PlacesUtils.promiseDBConnection();
Assert.equal((yield db.getSchemaVersion()), CURRENT_SCHEMA_VERSION);
});
@@ -33,4 +33,5 @@ support-files =
[test_current_from_v27.js]
[test_current_from_v31.js]
[test_current_from_v34.js]
[test_current_from_v34_no_roots.js]
[test_current_from_v35.js]
@@ -2716,14 +2716,12 @@ nsExternalHelperAppService::GetTypeFromExtension(const nsACString& aFileExt,
}
// Ask OS.
bool found = false;
nsCOMPtr<nsIMIMEInfo> mi = GetMIMEInfoFromOS(EmptyCString(), aFileExt, &found);
if (mi && found) {
return mi->GetMIMEType(aContentType);
if (GetMIMETypeFromOSForExtension(aFileExt, aContentType)) {
return NS_OK;
}
// Check extras array.
found = GetTypeFromExtras(aFileExt, aContentType);
bool found = GetTypeFromExtras(aFileExt, aContentType);
if (found) {
return NS_OK;
}
@@ -2922,3 +2920,11 @@ bool nsExternalHelperAppService::GetTypeFromExtras(const nsACString& aExtension,
return false;
}
bool
nsExternalHelperAppService::GetMIMETypeFromOSForExtension(const nsACString& aExtension, nsACString& aMIMEType)
{
bool found = false;
nsCOMPtr<nsIMIMEInfo> mimeInfo = GetMIMEInfoFromOS(EmptyCString(), aExtension, &found);
return found && mimeInfo && NS_SUCCEEDED(mimeInfo->GetMIMEType(aMIMEType));
}
@@ -108,6 +108,15 @@ public:
virtual nsresult OSProtocolHandlerExists(const char *aScheme,
bool *aExists) = 0;
/**
* Given an extension, get a MIME type string. If not overridden by
* the OS-specific nsOSHelperAppService, will call into GetMIMEInfoFromOS
* with an empty mimetype.
* @return true if we successfully found a mimetype.
*/
virtual bool GetMIMETypeFromOSForExtension(const nsACString& aExtension,
nsACString& aMIMEType);
protected:
virtual ~nsExternalHelperAppService();
@@ -395,43 +395,25 @@ already_AddRefed<nsMIMEInfoWin> nsOSHelperAppService::GetByExtension(const nsAFl
if (aFileExt.IsEmpty())
return nullptr;
// windows registry assumes your file extension is going to include the '.'.
// so make sure it's there...
// Determine the mime type.
nsAutoCString typeToUse;
if (aTypeHint && *aTypeHint) {
typeToUse.Assign(aTypeHint);
} else if (!GetMIMETypeFromOSForExtension(NS_ConvertUTF16toUTF8(aFileExt), typeToUse)) {
return nullptr;
}
RefPtr<nsMIMEInfoWin> mimeInfo = new nsMIMEInfoWin(typeToUse);
// windows registry assumes your file extension is going to include the '.',
// but our APIs expect it to not be there, so make sure we normalize that bit.
nsAutoString fileExtToUse;
if (aFileExt.First() != char16_t('.'))
fileExtToUse = char16_t('.');
fileExtToUse.Append(aFileExt);
// Try to get an entry from the windows registry.
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1");
if (!regKey)
return nullptr;
nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT,
fileExtToUse,
nsIWindowsRegKey::ACCESS_QUERY_VALUE);
if (NS_FAILED(rv))
return nullptr;
nsAutoCString typeToUse;
if (aTypeHint && *aTypeHint) {
typeToUse.Assign(aTypeHint);
}
else {
nsAutoString temp;
if (NS_FAILED(regKey->ReadStringValue(NS_LITERAL_STRING("Content Type"),
temp)) || temp.IsEmpty()) {
return nullptr;
}
// Content-Type is always in ASCII
LossyAppendUTF16toASCII(temp, typeToUse);
}
RefPtr<nsMIMEInfoWin> mimeInfo = new nsMIMEInfoWin(typeToUse);
// don't append the '.'
// don't append the '.' for our APIs.
mimeInfo->AppendExtension(NS_ConvertUTF16toUTF8(Substring(fileExtToUse, 1)));
mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault);
@@ -458,8 +440,17 @@ already_AddRefed<nsMIMEInfoWin> nsOSHelperAppService::GetByExtension(const nsAFl
}
else
{
found = NS_SUCCEEDED(regKey->ReadStringValue(EmptyString(),
appInfo));
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1");
if (!regKey)
return nullptr;
nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT,
fileExtToUse,
nsIWindowsRegKey::ACCESS_QUERY_VALUE);
if (NS_SUCCEEDED(rv)) {
found = NS_SUCCEEDED(regKey->ReadStringValue(EmptyString(),
appInfo));
}
}
// Bug 358297 - ignore the default handler, force the user to choose app
@@ -596,3 +587,40 @@ nsOSHelperAppService::GetProtocolHandlerInfoFromOS(const nsACString &aScheme,
return NS_OK;
}
bool
nsOSHelperAppService::GetMIMETypeFromOSForExtension(const nsACString& aExtension,
nsACString& aMIMEType)
{
if (aExtension.IsEmpty())
return false;
// windows registry assumes your file extension is going to include the '.'.
// so make sure it's there...
nsAutoString fileExtToUse;
if (aExtension.First() != '.')
fileExtToUse = char16_t('.');
AppendUTF8toUTF16(aExtension, fileExtToUse);
// Try to get an entry from the windows registry.
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1");
if (!regKey)
return false;
nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT,
fileExtToUse,
nsIWindowsRegKey::ACCESS_QUERY_VALUE);
if (NS_FAILED(rv))
return false;
nsAutoString mimeType;
if (NS_FAILED(regKey->ReadStringValue(NS_LITERAL_STRING("Content Type"),
mimeType)) || mimeType.IsEmpty()) {
return false;
}
// Content-Type is always in ASCII
aMIMEType.Truncate();
LossyAppendUTF16toASCII(mimeType, aMIMEType);
return true;
}
@@ -40,6 +40,8 @@ public:
NS_IMETHOD GetProtocolHandlerInfoFromOS(const nsACString &aScheme,
bool *found,
nsIHandlerInfo **_retval);
virtual bool GetMIMETypeFromOSForExtension(const nsACString& aExtension,
nsACString& aMIMEType) override;
/** Get the string value of a registry value and store it in result.
* @return true on success, false on failure
+3
View File
@@ -493,6 +493,9 @@ public:
LayoutDeviceIntPoint CocoaPointsToDevPixels(const NSPoint& aPt) const {
return nsCocoaUtils::CocoaPointsToDevPixels(aPt, BackingScaleFactor());
}
LayoutDeviceIntPoint CocoaPointsToDevPixelsRoundDown(const NSPoint& aPt) const {
return nsCocoaUtils::CocoaPointsToDevPixelsRoundDown(aPt, BackingScaleFactor());
}
LayoutDeviceIntRect CocoaPointsToDevPixels(const NSRect& aRect) const {
return nsCocoaUtils::CocoaPointsToDevPixels(aRect, BackingScaleFactor());
}
+27 -8
View File
@@ -195,6 +195,7 @@ static uint32_t gNumberOfWidgetsNeedingEventThread = 0;
#endif
- (LayoutDeviceIntPoint)convertWindowCoordinates:(NSPoint)aPoint;
- (LayoutDeviceIntPoint)convertWindowCoordinatesRoundDown:(NSPoint)aPoint;
- (IAPZCTreeManager*)apzctm;
- (BOOL)inactiveWindowAcceptsMouseEvent:(NSEvent*)aEvent;
@@ -4832,16 +4833,20 @@ AccumulateIntegerDelta(NSEvent* aEvent)
static gfx::IntPoint
GetIntegerDeltaForEvent(NSEvent* aEvent)
{
if (nsCocoaFeatures::OnSierraOrLater()) {
if (nsCocoaFeatures::OnSierraOrLater() && [aEvent hasPreciseScrollingDeltas]) {
// Pixel scroll events (events with hasPreciseScrollingDeltas == YES)
// carry pixel deltas in the scrollingDeltaX/Y fields and line scroll
// information in the deltaX/Y fields.
// Prior to 10.12, these line scroll fields would be zero for most pixel
// scroll events and non-zero for some, whenever at least a full line
// worth of pixel scrolling had accumulated. That's the behavior we want.
// Starting with 10.12 however, pixel scroll events no longer accumulate
// deltaX and deltaY; they just report floating point values for every
// single event. So we need to do our own accumulation.
return AccumulateIntegerDelta(aEvent);
}
// Pre-10.12, deltaX/deltaY had the accumulation behavior that we want, and
// it worked more reliably than doing it on our own, so use it on pre-10.12
// versions. For example, with a traditional USB mouse, the first wheel
// "tick" would always senda line scroll of at least one line, but with our
// own accumulation you sometimes need to do multiple wheel ticks before one
// line has been accumulated.
// For line scrolls, or pre-10.12, just use the rounded up value of deltaX / deltaY.
return gfx::IntPoint(RoundUp([aEvent deltaX]), RoundUp([aEvent deltaY]));
}
@@ -4889,8 +4894,12 @@ GetIntegerDeltaForEvent(NSEvent* aEvent)
NSPoint locationInWindow = nsCocoaUtils::EventLocationForWindow(theEvent, [self window]);
// Use convertWindowCoordinatesRoundDown when converting the position to
// integer screen pixels in order to ensure that coordinates which are just
// inside the right / bottom edges of the window don't end up outside of the
// window after rounding.
ScreenPoint position = ViewAs<ScreenPixel>(
[self convertWindowCoordinates:locationInWindow],
[self convertWindowCoordinatesRoundDown:locationInWindow],
PixelCastJustification::LayoutDeviceIsScreenForUntransformedEvent);
bool usePreciseDeltas = nsCocoaUtils::HasPreciseScrollingDeltas(theEvent) &&
@@ -5603,6 +5612,16 @@ GetIntegerDeltaForEvent(NSEvent* aEvent)
return mGoannaChild->CocoaPointsToDevPixels(localPoint);
}
- (LayoutDeviceIntPoint)convertWindowCoordinatesRoundDown:(NSPoint)aPoint
{
if (!mGoannaChild) {
return LayoutDeviceIntPoint(0, 0);
}
NSPoint localPoint = [self convertPoint:aPoint fromView:nil];
return mGoannaChild->CocoaPointsToDevPixelsRoundDown(localPoint);
}
- (IAPZCTreeManager*)apzctm
{
return mGoannaChild ? mGoannaChild->APZCTM() : nullptr;
+7
View File
@@ -144,6 +144,13 @@ public:
NSToIntRound(aPt.y * aBackingScale));
}
static LayoutDeviceIntPoint
CocoaPointsToDevPixelsRoundDown(const NSPoint& aPt, CGFloat aBackingScale)
{
return LayoutDeviceIntPoint(NSToIntFloor(aPt.x * aBackingScale),
NSToIntFloor(aPt.y * aBackingScale));
}
static LayoutDeviceIntRect
CocoaPointsToDevPixels(const NSRect& aRect, CGFloat aBackingScale)
{
+28
View File
@@ -25,6 +25,12 @@
#include "nsComponentManagerUtils.h"
#include "nsITimer.h"
// These are two messages that the code in winspool.drv on Windows 7 explicitly
// waits for while it is pumping other Windows messages, during display of the
// Printer Properties dialog.
#define MOZ_WM_PRINTER_PROPERTIES_COMPLETION 0x5b7a
#define MOZ_WM_PRINTER_PROPERTIES_FAILURE 0x5b7f
using namespace mozilla;
using namespace mozilla::widget;
@@ -367,6 +373,15 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
continue; // the message is consumed.
}
// Store Printer Properties messages for reposting, because they are not
// processed by a window procedure, but are explicitly waited for in the
// winspool.drv code that will be further up the stack.
if (msg.message == MOZ_WM_PRINTER_PROPERTIES_COMPLETION ||
msg.message == MOZ_WM_PRINTER_PROPERTIES_FAILURE) {
mMsgsToRepost.push_back(msg);
continue;
}
::TranslateMessage(&msg);
::DispatchMessageW(&msg);
}
@@ -402,3 +417,16 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
return gotMessage;
}
nsresult
nsAppShell::AfterProcessNextEvent(nsIThreadInternal* /* unused */,
bool /* unused */)
{
if (!mMsgsToRepost.empty()) {
for (MSG msg : mMsgsToRepost) {
::PostMessageW(msg.hwnd, msg.message, msg.wParam, msg.lParam);
}
mMsgsToRepost.clear();
}
return NS_OK;
}
+5
View File
@@ -8,6 +8,7 @@
#include "nsBaseAppShell.h"
#include <windows.h>
#include <vector>
#include "mozilla/TimeStamp.h"
#include "mozilla/Mutex.h"
@@ -34,6 +35,9 @@ public:
static UINT GetTaskbarButtonCreatedMessage();
NS_IMETHOD AfterProcessNextEvent(nsIThreadInternal* thread,
bool eventWasProcessed) final;
protected:
NS_IMETHOD Run();
NS_IMETHOD Exit();
@@ -49,6 +53,7 @@ protected:
Mutex mLastNativeEventScheduledMutex;
TimeStamp mLastNativeEventScheduled;
std::vector<MSG> mMsgsToRepost;
};
#endif // nsAppShell_h__
+2 -7
View File
@@ -634,13 +634,8 @@ RegisterStaticAtoms(const nsStaticAtom* aAtoms, uint32_t aAtomCount)
if (!atom->IsStaticAtom()) {
nsAutoCString name;
atom->ToUTF8String(name);
static char sCrashReason[1024];
SprintfLiteral(sCrashReason,
"static atom registration for %s should be pushed back",
name.get());
MOZ_CRASH_ANNOTATE(sCrashReason);
MOZ_REALLY_CRASH();
MOZ_CRASH_UNSAFE_PRINTF(
"Static atom registration for %s should be pushed back", name.get());
}
} else {
atom = new StaticAtom(stringBuffer, stringLen, hash);
+4 -11
View File
@@ -9,6 +9,7 @@
#include "nsXPCOM.h"
#include "nsDebug.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/IntegerPrintfMacros.h"
nsTArrayHeader nsTArrayHeader::sEmptyHdr = { 0, 0, 0 };
@@ -22,15 +23,7 @@ IsTwiceTheRequiredBytesRepresentableAsUint32(size_t aCapacity, size_t aElemSize)
MOZ_NORETURN MOZ_COLD void
InvalidArrayIndex_CRASH(size_t aIndex, size_t aLength)
{
const size_t CAPACITY = 512;
// Leak the buffer on the heap to make sure that it lives long enough, as
// MOZ_CRASH_ANNOTATE expects the pointer passed to it to live to the end of
// the program.
auto* buffer = new char[CAPACITY];
snprintf(buffer, CAPACITY,
"ElementAt(aIndex = %llu, aLength = %llu)",
(long long unsigned) aIndex,
(long long unsigned) aLength);
MOZ_CRASH_ANNOTATE(buffer);
MOZ_REALLY_CRASH();
MOZ_CRASH_UNSAFE_PRINTF(
"ElementAt(aIndex = %" PRIu64 ", aLength = %" PRIu64 ")",
static_cast<uint64_t>(aIndex), static_cast<uint64_t>(aLength));
}