Merge inbound to central, a=merge

MozReview-Commit-ID: EI67EKp8ykS
This commit is contained in:
Wes Kocher 2017-05-19 15:14:19 -07:00
Родитель b3e139291b c0fe8b0e0e
Коммит 15edcfd962
46 изменённых файлов: 570 добавлений и 407 удалений

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

@ -268,13 +268,17 @@ menuitem.bookmark-item {
#main-window { #main-window {
--urlbar-border-color: ThreeDShadow; --urlbar-border-color: ThreeDShadow;
--urlbar-border-color-hover: var(--urlbar-border-color); --urlbar-border-color-hover: var(--urlbar-border-color);
--urlbar-background-color: -moz-field;
} }
#navigator-toolbox:-moz-lwtheme { #navigator-toolbox:-moz-lwtheme {
--urlbar-border-color: rgba(0,0,0,.3); --urlbar-border-color: rgba(0,0,0,.3);
} }
#urlbar {
/* override textbox[enablehistory="true"] styling: */
background-color: -moz-field;
}
%include ../shared/urlbar-searchbar.inc.css %include ../shared/urlbar-searchbar.inc.css
%ifdef MOZ_PHOTON_THEME %ifdef MOZ_PHOTON_THEME
@ -301,10 +305,6 @@ menuitem.bookmark-item {
border-color: Highlight; border-color: Highlight;
} }
#urlbar {
background-color: -moz-field;
}
#urlbar:-moz-lwtheme, #urlbar:-moz-lwtheme,
.searchbar-textbox:-moz-lwtheme { .searchbar-textbox:-moz-lwtheme {
background-color: rgba(255,255,255,.8); background-color: rgba(255,255,255,.8);

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

@ -527,7 +527,6 @@ toolbarpaletteitem[place="palette"] > #personal-bookmarks > #bookmarks-toolbar-p
#main-window { #main-window {
--urlbar-border-color: hsla(240, 5%, 5%, .25); --urlbar-border-color: hsla(240, 5%, 5%, .25);
--urlbar-border-color-hover: hsla(240, 5%, 5%, .35); --urlbar-border-color-hover: hsla(240, 5%, 5%, .35);
--urlbar-background-color: -moz-field;
} }
#urlbar[focused="true"], #urlbar[focused="true"],

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

@ -8,7 +8,6 @@
.searchbar-textbox { .searchbar-textbox {
-moz-appearance: none; -moz-appearance: none;
background-clip: content-box; background-clip: content-box;
background-color: var(--urlbar-background-color);
border: 1px solid var(--urlbar-border-color); border: 1px solid var(--urlbar-border-color);
border-radius: var(--toolbarbutton-border-radius); border-radius: var(--toolbarbutton-border-radius);
box-shadow: 0 1px 4px hsla(0, 0%, 0%, .05); box-shadow: 0 1px 4px hsla(0, 0%, 0%, .05);

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

@ -670,7 +670,6 @@ toolbar[brighttext] #close-button {
#main-window:not(:-moz-lwtheme) { #main-window:not(:-moz-lwtheme) {
--urlbar-border-color: hsla(240, 5%, 5%, .25); --urlbar-border-color: hsla(240, 5%, 5%, .25);
--urlbar-border-color-hover: hsla(240, 5%, 5%, .35); --urlbar-border-color-hover: hsla(240, 5%, 5%, .35);
--urlbar-background-color: -moz-field;
} }
} }

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

@ -256,6 +256,7 @@ TimeoutManager::TimeoutManager(nsGlobalWindow& aWindow)
TimeoutManager::~TimeoutManager() TimeoutManager::~TimeoutManager()
{ {
MOZ_DIAGNOSTIC_ASSERT(mWindow.AsInner()->InnerObjectsFreed());
MOZ_DIAGNOSTIC_ASSERT(!mThrottleTrackingTimeoutsTimer); MOZ_DIAGNOSTIC_ASSERT(!mThrottleTrackingTimeoutsTimer);
MOZ_LOG(gLog, LogLevel::Debug, MOZ_LOG(gLog, LogLevel::Debug,
@ -1472,7 +1473,8 @@ TimeoutManager::OnDocumentLoaded()
void void
TimeoutManager::MaybeStartThrottleTrackingTimout() TimeoutManager::MaybeStartThrottleTrackingTimout()
{ {
if (gTrackingTimeoutThrottlingDelay <= 0) { if (gTrackingTimeoutThrottlingDelay <= 0 ||
mWindow.AsInner()->InnerObjectsFreed()) {
return; return;
} }

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

@ -424,6 +424,10 @@ def DOMClass(descriptor):
hooks=NativePropertyHooks(descriptor)) hooks=NativePropertyHooks(descriptor))
def InstanceReservedSlots(descriptor):
return INSTANCE_RESERVED_SLOTS + descriptor.interface.totalMembersInSlots
class CGDOMJSClass(CGThing): class CGDOMJSClass(CGThing):
""" """
Generate a DOMJSClass for a given descriptor Generate a DOMJSClass for a given descriptor
@ -438,7 +442,7 @@ class CGDOMJSClass(CGThing):
def define(self): def define(self):
callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr' callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr'
objectMovedHook = OBJECT_MOVED_HOOK_NAME if self.descriptor.wrapperCache else 'nullptr' objectMovedHook = OBJECT_MOVED_HOOK_NAME if self.descriptor.wrapperCache else 'nullptr'
slotCount = INSTANCE_RESERVED_SLOTS + self.descriptor.interface.totalMembersInSlots slotCount = InstanceReservedSlots(self.descriptor)
classFlags = "JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | " classFlags = "JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | "
if self.descriptor.isGlobal(): if self.descriptor.isGlobal():
classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS)" classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS)"
@ -528,9 +532,10 @@ class CGDOMProxyJSClass(CGThing):
return "" return ""
def define(self): def define(self):
slotCount = InstanceReservedSlots(self.descriptor)
# We need one reserved slot (DOM_OBJECT_SLOT). # We need one reserved slot (DOM_OBJECT_SLOT).
flags = ["JSCLASS_IS_DOMJSCLASS", flags = ["JSCLASS_IS_DOMJSCLASS",
"JSCLASS_HAS_RESERVED_SLOTS(1)"] "JSCLASS_HAS_RESERVED_SLOTS(%d)" % slotCount]
# We don't use an IDL annotation for JSCLASS_EMULATES_UNDEFINED because # We don't use an IDL annotation for JSCLASS_EMULATES_UNDEFINED because
# we don't want people ever adding that to any interface other than # we don't want people ever adding that to any interface other than
# HTMLAllCollection. So just hardcode it here. # HTMLAllCollection. So just hardcode it here.
@ -12717,10 +12722,6 @@ class CGDescriptor(CGThing):
if descriptor.concrete: if descriptor.concrete:
if descriptor.proxy: if descriptor.proxy:
if descriptor.interface.totalMembersInSlots != 0:
raise TypeError("We can't have extra reserved slots for "
"proxy interface %s" %
descriptor.interface.identifier.name)
cgThings.append(CGGeneric(fill( cgThings.append(CGGeneric(fill(
""" """
static_assert(IsBaseOf<nsISupports, ${nativeType} >::value, static_assert(IsBaseOf<nsISupports, ${nativeType} >::value,
@ -12741,6 +12742,7 @@ class CGDescriptor(CGThing):
else: else:
cgThings.append(CGDOMJSClass(descriptor)) cgThings.append(CGDOMJSClass(descriptor))
cgThings.append(CGGetJSClassMethod(descriptor)) cgThings.append(CGGetJSClassMethod(descriptor))
if descriptor.interface.hasMembersInSlots(): if descriptor.interface.hasMembersInSlots():
cgThings.append(CGUpdateMemberSlotsMethod(descriptor)) cgThings.append(CGUpdateMemberSlotsMethod(descriptor))

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

@ -1217,6 +1217,8 @@ public:
uint32_t Item(uint32_t, bool&) = delete; uint32_t Item(uint32_t, bool&) = delete;
uint32_t Length(); uint32_t Length();
void LegacyCall(JS::Handle<JS::Value>); void LegacyCall(JS::Handle<JS::Value>);
int32_t CachedAttr();
int32_t StoreInSlotAttr();
}; };
class TestNamedGetterInterface : public nsISupports, class TestNamedGetterInterface : public nsISupports,

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

@ -1188,6 +1188,8 @@ interface TestIndexedGetterInterface {
getter long item(unsigned long idx); getter long item(unsigned long idx);
readonly attribute unsigned long length; readonly attribute unsigned long length;
legacycaller void(); legacycaller void();
[Cached, Pure] readonly attribute long cachedAttr;
[StoreInSlot, Pure] readonly attribute long storeInSlotAttr;
}; };
interface TestNamedGetterInterface { interface TestNamedGetterInterface {

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

@ -192,6 +192,10 @@ IPCBlobInputStream::Clone(nsIInputStream** aResult)
MOZ_ASSERT(mActor); MOZ_ASSERT(mActor);
nsCOMPtr<nsIInputStream> stream = mActor->CreateStream(); nsCOMPtr<nsIInputStream> stream = mActor->CreateStream();
if (!stream) {
return NS_ERROR_FAILURE;
}
stream.forget(aResult); stream.forget(aResult);
return NS_OK; return NS_OK;
} }

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

@ -13,19 +13,17 @@ namespace {
// This runnable is used in case the last stream is forgotten on the 'wrong' // This runnable is used in case the last stream is forgotten on the 'wrong'
// thread. // thread.
class DeleteRunnable final : public Runnable class ShutdownRunnable final : public Runnable
{ {
public: public:
explicit DeleteRunnable(IPCBlobInputStreamChild* aActor) explicit ShutdownRunnable(IPCBlobInputStreamChild* aActor)
: mActor(aActor) : mActor(aActor)
{} {}
NS_IMETHOD NS_IMETHOD
Run() override Run() override
{ {
if (mActor->IsAlive()) { mActor->Shutdown();
mActor->Send__delete__(mActor);
}
return NS_OK; return NS_OK;
} }
@ -95,13 +93,32 @@ IPCBlobInputStreamChild::IPCBlobInputStreamChild(const nsID& aID,
IPCBlobInputStreamChild::~IPCBlobInputStreamChild() IPCBlobInputStreamChild::~IPCBlobInputStreamChild()
{} {}
void
IPCBlobInputStreamChild::Shutdown()
{
MutexAutoLock lock(mMutex);
RefPtr<IPCBlobInputStreamChild> kungFuDeathGrip = this;
mPendingOperations.Clear();
if (mActorAlive) {
SendClose();
mActorAlive = false;
}
}
void void
IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason) IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason)
{
{ {
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
mActorAlive = false; mActorAlive = false;
} }
Shutdown();
}
bool bool
IPCBlobInputStreamChild::IsAlive() IPCBlobInputStreamChild::IsAlive()
{ {
@ -114,6 +131,10 @@ IPCBlobInputStreamChild::CreateStream()
{ {
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
if (!mActorAlive) {
return nullptr;
}
RefPtr<IPCBlobInputStream> stream = new IPCBlobInputStream(this); RefPtr<IPCBlobInputStream> stream = new IPCBlobInputStream(this);
mStreams.AppendElement(stream); mStreams.AppendElement(stream);
return stream.forget(); return stream.forget();
@ -124,7 +145,7 @@ IPCBlobInputStreamChild::ForgetStream(IPCBlobInputStream* aStream)
{ {
MOZ_ASSERT(aStream); MOZ_ASSERT(aStream);
RefPtr<IPCBlobInputStreamChild> kungFoDeathGrip = this; RefPtr<IPCBlobInputStreamChild> kungFuDeathGrip = this;
{ {
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
@ -136,11 +157,11 @@ IPCBlobInputStreamChild::ForgetStream(IPCBlobInputStream* aStream)
} }
if (mOwningThread == NS_GetCurrentThread()) { if (mOwningThread == NS_GetCurrentThread()) {
Send__delete__(this); Shutdown();
return; return;
} }
RefPtr<DeleteRunnable> runnable = new DeleteRunnable(this); RefPtr<ShutdownRunnable> runnable = new ShutdownRunnable(this);
mOwningThread->Dispatch(runnable, NS_DISPATCH_NORMAL); mOwningThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
} }
@ -149,6 +170,11 @@ IPCBlobInputStreamChild::StreamNeeded(IPCBlobInputStream* aStream,
nsIEventTarget* aEventTarget) nsIEventTarget* aEventTarget)
{ {
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
if (!mActorAlive) {
return;
}
MOZ_ASSERT(mStreams.Contains(aStream)); MOZ_ASSERT(mStreams.Contains(aStream));
PendingOperation* opt = mPendingOperations.AppendElement(); PendingOperation* opt = mPendingOperations.AppendElement();
@ -175,6 +201,7 @@ IPCBlobInputStreamChild::RecvStreamReady(const OptionalIPCStream& aStream)
{ {
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
MOZ_ASSERT(!mPendingOperations.IsEmpty()); MOZ_ASSERT(!mPendingOperations.IsEmpty());
MOZ_ASSERT(mActorAlive);
pendingStream = mPendingOperations[0].mStream; pendingStream = mPendingOperations[0].mStream;
eventTarget = mPendingOperations[0].mEventTarget; eventTarget = mPendingOperations[0].mEventTarget;

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

@ -56,6 +56,9 @@ public:
mozilla::ipc::IPCResult mozilla::ipc::IPCResult
RecvStreamReady(const OptionalIPCStream& aStream) override; RecvStreamReady(const OptionalIPCStream& aStream) override;
void
Shutdown();
private: private:
~IPCBlobInputStreamChild(); ~IPCBlobInputStreamChild();

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

@ -96,5 +96,14 @@ IPCBlobInputStreamParent::RecvStreamNeeded()
return IPC_OK(); return IPC_OK();
} }
mozilla::ipc::IPCResult
IPCBlobInputStreamParent::RecvClose()
{
MOZ_ASSERT(mContentManager || mPBackgroundManager);
Unused << Send__delete__(this);
return IPC_OK();
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

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

@ -44,6 +44,9 @@ public:
mozilla::ipc::IPCResult mozilla::ipc::IPCResult
RecvStreamNeeded() override; RecvStreamNeeded() override;
mozilla::ipc::IPCResult
RecvClose() override;
private: private:
IPCBlobInputStreamParent(const nsID& aID, uint64_t aSize, IPCBlobInputStreamParent(const nsID& aID, uint64_t aSize,
nsIContentParent* aManager); nsIContentParent* aManager);

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

@ -20,11 +20,11 @@ protocol PIPCBlobInputStream
parent: parent:
async StreamNeeded(); async StreamNeeded();
async Close();
async __delete__();
child: child:
async StreamReady(OptionalIPCStream aStream); async StreamReady(OptionalIPCStream aStream);
async __delete__();
}; };
} // namespace dom } // namespace dom

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

@ -44,6 +44,11 @@ public:
bool Selected() const; bool Selected() const;
bool DefaultSelected() const; bool DefaultSelected() const;
void SetSelectedChanged(bool aValue)
{
mSelectedChanged = aValue;
}
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
int32_t aModType) const override; int32_t aModType) const override;

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

@ -1072,7 +1072,7 @@ HTMLSelectElement::SetOptionsSelectedByIndex(int32_t aStartIndex,
} }
// Make sure something is selected unless we were set to -1 (none) // Make sure something is selected unless we were set to -1 (none)
if (optionsDeselected && aStartIndex != -1) { if (optionsDeselected && aStartIndex != -1 && !(aOptionsMask & NO_RESELECT)) {
optionsSelected = optionsSelected =
CheckSelectSomething(aOptionsMask & NOTIFY) || optionsSelected; CheckSelectSomething(aOptionsMask & NOTIFY) || optionsSelected;
} }
@ -1648,13 +1648,14 @@ HTMLSelectElement::Reset()
// Reset the option to its default value // Reset the option to its default value
// //
uint32_t mask = SET_DISABLED | NOTIFY; uint32_t mask = SET_DISABLED | NOTIFY | NO_RESELECT;
if (option->DefaultSelected()) { if (option->DefaultSelected()) {
mask |= IS_SELECTED; mask |= IS_SELECTED;
numSelected++; numSelected++;
} }
SetOptionsSelectedByIndex(i, i, mask); SetOptionsSelectedByIndex(i, i, mask);
option->SetSelectedChanged(false);
} }
} }

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

@ -134,12 +134,16 @@ public:
* (for JavaScript) * (for JavaScript)
* *
* NOTIFY whether to notify frames and such * NOTIFY whether to notify frames and such
*
* NO_RESELECT no need to select something after an option is deselected
* (for reset)
*/ */
enum OptionType { enum OptionType {
IS_SELECTED = 1 << 0, IS_SELECTED = 1 << 0,
CLEAR_ALL = 1 << 1, CLEAR_ALL = 1 << 1,
SET_DISABLED = 1 << 2, SET_DISABLED = 1 << 2,
NOTIFY = 1 << 3 NOTIFY = 1 << 3,
NO_RESELECT = 1 << 4
}; };
using nsIConstraintValidation::GetValidationMessage; using nsIConstraintValidation::GetValidationMessage;

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

@ -89,7 +89,7 @@ SessionStorageManager::GetStorage(mozIDOMWindow* aWindow,
nsAutoCString originKey; nsAutoCString originKey;
nsAutoCString originAttributes; nsAutoCString originAttributes;
nsresult rv = GenerateOriginKey(aPrincipal, originAttributes, originKey); nsresult rv = GenerateOriginKey(aPrincipal, originAttributes, originKey);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_FAILED(rv)) {
return rv; return rv;
} }
@ -128,7 +128,7 @@ SessionStorageManager::CloneStorage(nsIDOMStorage* aStorage)
nsAutoCString originAttributes; nsAutoCString originAttributes;
nsresult rv = GenerateOriginKey(storage->Principal(), originAttributes, nsresult rv = GenerateOriginKey(storage->Principal(), originAttributes,
originKey); originKey);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_FAILED(rv)) {
return rv; return rv;
} }

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

@ -67,6 +67,7 @@ AndroidDynamicToolbarAnimator::AndroidDynamicToolbarAnimator()
, mCompositorReceivedFirstPaint(false) , mCompositorReceivedFirstPaint(false)
, mCompositorWaitForPageResize(false) , mCompositorWaitForPageResize(false)
, mCompositorToolbarShowRequested(false) , mCompositorToolbarShowRequested(false)
, mCompositorSendResponseForSnapshotUpdate(false)
, mCompositorAnimationStyle(eAnimate) , mCompositorAnimationStyle(eAnimate)
, mCompositorMaxToolbarHeight(0) , mCompositorMaxToolbarHeight(0)
, mCompositorToolbarHeight(0) , mCompositorToolbarHeight(0)
@ -270,30 +271,6 @@ AndroidDynamicToolbarAnimator::GetCompositionHeight() const
return mCompositorCompositionSize.height; return mCompositorCompositionSize.height;
} }
bool
AndroidDynamicToolbarAnimator::SetCompositionSize(ScreenIntSize aSize)
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
if (mCompositorCompositionSize == aSize) {
return false;
}
ScreenIntSize prevSize = mCompositorCompositionSize;
mCompositorCompositionSize = aSize;
// The width has changed so the static snapshot needs to be updated
if ((prevSize.width != aSize.width) && (mToolbarState != eToolbarVisible)) {
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
}
if (prevSize.height != aSize.height) {
UpdateControllerCompositionHeight(aSize.height);
UpdateFixedLayerMargins();
}
return true;
}
void void
AndroidDynamicToolbarAnimator::SetScrollingRootContent() AndroidDynamicToolbarAnimator::SetScrollingRootContent()
{ {
@ -318,8 +295,8 @@ AndroidDynamicToolbarAnimator::ToolbarAnimatorMessageFromUI(int32_t aMessage)
StartCompositorAnimation(mCompositorAnimationDirection, mCompositorAnimationStyle, mCompositorToolbarHeight, mCompositorWaitForPageResize); StartCompositorAnimation(mCompositorAnimationDirection, mCompositorAnimationStyle, mCompositorToolbarHeight, mCompositorWaitForPageResize);
} }
} else { } else {
// The compositor is already animating the toolbar so no need to defer. // Animation already running so just make sure it is going the right direction.
mCompositorAnimationDeferred = false; StartCompositorAnimation(MOVE_TOOLBAR_UP, mCompositorAnimationStyle, mCompositorToolbarHeight, mCompositorWaitForPageResize);
} }
break; break;
case TOOLBAR_VISIBLE: case TOOLBAR_VISIBLE:
@ -470,6 +447,35 @@ AndroidDynamicToolbarAnimator::UpdateRootFrameMetrics(const FrameMetrics& aMetri
UpdateFrameMetrics(scrollOffset, scale, cssPageRect); UpdateFrameMetrics(scrollOffset, scale, cssPageRect);
} }
void
AndroidDynamicToolbarAnimator::MaybeUpdateCompositionSizeAndRootFrameMetrics(const FrameMetrics& aMetrics)
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
CSSToScreenScale scale = ViewTargetAs<ScreenPixel>(aMetrics.GetZoom().ToScaleFactor(),
PixelCastJustification::ScreenIsParentLayerForRoot);
ScreenIntSize size = ScreenIntSize::Round(aMetrics.GetRootCompositionSize() * scale);
if (mCompositorCompositionSize == size) {
return;
}
ScreenIntSize prevSize = mCompositorCompositionSize;
mCompositorCompositionSize = size;
// The width has changed so the static snapshot needs to be updated
if ((prevSize.width != size.width) && (mToolbarState == eToolbarUnlocked)) {
// No need to set mCompositorSendResponseForSnapshotUpdate. If it is already true we don't want to change it.
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
}
if (prevSize.height != size.height) {
UpdateControllerCompositionHeight(size.height);
UpdateFixedLayerMargins();
}
UpdateRootFrameMetrics(aMetrics);
}
// Layers updates are need by Robocop test which enables them // Layers updates are need by Robocop test which enables them
void void
AndroidDynamicToolbarAnimator::EnableLayersUpdateNotifications(bool aEnable) AndroidDynamicToolbarAnimator::EnableLayersUpdateNotifications(bool aEnable)
@ -525,7 +531,8 @@ AndroidDynamicToolbarAnimator::GetToolbarEffect(CompositorOGL* gl)
uiController->DeallocShmem(mCompositorToolbarPixels.ref()); uiController->DeallocShmem(mCompositorToolbarPixels.ref());
mCompositorToolbarPixels.reset(); mCompositorToolbarPixels.reset();
// Send notification that texture is ready after the current composition has completed. // Send notification that texture is ready after the current composition has completed.
if (mCompositorToolbarTexture) { if (mCompositorToolbarTexture && mCompositorSendResponseForSnapshotUpdate) {
mCompositorSendResponseForSnapshotUpdate = false;
CompositorThreadHolder::Loop()->PostTask(NewRunnableMethod(this, &AndroidDynamicToolbarAnimator::PostToolbarReady)); CompositorThreadHolder::Loop()->PostTask(NewRunnableMethod(this, &AndroidDynamicToolbarAnimator::PostToolbarReady));
} }
} }
@ -574,6 +581,7 @@ AndroidDynamicToolbarAnimator::ProcessTouchDelta(StaticToolbarState aCurrentTool
if (aCurrentToolbarState == eToolbarVisible) { if (aCurrentToolbarState == eToolbarVisible) {
if (tryingToHideToolbar && (mControllerState != eUnlockPending)) { if (tryingToHideToolbar && (mControllerState != eUnlockPending)) {
mCompositorSendResponseForSnapshotUpdate = true;
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE); PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
mControllerState = eUnlockPending; mControllerState = eUnlockPending;
} }
@ -796,7 +804,7 @@ AndroidDynamicToolbarAnimator::UpdateFixedLayerMargins()
} }
AsyncCompositionManager* manager = parent->GetCompositionManager(nullptr); AsyncCompositionManager* manager = parent->GetCompositionManager(nullptr);
if (manager) { if (manager) {
if (mToolbarState == eToolbarAnimating) { if ((mToolbarState == eToolbarAnimating) && mCompositorAnimationStarted) {
manager->SetFixedLayerMargins(mCompositorToolbarHeight, 0); manager->SetFixedLayerMargins(mCompositorToolbarHeight, 0);
} else { } else {
manager->SetFixedLayerMargins(0, GetFixedLayerMarginsBottom()); manager->SetFixedLayerMargins(0, GetFixedLayerMarginsBottom());
@ -851,6 +859,7 @@ AndroidDynamicToolbarAnimator::StartCompositorAnimation(int32_t aDirection, Anim
// and defer animation until it has been unlocked // and defer animation until it has been unlocked
if ((initialToolbarState != eToolbarUnlocked) && (initialToolbarState != eToolbarAnimating)) { if ((initialToolbarState != eToolbarUnlocked) && (initialToolbarState != eToolbarAnimating)) {
mCompositorAnimationDeferred = true; mCompositorAnimationDeferred = true;
mCompositorSendResponseForSnapshotUpdate = true;
PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE); PostMessage(STATIC_TOOLBAR_NEEDS_UPDATE);
} else { } else {
// Toolbar is either unlocked or already animating so animation may begin immediately // Toolbar is either unlocked or already animating so animation may begin immediately
@ -859,13 +868,14 @@ AndroidDynamicToolbarAnimator::StartCompositorAnimation(int32_t aDirection, Anim
if (initialToolbarState != eToolbarAnimating) { if (initialToolbarState != eToolbarAnimating) {
mCompositorAnimationStarted = false; mCompositorAnimationStarted = false;
} }
// Let the controller know we starting an animation so it may clear the AnimationStartPending flag. // Let the controller know we are starting an animation so it may clear the AnimationStartPending flag.
NotifyControllerAnimationStarted(); NotifyControllerAnimationStarted();
// Only reset the time stamp and start compositor animation if not already animating.
if (initialToolbarState != eToolbarAnimating) {
CompositorBridgeParent* parent = CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(mRootLayerTreeId); CompositorBridgeParent* parent = CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(mRootLayerTreeId);
if (parent) { if (parent) {
mCompositorAnimationStartTimeStamp = parent->GetAPZCTreeManager()->GetFrameTime(); mCompositorAnimationStartTimeStamp = parent->GetAPZCTreeManager()->GetFrameTime();
} }
if (initialToolbarState != eToolbarAnimating) {
// Kick the compositor to start the animation if we aren't already animating. // Kick the compositor to start the animation if we aren't already animating.
RequestComposite(); RequestComposite();
} }

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

@ -81,8 +81,6 @@ public:
// shown, the content may extend beyond the bottom of the surface until the toolbar is completely // shown, the content may extend beyond the bottom of the surface until the toolbar is completely
// visible or hidden. // visible or hidden.
ScreenIntCoord GetCompositionHeight() const; ScreenIntCoord GetCompositionHeight() const;
// Returns true if the composition size has changed from the last time it was set.
bool SetCompositionSize(ScreenIntSize aSize);
// Called to signal that root content is being scrolled. This prevents sub scroll frames from // Called to signal that root content is being scrolled. This prevents sub scroll frames from
// affecting the toolbar when being scrolled up. The idea is a scrolling down will always // affecting the toolbar when being scrolled up. The idea is a scrolling down will always
// show the toolbar while scrolling up will only hide the toolbar if it is the root content // show the toolbar while scrolling up will only hide the toolbar if it is the root content
@ -95,6 +93,8 @@ public:
void FirstPaint(); void FirstPaint();
// Called whenever the root document's FrameMetrics have reached a steady state. // Called whenever the root document's FrameMetrics have reached a steady state.
void UpdateRootFrameMetrics(const FrameMetrics& aMetrics); void UpdateRootFrameMetrics(const FrameMetrics& aMetrics);
// Only update the frame metrics if the root composition size has changed
void MaybeUpdateCompositionSizeAndRootFrameMetrics(const FrameMetrics& aMetrics);
// When aEnable is set to true, it informs the animator that the UI thread expects to // When aEnable is set to true, it informs the animator that the UI thread expects to
// be notified when the layer tree has been updated. Enabled currently by robocop tests. // be notified when the layer tree has been updated. Enabled currently by robocop tests.
void EnableLayersUpdateNotifications(bool aEnable); void EnableLayersUpdateNotifications(bool aEnable);
@ -225,7 +225,8 @@ protected:
bool mCompositorReceivedFirstPaint; // Set to true when a first paint occurs. Used by toolbar animator to detect a new page load. bool mCompositorReceivedFirstPaint; // Set to true when a first paint occurs. Used by toolbar animator to detect a new page load.
bool mCompositorWaitForPageResize; // Set to true if the bottom of the page has been reached and the toolbar animator should wait for the page to resize before ending animation. bool mCompositorWaitForPageResize; // Set to true if the bottom of the page has been reached and the toolbar animator should wait for the page to resize before ending animation.
bool mCompositorToolbarShowRequested; // Set to true if the animator has already requested the real toolbar chrome be shown bool mCompositorToolbarShowRequested; // Set to true if the animator has already requested the real toolbar chrome be shown
AnimationStyle mCompositorAnimationStyle; // Set to true when the snap should be immediately hidden or shown in the animation update bool mCompositorSendResponseForSnapshotUpdate; // Set to true when a message should be sent after a static toolbar snapshot update
AnimationStyle mCompositorAnimationStyle; // Set to true when the snapshot should be immediately hidden or shown in the animation update
ScreenIntCoord mCompositorMaxToolbarHeight; // Should contain the same value as mControllerMaxToolbarHeight ScreenIntCoord mCompositorMaxToolbarHeight; // Should contain the same value as mControllerMaxToolbarHeight
ScreenIntCoord mCompositorToolbarHeight; // This value is only updated by the compositor thread when the mToolbarState == ToolbarAnimating ScreenIntCoord mCompositorToolbarHeight; // This value is only updated by the compositor thread when the mToolbarState == ToolbarAnimating
ScreenIntCoord mCompositorSurfaceHeight; // Current height of the render surface ScreenIntCoord mCompositorSurfaceHeight; // Current height of the render surface

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

@ -3477,12 +3477,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
if (APZCTreeManager* manager = GetApzcTreeManager()) { if (APZCTreeManager* manager = GetApzcTreeManager()) {
AndroidDynamicToolbarAnimator* animator = manager->GetAndroidDynamicToolbarAnimator(); AndroidDynamicToolbarAnimator* animator = manager->GetAndroidDynamicToolbarAnimator();
MOZ_ASSERT(animator); MOZ_ASSERT(animator);
CSSToScreenScale scale = ViewTargetAs<ScreenPixel>(aLayerMetrics.GetZoom().ToScaleFactor(), animator->MaybeUpdateCompositionSizeAndRootFrameMetrics(aLayerMetrics);
PixelCastJustification::ScreenIsParentLayerForRoot);
ScreenIntSize size = ScreenIntSize::Round(aLayerMetrics.GetRootCompositionSize() * scale);
if (animator->SetCompositionSize(size)) {
animator->UpdateRootFrameMetrics(aLayerMetrics);
}
} }
} }
#endif #endif

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

@ -945,23 +945,24 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
if (*aOutFoundRoot) { if (*aOutFoundRoot) {
mRootScrollableId = metrics.GetScrollId(); mRootScrollableId = metrics.GetScrollId();
Compositor* compositor = mLayerManager->GetCompositor(); Compositor* compositor = mLayerManager->GetCompositor();
if (mIsFirstPaint) {
if (CompositorBridgeParent* bridge = compositor->GetCompositorBridgeParent()) { if (CompositorBridgeParent* bridge = compositor->GetCompositorBridgeParent()) {
AndroidDynamicToolbarAnimator* animator = bridge->GetAPZCTreeManager()->GetAndroidDynamicToolbarAnimator(); AndroidDynamicToolbarAnimator* animator = bridge->GetAPZCTreeManager()->GetAndroidDynamicToolbarAnimator();
MOZ_ASSERT(animator); MOZ_ASSERT(animator);
if (mIsFirstPaint) {
animator->UpdateRootFrameMetrics(metrics); animator->UpdateRootFrameMetrics(metrics);
animator->FirstPaint(); animator->FirstPaint();
} mIsFirstPaint = false;
} }
if (mLayersUpdated) { if (mLayersUpdated) {
if (CompositorBridgeParent* bridge = compositor->GetCompositorBridgeParent()) {
AndroidDynamicToolbarAnimator* animator = bridge->GetAPZCTreeManager()->GetAndroidDynamicToolbarAnimator();
MOZ_ASSERT(animator);
animator->NotifyLayersUpdated(); animator->NotifyLayersUpdated();
}
mLayersUpdated = false; mLayersUpdated = false;
} }
mIsFirstPaint = false; // If this is not actually the root content then the animator is not getting updated in AsyncPanZoomController::NotifyLayersUpdated
// because the root content document is not scrollable. So update it here so it knows if the root composition size has changed.
if (!metrics.IsRootContent()) {
animator->MaybeUpdateCompositionSizeAndRootFrameMetrics(metrics);
}
}
fixedLayerMargins = mFixedLayerMargins; fixedLayerMargins = mFixedLayerMargins;
} }
} }

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

@ -81,9 +81,9 @@ public:
class Record { class Record {
public: public:
Record() { explicit Record(TimeStamp aStart = TimeStamp()) {
if (gfxPrefs::LayersDrawFPS()) { if (gfxPrefs::LayersDrawFPS()) {
mStart = TimeStamp::Now(); mStart = aStart.IsNull() ? TimeStamp::Now() : aStart;
} }
} }
bool Recording() const { bool Recording() const {

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

@ -919,7 +919,7 @@ LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion, const nsIntRegi
// Render our layers. // Render our layers.
{ {
Diagnostics::Record record; Diagnostics::Record record(mRenderStartTime);
RootLayer()->Prepare(ViewAs<RenderTargetPixel>(clipRect, PixelCastJustification::RenderTargetIsParentLayerForRoot)); RootLayer()->Prepare(ViewAs<RenderTargetPixel>(clipRect, PixelCastJustification::RenderTargetIsParentLayerForRoot));
if (record.Recording()) { if (record.Recording()) {
mDiagnostics->RecordPrepareTime(record.Duration()); mDiagnostics->RecordPrepareTime(record.Duration());

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

@ -569,11 +569,14 @@ BackgroundChildImpl::DeallocPGamepadTestChannelChild(PGamepadTestChannelChild* a
void void
BackgroundChildImpl::OnChannelReceivedMessage(const Message& aMsg) BackgroundChildImpl::OnChannelReceivedMessage(const Message& aMsg)
{ {
// Telemetry collection temporarily disabled in bug 1366156.
#if 0
if (aMsg.type() == layout::PVsync::MessageType::Msg_Notify__ID) { if (aMsg.type() == layout::PVsync::MessageType::Msg_Notify__ID) {
// Not really necessary to look at the message payload, it will be // Not really necessary to look at the message payload, it will be
// <0.5ms away from TimeStamp::Now() // <0.5ms away from TimeStamp::Now()
SchedulerGroup::MarkVsyncReceived(); SchedulerGroup::MarkVsyncReceived();
} }
#endif
} }
#endif #endif

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

@ -6,6 +6,7 @@
#include "builtin/TestingFunctions.h" #include "builtin/TestingFunctions.h"
#include "mozilla/Atomics.h"
#include "mozilla/FloatingPoint.h" #include "mozilla/FloatingPoint.h"
#include "mozilla/Move.h" #include "mozilla/Move.h"
#include "mozilla/Sprintf.h" #include "mozilla/Sprintf.h"
@ -67,11 +68,11 @@ using mozilla::Move;
// If fuzzingSafe is set, remove functionality that could cause problems with // If fuzzingSafe is set, remove functionality that could cause problems with
// fuzzers. Set this via the environment variable MOZ_FUZZING_SAFE. // fuzzers. Set this via the environment variable MOZ_FUZZING_SAFE.
static bool fuzzingSafe = false; static mozilla::Atomic<bool> fuzzingSafe(false);
// If disableOOMFunctions is set, disable functionality that causes artificial // If disableOOMFunctions is set, disable functionality that causes artificial
// OOM conditions. // OOM conditions.
static bool disableOOMFunctions = false; static mozilla::Atomic<bool> disableOOMFunctions(false);
static bool static bool
EnvVarIsDefined(const char* name) EnvVarIsDefined(const char* name)

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

@ -49,6 +49,7 @@
# | E | | E'| # | E | | E'|
# +---+ +---+ # +---+ +---+
import re
import sys import sys
import collections import collections
@ -174,52 +175,56 @@ AllPhaseKinds = findAllPhaseKinds()
# one parent. # one parent.
class Phase: class Phase:
def __init__(self, phaseKind, parent, depth): def __init__(self, phaseKind, parent):
self.phaseKind = phaseKind self.phaseKind = phaseKind
self.parent = parent self.parent = parent
self.depth = depth self.depth = parent.depth + 1 if parent else 0
self.children = [] self.children = []
self.nextSibling = None self.nextSibling = None
self.nextInPhaseKind = None self.nextInPhaseKind = None
self.path = re.sub(r'\W+', '_', phaseKind.name.lower())
if parent is not None:
self.path = parent.path + '.' + self.path
def expandPhases(): def expandPhases():
phases = [] phases = []
phasesForPhase = collections.defaultdict(list) phasesForKind = collections.defaultdict(list)
def traverse(phaseKind, parent, depth): def traverse(phaseKind, parent):
ep = Phase(phaseKind, parent, depth) ep = Phase(phaseKind, parent)
phases.append(ep) phases.append(ep)
# Update list of expanded phases for this phase kind. # Update list of expanded phases for this phase kind.
if phasesForPhase[phaseKind]: if phasesForKind[phaseKind]:
phasesForPhase[phaseKind][-1].nextInPhaseKind = ep phasesForKind[phaseKind][-1].nextInPhaseKind = ep
phasesForPhase[phaseKind].append(ep) phasesForKind[phaseKind].append(ep)
# Recurse over children. # Recurse over children.
for child in phaseKind.children: for child in phaseKind.children:
child_ep = traverse(child, ep, depth + 1) child_ep = traverse(child, ep)
if ep.children: if ep.children:
ep.children[-1].nextSibling = child_ep ep.children[-1].nextSibling = child_ep
ep.children.append(child_ep) ep.children.append(child_ep)
return ep return ep
for phaseKind in PhaseKindGraphRoots: for phaseKind in PhaseKindGraphRoots:
traverse(phaseKind, None, 0) traverse(phaseKind, None)
return phases, phasesForPhase return phases, phasesForKind
AllPhases, PhasesForPhaseKind = expandPhases() AllPhases, PhasesForPhaseKind = expandPhases()
# Name expanded phases based on phase kind name and index if there are # Name phases based on phase kind name and index if there are multiple phases
# multiple expanded phases corresponding to a single phase kind. # corresponding to a single phase kind.
for phaseKind in AllPhaseKinds: for phaseKind in AllPhaseKinds:
phases = PhasesForPhaseKind[phaseKind] phases = PhasesForPhaseKind[phaseKind]
if len(phases) == 1: if len(phases) == 1:
phases[0].name = "%s" % phaseKind.name phases[0].name = "%s" % phaseKind.name
else: else:
for index, xphase in enumerate(phases): for index, phase in enumerate(phases):
xphase.name = "%s_%d" % (phaseKind.name, index + 1) phase.name = "%s_%d" % (phaseKind.name, index + 1)
# Generate code. # Generate code.
@ -250,13 +255,13 @@ def generateHeader(out):
# #
# Generate Phase enum. # Generate Phase enum.
# #
expandedPhaseNames = map(lambda xphase: xphase.name, AllPhases) phaseNames = map(lambda phase: phase.name, AllPhases)
extraPhases = [ extraPhases = [
"NONE = LIMIT", "NONE = LIMIT",
"EXPLICIT_SUSPENSION = LIMIT", "EXPLICIT_SUSPENSION = LIMIT",
"IMPLICIT_SUSPENSION" "IMPLICIT_SUSPENSION"
] ]
writeEnumClass(out, "Phase", "uint8_t", expandedPhaseNames, extraPhases) writeEnumClass(out, "Phase", "uint8_t", phaseNames, extraPhases)
def generateCpp(out): def generateCpp(out):
# #
@ -264,29 +269,30 @@ def generateCpp(out):
# #
out.write("static const PhaseKindTable phaseKinds = {\n") out.write("static const PhaseKindTable phaseKinds = {\n")
for phaseKind in AllPhaseKinds: for phaseKind in AllPhaseKinds:
xPhase = PhasesForPhaseKind[phaseKind][0] phase = PhasesForPhaseKind[phaseKind][0]
out.write(" /* PhaseKind::%s */ PhaseKindInfo { Phase::%s, %d },\n" % out.write(" /* PhaseKind::%s */ PhaseKindInfo { Phase::%s, %d },\n" %
(phaseKind.name, xPhase.name, phaseKind.bucket)) (phaseKind.name, phase.name, phaseKind.bucket))
out.write("};\n") out.write("};\n")
out.write("\n") out.write("\n")
# #
# Generate the PhaseInfo tree. # Generate the PhaseInfo tree.
# #
def name(xphase): def name(phase):
return "Phase::" + xphase.name if xphase else "Phase::NONE" return "Phase::" + phase.name if phase else "Phase::NONE"
out.write("static const PhaseTable phases = {\n") out.write("static const PhaseTable phases = {\n")
for xphase in AllPhases: for phase in AllPhases:
firstChild = xphase.children[0] if xphase.children else None firstChild = phase.children[0] if phase.children else None
phaseKind = xphase.phaseKind phaseKind = phase.phaseKind
out.write(" /* %s */ PhaseInfo { %s, %s, %s, %s, PhaseKind::%s, %d, \"%s\" },\n" % out.write(" /* %s */ PhaseInfo { %s, %s, %s, %s, PhaseKind::%s, %d, \"%s\", \"%s\" },\n" %
(name(xphase), (name(phase),
name(xphase.parent), name(phase.parent),
name(firstChild), name(firstChild),
name(xphase.nextSibling), name(phase.nextSibling),
name(xphase.nextInPhaseKind), name(phase.nextInPhaseKind),
phaseKind.name, phaseKind.name,
xphase.depth, phase.depth,
phaseKind.descr)) phaseKind.descr,
phase.path))
out.write("};\n") out.write("};\n")

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

@ -107,12 +107,13 @@ struct PhaseInfo
PhaseKind phaseKind; PhaseKind phaseKind;
uint8_t depth; uint8_t depth;
const char* name; const char* name;
const char* path;
}; };
// A table of ExpandePhaseInfo indexed by Phase. // A table of PhaseInfo indexed by Phase.
using PhaseTable = EnumeratedArray<Phase, Phase::LIMIT, PhaseInfo>; using PhaseTable = EnumeratedArray<Phase, Phase::LIMIT, PhaseInfo>;
// A table of PhaseKindInfo indexed by Phase. // A table of PhaseKindInfo indexed by PhaseKind.
using PhaseKindTable = EnumeratedArray<PhaseKind, PhaseKind::LIMIT, PhaseKindInfo>; using PhaseKindTable = EnumeratedArray<PhaseKind, PhaseKind::LIMIT, PhaseKindInfo>;
#include "gc/StatsPhasesGenerated.cpp" #include "gc/StatsPhasesGenerated.cpp"
@ -132,8 +133,8 @@ Statistics::currentPhase() const
PhaseKind PhaseKind
Statistics::currentPhaseKind() const Statistics::currentPhaseKind() const
{ {
// Public API to get the current phase. Return the current phase, // Public API to get the current phase kind, suppressing the synthetic
// suppressing the synthetic PhaseKind::MUTATOR phase. // PhaseKind::MUTATOR phase.
Phase phase = currentPhase(); Phase phase = currentPhase();
MOZ_ASSERT_IF(phase == Phase::MUTATOR, phaseNestingDepth == 1); MOZ_ASSERT_IF(phase == Phase::MUTATOR, phaseNestingDepth == 1);
@ -621,35 +622,13 @@ Statistics::formatJsonSliceDescription(unsigned i, const SliceData& slice, JSONP
json.property("end_timestamp", slice.end - originTime, JSONPrinter::SECONDS); json.property("end_timestamp", slice.end - originTime, JSONPrinter::SECONDS);
} }
static UniqueChars
SanitizeJsonKey(const char* const buffer)
{
char* mut = strdup(buffer);
if (!mut)
return UniqueChars(nullptr);
char* c = mut;
while (*c) {
if (!isalpha(*c))
*c = '_';
else if (isupper(*c))
*c = tolower(*c);
++c;
}
return UniqueChars(mut);
}
void void
Statistics::formatJsonPhaseTimes(const PhaseTimeTable& phaseTimes, JSONPrinter& json) const Statistics::formatJsonPhaseTimes(const PhaseTimeTable& phaseTimes, JSONPrinter& json) const
{ {
for (auto phase : AllPhases()) { for (auto phase : AllPhases()) {
UniqueChars name = SanitizeJsonKey(phases[phase].name);
if (!name)
json.outOfMemory();
TimeDuration ownTime = phaseTimes[phase]; TimeDuration ownTime = phaseTimes[phase];
if (!ownTime.IsZero()) if (!ownTime.IsZero())
json.property(name.get(), ownTime, JSONPrinter::MILLISECONDS); json.property(phases[phase].path, ownTime, JSONPrinter::MILLISECONDS);
} }
} }

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

@ -11437,6 +11437,11 @@ CodeGenerator::visitGetDOMProperty(LGetDOMProperty* ins)
// It's a bit annoying to redo these slot calculations, which duplcate // It's a bit annoying to redo these slot calculations, which duplcate
// LSlots and a few other things like that, but I'm not sure there's a // LSlots and a few other things like that, but I'm not sure there's a
// way to reuse those here. // way to reuse those here.
//
// If this ever gets fixed to work with proxies (by not assuming that
// reserved slot indices, which is what domMemberSlotIndex() returns,
// match fixed slot indices), we can reenable MGetDOMProperty for
// proxies in IonBuilder.
if (slot < NativeObject::MAX_FIXED_SLOTS) { if (slot < NativeObject::MAX_FIXED_SLOTS) {
masm.loadValue(Address(ObjectReg, NativeObject::getFixedSlotOffset(slot)), masm.loadValue(Address(ObjectReg, NativeObject::getFixedSlotOffset(slot)),
JSReturnOperand); JSReturnOperand);
@ -11509,6 +11514,11 @@ CodeGenerator::visitGetDOMMemberV(LGetDOMMemberV* ins)
// require us to have MGetDOMMember inherit from MLoadFixedSlot, and then // require us to have MGetDOMMember inherit from MLoadFixedSlot, and then
// we'd have to duplicate a bunch of stuff we now get for free from // we'd have to duplicate a bunch of stuff we now get for free from
// MGetDOMProperty. // MGetDOMProperty.
//
// If this ever gets fixed to work with proxies (by not assuming that
// reserved slot indices, which is what domMemberSlotIndex() returns,
// match fixed slot indices), we can reenable MGetDOMMember for
// proxies in IonBuilder.
Register object = ToRegister(ins->object()); Register object = ToRegister(ins->object());
size_t slot = ins->mir()->domMemberSlotIndex(); size_t slot = ins->mir()->domMemberSlotIndex();
ValueOperand result = GetValueOutput(ins); ValueOperand result = GetValueOutput(ins);
@ -11524,6 +11534,11 @@ CodeGenerator::visitGetDOMMemberT(LGetDOMMemberT* ins)
// require us to have MGetDOMMember inherit from MLoadFixedSlot, and then // require us to have MGetDOMMember inherit from MLoadFixedSlot, and then
// we'd have to duplicate a bunch of stuff we now get for free from // we'd have to duplicate a bunch of stuff we now get for free from
// MGetDOMProperty. // MGetDOMProperty.
//
// If this ever gets fixed to work with proxies (by not assuming that
// reserved slot indices, which is what domMemberSlotIndex() returns,
// match fixed slot indices), we can reenable MGetDOMMember for
// proxies in IonBuilder.
Register object = ToRegister(ins->object()); Register object = ToRegister(ins->object());
size_t slot = ins->mir()->domMemberSlotIndex(); size_t slot = ins->mir()->domMemberSlotIndex();
AnyRegister result = ToAnyRegister(ins->getDef(0)); AnyRegister result = ToAnyRegister(ins->getDef(0));

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

@ -10881,11 +10881,18 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
if (isDOM) { if (isDOM) {
const JSJitInfo* jitinfo = commonGetter->jitInfo(); const JSJitInfo* jitinfo = commonGetter->jitInfo();
// We don't support MGetDOMProperty/MGetDOMMember on things that might
// be proxies when the value might be in a slot, because the
// CodeGenerator code for LGetDOMProperty/LGetDOMMember doesn't handle
// that case correctly.
if ((!jitinfo->isAlwaysInSlot && !jitinfo->isLazilyCachedInSlot) ||
!objTypes->maybeProxy(constraints())) {
MInstruction* get; MInstruction* get;
if (jitinfo->isAlwaysInSlot) { if (jitinfo->isAlwaysInSlot) {
// If our object is a singleton and we know the property is // If our object is a singleton and we know the property is
// constant (which is true if and only if the get doesn't alias // constant (which is true if and only if the get doesn't alias
// anything), we can just read the slot here and use that constant. // anything), we can just read the slot here and use that
// constant.
JSObject* singleton = objTypes->maybeSingleton(); JSObject* singleton = objTypes->maybeSingleton();
if (singleton && jitinfo->aliasSet() == JSJitInfo::AliasNone) { if (singleton && jitinfo->aliasSet() == JSJitInfo::AliasNone) {
size_t slot = jitinfo->slotIndex; size_t slot = jitinfo->slotIndex;
@ -10894,8 +10901,9 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
return Ok(); return Ok();
} }
// We can't use MLoadFixedSlot here because it might not have the // We can't use MLoadFixedSlot here because it might not have
// right aliasing behavior; we want to alias DOM setters as needed. // the right aliasing behavior; we want to alias DOM setters as
// needed.
get = MGetDOMMember::New(alloc(), jitinfo, obj, guard, globalGuard); get = MGetDOMMember::New(alloc(), jitinfo, obj, guard, globalGuard);
} else { } else {
get = MGetDOMProperty::New(alloc(), jitinfo, obj, guard, globalGuard); get = MGetDOMProperty::New(alloc(), jitinfo, obj, guard, globalGuard);
@ -10914,6 +10922,7 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
*emitted = true; *emitted = true;
return Ok(); return Ok();
} }
}
// Don't call the getter with a primitive value. // Don't call the getter with a primitive value.
if (obj->type() != MIRType::Object) { if (obj->type() != MIRType::Object) {

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

@ -45,9 +45,6 @@
using js::shell::RCFile; using js::shell::RCFile;
static RCFile** gErrFilePtr = nullptr;
static RCFile** gOutFilePtr = nullptr;
namespace js { namespace js {
namespace shell { namespace shell {
@ -555,13 +552,15 @@ Redirect(JSContext* cx, const CallArgs& args, RCFile** outFile)
static bool static bool
osfile_redirectOutput(JSContext* cx, unsigned argc, Value* vp) { osfile_redirectOutput(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp); CallArgs args = CallArgsFromVp(argc, vp);
return Redirect(cx, args, gOutFilePtr); ShellContext* scx = GetShellContext(cx);
return Redirect(cx, args, scx->outFilePtr);
} }
static bool static bool
osfile_redirectError(JSContext* cx, unsigned argc, Value* vp) { osfile_redirectError(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp); CallArgs args = CallArgsFromVp(argc, vp);
return Redirect(cx, args, gErrFilePtr); ShellContext* scx = GetShellContext(cx);
return Redirect(cx, args, scx->errFilePtr);
} }
static bool static bool
@ -1010,8 +1009,9 @@ DefineOS(JSContext* cx, HandleObject global,
if (!GenerateInterfaceHelp(cx, obj, "os")) if (!GenerateInterfaceHelp(cx, obj, "os"))
return false; return false;
gOutFilePtr = shellOut; ShellContext* scx = GetShellContext(cx);
gErrFilePtr = shellErr; scx->outFilePtr = shellOut;
scx->errFilePtr = shellErr;
// For backwards compatibility, expose various os.file.* functions as // For backwards compatibility, expose various os.file.* functions as
// direct methods on the global. // direct methods on the global.

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

@ -113,6 +113,8 @@ using namespace js;
using namespace js::cli; using namespace js::cli;
using namespace js::shell; using namespace js::shell;
using js::shell::RCFile;
using mozilla::ArrayLength; using mozilla::ArrayLength;
using mozilla::Atomic; using mozilla::Atomic;
using mozilla::MakeScopeExit; using mozilla::MakeScopeExit;
@ -152,35 +154,8 @@ static const TimeDuration MAX_TIMEOUT_INTERVAL = TimeDuration::FromSeconds(1800.
// SharedArrayBuffer and Atomics are enabled by default (tracking Firefox). // SharedArrayBuffer and Atomics are enabled by default (tracking Firefox).
#define SHARED_MEMORY_DEFAULT 1 #define SHARED_MEMORY_DEFAULT 1
// Some platform hooks must be implemented for single-step profiling. bool
#if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS64) OffThreadState::startIfIdle(JSContext* cx, ScriptKind kind, ScopedJSFreePtr<char16_t>& newSource)
# define SINGLESTEP_PROFILING
#endif
enum class ScriptKind
{
Script,
DecodeScript,
Module
};
class OffThreadState {
enum State {
IDLE, /* ready to work; no token, no source */
COMPILING, /* working; no token, have source */
DONE /* compilation done: have token and source */
};
public:
OffThreadState()
: monitor(mutexid::ShellOffThreadState),
state(IDLE),
token(),
source(nullptr)
{ }
bool startIfIdle(JSContext* cx, ScriptKind kind,
ScopedJSFreePtr<char16_t>& newSource)
{ {
AutoLockMonitor alm(monitor); AutoLockMonitor alm(monitor);
if (state != IDLE) if (state != IDLE)
@ -195,8 +170,8 @@ class OffThreadState {
return true; return true;
} }
bool startIfIdle(JSContext* cx, ScriptKind kind, bool
JS::TranscodeBuffer&& newXdr) OffThreadState::startIfIdle(JSContext* cx, ScriptKind kind, JS::TranscodeBuffer&& newXdr)
{ {
AutoLockMonitor alm(monitor); AutoLockMonitor alm(monitor);
if (state != IDLE) if (state != IDLE)
@ -211,7 +186,9 @@ class OffThreadState {
return true; return true;
} }
void abandon(JSContext* cx) { void
OffThreadState::abandon(JSContext* cx)
{
AutoLockMonitor alm(monitor); AutoLockMonitor alm(monitor);
MOZ_ASSERT(state == COMPILING); MOZ_ASSERT(state == COMPILING);
MOZ_ASSERT(!token); MOZ_ASSERT(!token);
@ -225,7 +202,9 @@ class OffThreadState {
state = IDLE; state = IDLE;
} }
void markDone(void* newToken) { void
OffThreadState::markDone(void* newToken)
{
AutoLockMonitor alm(monitor); AutoLockMonitor alm(monitor);
MOZ_ASSERT(state == COMPILING); MOZ_ASSERT(state == COMPILING);
MOZ_ASSERT(!token); MOZ_ASSERT(!token);
@ -237,7 +216,9 @@ class OffThreadState {
alm.notify(); alm.notify();
} }
void* waitUntilDone(JSContext* cx, ScriptKind kind) { void*
OffThreadState::waitUntilDone(JSContext* cx, ScriptKind kind)
{
AutoLockMonitor alm(monitor); AutoLockMonitor alm(monitor);
if (state == IDLE || scriptKind != kind) if (state == IDLE || scriptKind != kind)
return nullptr; return nullptr;
@ -260,81 +241,10 @@ class OffThreadState {
return holdToken; return holdToken;
} }
JS::TranscodeBuffer& xdrBuffer() { return xdr; }
private:
Monitor monitor;
ScriptKind scriptKind;
State state;
void* token;
char16_t* source;
JS::TranscodeBuffer xdr;
};
#ifdef SINGLESTEP_PROFILING
typedef Vector<char16_t, 0, SystemAllocPolicy> StackChars;
#endif
class NonshrinkingGCObjectVector : public GCVector<JSObject*, 0, SystemAllocPolicy>
{
public:
void sweep() {
for (uint32_t i = 0; i < this->length(); i++) {
if (JS::GCPolicy<JSObject*>::needsSweep(&(*this)[i]))
(*this)[i] = nullptr;
}
}
};
using MarkBitObservers = JS::WeakCache<NonshrinkingGCObjectVector>;
struct ShellCompartmentPrivate { struct ShellCompartmentPrivate {
JS::Heap<JSObject*> grayRoot; JS::Heap<JSObject*> grayRoot;
}; };
// Per-context shell state.
struct ShellContext
{
explicit ShellContext(JSContext* cx);
bool isWorker;
double timeoutInterval;
double startTime;
Atomic<bool> serviceInterrupt;
Atomic<bool> haveInterruptFunc;
JS::PersistentRootedValue interruptFunc;
bool lastWarningEnabled;
JS::PersistentRootedValue lastWarning;
JS::PersistentRootedValue promiseRejectionTrackerCallback;
#ifdef SINGLESTEP_PROFILING
Vector<StackChars, 0, SystemAllocPolicy> stacks;
#endif
/*
* Watchdog thread state.
*/
Mutex watchdogLock;
ConditionVariable watchdogWakeup;
Maybe<Thread> watchdogThread;
Maybe<TimeStamp> watchdogTimeout;
ConditionVariable sleepWakeup;
int exitCode;
bool quitting;
UniqueChars readLineBuf;
size_t readLineBufPos;
static const uint32_t GeckoProfilingMaxStackSize = 1000;
ProfileEntry geckoProfilingStack[GeckoProfilingMaxStackSize];
mozilla::Atomic<uint32_t> geckoProfilingStackSize;
OffThreadState offThreadState;
UniqueChars moduleLoadPath;
UniquePtr<MarkBitObservers> markObservers;
};
struct MOZ_STACK_CLASS EnvironmentPreparer : public js::ScriptEnvironmentPreparer { struct MOZ_STACK_CLASS EnvironmentPreparer : public js::ScriptEnvironmentPreparer {
JSContext* cx; JSContext* cx;
explicit EnvironmentPreparer(JSContext* cx) explicit EnvironmentPreparer(JSContext* cx)
@ -476,11 +386,13 @@ ShellContext::ShellContext(JSContext* cx)
exitCode(0), exitCode(0),
quitting(false), quitting(false),
readLineBufPos(0), readLineBufPos(0),
errFilePtr(nullptr),
outFilePtr(nullptr),
geckoProfilingStackSize(0) geckoProfilingStackSize(0)
{} {}
static ShellContext* ShellContext*
GetShellContext(JSContext* cx) js::shell::GetShellContext(JSContext* cx)
{ {
ShellContext* sc = static_cast<ShellContext*>(JS_GetContextPrivate(cx)); ShellContext* sc = static_cast<ShellContext*>(JS_GetContextPrivate(cx));
MOZ_ASSERT(sc); MOZ_ASSERT(sc);

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

@ -7,8 +7,25 @@
#ifndef jsshell_js_h #ifndef jsshell_js_h
#define jsshell_js_h #define jsshell_js_h
#include "mozilla/Atomics.h"
#include "mozilla/Maybe.h"
#include "mozilla/TimeStamp.h"
#include "jsapi.h" #include "jsapi.h"
#include "js/GCVector.h"
#include "threading/ConditionVariable.h"
#include "threading/LockGuard.h"
#include "threading/Mutex.h"
#include "threading/Thread.h"
#include "vm/GeckoProfiler.h"
#include "vm/Monitor.h"
// Some platform hooks must be implemented for single-step profiling.
#if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS64)
# define SINGLESTEP_PROFILING
#endif
namespace js { namespace js {
namespace shell { namespace shell {
@ -90,6 +107,115 @@ struct RCFile {
bool bool
CreateAlias(JSContext* cx, const char* dstName, JS::HandleObject namespaceObj, const char* srcName); CreateAlias(JSContext* cx, const char* dstName, JS::HandleObject namespaceObj, const char* srcName);
enum class ScriptKind
{
Script,
DecodeScript,
Module
};
class OffThreadState {
enum State {
IDLE, /* ready to work; no token, no source */
COMPILING, /* working; no token, have source */
DONE /* compilation done: have token and source */
};
public:
OffThreadState()
: monitor(mutexid::ShellOffThreadState),
state(IDLE),
token(),
source(nullptr)
{ }
bool startIfIdle(JSContext* cx, ScriptKind kind, ScopedJSFreePtr<char16_t>& newSource);
bool startIfIdle(JSContext* cx, ScriptKind kind, JS::TranscodeBuffer&& newXdr);
void abandon(JSContext* cx);
void markDone(void* newToken);
void* waitUntilDone(JSContext* cx, ScriptKind kind);
JS::TranscodeBuffer& xdrBuffer() { return xdr; }
private:
js::Monitor monitor;
ScriptKind scriptKind;
State state;
void* token;
char16_t* source;
JS::TranscodeBuffer xdr;
};
class NonshrinkingGCObjectVector : public GCVector<JSObject*, 0, SystemAllocPolicy>
{
public:
void sweep() {
for (uint32_t i = 0; i < this->length(); i++) {
if (JS::GCPolicy<JSObject*>::needsSweep(&(*this)[i]))
(*this)[i] = nullptr;
}
}
};
using MarkBitObservers = JS::WeakCache<NonshrinkingGCObjectVector>;
#ifdef SINGLESTEP_PROFILING
using StackChars = Vector<char16_t, 0, SystemAllocPolicy>;
#endif
// Per-context shell state.
struct ShellContext
{
explicit ShellContext(JSContext* cx);
bool isWorker;
double timeoutInterval;
double startTime;
mozilla::Atomic<bool> serviceInterrupt;
mozilla::Atomic<bool> haveInterruptFunc;
JS::PersistentRootedValue interruptFunc;
bool lastWarningEnabled;
JS::PersistentRootedValue lastWarning;
JS::PersistentRootedValue promiseRejectionTrackerCallback;
#ifdef SINGLESTEP_PROFILING
Vector<StackChars, 0, SystemAllocPolicy> stacks;
#endif
/*
* Watchdog thread state.
*/
js::Mutex watchdogLock;
js::ConditionVariable watchdogWakeup;
mozilla::Maybe<js::Thread> watchdogThread;
mozilla::Maybe<mozilla::TimeStamp> watchdogTimeout;
js::ConditionVariable sleepWakeup;
int exitCode;
bool quitting;
JS::UniqueChars readLineBuf;
size_t readLineBufPos;
js::shell::RCFile** errFilePtr;
js::shell::RCFile** outFilePtr;
static const uint32_t GeckoProfilingMaxStackSize = 1000;
js::ProfileEntry geckoProfilingStack[GeckoProfilingMaxStackSize];
mozilla::Atomic<uint32_t> geckoProfilingStackSize;
OffThreadState offThreadState;
JS::UniqueChars moduleLoadPath;
UniquePtr<MarkBitObservers> markObservers;
};
extern ShellContext*
GetShellContext(JSContext* cx);
} /* namespace shell */ } /* namespace shell */
} /* namespace js */ } /* namespace js */

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

@ -2409,6 +2409,27 @@ TemporaryTypeSet::maybeCallable(CompilerConstraintList* constraints)
return false; return false;
} }
bool
TemporaryTypeSet::maybeProxy(CompilerConstraintList* constraints)
{
if (!maybeObject())
return false;
if (unknownObject())
return true;
unsigned count = getObjectCount();
for (unsigned i = 0; i < count; i++) {
const Class* clasp = getObjectClass(i);
if (!clasp)
continue;
if (clasp->isProxy() || !getObject(i)->hasStableClassAndProto(constraints))
return true;
}
return false;
}
bool bool
TemporaryTypeSet::maybeEmulatesUndefined(CompilerConstraintList* constraints) TemporaryTypeSet::maybeEmulatesUndefined(CompilerConstraintList* constraints)
{ {

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

@ -829,6 +829,9 @@ class TemporaryTypeSet : public TypeSet
/* Whether clasp->isCallable() is true for one or more objects in this set. */ /* Whether clasp->isCallable() is true for one or more objects in this set. */
bool maybeCallable(CompilerConstraintList* constraints); bool maybeCallable(CompilerConstraintList* constraints);
/* Whether clasp->isProxy() might be true for one or more objects in this set. */
bool maybeProxy(CompilerConstraintList* constraints);
/* Whether clasp->emulatesUndefined() is true for one or more objects in this set. */ /* Whether clasp->emulatesUndefined() is true for one or more objects in this set. */
bool maybeEmulatesUndefined(CompilerConstraintList* constraints); bool maybeEmulatesUndefined(CompilerConstraintList* constraints);

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

@ -33,7 +33,7 @@
#define DOC_ELEM_INSERTED_TOPIC "document-element-inserted" #define DOC_ELEM_INSERTED_TOPIC "document-element-inserted"
#define CLEANUP_TOPIC "xpcom-shutdown" #define CLEANUP_TOPIC "xpcom-shutdown"
#define SHUTDOWN_TOPIC "quit-application-granted" #define SHUTDOWN_TOPIC "quit-application-granted"
#define CACHE_FLUSH_TOPIC "startupcache-invalidate" #define CACHE_INVALIDATE_TOPIC "startupcache-invalidate"
namespace mozilla { namespace mozilla {
namespace { namespace {
@ -163,7 +163,9 @@ ScriptPreloader::InitContentChild(ContentParent& parent)
cache.mInitializedProcesses += processType; cache.mInitializedProcesses += processType;
auto fd = cache.mCacheData.cloneFileDescriptor(); auto fd = cache.mCacheData.cloneFileDescriptor();
if (fd.IsValid()) { // Don't send original cache data to new processes if the cache has been
// invalidated.
if (fd.IsValid() && !cache.mCacheInvalidated) {
Unused << parent.SendPScriptCacheConstructor(fd, wantScriptData); Unused << parent.SendPScriptCacheConstructor(fd, wantScriptData);
} else { } else {
Unused << parent.SendPScriptCacheConstructor(NS_ERROR_FILE_NOT_FOUND, wantScriptData); Unused << parent.SendPScriptCacheConstructor(NS_ERROR_FILE_NOT_FOUND, wantScriptData);
@ -227,7 +229,7 @@ ScriptPreloader::ScriptPreloader()
} }
obs->AddObserver(this, SHUTDOWN_TOPIC, false); obs->AddObserver(this, SHUTDOWN_TOPIC, false);
obs->AddObserver(this, CLEANUP_TOPIC, false); obs->AddObserver(this, CLEANUP_TOPIC, false);
obs->AddObserver(this, CACHE_FLUSH_TOPIC, false); obs->AddObserver(this, CACHE_INVALIDATE_TOPIC, false);
AutoSafeJSAPI jsapi; AutoSafeJSAPI jsapi;
JS_AddExtraGCRootsTracer(jsapi.cx(), TraceOp, this); JS_AddExtraGCRootsTracer(jsapi.cx(), TraceOp, this);
@ -265,10 +267,12 @@ ScriptPreloader::Cleanup()
} }
void void
ScriptPreloader::FlushCache() ScriptPreloader::InvalidateCache()
{ {
MonitorAutoLock mal(mMonitor); MonitorAutoLock mal(mMonitor);
mCacheInvalidated = true;
for (auto& script : IterHash(mScripts)) { for (auto& script : IterHash(mScripts)) {
// We can only purge finished scripts here. Async scripts that are // We can only purge finished scripts here. Async scripts that are
// still being parsed off-thread have a non-refcounted reference to // still being parsed off-thread have a non-refcounted reference to
@ -321,8 +325,8 @@ ScriptPreloader::Observe(nsISupports* subject, const char* topic, const char16_t
ForceWriteCacheFile(); ForceWriteCacheFile();
} else if (!strcmp(topic, CLEANUP_TOPIC)) { } else if (!strcmp(topic, CLEANUP_TOPIC)) {
Cleanup(); Cleanup();
} else if (!strcmp(topic, CACHE_FLUSH_TOPIC)) { } else if (!strcmp(topic, CACHE_INVALIDATE_TOPIC)) {
FlushCache(); InvalidateCache();
} }
return NS_OK; return NS_OK;
@ -724,6 +728,21 @@ ScriptPreloader::NoteScript(const nsCString& url, const nsCString& cachePath,
} }
} }
if (!script->mSize && !script->mScript) {
// If the content process is sending us a script entry for a script
// which was in the cache at startup, it expects us to already have this
// script data, so it doesn't send it.
//
// However, the cache may have been invalidated at this point (usually
// due to the add-on manager installing or uninstalling a legacy
// extension during very early startup), which means we may no longer
// have an entry for this script. Since that means we have no data to
// write to the new cache, and no JSScript to generate it from, we need
// to discard this entry.
mScripts.Remove(cachePath);
return;
}
script->UpdateLoadTime(loadTime); script->UpdateLoadTime(loadTime);
script->mProcessTypes += processType; script->mProcessTypes += processType;
} }

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

@ -350,7 +350,7 @@ private:
void ForceWriteCacheFile(); void ForceWriteCacheFile();
void Cleanup(); void Cleanup();
void FlushCache(); void InvalidateCache();
// Opens the cache file for reading. // Opens the cache file for reading.
Result<Ok, nsresult> OpenCache(); Result<Ok, nsresult> OpenCache();
@ -404,6 +404,7 @@ private:
bool mCacheInitialized = false; bool mCacheInitialized = false;
bool mSaveComplete = false; bool mSaveComplete = false;
bool mDataPrepared = false; bool mDataPrepared = false;
bool mCacheInvalidated = false;
// The process type of the current process. // The process type of the current process.
static ProcessType sProcessType; static ProcessType sProcessType;

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

@ -1708,7 +1708,15 @@ public class BrowserApp extends GeckoApp
@Override @Override
public void toggleToolbarChrome(final boolean aShow) { public void toggleToolbarChrome(final boolean aShow) {
toggleChrome(aShow); if (aShow) {
mBrowserChrome.setVisibility(View.VISIBLE);
} else {
// The chrome needs to be INVISIBLE instead of GONE so that
// it will continue update when the layout changes. This
// ensures the bitmap generated for the static toolbar
// snapshot is the correct size.
mBrowserChrome.setVisibility(View.INVISIBLE);
}
} }
public void refreshToolbarHeight() { public void refreshToolbarHeight() {
@ -1730,22 +1738,17 @@ public class BrowserApp extends GeckoApp
@Override @Override
void toggleChrome(final boolean aShow) { void toggleChrome(final boolean aShow) {
if (aShow) { if (mDynamicToolbar != null) {
mBrowserChrome.setVisibility(View.VISIBLE); mDynamicToolbar.setVisible(aShow, VisibilityTransition.IMMEDIATE);
} else {
// The chrome needs to be INVISIBLE instead of GONE so that
// it will continue update when the layout changes. This
// ensures the bitmap generated for the static toolbar
// snapshot is the correct size.
mBrowserChrome.setVisibility(View.INVISIBLE);
} }
super.toggleChrome(aShow); super.toggleChrome(aShow);
} }
@Override @Override
void focusChrome() { void focusChrome() {
mBrowserChrome.setVisibility(View.VISIBLE); if (mDynamicToolbar != null) {
mDynamicToolbar.setVisible(true, VisibilityTransition.IMMEDIATE);
}
mActionBarFlipper.requestFocusFromTouch(); mActionBarFlipper.requestFocusFromTouch();
super.focusChrome(); super.focusChrome();

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

@ -481,6 +481,11 @@ nsHttpHandler::Init()
"net:current-toplevel-outer-content-windowid", "net:current-toplevel-outer-content-windowid",
true); true);
if (mFastOpenSupported) {
obsService->AddObserver(this, "captive-portal-login", true);
obsService->AddObserver(this, "captive-portal-login-success", true);
}
// disabled as its a nop right now // disabled as its a nop right now
// obsService->AddObserver(this, "net:failed-to-process-uri-content", true); // obsService->AddObserver(this, "net:failed-to-process-uri-content", true);
} }
@ -648,7 +653,6 @@ nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter()
if (mFastOpenConsecutiveFailureCounter == mFastOpenConsecutiveFailureLimit) { if (mFastOpenConsecutiveFailureCounter == mFastOpenConsecutiveFailureLimit) {
LOG(("nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter - " LOG(("nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter - "
"Fast open failed too many times")); "Fast open failed too many times"));
SetFastOpenNotSupported();
} }
} }
} }
@ -2315,6 +2319,11 @@ nsHttpHandler::Observe(nsISupports *subject,
} }
} }
} }
} else if (!strcmp(topic, "captive-portal-login") ||
!strcmp(topic, "captive-portal-login-success")) {
// We have detected a captive portal and we will reset the Fast Open
// failure counter.
ResetFastOpenConsecutiveFailureCounter();
} }
return NS_OK; return NS_OK;

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

@ -164,7 +164,11 @@ public:
return mTCPKeepaliveLongLivedIdleTimeS; return mTCPKeepaliveLongLivedIdleTimeS;
} }
bool UseFastOpen() { return mUseFastOpen && mFastOpenSupported; } bool UseFastOpen()
{
return mUseFastOpen && mFastOpenSupported &&
mFastOpenConsecutiveFailureCounter < mFastOpenConsecutiveFailureLimit;
}
// If one of tcp connections return PR_NOT_TCP_SOCKET_ERROR while trying // If one of tcp connections return PR_NOT_TCP_SOCKET_ERROR while trying
// fast open, it means that Fast Open is turned off so we will not try again // fast open, it means that Fast Open is turned off so we will not try again
// until a restart. This is only on Linux. // until a restart. This is only on Linux.

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

@ -2,9 +2,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
import sys
import unittest
from firefox_puppeteer import PuppeteerMixin from firefox_puppeteer import PuppeteerMixin
from marionette_driver import Wait from marionette_driver import Wait
from marionette_harness import MarionetteTestCase from marionette_harness import MarionetteTestCase
@ -57,25 +54,3 @@ class TestBrowserWindowShortcuts(PuppeteerMixin, MarionetteTestCase):
return selection_name == "input" return selection_name == "input"
Wait(self.marionette).until(has_input_selected) Wait(self.marionette).until(has_input_selected)
@unittest.skipIf(sys.platform == 'darwin',
'Quit Shotcut not supported due to native menu of Mac OS')
class TestBrowserQuitShortcut(PuppeteerMixin, MarionetteTestCase):
def test_quit_firefox_shortcut(self):
def quit_via_shortcut_callback():
if self.puppeteer.platform == 'win':
key = 'quitApplicationCmdWin2.accesskey'
else:
key = 'quitApplicationCmdUnix.key'
self.browser.send_shortcut(self.browser.localize_entity(key),
accel=True)
self.marionette.quit(in_app=True, callback=quit_via_shortcut_callback)
self.assertIsNone(self.marionette.session)
def tearDown(self):
self.marionette.start_session()
super(TestBrowserQuitShortcut, self).tearDown()

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

@ -409,7 +409,8 @@ class BaseWindow(BaseLib):
if kwargs[modifier] is True: if kwargs[modifier] is True:
keys.append(keymap[modifier]) keys.append(keymap[modifier])
keys.append(command_key) # Bug 1125209 - Only lower-case command keys should be sent
keys.append(command_key.lower())
self.switch_to() self.switch_to()

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

@ -94,8 +94,8 @@ function testInit() {
}; };
var listener = 'data:,function doLoad(e) { var data=e.detail&&e.detail.data;removeEventListener("contentEvent", function (e) { doLoad(e); }, false, true);sendAsyncMessage("chromeEvent", {"data":data}); };addEventListener("contentEvent", function (e) { doLoad(e); }, false, true);'; var listener = 'data:,function doLoad(e) { var data=e.detail&&e.detail.data;removeEventListener("contentEvent", function (e) { doLoad(e); }, false, true);sendAsyncMessage("chromeEvent", {"data":data}); };addEventListener("contentEvent", function (e) { doLoad(e); }, false, true);';
messageManager.loadFrameScript(listener, true);
messageManager.addMessageListener("chromeEvent", messageHandler); messageManager.addMessageListener("chromeEvent", messageHandler);
messageManager.loadFrameScript(listener, true);
} }
if (gConfig.e10s) { if (gConfig.e10s) {
e10s_init(); e10s_init();

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

@ -27,6 +27,8 @@
// added until then. // added until then.
window.addEventListener("MozAfterPaint", function() { window.addEventListener("MozAfterPaint", function() {
setTimeout(redirectToHarness, 0); setTimeout(redirectToHarness, 0);
// In case the listener was not ready, try again after a few seconds.
setTimeout(redirectToHarness, 5000);
}, {once: true}); }, {once: true});
} }

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

@ -12914,7 +12914,7 @@
}, },
"DISPLAY_ITEM_USAGE_COUNT": { "DISPLAY_ITEM_USAGE_COUNT": {
"record_in_processes": ["main", "content"], "record_in_processes": ["main", "content"],
"alert_emails": ["mchang@mozilla.com", "gfx-telemetry@mozilla.com"], "alert_emails": ["mchang@mozilla.com", "gfx-telemetry-alerts@mozilla.com"],
"bug_numbers": [1353521], "bug_numbers": [1353521],
"expires_in_version": "56", "expires_in_version": "56",
"kind": "enumerated", "kind": "enumerated",

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

@ -61,17 +61,23 @@ public:
: mIsBackground(aRunnable->IsBackground()) : mIsBackground(aRunnable->IsBackground())
{ {
MOZ_GUARD_OBJECT_NOTIFIER_INIT; MOZ_GUARD_OBJECT_NOTIFIER_INIT;
// Telemetry collection temporarily disabled in bug 1366156.
#if 0
#ifdef EARLY_BETA_OR_EARLIER #ifdef EARLY_BETA_OR_EARLIER
aRunnable->GetName(mKey); aRunnable->GetName(mKey);
mStart = TimeStamp::Now(); mStart = TimeStamp::Now();
#endif
#endif #endif
} }
~AutoCollectVsyncTelemetry() ~AutoCollectVsyncTelemetry()
{ {
// Telemetry collection temporarily disabled in bug 1366156.
#if 0
#ifdef EARLY_BETA_OR_EARLIER #ifdef EARLY_BETA_OR_EARLIER
if (Telemetry::CanRecordBase()) { if (Telemetry::CanRecordBase()) {
CollectTelemetry(); CollectTelemetry();
} }
#endif
#endif #endif
} }