Merge mozilla-central to mozilla-inbound

This commit is contained in:
Carsten "Tomcat" Book 2017-03-27 12:59:33 +02:00
Родитель 1bdeb0ab34 8fa2774978
Коммит 48d1be80d3
162 изменённых файлов: 4164 добавлений и 5616 удалений

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

@ -332,12 +332,8 @@ EffectCompositor::PostRestyleForAnimation(dom::Element* aElement,
// second traversal so we don't need to post any restyle requests to the
// PresShell.
return;
} else if (!mPresContext->RestyleManager()->IsInStyleRefresh()) {
// FIXME: stylo only supports Self and Subtree hints now, so we override
// it for stylo if we are not in process of restyling.
hint = eRestyle_Self | eRestyle_Subtree;
} else {
MOZ_ASSERT_UNREACHABLE("Should not request restyle");
MOZ_ASSERT(!mPresContext->RestyleManager()->IsInStyleRefresh());
}
}
mPresContext->PresShell()->RestyleForAnimation(element, hint);
@ -983,8 +979,8 @@ EffectCompositor::PreTraverse()
// We can't call PostRestyleEvent directly here since we are still in the
// middle of the servo traversal.
mPresContext->RestyleManager()->AsServo()->
PostRestyleEventForAnimations(target.mElement,
eRestyle_Self | eRestyle_Subtree);
PostRestyleEventForAnimations(target.mElement, eRestyle_CSSAnimations);
foundElementsNeedingRestyle = true;
EffectSet* effects =
@ -1035,7 +1031,7 @@ EffectCompositor::PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull)
}
mPresContext->RestyleManager()->AsServo()->
PostRestyleEventForAnimations(aElement, eRestyle_Self);
PostRestyleEventForAnimations(aElement, eRestyle_CSSAnimations);
EffectSet* effects = EffectSet::GetEffectSet(aElement, pseudoType);
if (effects) {

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

@ -407,33 +407,6 @@ KeyframeEffectReadOnly::CompositeValue(
return StyleAnimationValue();
}
StyleAnimationValue
KeyframeEffectReadOnly::ResolveBaseStyle(nsCSSPropertyID aProperty,
nsStyleContext* aStyleContext)
{
StyleAnimationValue result;
if (mBaseStyleValues.Get(aProperty, &result)) {
return result;
}
RefPtr<nsStyleContext> styleContextWithoutAnimation =
aStyleContext->PresContext()->StyleSet()->AsGecko()->
ResolveStyleByRemovingAnimation(mTarget->mElement,
aStyleContext,
eRestyle_AllHintsWithAnimations);
DebugOnly<bool> success =
StyleAnimationValue::ExtractComputedValue(aProperty,
styleContextWithoutAnimation,
result);
MOZ_ASSERT(success, "Should be able to extract computed animation value");
MOZ_ASSERT(!result.IsNull(), "Should have a valid StyleAnimationValue");
mBaseStyleValues.Put(aProperty, result);
return result;
}
StyleAnimationValue
KeyframeEffectReadOnly::GetUnderlyingStyle(
nsCSSPropertyID aProperty,
@ -490,18 +463,52 @@ KeyframeEffectReadOnly::EnsureBaseStyles(
mBaseStyleValues.Clear();
RefPtr<nsStyleContext> cachedBaseStyleContext;
for (const AnimationProperty& property : aProperties) {
for (const AnimationPropertySegment& segment : property.mSegments) {
if (segment.HasReplacableValues()) {
if (segment.HasReplaceableValues()) {
continue;
}
Unused << ResolveBaseStyle(property.mProperty, aStyleContext);
EnsureBaseStyle(property.mProperty,
aStyleContext,
cachedBaseStyleContext);
break;
}
}
}
void
KeyframeEffectReadOnly::EnsureBaseStyle(
nsCSSPropertyID aProperty,
nsStyleContext* aStyleContext,
RefPtr<nsStyleContext>& aCachedBaseStyleContext)
{
if (mBaseStyleValues.Contains(aProperty)) {
return;
}
if (!aCachedBaseStyleContext) {
aCachedBaseStyleContext =
aStyleContext->PresContext()->StyleSet()->AsGecko()->
ResolveStyleByRemovingAnimation(mTarget->mElement,
aStyleContext,
eRestyle_AllHintsWithAnimations);
}
StyleAnimationValue result;
DebugOnly<bool> success =
StyleAnimationValue::ExtractComputedValue(aProperty,
aCachedBaseStyleContext,
result);
MOZ_ASSERT(success, "Should be able to extract computed animation value");
MOZ_ASSERT(!result.IsNull(), "Should have a valid StyleAnimationValue");
mBaseStyleValues.Put(aProperty, result);
}
void
KeyframeEffectReadOnly::WillComposeStyle()
{
@ -1653,7 +1660,7 @@ KeyframeEffectReadOnly::CalculateCumulativeChangeHint(
// we can't throttle animations which will not cause any layout changes
// on invisible elements because we can't calculate the change hint for
// such properties until we compose it.
if (!segment.HasReplacableValues()) {
if (!segment.HasReplaceableValues()) {
mCumulativeChangeHint = ~nsChangeHint_Hints_CanIgnoreIfNotVisible;
return;
}

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

@ -65,18 +65,18 @@ struct AnimationPropertySegment
dom::CompositeOperation mFromComposite = dom::CompositeOperation::Replace;
dom::CompositeOperation mToComposite = dom::CompositeOperation::Replace;
bool HasReplacableValues() const
bool HasReplaceableValues() const
{
return HasReplacableFromValue() && HasReplacableToValue();
return HasReplaceableFromValue() && HasReplaceableToValue();
}
bool HasReplacableFromValue() const
bool HasReplaceableFromValue() const
{
return !mFromValue.IsNull() &&
mFromComposite == dom::CompositeOperation::Replace;
}
bool HasReplacableToValue() const
bool HasReplaceableToValue() const
{
return !mToValue.IsNull() &&
mToComposite == dom::CompositeOperation::Replace;
@ -417,9 +417,14 @@ protected:
// FIXME: Bug 1311257: Support missing keyframes.
}
// Returns the base style resolved by |aStyleContext| for |aProperty|.
StyleAnimationValue ResolveBaseStyle(nsCSSPropertyID aProperty,
nsStyleContext* aStyleContext);
// If no base style is already stored for |aProperty|, resolves the base style
// for |aProperty| using |aStyleContext| and stores it in mBaseStyleValues.
// If |aCachedBaseStyleContext| is non-null, it will be used, otherwise the
// base style context will be resolved and stored in
// |aCachedBaseStyleContext|.
void EnsureBaseStyle(nsCSSPropertyID aProperty,
nsStyleContext* aStyleContext,
RefPtr<nsStyleContext>& aCachedBaseStyleContext);
Maybe<OwningAnimationTarget> mTarget;

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

@ -214,6 +214,11 @@ enum {
// Whether this node has dirty descendants for Servo's style system.
NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO = NODE_SHARED_RESTYLE_BIT_1,
// Whether this node has dirty descendants for animation-only restyle for
// Servo's style system.
NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO =
NODE_SHARED_RESTYLE_BIT_2,
// Remaining bits are node type specific.
NODE_TYPE_SPECIFIC_BITS_OFFSET = 23
};

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

@ -885,9 +885,6 @@ private:
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
("HTMLMediaElement::AudioChannelAgentCallback, SetAudioChannelSuspended, "
"this = %p, aSuspend = %s\n", this, SuspendTypeToStr(aSuspend)));
NotifyAudioPlaybackChanged(
AudioChannelService::AudibleChangedReasons::ePauseStateChanged);
}
void
@ -908,6 +905,9 @@ private:
if (rv.Failed()) {
NS_WARNING("Not able to resume from AudioChannel.");
}
NotifyAudioPlaybackChanged(
AudioChannelService::AudibleChangedReasons::ePauseStateChanged);
}
void
@ -925,6 +925,8 @@ private:
return;
}
}
NotifyAudioPlaybackChanged(
AudioChannelService::AudibleChangedReasons::ePauseStateChanged);
}
void
@ -1015,8 +1017,9 @@ private:
return AudioChannelService::AudibleState::eMaybeAudible;
}
// Media is suspended.
if (mSuspended != nsISuspendedTypes::NONE_SUSPENDED) {
// Suspended or paused media doesn't produce any sound.
if (mSuspended != nsISuspendedTypes::NONE_SUSPENDED ||
mOwner->mPaused) {
return AudioChannelService::AudibleState::eNotAudible;
}

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

@ -61,6 +61,7 @@
#include "mozilla/net/CaptivePortalService.h"
#include "mozilla/plugins/PluginInstanceParent.h"
#include "mozilla/plugins/PluginModuleParent.h"
#include "mozilla/widget/ScreenManager.h"
#include "mozilla/widget/WidgetMessageUtils.h"
#include "nsBaseDragService.h"
#include "mozilla/media/MediaChild.h"
@ -99,7 +100,6 @@
#include "nsIMutable.h"
#include "nsIObserverService.h"
#include "nsIScriptSecurityManager.h"
#include "nsScreenManagerProxy.h"
#include "nsMemoryInfoDumper.h"
#include "nsServiceManagerUtils.h"
#include "nsStyleSheetService.h"
@ -1748,28 +1748,6 @@ ContentChild::DeallocPParentToChildStreamChild(PParentToChildStreamChild* aActor
return nsIContentChild::DeallocPParentToChildStreamChild(aActor);
}
PScreenManagerChild*
ContentChild::AllocPScreenManagerChild(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
// The ContentParent should never attempt to allocate the
// nsScreenManagerProxy. Instead, the nsScreenManagerProxy
// service is requested and instantiated via XPCOM, and the
// constructor of nsScreenManagerProxy sets up the IPC connection.
MOZ_CRASH("Should never get here!");
return nullptr;
}
bool
ContentChild::DeallocPScreenManagerChild(PScreenManagerChild* aService)
{
// nsScreenManagerProxy is AddRef'd in its constructor.
nsScreenManagerProxy *child = static_cast<nsScreenManagerProxy*>(aService);
child->Release();
return true;
}
PPSMContentDownloaderChild*
ContentChild::AllocPPSMContentDownloaderChild(const uint32_t& aCertType)
{
@ -3268,7 +3246,14 @@ ContentChild::RecvSetPermissionsWithKey(const nsCString& aPermissionKey,
nsCOMPtr<nsIPermissionManager> permissionManager =
services::GetPermissionManager();
permissionManager->SetPermissionsWithKey(aPermissionKey, aPerms);
return IPC_OK();
}
mozilla::ipc::IPCResult
ContentChild::RecvRefreshScreens(nsTArray<ScreenDetails>&& aScreens)
{
ScreenManager& screenManager = ScreenManager::GetSingleton();
screenManager.Refresh(Move(aScreens));
return IPC_OK();
}

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

@ -242,13 +242,6 @@ public:
virtual PParentToChildStreamChild* AllocPParentToChildStreamChild() override;
virtual bool DeallocPParentToChildStreamChild(PParentToChildStreamChild*) override;
virtual PScreenManagerChild*
AllocPScreenManagerChild(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess) override;
virtual bool DeallocPScreenManagerChild(PScreenManagerChild*) override;
virtual PPSMContentDownloaderChild*
AllocPPSMContentDownloaderChild( const uint32_t& aCertType) override;
@ -477,6 +470,9 @@ public:
virtual mozilla::ipc::IPCResult RecvParentActivated(PBrowserChild* aTab, const bool& aActivated) override;
mozilla::ipc::IPCResult
RecvRefreshScreens(nsTArray<ScreenDetails>&& aScreens) override;
// Get the directory for IndexedDB files. We query the parent for this and
// cache the value
nsString &GetIndexedDBPath();

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

@ -97,6 +97,7 @@
#include "mozilla/Telemetry.h"
#include "mozilla/TelemetryIPC.h"
#include "mozilla/WebBrowserPersistDocumentParent.h"
#include "mozilla/widget/ScreenManager.h"
#include "mozilla/Unused.h"
#include "nsAnonymousTemporaryFile.h"
#include "nsAppRunner.h"
@ -162,7 +163,6 @@
#include "PreallocatedProcessManager.h"
#include "ProcessPriorityManager.h"
#include "SandboxHal.h"
#include "ScreenManagerParent.h"
#include "SourceSurfaceRawData.h"
#include "TabParent.h"
#include "URIUtils.h"
@ -2233,6 +2233,9 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
storage->GetAll(&entry.items());
xpcomInit.dataStorage().AppendElement(Move(entry));
}
// Must send screen info before send initialData
ScreenManager& screenManager = ScreenManager::GetSingleton();
screenManager.CopyScreensToRemote(this);
Unused << SendSetXPCOMProcessAttributes(xpcomInit, initialData, lnfCache);
@ -3136,21 +3139,6 @@ ContentParent::DeallocPParentToChildStreamParent(PParentToChildStreamParent* aAc
return nsIContentParent::DeallocPParentToChildStreamParent(aActor);
}
PScreenManagerParent*
ContentParent::AllocPScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
return new ScreenManagerParent(aNumberOfScreens, aSystemDefaultScale, aSuccess);
}
bool
ContentParent::DeallocPScreenManagerParent(PScreenManagerParent* aActor)
{
delete aActor;
return true;
}
PPSMContentDownloaderParent*
ContentParent::AllocPPSMContentDownloaderParent(const uint32_t& aCertType)
{

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

@ -446,14 +446,6 @@ public:
virtual bool
DeallocPParentToChildStreamParent(PParentToChildStreamParent* aActor) override;
virtual PScreenManagerParent*
AllocPScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess) override;
virtual bool
DeallocPScreenManagerParent(PScreenManagerParent* aActor) override;
virtual PHalParent* AllocPHalParent() override;
virtual mozilla::ipc::IPCResult RecvPHalConstructor(PHalParent* aActor) override

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

@ -16,6 +16,11 @@ using struct mozilla::void_t
using struct mozilla::SerializedStructuredCloneBuffer
from "ipc/IPCMessageUtils.h";
using LayoutDeviceIntRect from "Units.h";
using DesktopIntRect from "Units.h";
using DesktopToLayoutDeviceScale from "Units.h";
using CSSToLayoutDeviceScale from "Units.h";
namespace mozilla {
namespace dom {
@ -178,5 +183,16 @@ struct IPCDataTransfer
IPCDataTransferItem[] items;
};
struct ScreenDetails {
LayoutDeviceIntRect rect;
DesktopIntRect rectDisplayPix;
LayoutDeviceIntRect availRect;
DesktopIntRect availRectDisplayPix;
int32_t pixelDepth;
int32_t colorDepth;
DesktopToLayoutDeviceScale contentsScaleFactor;
CSSToLayoutDeviceScale defaultCSSScaleFactor;
};
} // namespace dom
} // namespace mozilla

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

@ -28,7 +28,6 @@ using class mozilla::gfx::Matrix from "mozilla/gfx/Matrix.h";
using struct gfxSize from "gfxPoint.h";
using CSSRect from "Units.h";
using CSSSize from "Units.h";
using mozilla::LayoutDeviceIntRect from "Units.h";
using mozilla::LayoutDeviceIntPoint from "Units.h";
using mozilla::LayoutDevicePoint from "Units.h";
using mozilla::ScreenIntPoint from "Units.h";

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

@ -30,7 +30,6 @@ include protocol PChildToParentStream;
include protocol PParentToChildStream;
include protocol POfflineCacheUpdate;
include protocol PRenderFrame;
include protocol PScreenManager;
include protocol PSpeechSynthesis;
include protocol PStorage;
include protocol PTestShell;
@ -289,7 +288,6 @@ nested(upto inside_cpow) sync protocol PContent
manages PPrinting;
manages PChildToParentStream;
manages PParentToChildStream;
manages PScreenManager;
manages PSpeechSynthesis;
manages PStorage;
manages PTestShell;
@ -595,6 +593,8 @@ child:
async SetPermissionsWithKey(nsCString aPermissionKey, Permission[] aPermissions);
async RefreshScreens(ScreenDetails[] aScreens);
parent:
async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
@ -711,11 +711,6 @@ parent:
async PChildToParentStream();
nested(inside_sync) sync PScreenManager()
returns (uint32_t numberOfScreens,
float systemDefaultScale,
bool success);
async PSpeechSynthesis();
nested(inside_cpow) async PStorage();

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

@ -1,63 +0,0 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBrowser;
include protocol PContent;
include "mozilla/GfxMessageUtils.h";
using nsIntRect from "nsRect.h";
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
namespace mozilla {
namespace dom {
struct ScreenDetails {
uint32_t id;
nsIntRect rect;
nsIntRect rectDisplayPix;
nsIntRect availRect;
nsIntRect availRectDisplayPix;
int32_t pixelDepth;
int32_t colorDepth;
double contentsScaleFactor;
double defaultCSSScaleFactor;
};
nested(upto inside_cpow) sync protocol PScreenManager
{
manager PContent;
parent:
nested(inside_sync) sync Refresh()
returns (uint32_t numberOfScreens,
float systemDefaultScale,
bool success);
nested(inside_cpow) sync ScreenRefresh(uint32_t aId)
returns (ScreenDetails screen,
bool success);
nested(inside_sync) sync GetPrimaryScreen()
returns (ScreenDetails screen,
bool success);
nested(inside_sync) sync ScreenForRect(int32_t aLeft,
int32_t aTop,
int32_t aWidth,
int32_t aHeight)
returns (ScreenDetails screen,
bool success);
nested(inside_cpow) sync ScreenForBrowser(TabId aTabId)
returns (ScreenDetails screen,
bool success);
child:
async __delete__();
};
} // namespace dom
} // namespace mozilla

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

@ -1,234 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/Unused.h"
#include "nsIWidget.h"
#include "nsServiceManagerUtils.h"
#include "ScreenManagerParent.h"
#include "ContentProcessManager.h"
namespace mozilla {
namespace dom {
static const char *sScreenManagerContractID = "@mozilla.org/gfx/screenmanager;1";
ScreenManagerParent::ScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
mScreenMgr = do_GetService(sScreenManagerContractID);
if (!mScreenMgr) {
MOZ_CRASH("Couldn't get nsIScreenManager from ScreenManagerParent.");
}
Unused << RecvRefresh(aNumberOfScreens, aSystemDefaultScale, aSuccess);
}
mozilla::ipc::IPCResult
ScreenManagerParent::RecvRefresh(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess)
{
*aSuccess = false;
nsresult rv = mScreenMgr->GetNumberOfScreens(aNumberOfScreens);
if (NS_FAILED(rv)) {
return IPC_OK();
}
rv = mScreenMgr->GetSystemDefaultScale(aSystemDefaultScale);
if (NS_FAILED(rv)) {
return IPC_OK();
}
*aSuccess = true;
return IPC_OK();
}
mozilla::ipc::IPCResult
ScreenManagerParent::RecvScreenRefresh(const uint32_t& aId,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
nsCOMPtr<nsIScreen> screen;
nsresult rv = mScreenMgr->ScreenForId(aId, getter_AddRefs(screen));
if (NS_FAILED(rv)) {
return IPC_OK();
}
ScreenDetails details;
Unused << ExtractScreenDetails(screen, details);
*aRetVal = details;
*aSuccess = true;
return IPC_OK();
}
mozilla::ipc::IPCResult
ScreenManagerParent::RecvGetPrimaryScreen(ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
nsCOMPtr<nsIScreen> screen;
nsresult rv = mScreenMgr->GetPrimaryScreen(getter_AddRefs(screen));
NS_ENSURE_SUCCESS(rv, IPC_OK());
ScreenDetails details;
if (!ExtractScreenDetails(screen, details)) {
return IPC_OK();
}
*aRetVal = details;
*aSuccess = true;
return IPC_OK();
}
mozilla::ipc::IPCResult
ScreenManagerParent::RecvScreenForRect(const int32_t& aLeft,
const int32_t& aTop,
const int32_t& aWidth,
const int32_t& aHeight,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
nsCOMPtr<nsIScreen> screen;
nsresult rv = mScreenMgr->ScreenForRect(aLeft, aTop, aWidth, aHeight, getter_AddRefs(screen));
NS_ENSURE_SUCCESS(rv, IPC_OK());
ScreenDetails details;
if (!ExtractScreenDetails(screen, details)) {
return IPC_OK();
}
*aRetVal = details;
*aSuccess = true;
return IPC_OK();
}
mozilla::ipc::IPCResult
ScreenManagerParent::RecvScreenForBrowser(const TabId& aTabId,
ScreenDetails* aRetVal,
bool* aSuccess)
{
*aSuccess = false;
#ifdef MOZ_VALGRIND
// Zero this so that Valgrind doesn't complain when we send it to another
// process.
memset(aRetVal, 0, sizeof(ScreenDetails));
#endif
// Find the mWidget associated with the tabparent, and then return
// the nsIScreen it's on.
ContentParent* cp = static_cast<ContentParent*>(this->Manager());
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
RefPtr<TabParent> tabParent =
cpm->GetTopLevelTabParentByProcessAndTabId(cp->ChildID(), aTabId);
if(!tabParent){
return IPC_FAIL_NO_REASON(this);
}
nsCOMPtr<nsIWidget> widget = tabParent->GetWidget();
nsCOMPtr<nsIScreen> screen;
if (widget && widget->GetNativeData(NS_NATIVE_WINDOW)) {
mScreenMgr->ScreenForNativeWidget(widget->GetNativeData(NS_NATIVE_WINDOW),
getter_AddRefs(screen));
} else {
nsresult rv = mScreenMgr->GetPrimaryScreen(getter_AddRefs(screen));
if (NS_WARN_IF(NS_FAILED(rv))) {
return IPC_OK();
}
}
NS_ENSURE_TRUE(screen, IPC_OK());
ScreenDetails details;
if (!ExtractScreenDetails(screen, details)) {
return IPC_OK();
}
*aRetVal = details;
*aSuccess = true;
return IPC_OK();
}
bool
ScreenManagerParent::ExtractScreenDetails(nsIScreen* aScreen, ScreenDetails &aDetails)
{
if (!aScreen) {
return false;
}
uint32_t id;
nsresult rv = aScreen->GetId(&id);
NS_ENSURE_SUCCESS(rv, false);
aDetails.id() = id;
nsIntRect rect;
rv = aScreen->GetRect(&rect.x, &rect.y, &rect.width, &rect.height);
NS_ENSURE_SUCCESS(rv, false);
aDetails.rect() = rect;
nsIntRect rectDisplayPix;
rv = aScreen->GetRectDisplayPix(&rectDisplayPix.x, &rectDisplayPix.y,
&rectDisplayPix.width, &rectDisplayPix.height);
NS_ENSURE_SUCCESS(rv, false);
aDetails.rectDisplayPix() = rectDisplayPix;
nsIntRect availRect;
rv = aScreen->GetAvailRect(&availRect.x, &availRect.y, &availRect.width,
&availRect.height);
NS_ENSURE_SUCCESS(rv, false);
aDetails.availRect() = availRect;
nsIntRect availRectDisplayPix;
rv = aScreen->GetAvailRectDisplayPix(&availRectDisplayPix.x,
&availRectDisplayPix.y,
&availRectDisplayPix.width,
&availRectDisplayPix.height);
NS_ENSURE_SUCCESS(rv, false);
aDetails.availRectDisplayPix() = availRectDisplayPix;
int32_t pixelDepth = 0;
rv = aScreen->GetPixelDepth(&pixelDepth);
NS_ENSURE_SUCCESS(rv, false);
aDetails.pixelDepth() = pixelDepth;
int32_t colorDepth = 0;
rv = aScreen->GetColorDepth(&colorDepth);
NS_ENSURE_SUCCESS(rv, false);
aDetails.colorDepth() = colorDepth;
double contentsScaleFactor = 1.0;
rv = aScreen->GetContentsScaleFactor(&contentsScaleFactor);
NS_ENSURE_SUCCESS(rv, false);
aDetails.contentsScaleFactor() = contentsScaleFactor;
double defaultCSSScaleFactor = 1.0;
rv = aScreen->GetDefaultCSSScaleFactor(&defaultCSSScaleFactor);
NS_ENSURE_SUCCESS(rv, false);
aDetails.defaultCSSScaleFactor() = defaultCSSScaleFactor;
return true;
}
void
ScreenManagerParent::ActorDestroy(ActorDestroyReason why)
{
}
} // namespace dom
} // namespace mozilla

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

@ -1,56 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_ScreenManagerParent_h
#define mozilla_dom_ScreenManagerParent_h
#include "mozilla/dom/PScreenManagerParent.h"
#include "nsIScreenManager.h"
namespace mozilla {
namespace dom {
class ScreenManagerParent : public PScreenManagerParent
{
public:
ScreenManagerParent(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess);
~ScreenManagerParent() {};
virtual mozilla::ipc::IPCResult RecvRefresh(uint32_t* aNumberOfScreens,
float* aSystemDefaultScale,
bool* aSuccess) override;
virtual mozilla::ipc::IPCResult RecvScreenRefresh(const uint32_t& aId,
ScreenDetails* aRetVal,
bool* aSuccess) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual mozilla::ipc::IPCResult RecvGetPrimaryScreen(ScreenDetails* aRetVal,
bool* aSuccess) override;
virtual mozilla::ipc::IPCResult RecvScreenForRect(const int32_t& aLeft,
const int32_t& aTop,
const int32_t& aWidth,
const int32_t& aHeight,
ScreenDetails* aRetVal,
bool* aSuccess) override;
virtual mozilla::ipc::IPCResult RecvScreenForBrowser(const TabId& aTabId,
ScreenDetails* aRetVal,
bool* aSuccess) override;
private:
bool ExtractScreenDetails(nsIScreen* aScreen, ScreenDetails &aDetails);
nsCOMPtr<nsIScreenManager> mScreenMgr;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ScreenManagerParent_h

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

@ -65,7 +65,6 @@ UNIFIED_SOURCES += [
'PermissionMessageUtils.cpp',
'PreallocatedProcessManager.cpp',
'ProcessPriorityManager.cpp',
'ScreenManagerParent.cpp',
'StructuredCloneData.cpp',
'TabChild.cpp',
'TabContext.cpp',
@ -97,7 +96,6 @@ IPDL_SOURCES += [
'PFilePicker.ipdl',
'PPluginWidget.ipdl',
'PProcessHangMonitor.ipdl',
'PScreenManager.ipdl',
'PTabContext.ipdlh',
'PURLClassifier.ipdl',
'PURLClassifierInfo.ipdlh',

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

@ -170,6 +170,8 @@ private:
DECL_MEDIA_PREF("media.rust.test_mode", RustTestMode, bool, false);
#endif
DECL_MEDIA_PREF("media.rust.mp4parser", EnableRustMP4Parser, bool, false);
public:
// Manage the singleton:
static MediaPrefs& GetSingleton();

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

@ -1172,12 +1172,7 @@ NPBool nsPluginInstanceOwner::ConvertPointNoPuppet(nsIWidget *widget,
double scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/
presContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom();
nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
if (!screenMgr) {
return false;
}
nsCOMPtr<nsIScreen> screen;
screenMgr->ScreenForNativeWidget(widget->GetNativeData(NS_NATIVE_WINDOW), getter_AddRefs(screen));
nsCOMPtr<nsIScreen> screen = widget->GetWidgetScreen();
if (!screen) {
return false;
}

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

@ -609,21 +609,8 @@ nsDeviceContext::FindScreen(nsIScreen** outScreen)
CheckDPIChange();
if (mWidget->GetOwningTabChild()) {
mScreenManager->ScreenForNativeWidget((void *)mWidget->GetOwningTabChild(),
outScreen);
}
else if (mWidget->GetNativeData(NS_NATIVE_WINDOW)) {
mScreenManager->ScreenForNativeWidget(mWidget->GetNativeData(NS_NATIVE_WINDOW),
outScreen);
}
#ifdef MOZ_WIDGET_ANDROID
if (!(*outScreen)) {
nsCOMPtr<nsIScreen> screen = mWidget->GetWidgetScreen();
screen.forget(outScreen);
}
#endif
nsCOMPtr<nsIScreen> screen = mWidget->GetWidgetScreen();
screen.forget(outScreen);
if (!(*outScreen)) {
mScreenManager->GetPrimaryScreen(outScreen);

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

@ -36,7 +36,7 @@ public:
// construct a wrapper around the specified drawable with dpy/format,
// and known width/height.
gfxXlibSurface(Screen *screen, Drawable drawable, XRenderPictFormat *format,
gfxXlibSurface(::Screen *screen, Drawable drawable, XRenderPictFormat *format,
const mozilla::gfx::IntSize& size);
explicit gfxXlibSurface(cairo_surface_t *csurf);
@ -46,13 +46,13 @@ public:
// the pixmap should be in video or system memory. It must be on
// |screen| (if specified).
static already_AddRefed<gfxXlibSurface>
Create(Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size,
Create(::Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size,
Drawable relatedDrawable = X11None);
static cairo_surface_t *
CreateCairoSurface(Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size,
CreateCairoSurface(::Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size,
Drawable relatedDrawable = X11None);
static already_AddRefed<gfxXlibSurface>
Create(Screen* screen, XRenderPictFormat *format, const mozilla::gfx::IntSize& size,
Create(::Screen* screen, XRenderPictFormat *format, const mozilla::gfx::IntSize& size,
Drawable relatedDrawable = X11None);
virtual ~gfxXlibSurface();
@ -65,12 +65,12 @@ public:
virtual const mozilla::gfx::IntSize GetSize() const override;
Display* XDisplay() { return mDisplay; }
Screen* XScreen();
::Screen* XScreen();
Drawable XDrawable() { return mDrawable; }
XRenderPictFormat* XRenderFormat();
static int DepthOfVisual(const Screen* screen, const Visual* visual);
static Visual* FindVisual(Screen* screen, gfxImageFormat format);
static int DepthOfVisual(const ::Screen* screen, const Visual* visual);
static Visual* FindVisual(::Screen* screen, gfxImageFormat format);
static XRenderPictFormat *FindRenderFormat(Display *dpy, gfxImageFormat format);
static bool GetColormapAndVisual(cairo_surface_t* aXlibSurface, Colormap* colormap, Visual **visual);

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

@ -71,7 +71,6 @@
#include "nsThreadUtils.h"
#include "nsIThread.h"
#include "nsXULAppAPI.h"
#include "OrientationObserver.h"
#include "UeventPoller.h"
#include "nsIWritablePropertyBag2.h"
#include <algorithm>
@ -1012,13 +1011,12 @@ GetCurrentScreenConfiguration(hal::ScreenConfiguration* aScreenConfiguration)
bool
LockScreenOrientation(const dom::ScreenOrientationInternal& aOrientation)
{
return OrientationObserver::GetInstance()->LockScreenOrientation(aOrientation);
return false;
}
void
UnlockScreenOrientation()
{
OrientationObserver::GetInstance()->UnlockScreenOrientation();
}
// This thread will wait for the alarm firing by a blocking IO.

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

@ -884,8 +884,6 @@ description =
description =
[PContent::IsSecureURI]
description =
[PContent::PScreenManager]
description =
[PContent::PURLClassifier]
description =
[PContent::ClassifyLocal]
@ -934,16 +932,6 @@ description =
description =
[PContentBridge::SyncMessage]
description =
[PScreenManager::Refresh]
description =
[PScreenManager::ScreenRefresh]
description =
[PScreenManager::GetPrimaryScreen]
description =
[PScreenManager::ScreenForRect]
description =
[PScreenManager::ScreenForBrowser]
description =
[PGMP::StartPlugin]
description =
[PGMPService::LaunchGMP]

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

@ -603,10 +603,10 @@ GetMinAndMaxScaleForAnimationProperty(const nsIFrame* aFrame,
for (const AnimationPropertySegment& segment : prop.mSegments) {
// In case of add or accumulate composite, StyleAnimationValue does
// not have a valid value.
if (segment.HasReplacableFromValue()) {
if (segment.HasReplaceableFromValue()) {
UpdateMinMaxScale(aFrame, segment.mFromValue, aMinScale, aMaxScale);
}
if (segment.HasReplacableToValue()) {
if (segment.HasReplaceableToValue()) {
UpdateMinMaxScale(aFrame, segment.mToValue, aMinScale, aMaxScale);
}
}

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

@ -675,7 +675,9 @@ void nsTextControlFrame::SetFocus(bool aOn, bool aRepaint)
}
if (!(lastFocusMethod & nsIFocusManager::FLAG_BYMOUSE)) {
RefPtr<ScrollOnFocusEvent> event = new ScrollOnFocusEvent(this);
nsresult rv = NS_DispatchToCurrentThread(event);
nsresult rv = mContent->OwnerDoc()->Dispatch("ScrollOnFocusEvent",
TaskCategory::Other,
do_AddRef(event));
if (NS_SUCCEEDED(rv)) {
mScrollEvent = event;
}

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

@ -365,9 +365,6 @@ to mochitest command.
* test_variables.html `--weird`: name of custom property is not escaped properly servo/servo#15399 [1]
* image-layer values should omit some of its parts when they are initial servo/servo#15951
* test_shorthand_property_getters.html `background` [2]
* counter-{reset,increment} doesn't serialize none servo/servo#15977
* test_value_storage.html `counter-reset` [2]
* test_value_storage.html `counter-increment` [2]
* :not(*) doesn't serialize properly servo/servo#16017
* test_selectors.html `:not()` [8]
* ... `:not(html|)` [1]
@ -410,7 +407,6 @@ to mochitest command.
* ... `perspective'`: servo/servo#15449 [20]
* ... `'text-shadow'`: third length of text-shadow servo/servo#15999 [2]
* ... `flex-basis`: servo/servo#15902 [6]
* ... `border-image-slice`: servo/servo#15339 [2]
* Quirks mode support
* hashless color servo/servo#15341
* test_property_syntax_errors.html `color: 000000` [22]

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

@ -230,7 +230,7 @@ IndiceWrapperRust::GetIndice(size_t aIndex, Index::Indice& aIndice) const
MP4Metadata::MP4Metadata(Stream* aSource)
: mStagefright(MakeUnique<MP4MetadataStagefright>(aSource))
, mRust(MakeUnique<MP4MetadataRust>(aSource))
, mPreferRust(false)
, mPreferRust(MediaPrefs::EnableRustMP4Parser())
, mReportedAudioTrackTelemetry(false)
, mReportedVideoTrackTelemetry(false)
#ifndef RELEASE_OR_BETA

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

@ -5,6 +5,7 @@
#include "gtest/gtest.h"
#include "MediaData.h"
#include "MediaPrefs.h"
#include "mozilla/ArrayUtils.h"
#include "mp4_demuxer/BufferStream.h"
#include "mp4_demuxer/MP4Metadata.h"
@ -205,10 +206,64 @@ static const TestFileData testFiles[] = {
false, 0, false, false, 2 },
};
static const TestFileData rustTestFiles[] = {
// filename #V dur w h #A dur crypt off moof headr audio_profile
{ "test_case_1156505.mp4", 0, -1, 0, 0, 0, -1, false, 152, false, false, 0 },
{ "test_case_1181213.mp4", 1, 416666,
320, 240, 1, 477460,
true, 0, false, false, 2 },
{ "test_case_1181215.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 },
{ "test_case_1181220.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 },
{ "test_case_1181223.mp4", 1, 416666,
320, 240, 0, -1, false, 0, false, false, 0 },
{ "test_case_1181719.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 },
{ "test_case_1185230.mp4", 2, 416666,
320, 240, 2, 5, false, 0, false, false, 2 },
{ "test_case_1187067.mp4", 1, 80000,
160, 90, 0, -1, false, 0, false, false, 0 },
{ "test_case_1200326.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 },
{ "test_case_1204580.mp4", 1, 502500,
320, 180, 0, -1, false, 0, false, false, 0 },
{ "test_case_1216748.mp4", 0, -1, 0, 0, 0, -1, false, 152, false, false, 0 },
{ "test_case_1296473.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 },
{ "test_case_1296532.mp4", 1, 5589333,
560, 320, 1, 5589333,
true, 0, true, true, 2 },
{ "test_case_1301065.mp4", 0, -1, 0, 0, 1, 100079991719000000,
false, 0, false, false, 2 },
{ "test_case_1301065-u32max.mp4", 0, -1, 0, 0, 1, 97391548639,
false, 0, false, false, 2 },
{ "test_case_1301065-max-ez.mp4", 0, -1, 0, 0, 1, 209146758205306,
false, 0, false, false, 2 },
{ "test_case_1301065-harder.mp4", 0, -1, 0, 0, 1, 209146758205328,
false, 0, false, false, 2 },
{ "test_case_1301065-max-ok.mp4", 0, -1, 0, 0, 1, 9223372036854775804,
false, 0, false, false, 2 },
// The duration is overflow for int64_t in TestFileData, rust parser uses uint64_t so
// this file is ignore.
//{ "test_case_1301065-overfl.mp4", 0, -1, 0, 0, 1, 9223372036854775827,
// false, 0, false, false, 2 },
{ "test_case_1301065-i64max.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 },
{ "test_case_1301065-i64min.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false, 0 },
{ "test_case_1301065-u64max.mp4", 0, -1, 0, 0, 1, 0, false, 0, false, false, 2 },
{ "test_case_1329061.mov", 0, -1, 0, 0, 1, 234567981,
false, 0, false, false, 2 },
};
TEST(stagefright_MPEG4Metadata, test_case_mp4)
{
for (size_t test = 0; test < ArrayLength(testFiles); ++test) {
nsTArray<uint8_t> buffer = ReadTestFile(testFiles[test].mFilename);
const TestFileData* tests = nullptr;
size_t length = 0;
if (MediaPrefs::EnableRustMP4Parser()) {
tests = rustTestFiles;
length = ArrayLength(rustTestFiles);
} else {
tests = testFiles;
length = ArrayLength(testFiles);
}
for (size_t test = 0; test < length; ++test) {
nsTArray<uint8_t> buffer = ReadTestFile(tests[test].mFilename);
ASSERT_FALSE(buffer.IsEmpty());
RefPtr<Stream> stream = new TestStream(buffer.Elements(), buffer.Length());
@ -217,15 +272,15 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4)
MP4Metadata metadata(stream);
EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kUndefinedTrack));
EXPECT_EQ(testFiles[test].mNumberAudioTracks,
EXPECT_EQ(tests[test].mNumberAudioTracks,
metadata.GetNumberTracks(TrackInfo::kAudioTrack));
EXPECT_EQ(testFiles[test].mNumberVideoTracks,
EXPECT_EQ(tests[test].mNumberVideoTracks,
metadata.GetNumberTracks(TrackInfo::kVideoTrack));
EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kTextTrack));
EXPECT_EQ(0u, metadata.GetNumberTracks(static_cast<TrackInfo::TrackType>(-1)));
EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kUndefinedTrack, 0));
UniquePtr<TrackInfo> trackInfo = metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0);
if (testFiles[test].mNumberVideoTracks == 0) {
if (tests[test].mNumberVideoTracks == 0) {
EXPECT_TRUE(!trackInfo);
} else {
ASSERT_TRUE(!!trackInfo);
@ -233,9 +288,9 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4)
ASSERT_TRUE(!!videoInfo);
EXPECT_TRUE(videoInfo->IsValid());
EXPECT_TRUE(videoInfo->IsVideo());
EXPECT_EQ(testFiles[test].mVideoDuration, videoInfo->mDuration);
EXPECT_EQ(testFiles[test].mWidth, videoInfo->mDisplay.width);
EXPECT_EQ(testFiles[test].mHeight, videoInfo->mDisplay.height);
EXPECT_EQ(tests[test].mVideoDuration, videoInfo->mDuration);
EXPECT_EQ(tests[test].mWidth, videoInfo->mDisplay.width);
EXPECT_EQ(tests[test].mHeight, videoInfo->mDisplay.height);
UniquePtr<IndiceWrapper> indices = metadata.GetTrackIndice(videoInfo->mTrackId);
EXPECT_TRUE(!!indices);
@ -247,7 +302,7 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4)
}
}
trackInfo = metadata.GetTrackInfo(TrackInfo::kAudioTrack, 0);
if (testFiles[test].mNumberAudioTracks == 0) {
if (tests[test].mNumberAudioTracks == 0) {
EXPECT_TRUE(!trackInfo);
} else {
ASSERT_TRUE(!!trackInfo);
@ -255,8 +310,11 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4)
ASSERT_TRUE(!!audioInfo);
EXPECT_TRUE(audioInfo->IsValid());
EXPECT_TRUE(audioInfo->IsAudio());
EXPECT_EQ(testFiles[test].mAudioDuration, audioInfo->mDuration);
EXPECT_EQ(testFiles[test].mAudioProfile, audioInfo->mProfile);
EXPECT_EQ(tests[test].mAudioDuration, audioInfo->mDuration);
EXPECT_EQ(tests[test].mAudioProfile, audioInfo->mProfile);
if (tests[test].mAudioDuration != audioInfo->mDuration) {
MOZ_RELEASE_ASSERT(false);
}
UniquePtr<IndiceWrapper> indices = metadata.GetTrackIndice(audioInfo->mTrackId);
EXPECT_TRUE(!!indices);
@ -264,14 +322,14 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4)
Index::Indice data;
EXPECT_TRUE(indices->GetIndice(i, data));
EXPECT_TRUE(data.start_offset <= data.end_offset);
EXPECT_TRUE(data.start_composition <= data.end_composition);
EXPECT_TRUE(int64_t(data.start_composition) <= int64_t(data.end_composition));
}
}
EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kTextTrack, 0));
EXPECT_FALSE(metadata.GetTrackInfo(static_cast<TrackInfo::TrackType>(-1), 0));
// We can see anywhere in any MPEG4.
EXPECT_TRUE(metadata.CanSeek());
EXPECT_EQ(testFiles[test].mHasCrypto, metadata.Crypto().valid);
EXPECT_EQ(tests[test].mHasCrypto, metadata.Crypto().valid);
}
}
@ -315,8 +373,19 @@ TEST(stagefright_MPEG4Metadata, test_case_mp4_subsets)
TEST(stagefright_MoofParser, test_case_mp4)
{
for (size_t test = 0; test < ArrayLength(testFiles); ++test) {
nsTArray<uint8_t> buffer = ReadTestFile(testFiles[test].mFilename);
const TestFileData* tests = nullptr;
size_t length = 0;
if (MediaPrefs::EnableRustMP4Parser()) {
tests = rustTestFiles;
length = ArrayLength(rustTestFiles);
} else {
tests = testFiles;
length = ArrayLength(testFiles);
}
for (size_t test = 0; test < length; ++test) {
nsTArray<uint8_t> buffer = ReadTestFile(tests[test].mFilename);
ASSERT_FALSE(buffer.IsEmpty());
RefPtr<Stream> stream = new TestStream(buffer.Elements(), buffer.Length());
@ -332,20 +401,20 @@ TEST(stagefright_MoofParser, test_case_mp4)
EXPECT_FALSE(parser.mInitRange.IsEmpty());
const MediaByteRangeSet byteRanges(
MediaByteRange(0, int64_t(buffer.Length())));
EXPECT_EQ(testFiles[test].mValidMoof,
EXPECT_EQ(tests[test].mValidMoof,
parser.RebuildFragmentedIndex(byteRanges));
if (testFiles[test].mMoofReachedOffset == 0) {
if (tests[test].mMoofReachedOffset == 0) {
EXPECT_EQ(buffer.Length(), parser.mOffset);
EXPECT_TRUE(parser.ReachedEnd());
} else {
EXPECT_EQ(testFiles[test].mMoofReachedOffset, parser.mOffset);
EXPECT_EQ(tests[test].mMoofReachedOffset, parser.mOffset);
EXPECT_FALSE(parser.ReachedEnd());
}
EXPECT_FALSE(parser.mInitRange.IsEmpty());
EXPECT_TRUE(parser.GetCompositionRange(byteRanges).IsNull());
EXPECT_TRUE(parser.FirstCompleteMediaSegment().IsEmpty());
EXPECT_EQ(testFiles[test].mHeader,
EXPECT_EQ(tests[test].mHeader,
!parser.FirstCompleteMediaHeader().IsEmpty());
}
}

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

@ -313,8 +313,6 @@ public class MediaControlService extends Service implements Tabs.OnTabsChangedLi
super.onPlay();
setState(State.PLAYING);
notifyObservers("MediaControl", "resumeMedia");
// To make sure we always own audio focus during playing.
AudioFocusAgent.notifyStartedPlaying();
}
@Override
@ -323,7 +321,6 @@ public class MediaControlService extends Service implements Tabs.OnTabsChangedLi
super.onPause();
setState(State.PAUSED);
notifyObservers("MediaControl", "mediaControlPaused");
AudioFocusAgent.notifyStoppedPlaying();
}
@Override

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

@ -1060,16 +1060,6 @@ public class GeckoAppShell
vibrator().cancel();
}
@WrapForJNI(calledFrom = "gecko")
private static void setKeepScreenOn(final boolean on) {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
// TODO
}
});
}
@WrapForJNI(calledFrom = "gecko")
private static boolean isNetworkLinkUp() {
ConnectivityManager cm = (ConnectivityManager)

64
servo/Cargo.lock сгенерированный
Просмотреть файл

@ -135,6 +135,14 @@ dependencies = [
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "base64"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bincode"
version = "1.0.0-alpha2"
@ -284,7 +292,7 @@ dependencies = [
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"offscreen_gl_context 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_config 0.0.1",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -298,7 +306,7 @@ dependencies = [
"ipc-channel 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -419,8 +427,8 @@ dependencies = [
"servo_url 0.0.1",
"style_traits 0.0.1",
"time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender 0.25.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -453,7 +461,7 @@ dependencies = [
"servo_remutex 0.0.1",
"servo_url 0.0.1",
"style_traits 0.0.1",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
"webvr_traits 0.0.1",
]
@ -698,7 +706,7 @@ dependencies = [
"servo_geometry 0.0.1",
"servo_url 0.0.1",
"style_traits 0.0.1",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
"x11 2.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -980,7 +988,7 @@ dependencies = [
"time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
"truetype 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
"xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1059,7 +1067,7 @@ dependencies = [
"servo_url 0.0.1",
"style_traits 0.0.1",
"user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1370,7 +1378,7 @@ dependencies = [
"style_traits 0.0.1",
"unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -1410,7 +1418,7 @@ dependencies = [
"servo_geometry 0.0.1",
"servo_url 0.0.1",
"style 0.0.1",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -1424,7 +1432,7 @@ dependencies = [
"profile_traits 0.0.1",
"script_traits 0.0.1",
"servo_url 0.0.1",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -1509,8 +1517,8 @@ dependencies = [
"style 0.0.1",
"style_traits 0.0.1",
"webdriver_server 0.0.1",
"webrender 0.25.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
"webvr 0.0.1",
"webvr_traits 0.0.1",
]
@ -1659,7 +1667,7 @@ dependencies = [
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -1671,6 +1679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "net"
version = "0.0.1"
dependencies = [
"base64 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"brotli 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"devtools_traits 0.0.1",
@ -1688,7 +1697,6 @@ dependencies = [
"openssl 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-verify 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"profile_traits 0.0.1",
"rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1701,7 +1709,7 @@ dependencies = [
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -1759,7 +1767,7 @@ dependencies = [
"servo_url 0.0.1",
"url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
]
[[package]]
@ -2241,6 +2249,7 @@ dependencies = [
"app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"audio-video-metadata 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"base64 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bluetooth_traits 0.0.1",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2285,7 +2294,6 @@ dependencies = [
"ref_filter_map 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ref_slice 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
"script_layout_interface 0.0.1",
"script_plugins 0.0.1",
"script_traits 0.0.1",
@ -2304,7 +2312,7 @@ dependencies = [
"tinyfiledialogs 2.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
"webvr 0.0.1",
"webvr_traits 0.0.1",
"xml5ever 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3157,6 +3165,7 @@ dependencies = [
name = "webdriver_server"
version = "0.0.1"
dependencies = [
"base64 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3177,8 +3186,8 @@ dependencies = [
[[package]]
name = "webrender"
version = "0.25.0"
source = "git+https://github.com/servo/webrender#0794911f97cae92496fca992d7430da696fa24eb"
version = "0.26.0"
source = "git+https://github.com/servo/webrender#b2dd9f792d0cb3dfc591567c105755f56f35956d"
dependencies = [
"app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 1.0.0-alpha2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3200,13 +3209,13 @@ dependencies = [
"thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
]
[[package]]
name = "webrender_traits"
version = "0.26.0"
source = "git+https://github.com/servo/webrender#0794911f97cae92496fca992d7430da696fa24eb"
version = "0.27.0"
source = "git+https://github.com/servo/webrender#b2dd9f792d0cb3dfc591567c105755f56f35956d"
dependencies = [
"app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3230,7 +3239,7 @@ dependencies = [
"msg 0.0.1",
"script_traits 0.0.1",
"servo_config 0.0.1",
"webrender_traits 0.26.0 (git+https://github.com/servo/webrender)",
"webrender_traits 0.27.0 (git+https://github.com/servo/webrender)",
"webvr_traits 0.0.1",
]
@ -3336,6 +3345,7 @@ dependencies = [
"checksum azure 0.15.0 (git+https://github.com/servo/rust-azure)" = "<none>"
"checksum backtrace 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f551bc2ddd53aea015d453ef0b635af89444afa5ed2405dd0b2062ad5d600d80"
"checksum backtrace-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d192fd129132fbc97497c1f2ec2c2c5174e376b95f535199ef4fe0a293d33842"
"checksum base64 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9892882c3bd89ed02dec391c128984c772b663a29700c32b5de0b33861cdf2bd"
"checksum bincode 1.0.0-alpha2 (registry+https://github.com/rust-lang/crates.io-index)" = "62650bb5651ba8f0580cebf4ef255d791b8b0ef53800322661e1bb5791d42966"
"checksum bindgen 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "facc480c409c373db3c870e377ce223e5e07d979efc2604691dc6f583e8ded0f"
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
@ -3572,8 +3582,8 @@ dependencies = [
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
"checksum webdriver 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdc28802daddee94267a657ffeac2593a33881fb7a3a44fedd320b1319efcaf6"
"checksum webrender 0.25.0 (git+https://github.com/servo/webrender)" = "<none>"
"checksum webrender_traits 0.26.0 (git+https://github.com/servo/webrender)" = "<none>"
"checksum webrender 0.26.0 (git+https://github.com/servo/webrender)" = "<none>"
"checksum webrender_traits 0.27.0 (git+https://github.com/servo/webrender)" = "<none>"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum ws 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04614a58714f3fd4a8b1da4bcae9f031c532d35988c3d39627619248113f8be8"

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

@ -567,7 +567,8 @@ impl<'a> CanvasPaintThread<'a> {
offset: 0,
is_opaque: false,
},
element.into());
element.into(),
None);
let data = CanvasImageData {
image_key: self.webrender_image_key,

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

@ -261,7 +261,8 @@ impl WebGLPaintThread {
offset: 0,
is_opaque: false,
},
pixels.clone());
pixels.clone(),
None);
let image_data = CanvasImageData {
image_key: image_key,

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

@ -886,10 +886,7 @@ pub struct IframeDisplayItem {
/// Paints a gradient.
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
pub struct GradientDisplayItem {
/// Fields common to all display items.
pub base: BaseDisplayItem,
pub struct Gradient {
/// The start point of the gradient (computed during display list construction).
pub start_point: Point2D<Au>,
@ -900,6 +897,15 @@ pub struct GradientDisplayItem {
pub stops: Vec<GradientStop>,
}
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
pub struct GradientDisplayItem {
/// Fields common to all display item.
pub base: BaseDisplayItem,
/// Contains all gradient data. Included start, end point and color stops.
pub gradient: Gradient,
}
/// A normal border, supporting CSS border styles.
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
pub struct NormalBorder {
@ -939,11 +945,22 @@ pub struct ImageBorder {
pub repeat_vertical: webrender_traits::RepeatMode,
}
/// A border that is made of linear gradient
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
pub struct GradientBorder {
/// The gradient info that this border uses, border-image-source.
pub gradient: Gradient,
/// Outsets for the border, as per border-image-outset.
pub outset: SideOffsets2D<f32>,
}
/// Specifies the type of border
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
pub enum BorderDetails {
Normal(NormalBorder),
Image(ImageBorder),
Gradient(GradientBorder),
}
/// Paints a border.

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

@ -20,6 +20,7 @@ use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
use flow_ref::FlowRef;
use fragment::{CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo};
use fragment::{SpecificFragmentInfo, TruncatedFragmentInfo};
use gfx::display_list;
use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails};
use gfx::display_list::{BorderDisplayItem, ImageBorder, NormalBorder};
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion};
@ -350,6 +351,12 @@ pub trait FragmentDisplayListBuilding {
image_url: &ServoUrl,
background_index: usize);
fn convert_gradient(&self,
absolute_bounds: &Rect<Au>,
gradient: &Gradient,
style: &ServoComputedValues)
-> Option<display_list::Gradient>;
/// Adds the display items necessary to paint the background linear gradient of this fragment
/// to the appropriate section of the display list.
fn build_display_list_for_background_gradient(&self,
@ -831,20 +838,13 @@ impl FragmentDisplayListBuilding for Fragment {
}
}
fn build_display_list_for_background_gradient(&self,
state: &mut DisplayListBuildState,
display_list_section: DisplayListSection,
absolute_bounds: &Rect<Au>,
clip: &ClippingRegion,
gradient: &Gradient,
style: &ServoComputedValues) {
let mut clip = clip.clone();
clip.intersect_rect(absolute_bounds);
fn convert_gradient(&self,
absolute_bounds: &Rect<Au>,
gradient: &Gradient,
style: &ServoComputedValues) -> Option<display_list::Gradient> {
// FIXME: Repeating gradients aren't implemented yet.
if gradient.repeating {
return;
return None;
}
let angle = if let GradientKind::Linear(angle_or_corner) = gradient.gradient_kind {
match angle_or_corner {
@ -869,7 +869,7 @@ impl FragmentDisplayListBuilding for Fragment {
}
} else {
// FIXME: Radial gradients aren't implemented yet.
return;
return None;
};
// Get correct gradient line length, based on:
@ -953,19 +953,39 @@ impl FragmentDisplayListBuilding for Fragment {
let center = Point2D::new(absolute_bounds.origin.x + absolute_bounds.size.width / 2,
absolute_bounds.origin.y + absolute_bounds.size.height / 2);
let base = state.create_base_display_item(absolute_bounds,
&clip,
self.node,
style.get_cursor(Cursor::Default),
display_list_section);
let gradient_display_item = DisplayItem::Gradient(box GradientDisplayItem {
base: base,
Some(display_list::Gradient {
start_point: center - delta,
end_point: center + delta,
stops: stops,
});
})
}
state.add_display_item(gradient_display_item);
fn build_display_list_for_background_gradient(&self,
state: &mut DisplayListBuildState,
display_list_section: DisplayListSection,
absolute_bounds: &Rect<Au>,
clip: &ClippingRegion,
gradient: &Gradient,
style: &ServoComputedValues) {
let mut clip = clip.clone();
clip.intersect_rect(absolute_bounds);
let grad = self.convert_gradient(absolute_bounds, gradient, style);
if let Some(x) = grad {
let base = state.create_base_display_item(absolute_bounds,
&clip,
self.node,
style.get_cursor(Cursor::Default),
display_list_section);
let gradient_display_item = DisplayItem::Gradient(box GradientDisplayItem {
base: base,
gradient: x,
});
state.add_display_item(gradient_display_item);
}
}
fn build_display_list_for_box_shadow_if_applicable(&self,
@ -1076,8 +1096,28 @@ impl FragmentDisplayListBuilding for Fragment {
}),
}));
}
Some(computed::Image::Gradient(..)) => {
// TODO(gw): Handle border-image with gradient.
Some(computed::Image::Gradient(ref gradient)) => {
match gradient.gradient_kind {
GradientKind::Linear(_) => {
let grad = self.convert_gradient(&bounds, gradient, style);
if let Some(x) = grad {
state.add_display_item(DisplayItem::Border(box BorderDisplayItem {
base: base,
border_widths: border.to_physical(style.writing_mode),
details: BorderDetails::Gradient(display_list::GradientBorder {
gradient: x,
// TODO(gw): Support border-image-outset
outset: SideOffsets2D::zero(),
}),
}));
}
}
GradientKind::Radial(_, _) => {
// TODO(gw): Handle border-image with radial gradient.
}
}
}
Some(computed::Image::ImageRect(..)) => {
// TODO: Handle border-image with `-moz-image-rect`.

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

@ -351,20 +351,30 @@ impl WebRenderDisplayItemConverter for DisplayItem {
}
}
}
BorderDetails::Gradient(ref gradient) => {
webrender_traits::BorderDetails::Gradient(webrender_traits::GradientBorder {
gradient: builder.create_gradient(
gradient.gradient.start_point.to_pointf(),
gradient.gradient.end_point.to_pointf(),
gradient.gradient.stops.clone(),
ExtendMode::Clamp),
outset: gradient.outset,
})
}
};
builder.push_border(rect, clip, widths, details);
}
DisplayItem::Gradient(ref item) => {
let rect = item.base.bounds.to_rectf();
let start_point = item.start_point.to_pointf();
let end_point = item.end_point.to_pointf();
let start_point = item.gradient.start_point.to_pointf();
let end_point = item.gradient.end_point.to_pointf();
let clip = item.base.clip.to_clip_region(builder);
builder.push_gradient(rect,
clip,
start_point,
end_point,
item.stops.clone(),
item.gradient.stops.clone(),
ExtendMode::Clamp);
}
DisplayItem::Line(..) => {
@ -394,10 +404,6 @@ impl WebRenderDisplayItemConverter for DisplayItem {
let stacking_context = &item.stacking_context;
debug_assert!(stacking_context.context_type == StackingContextType::Real);
let clip = builder.new_clip_region(&stacking_context.overflow.to_rectf(),
vec![],
None);
let transform = stacking_context.transform.map(|transform| {
LayoutTransform::from_untyped(&transform).into()
});
@ -407,7 +413,6 @@ impl WebRenderDisplayItemConverter for DisplayItem {
builder.push_stacking_context(stacking_context.scroll_policy,
stacking_context.bounds.to_rectf(),
clip,
stacking_context.z_index,
transform,
perspective,

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

@ -120,7 +120,7 @@ use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets};
use style::stylist::Stylist;
use style::thread_state;
use style::timer::Timer;
use style::traversal::{DomTraversal, TraversalDriver};
use style::traversal::{DomTraversal, TraversalDriver, TraversalFlags};
/// Information needed by the layout thread.
pub struct LayoutThread {
@ -520,6 +520,7 @@ impl LayoutThread {
local_context_creation_data: Mutex::new(thread_local_style_context_creation_data),
timer: self.timer.clone(),
quirks_mode: self.quirks_mode.unwrap(),
animation_only_restyle: false,
},
image_cache_thread: Mutex::new(self.image_cache_thread.clone()),
font_cache_thread: Mutex::new(self.font_cache_thread.clone()),
@ -1143,7 +1144,7 @@ impl LayoutThread {
let stylist = &<RecalcStyleAndConstructFlows as
DomTraversal<ServoLayoutElement>>::shared_context(&traversal).stylist;
<RecalcStyleAndConstructFlows as
DomTraversal<ServoLayoutElement>>::pre_traverse(element, stylist, /* skip_root = */ false)
DomTraversal<ServoLayoutElement>>::pre_traverse(element, stylist, TraversalFlags::empty())
};
if token.should_traverse() {

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

@ -10,6 +10,7 @@ name = "net"
path = "lib.rs"
[dependencies]
base64 = "0.4.1"
brotli = "1.0.6"
cookie = "0.2.5"
devtools_traits = {path = "../devtools_traits"}
@ -27,7 +28,6 @@ net_traits = {path = "../net_traits"}
openssl = "0.7.6"
openssl-verify = "0.1"
profile_traits = {path = "../profile_traits"}
rustc-serialize = "0.3"
serde = "0.9"
serde_derive = "0.9"
serde_json = "0.9"

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

@ -2,8 +2,8 @@
* 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/. */
use base64;
use hyper::mime::{Attr, Mime, SubLevel, TopLevel, Value};
use rustc_serialize::base64::FromBase64;
use servo_url::ServoUrl;
use url::Position;
use url::percent_encoding::percent_decode;
@ -46,7 +46,7 @@ pub fn decode(url: &ServoUrl) -> Result<DecodeData, DecodeError> {
// FIXME(#2909): Its unclear what to do with non-alphabet characters,
// but Acid 3 apparently depends on spaces being ignored.
bytes = bytes.into_iter().filter(|&b| b != b' ').collect::<Vec<u8>>();
match bytes.from_base64() {
match base64::decode(&bytes) {
Err(..) => return Err(DecodeError::NonBase64DataUri),
Ok(data) => bytes = data,
}

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

@ -192,7 +192,7 @@ pub fn main_fetch(request: Rc<Request>,
.read()
.unwrap()
.is_host_secure(request.current_url().domain().unwrap()) {
request.url_list.borrow_mut().last_mut().unwrap().as_mut_url().unwrap().set_scheme("https").unwrap();
request.url_list.borrow_mut().last_mut().unwrap().as_mut_url().set_scheme("https").unwrap();
}
}

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

@ -15,6 +15,7 @@ use hsts::HstsList;
use hyper::Error as HttpError;
use hyper::LanguageTag;
use hyper::client::{Pool, Request as HyperRequest, Response as HyperResponse};
use hyper::client::pool::PooledStream;
use hyper::header::{AcceptEncoding, AcceptLanguage, AccessControlAllowCredentials};
use hyper::header::{AccessControlAllowOrigin, AccessControlAllowHeaders, AccessControlAllowMethods};
use hyper::header::{AccessControlRequestHeaders, AccessControlMaxAge, AccessControlRequestMethod};
@ -24,17 +25,18 @@ use hyper::header::{IfUnmodifiedSince, IfModifiedSince, IfNoneMatch, Location, P
use hyper::header::{QualityItem, Referer, SetCookie, UserAgent, qitem};
use hyper::header::Origin as HyperOrigin;
use hyper::method::Method;
use hyper::net::Fresh;
use hyper::net::{Fresh, HttpStream, HttpsStream, NetworkConnector};
use hyper::status::StatusCode;
use hyper_serde::Serde;
use log;
use msg::constellation_msg::PipelineId;
use net_traits::{CookieSource, FetchMetadata, NetworkError, ReferrerPolicy};
use net_traits::hosts::replace_hosts;
use net_traits::hosts::replace_host;
use net_traits::request::{CacheMode, CredentialsMode, Destination, Origin};
use net_traits::request::{RedirectMode, Referrer, Request, RequestMode, ResponseTainting};
use net_traits::response::{HttpsState, Response, ResponseBody, ResponseType};
use openssl;
use openssl::ssl::SslStream;
use openssl::ssl::error::{OpensslError, SslError};
use resource_thread::AuthCache;
use servo_url::{ImmutableOrigin, ServoUrl};
@ -125,12 +127,18 @@ struct NetworkHttpRequestFactory {
pub connector: Arc<Pool<Connector>>,
}
impl NetworkConnector for NetworkHttpRequestFactory {
type Stream = PooledStream<HttpsStream<SslStream<HttpStream>>>;
fn connect(&self, host: &str, port: u16, scheme: &str) -> Result<Self::Stream, HttpError> {
self.connector.connect(&replace_host(host), port, scheme)
}
}
impl NetworkHttpRequestFactory {
fn create(&self, url: ServoUrl, method: Method, headers: Headers)
-> Result<HyperRequest<Fresh>, NetworkError> {
let connection = HyperRequest::with_connector(method,
url.clone().into_url().unwrap(),
&*self.connector);
let connection = HyperRequest::with_connector(method, url.clone().into_url(), self);
if let Err(HttpError::Ssl(ref error)) = connection {
let error: &(Error + Send + 'static) = &**error;
@ -222,7 +230,7 @@ fn strict_origin_when_cross_origin(referrer_url: ServoUrl, url: ServoUrl) -> Opt
fn strip_url(mut referrer_url: ServoUrl, origin_only: bool) -> Option<ServoUrl> {
if referrer_url.scheme() == "https" || referrer_url.scheme() == "http" {
{
let referrer = referrer_url.as_mut_url().unwrap();
let referrer = referrer_url.as_mut_url();
referrer.set_username("").unwrap();
referrer.set_password(None).unwrap();
referrer.set_fragment(None);
@ -408,7 +416,6 @@ fn obtain_response(request_factory: &NetworkHttpRequestFactory,
is_xhr: bool)
-> Result<(WrappedHttpResponse, Option<ChromeToDevtoolsControlMsg>), NetworkError> {
let null_data = None;
let connection_url = replace_hosts(&url);
// loop trying connections in connection pool
// they may have grown stale (disconnected), in which case we'll get
@ -439,7 +446,7 @@ fn obtain_response(request_factory: &NetworkHttpRequestFactory,
}
if log_enabled!(log::LogLevel::Info) {
info!("{} {}", method, connection_url);
info!("{} {}", method, url);
for header in headers.iter() {
info!(" - {}", header);
}
@ -448,7 +455,7 @@ fn obtain_response(request_factory: &NetworkHttpRequestFactory,
let connect_start = precise_time_ms();
let request = try!(request_factory.create(connection_url.clone(), method.clone(),
let request = try!(request_factory.create(url.clone(), method.clone(),
headers.clone()));
let connect_end = precise_time_ms();
@ -900,7 +907,7 @@ fn http_network_or_cache_fetch(request: Rc<Request>,
let headers = &mut *http_request.headers.borrow_mut();
let host = Host {
hostname: current_url.host_str().unwrap().to_owned(),
port: current_url.port_or_known_default()
port: current_url.port()
};
headers.set(host);
// unlike http_loader, we should not set the accept header

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

@ -7,6 +7,7 @@
#![feature(mpsc_select)]
#![feature(step_by)]
extern crate base64;
extern crate brotli;
extern crate cookie as cookie_rs;
extern crate devtools_traits;
@ -25,7 +26,6 @@ extern crate net_traits;
extern crate openssl;
extern crate openssl_verify;
extern crate profile_traits;
extern crate rustc_serialize;
extern crate serde;
#[macro_use]
extern crate serde_derive;

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

@ -2,9 +2,9 @@
* 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/. */
use base64;
use net_traits::response::{Response, ResponseBody, ResponseType};
use openssl::crypto::hash::{hash, Type as MessageDigest};
use rustc_serialize::base64::{STANDARD, ToBase64};
use std::iter::Filter;
use std::str::Split;
use std::sync::MutexGuard;
@ -120,7 +120,7 @@ fn apply_algorithm_to_response(body: MutexGuard<ResponseBody>,
-> String {
if let ResponseBody::Done(ref vec) = *body {
let response_digest = hash(message_digest, vec);
response_digest.to_base64(STANDARD)
base64::encode(&response_digest)
} else {
unreachable!("Tried to calculate digest of incomplete response body")
}

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

@ -9,7 +9,7 @@ use http_loader;
use hyper::header::{Host, SetCookie};
use net_traits::{CookieSource, MessageData, WebSocketCommunicate};
use net_traits::{WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent};
use net_traits::hosts::replace_hosts;
use net_traits::hosts::replace_host_in_url;
use servo_url::ServoUrl;
use std::ascii::AsciiExt;
use std::sync::{Arc, Mutex, RwLock};
@ -25,84 +25,6 @@ use websocket::stream::WebSocketStream;
use websocket::ws::receiver::Receiver as WSReceiver;
use websocket::ws::sender::Sender as Sender_Object;
// https://fetch.spec.whatwg.org/#concept-websocket-establish
fn establish_a_websocket_connection(resource_url: &ServoUrl,
origin: String,
protocols: Vec<String>,
cookie_jar: Arc<RwLock<CookieStorage>>)
-> WebSocketResult<(Option<String>,
Sender<WebSocketStream>,
Receiver<WebSocketStream>)> {
// Steps 1-2 are not really applicable here, given we don't exactly go
// through the same infrastructure as the Fetch spec.
if should_be_blocked_due_to_bad_port(resource_url) {
// Subset of steps 11-12, we inline the bad port check here from the
// main fetch algorithm for the same reason steps 1-2 are not
// applicable.
return Err(WebSocketError::RequestError("Request should be blocked due to bad port."));
}
// Steps 3-7.
let net_url = replace_hosts(resource_url);
let mut request = try!(Client::connect(net_url.as_url()));
// Client::connect sets the Host header to the host of the URL that is
// passed to it, so we need to reset it afterwards to the correct one.
request.headers.set(Host {
hostname: resource_url.host_str().unwrap().to_owned(),
port: resource_url.port(),
});
// Step 8.
if !protocols.is_empty() {
request.headers.set(WebSocketProtocol(protocols.clone()));
}
// Steps 9-10.
// TODO: support for permessage-deflate extension.
// Subset of step 11.
// See step 2 of https://fetch.spec.whatwg.org/#concept-fetch.
request.headers.set(Origin(origin));
// Transitive subset of step 11.
// See step 17.1 of https://fetch.spec.whatwg.org/#concept-http-network-or-cache-fetch.
http_loader::set_request_cookies(&resource_url, &mut request.headers, &cookie_jar);
// Step 11, somewhat.
let response = try!(request.send());
// Step 12, 14.
try!(response.validate());
// Step 13 and transitive subset of step 14.
// See step 6 of http://tools.ietf.org/html/rfc6455#section-4.1.
let protocol_in_use = response.protocol().and_then(|header| {
// https://github.com/whatwg/fetch/issues/515
header.first().cloned()
});
if let Some(ref protocol_name) = protocol_in_use {
if !protocols.is_empty() && !protocols.iter().any(|p| (&**p).eq_ignore_ascii_case(protocol_name)) {
return Err(WebSocketError::ProtocolError("Protocol in Use not in client-supplied protocol list"));
};
};
// Transitive subset of step 11.
// See step 15 of https://fetch.spec.whatwg.org/#http-network-fetch.
if let Some(cookies) = response.headers.get::<SetCookie>() {
let mut jar = cookie_jar.write().unwrap();
for cookie in &**cookies {
if let Some(cookie) = Cookie::new_wrapped(cookie.clone(), resource_url, CookieSource::HTTP) {
jar.push(cookie, resource_url, CookieSource::HTTP);
}
}
}
let (sender, receiver) = response.begin().split();
Ok((protocol_in_use, sender, receiver))
}
pub fn init(connect: WebSocketCommunicate, connect_data: WebSocketConnectData, cookie_jar: Arc<RwLock<CookieStorage>>) {
thread::Builder::new().name(format!("WebSocket connection to {}", connect_data.resource_url)).spawn(move || {
let channel = establish_a_websocket_connection(&connect_data.resource_url,
@ -182,3 +104,81 @@ pub fn init(connect: WebSocketCommunicate, connect_data: WebSocketConnectData, c
}
}).expect("Thread spawning failed");
}
// https://fetch.spec.whatwg.org/#concept-websocket-establish
fn establish_a_websocket_connection(resource_url: &ServoUrl,
origin: String,
protocols: Vec<String>,
cookie_jar: Arc<RwLock<CookieStorage>>)
-> WebSocketResult<(Option<String>,
Sender<WebSocketStream>,
Receiver<WebSocketStream>)> {
// Steps 1-2 are not really applicable here, given we don't exactly go
// through the same infrastructure as the Fetch spec.
if should_be_blocked_due_to_bad_port(resource_url) {
// Subset of steps 11-12, we inline the bad port check here from the
// main fetch algorithm for the same reason steps 1-2 are not
// applicable.
return Err(WebSocketError::RequestError("Request should be blocked due to bad port."));
}
// Steps 3-7.
let net_url = replace_host_in_url(resource_url.clone());
let mut request = try!(Client::connect(net_url.as_url()));
// Client::connect sets the Host header to the host of the URL that is
// passed to it, so we need to reset it afterwards to the correct one.
request.headers.set(Host {
hostname: resource_url.host_str().unwrap().to_owned(),
port: resource_url.port(),
});
// Step 8.
if !protocols.is_empty() {
request.headers.set(WebSocketProtocol(protocols.clone()));
}
// Steps 9-10.
// TODO: support for permessage-deflate extension.
// Subset of step 11.
// See step 2 of https://fetch.spec.whatwg.org/#concept-fetch.
request.headers.set(Origin(origin));
// Transitive subset of step 11.
// See step 17.1 of https://fetch.spec.whatwg.org/#concept-http-network-or-cache-fetch.
http_loader::set_request_cookies(&resource_url, &mut request.headers, &cookie_jar);
// Step 11, somewhat.
let response = try!(request.send());
// Step 12, 14.
try!(response.validate());
// Step 13 and transitive subset of step 14.
// See step 6 of http://tools.ietf.org/html/rfc6455#section-4.1.
let protocol_in_use = response.protocol().and_then(|header| {
// https://github.com/whatwg/fetch/issues/515
header.first().cloned()
});
if let Some(ref protocol_name) = protocol_in_use {
if !protocols.is_empty() && !protocols.iter().any(|p| (&**p).eq_ignore_ascii_case(protocol_name)) {
return Err(WebSocketError::ProtocolError("Protocol in Use not in client-supplied protocol list"));
};
};
// Transitive subset of step 11.
// See step 15 of https://fetch.spec.whatwg.org/#http-network-fetch.
if let Some(cookies) = response.headers.get::<SetCookie>() {
let mut jar = cookie_jar.write().unwrap();
for cookie in &**cookies {
if let Some(cookie) = Cookie::new_wrapped(cookie.clone(), resource_url, CookieSource::HTTP) {
jar.push(cookie, resource_url, CookieSource::HTTP);
}
}
}
let (sender, receiver) = response.begin().split();
Ok((protocol_in_use, sender, receiver))
}

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

@ -4,6 +4,7 @@
use parse_hosts::HostsFile;
use servo_url::ServoUrl;
use std::borrow::Cow;
use std::collections::HashMap;
use std::env;
use std::fs::File;
@ -56,19 +57,24 @@ pub fn parse_hostsfile(hostsfile_content: &str) -> HashMap<String, IpAddr> {
host_table
}
pub fn replace_hosts(url: &ServoUrl) -> ServoUrl {
HOST_TABLE.lock().unwrap().as_ref().map_or_else(|| url.clone(),
|host_table| host_replacement(host_table, url))
pub fn replace_host(host: &str) -> Cow<str> {
HOST_TABLE.lock().unwrap().as_ref()
.and_then(|table| table.get(host))
.map_or(host.into(), |replaced_host| replaced_host.to_string().into())
}
pub fn host_replacement(host_table: &HashMap<String, IpAddr>, url: &ServoUrl) -> ServoUrl {
url.domain()
.and_then(|domain| {
host_table.get(domain).map(|ip| {
let mut new_url = url.clone();
new_url.set_ip_host(*ip).unwrap();
new_url
})
})
.unwrap_or_else(|| url.clone())
pub fn replace_host_in_url(url: ServoUrl) -> ServoUrl {
if let Some(table) = HOST_TABLE.lock().unwrap().as_ref() {
host_replacement(table, url)
} else {
url
}
}
pub fn host_replacement(host_table: &HashMap<String, IpAddr>, mut url: ServoUrl) -> ServoUrl {
let replacement = url.domain().and_then(|domain| host_table.get(domain));
if let Some(ip) = replacement {
url.set_ip_host(*ip).unwrap();
}
url
}

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

@ -28,6 +28,7 @@ angle = {git = "https://github.com/servo/angle", branch = "servo"}
app_units = "0.4"
audio-video-metadata = "0.1.2"
atomic_refcell = "0.1"
base64 = "0.4.1"
bitflags = "0.7"
bluetooth_traits = {path = "../bluetooth_traits"}
byteorder = "1.0"
@ -69,7 +70,6 @@ range = {path = "../range"}
ref_filter_map = "1.0.1"
ref_slice = "1.0"
regex = "0.2"
rustc-serialize = "0.3"
script_layout_interface = {path = "../script_layout_interface"}
script_plugins = {path = "../script_plugins"}
script_traits = {path = "../script_traits"}

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

@ -180,9 +180,9 @@ pub enum AdjacentPosition {
}
impl<'a> TryFrom<&'a str> for AdjacentPosition {
type Err = Error;
type Error = Error;
fn try_from(position: &'a str) -> Result<AdjacentPosition, Self::Err> {
fn try_from(position: &'a str) -> Result<AdjacentPosition, Self::Error> {
match_ignore_ascii_case! { &*position,
"beforebegin" => Ok(AdjacentPosition::BeforeBegin),
"afterbegin" => Ok(AdjacentPosition::AfterBegin),

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

@ -2,6 +2,7 @@
* 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/. */
use base64;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
@ -29,7 +30,6 @@ use js::jsapi::JSAutoCompartment;
use js::jsapi::JSContext;
use js::jsval::{self, JSVal};
use js::typedarray::{ArrayBuffer, CreateWith};
use rustc_serialize::base64::{CharacterSet, Config, Newline, ToBase64};
use script_thread::RunnableWrapper;
use servo_atoms::Atom;
use std::cell::Cell;
@ -247,13 +247,7 @@ impl FileReader {
//https://w3c.github.io/FileAPI/#dfn-readAsDataURL
fn perform_readasdataurl(result: &DOMRefCell<Option<FileReaderResult>>, data: ReadMetaData, bytes: &[u8]) {
let config = Config {
char_set: CharacterSet::UrlSafe,
newline: Newline::LF,
pad: true,
line_length: None
};
let base64 = bytes.to_base64(config);
let base64 = base64::encode(bytes);
let output = if data.blobtype.is_empty() {
format!("data:base64,{}", base64)

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

@ -2,6 +2,7 @@
* 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/. */
use base64;
use canvas_traits::{CanvasMsg, FromScriptMsg};
use dom::attr::Attr;
use dom::bindings::cell::DOMRefCell;
@ -33,7 +34,6 @@ use ipc_channel::ipc::{self, IpcSender};
use js::error::throw_type_error;
use js::jsapi::{HandleValue, JSContext};
use offscreen_gl_context::GLContextAttributes;
use rustc_serialize::base64::{STANDARD, ToBase64};
use script_layout_interface::HTMLCanvasData;
use std::iter::repeat;
use style::attr::AttrValue;
@ -296,7 +296,7 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
encoder.encode(&raw_data, self.Width(), self.Height(), ColorType::RGBA(8)).unwrap();
}
let encoded = encoded.to_base64(STANDARD);
let encoded = base64::encode(&encoded);
Ok(DOMString::from(format!("data:{};base64,{}", mime_type, encoded)))
}
}

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

@ -384,12 +384,12 @@ impl HTMLFormElement {
fn mutate_action_url(&self, form_data: &mut Vec<FormDatum>, mut load_data: LoadData, encoding: EncodingRef) {
let charset = &*encoding.whatwg_name().unwrap();
if let Some(ref mut url) = load_data.url.as_mut_url() {
url.query_pairs_mut().clear()
.encoding_override(Some(self.pick_encoding()))
.extend_pairs(form_data.into_iter()
.map(|field| (field.name.clone(), field.replace_value(charset))));
}
load_data.url
.as_mut_url()
.query_pairs_mut().clear()
.encoding_override(Some(self.pick_encoding()))
.extend_pairs(form_data.into_iter()
.map(|field| (field.name.clone(), field.replace_value(charset))));
self.plan_to_navigate(load_data);
}
@ -403,13 +403,12 @@ impl HTMLFormElement {
let charset = &*encoding.whatwg_name().unwrap();
load_data.headers.set(ContentType::form_url_encoded());
if let Some(ref mut url) = load_data.url.as_mut_url() {
url.query_pairs_mut().clear()
.encoding_override(Some(self.pick_encoding()))
.extend_pairs(form_data.into_iter()
.map(|field| (field.name.clone(), field.replace_value(charset))));
}
load_data.url
.as_mut_url()
.query_pairs_mut().clear()
.encoding_override(Some(self.pick_encoding()))
.extend_pairs(form_data.into_iter()
.map(|field| (field.name.clone(), field.replace_value(charset))));
load_data.url.query().unwrap_or("").to_string().into_bytes()
}

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

@ -52,9 +52,8 @@ impl URL {
}
pub fn set_query_pairs(&self, pairs: &[(String, String)]) {
if let Some(ref mut url) = self.url.borrow_mut().as_mut_url() {
url.query_pairs_mut().clear().extend_pairs(pairs);
}
let mut url = self.url.borrow_mut();
url.as_mut_url().query_pairs_mut().clear().extend_pairs(pairs);
}
}

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

@ -45,49 +45,31 @@ impl UrlHelper {
USVString(quirks::username(url.as_url()).to_owned())
}
pub fn SetHash(url: &mut ServoUrl, value: USVString) {
if let Some(ref mut url) = url.as_mut_url() {
quirks::set_hash(url, &value.0)
}
quirks::set_hash(url.as_mut_url(), &value.0)
}
pub fn SetHost(url: &mut ServoUrl, value: USVString) {
if let Some(ref mut url) = url.as_mut_url() {
let _ = quirks::set_host(url, &value.0);
}
let _ = quirks::set_host(url.as_mut_url(), &value.0);
}
pub fn SetPort(url: &mut ServoUrl, value: USVString) {
if let Some(ref mut url) = url.as_mut_url() {
let _ = quirks::set_port(url, &value.0);
}
let _ = quirks::set_port(url.as_mut_url(), &value.0);
}
pub fn SetSearch(url: &mut ServoUrl, value: USVString) {
if let Some(ref mut url) = url.as_mut_url() {
quirks::set_search(url, &value.0)
}
quirks::set_search(url.as_mut_url(), &value.0)
}
pub fn SetPathname(url: &mut ServoUrl, value: USVString) {
if let Some(ref mut url) = url.as_mut_url() {
quirks::set_pathname(url, &value.0)
}
quirks::set_pathname(url.as_mut_url(), &value.0)
}
pub fn SetHostname(url: &mut ServoUrl, value: USVString) {
if let Some(ref mut url) = url.as_mut_url() {
let _ = quirks::set_hostname(url, &value.0);
}
let _ = quirks::set_hostname(url.as_mut_url(), &value.0);
}
pub fn SetPassword(url: &mut ServoUrl, value: USVString) {
if let Some(ref mut url) = url.as_mut_url() {
let _ = quirks::set_password(url, &value.0);
}
let _ = quirks::set_password(url.as_mut_url(), &value.0);
}
pub fn SetProtocol(url: &mut ServoUrl, value: USVString) {
if let Some(ref mut url) = url.as_mut_url() {
let _ = quirks::set_protocol(url, &value.0);
}
let _ = quirks::set_protocol(url.as_mut_url(), &value.0);
}
pub fn SetUsername(url: &mut ServoUrl, value: USVString) {
if let Some(ref mut url) = url.as_mut_url() {
let _ = quirks::set_username(url, &value.0);
}
let _ = quirks::set_username(url.as_mut_url(), &value.0);
}
// https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
pub fn is_origin_trustworthy(url: &ServoUrl) -> bool {

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

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use app_units::Au;
use base64;
use bluetooth_traits::BluetoothRequest;
use cssparser::Parser;
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
@ -68,7 +69,6 @@ use num_traits::ToPrimitive;
use open;
use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::time::ProfilerChan as TimeProfilerChan;
use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64};
use script_layout_interface::{TrustedNodeAddress, PendingImageState};
use script_layout_interface::message::{Msg, Reflow, ReflowQueryType, ScriptReflow};
use script_layout_interface::reporter::CSSErrorReporter;
@ -410,16 +410,13 @@ pub fn base64_btoa(input: DOMString) -> Fallible<DOMString> {
// "and then must apply the base64 algorithm to that sequence of
// octets, and return the result. [RFC4648]"
Ok(DOMString::from(octets.to_base64(STANDARD)))
Ok(DOMString::from(base64::encode(&octets)))
}
}
// https://html.spec.whatwg.org/multipage/#atob
pub fn base64_atob(input: DOMString) -> Fallible<DOMString> {
// "Remove all space characters from input."
// serialize::base64::from_base64 ignores \r and \n,
// but it treats the other space characters as
// invalid input.
fn is_html_space(c: char) -> bool {
HTML_SPACE_CHARACTERS.iter().any(|&m| m == c)
}
@ -456,7 +453,7 @@ pub fn base64_atob(input: DOMString) -> Fallible<DOMString> {
return Err(Error::InvalidCharacter)
}
match input.from_base64() {
match base64::decode(&input) {
Ok(data) => Ok(DOMString::from(data.iter().map(|&b| b as char).collect::<String>())),
Err(..) => Err(Error::InvalidCharacter)
}

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

@ -28,6 +28,7 @@ extern crate angle;
extern crate app_units;
extern crate atomic_refcell;
extern crate audio_video_metadata;
extern crate base64;
#[macro_use]
extern crate bitflags;
extern crate bluetooth_traits;
@ -78,7 +79,6 @@ extern crate range;
extern crate ref_filter_map;
extern crate ref_slice;
extern crate regex;
extern crate rustc_serialize;
extern crate script_layout_interface;
extern crate script_traits;
extern crate selectors;

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

@ -87,6 +87,9 @@ pub struct SharedStyleContext<'a> {
/// The QuirksMode state which the document needs to be rendered with
pub quirks_mode: QuirksMode,
/// True if the traversal is processing only animation restyles.
pub animation_only_restyle: bool,
}
impl<'a> SharedStyleContext<'a> {

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

@ -9,7 +9,7 @@
use dom::TElement;
use properties::ComputedValues;
use properties::longhands::display::computed_value as display;
use restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
use restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
use rule_tree::StrongRuleNode;
use selector_parser::{PseudoElement, RestyleDamage, Snapshot};
use std::collections::HashMap;
@ -136,7 +136,12 @@ pub struct StoredRestyleHint(RestyleHint);
impl StoredRestyleHint {
/// Propagates this restyle hint to a child element.
pub fn propagate(&self) -> Self {
StoredRestyleHint(if self.0.contains(RESTYLE_DESCENDANTS) {
// If we have RESTYLE_CSS_ANIMATIONS restyle hint, it means we are in the
// middle of an animation only restyle. In that case, we don't need to
// propagate any restyle hints.
StoredRestyleHint(if self.0.contains(RESTYLE_CSS_ANIMATIONS) {
RestyleHint::empty()
} else if self.0.contains(RESTYLE_DESCENDANTS) {
RESTYLE_SELF | RESTYLE_DESCENDANTS
} else {
RestyleHint::empty()
@ -174,6 +179,16 @@ impl StoredRestyleHint {
pub fn insert(&mut self, other: &Self) {
self.0 |= other.0
}
/// Remove animation restyle hint.
pub fn remove_animation_hint(&mut self) {
self.0.remove(RESTYLE_CSS_ANIMATIONS)
}
/// Returns true if the hint has animation-only restyle.
pub fn has_animation_hint(&self) -> bool {
self.0.contains(RESTYLE_CSS_ANIMATIONS)
}
}
impl Default for StoredRestyleHint {

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

@ -309,6 +309,24 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
/// Only safe to call with exclusive access to the element.
unsafe fn unset_dirty_descendants(&self);
/// Similar to the dirty_descendants but for representing a descendant of
/// the element needs to be updated in animation-only traversal.
fn has_animation_only_dirty_descendants(&self) -> bool {
false
}
/// Flag that this element has a descendant for animation-only restyle processing.
///
/// Only safe to call with exclusive access to the element.
unsafe fn set_animation_only_dirty_descendants(&self) {
}
/// Flag that this element has no descendant for animation-only restyle processing.
///
/// Only safe to call with exclusive access to the element.
unsafe fn unset_animation_only_dirty_descendants(&self) {
}
/// Atomically stores the number of children of this node that we will
/// need to process during bottom-up traversal.
fn store_children_to_process(&self, n: isize);
@ -354,6 +372,16 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
/// Returns true if the element has a CSS animation.
fn has_css_animations(&self, _pseudo: Option<&PseudoElement>) -> bool;
/// Returns true if the element has animation restyle hints.
fn has_animation_restyle_hints(&self) -> bool {
let data = match self.borrow_data() {
Some(d) => d,
None => return false,
};
return data.get_restyle()
.map_or(false, |r| r.hint.has_animation_hint());
}
}
/// TNode and TElement aren't Send because we want to be careful and explicit

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

@ -42,6 +42,7 @@ use gecko_bindings::structs;
use gecko_bindings::structs::{RawGeckoElement, RawGeckoNode};
use gecko_bindings::structs::{nsIAtom, nsIContent, nsStyleContext};
use gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel;
use gecko_bindings::structs::NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO;
use gecko_bindings::structs::NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO;
use gecko_bindings::structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
use gecko_bindings::sugar::ownership::HasArcFFI;
@ -510,6 +511,18 @@ impl<'le> TElement for GeckoElement<'le> {
self.unset_flags(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
}
fn has_animation_only_dirty_descendants(&self) -> bool {
self.flags() & (NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32) != 0
}
unsafe fn set_animation_only_dirty_descendants(&self) {
self.set_flags(NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32)
}
unsafe fn unset_animation_only_dirty_descendants(&self) {
self.unset_flags(NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32)
}
fn store_children_to_process(&self, _: isize) {
// This is only used for bottom-up traversal, and is thus a no-op for Gecko.
}

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

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

@ -1632,14 +1632,14 @@ pub mod root {
#[repr(C)]
#[derive(Debug)]
pub struct MutexImpl {
pub platformData_: [*mut ::std::os::raw::c_void; 8usize],
pub platformData_: [*mut ::std::os::raw::c_void; 5usize],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct MutexImpl_PlatformData([u8; 0]);
#[test]
fn bindgen_test_layout_MutexImpl() {
assert_eq!(::std::mem::size_of::<MutexImpl>() , 64usize ,
assert_eq!(::std::mem::size_of::<MutexImpl>() , 40usize ,
concat ! ( "Size of: " , stringify ! ( MutexImpl )
));
assert_eq! (::std::mem::align_of::<MutexImpl>() , 8usize ,
@ -2993,6 +2993,14 @@ pub mod root {
#[allow(unused_imports)]
use self::super::super::super::super::root;
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CSSStyleSheetParsingMode {
Author = 0,
User = 1,
Agent = 2,
EndGuard_ = 3,
}
#[repr(C)]
#[derive(Debug)]
pub struct OriginAttributesDictionary {
@ -3052,18 +3060,6 @@ pub mod root {
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Promise([u8; 0]);
pub mod workers {
#[allow(unused_imports)]
use self::super::super::super::super::root;
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CSSStyleSheetParsingMode {
Author = 0,
User = 1,
Agent = 2,
EndGuard_ = 3,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct CSSRuleList([u8; 0]);
@ -4774,92 +4770,6 @@ pub mod root {
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EventListenerManager([u8; 0]);
/**
* BlockingResourceBase
* Base class of resources that might block clients trying to acquire them.
* Does debugging and deadlock detection in DEBUG builds.
**/
#[repr(C)]
#[derive(Debug)]
pub struct BlockingResourceBase {
pub _address: u8,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum BlockingResourceBase_BlockingResourceType {
eMutex = 0,
eReentrantMonitor = 1,
eCondVar = 2,
}
extern "C" {
#[link_name =
"_ZN7mozilla20BlockingResourceBase17kResourceTypeNameE"]
pub static mut BlockingResourceBase_kResourceTypeName:
[*const ::std::os::raw::c_char; 0usize];
}
#[test]
fn bindgen_test_layout_BlockingResourceBase() {
assert_eq!(::std::mem::size_of::<BlockingResourceBase>() , 1usize
, concat ! (
"Size of: " , stringify ! ( BlockingResourceBase ) ));
assert_eq! (::std::mem::align_of::<BlockingResourceBase>() ,
1usize , concat ! (
"Alignment of " , stringify ! ( BlockingResourceBase )
));
}
/**
* OffTheBooksMutex is identical to Mutex, except that OffTheBooksMutex doesn't
* include leak checking. Sometimes you want to intentionally "leak" a mutex
* until shutdown; in these cases, OffTheBooksMutex is for you.
*/
#[repr(C)]
#[derive(Debug)]
pub struct OffTheBooksMutex {
pub _base: root::mozilla::detail::MutexImpl,
}
#[test]
fn bindgen_test_layout_OffTheBooksMutex() {
assert_eq!(::std::mem::size_of::<OffTheBooksMutex>() , 64usize ,
concat ! (
"Size of: " , stringify ! ( OffTheBooksMutex ) ));
assert_eq! (::std::mem::align_of::<OffTheBooksMutex>() , 8usize ,
concat ! (
"Alignment of " , stringify ! ( OffTheBooksMutex ) ));
}
/**
* Mutex
* When possible, use MutexAutoLock/MutexAutoUnlock to lock/unlock this
* mutex within a scope, instead of calling Lock/Unlock directly.
*/
#[repr(C)]
#[derive(Debug)]
pub struct Mutex {
pub _base: root::mozilla::OffTheBooksMutex,
}
#[test]
fn bindgen_test_layout_Mutex() {
assert_eq!(::std::mem::size_of::<Mutex>() , 64usize , concat ! (
"Size of: " , stringify ! ( Mutex ) ));
assert_eq! (::std::mem::align_of::<Mutex>() , 8usize , concat ! (
"Alignment of " , stringify ! ( Mutex ) ));
}
pub mod net {
#[allow(unused_imports)]
use self::super::super::super::root;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ReferrerPolicy {
RP_No_Referrer = 2,
RP_Origin = 3,
RP_No_Referrer_When_Downgrade = 1,
RP_Origin_When_Crossorigin = 4,
RP_Unsafe_URL = 5,
RP_Same_Origin = 6,
RP_Strict_Origin = 7,
RP_Strict_Origin_When_Cross_Origin = 8,
RP_Unset = 0,
}
}
pub const FlushType_Frames: root::mozilla::FlushType =
FlushType::Style;
#[repr(u8)]
@ -5418,6 +5328,23 @@ pub mod root {
assert_eq! (::std::mem::align_of::<StyleSheet>() , 8usize , concat
! ( "Alignment of " , stringify ! ( StyleSheet ) ));
}
pub mod net {
#[allow(unused_imports)]
use self::super::super::super::root;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ReferrerPolicy {
RP_No_Referrer = 2,
RP_Origin = 3,
RP_No_Referrer_When_Downgrade = 1,
RP_Origin_When_Crossorigin = 4,
RP_Unsafe_URL = 5,
RP_Same_Origin = 6,
RP_Strict_Origin = 7,
RP_Strict_Origin_When_Cross_Origin = 8,
RP_Unset = 0,
}
}
#[repr(u8)]
/**
* Enumeration that represents one of the two supported style system backends.
@ -5530,7 +5457,7 @@ pub mod root {
eUseCounter_ImageBitmapRenderingContext_TransferImageBitmap = 86,
eUseCounter_URLCreateObjectURL_MediaStream = 87,
eUseCounter_XMLBaseAttribute = 88,
eUseCounter_XMLBaseAttributeWithStyledElement = 89,
eUseCounter_XMLBaseAttributeForStyleAttr = 89,
eUseCounter_Count = 90,
}
#[repr(u32)]
@ -6795,6 +6722,75 @@ pub mod root {
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct RestyleManager([u8; 0]);
/**
* BlockingResourceBase
* Base class of resources that might block clients trying to acquire them.
* Does debugging and deadlock detection in DEBUG builds.
**/
#[repr(C)]
#[derive(Debug)]
pub struct BlockingResourceBase {
pub _address: u8,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum BlockingResourceBase_BlockingResourceType {
eMutex = 0,
eReentrantMonitor = 1,
eCondVar = 2,
}
extern "C" {
#[link_name =
"_ZN7mozilla20BlockingResourceBase17kResourceTypeNameE"]
pub static mut BlockingResourceBase_kResourceTypeName:
[*const ::std::os::raw::c_char; 0usize];
}
#[test]
fn bindgen_test_layout_BlockingResourceBase() {
assert_eq!(::std::mem::size_of::<BlockingResourceBase>() , 1usize
, concat ! (
"Size of: " , stringify ! ( BlockingResourceBase ) ));
assert_eq! (::std::mem::align_of::<BlockingResourceBase>() ,
1usize , concat ! (
"Alignment of " , stringify ! ( BlockingResourceBase )
));
}
/**
* OffTheBooksMutex is identical to Mutex, except that OffTheBooksMutex doesn't
* include leak checking. Sometimes you want to intentionally "leak" a mutex
* until shutdown; in these cases, OffTheBooksMutex is for you.
*/
#[repr(C)]
#[derive(Debug)]
pub struct OffTheBooksMutex {
pub _base: root::mozilla::detail::MutexImpl,
}
#[test]
fn bindgen_test_layout_OffTheBooksMutex() {
assert_eq!(::std::mem::size_of::<OffTheBooksMutex>() , 40usize ,
concat ! (
"Size of: " , stringify ! ( OffTheBooksMutex ) ));
assert_eq! (::std::mem::align_of::<OffTheBooksMutex>() , 8usize ,
concat ! (
"Alignment of " , stringify ! ( OffTheBooksMutex ) ));
}
/**
* Mutex
* When possible, use MutexAutoLock/MutexAutoUnlock to lock/unlock this
* mutex within a scope, instead of calling Lock/Unlock directly.
*/
#[repr(C)]
#[derive(Debug)]
pub struct Mutex {
pub _base: root::mozilla::OffTheBooksMutex,
}
#[test]
fn bindgen_test_layout_Mutex() {
assert_eq!(::std::mem::size_of::<Mutex>() , 40usize , concat ! (
"Size of: " , stringify ! ( Mutex ) ));
assert_eq! (::std::mem::align_of::<Mutex>() , 8usize , concat ! (
"Alignment of " , stringify ! ( Mutex ) ));
}
pub mod image {
#[allow(unused_imports)]
use self::super::super::super::root;
@ -8185,12 +8181,6 @@ pub mod root {
pub type pair_first_type<_T1> = _T1;
pub type pair_second_type<_T2> = _T2;
#[repr(C)]
pub struct atomic<_Tp> {
pub _base: (),
pub _phantom_0: ::std::marker::PhantomData<_Tp>,
}
pub type atomic___base = [u8; 0usize];
#[repr(C)]
#[derive(Debug, Copy)]
pub struct input_iterator_tag {
pub _address: u8,
@ -8209,62 +8199,6 @@ pub mod root {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct forward_iterator_tag {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_forward_iterator_tag() {
assert_eq!(::std::mem::size_of::<forward_iterator_tag>() , 1usize
, concat ! (
"Size of: " , stringify ! ( forward_iterator_tag ) ));
assert_eq! (::std::mem::align_of::<forward_iterator_tag>() ,
1usize , concat ! (
"Alignment of " , stringify ! ( forward_iterator_tag )
));
}
impl Clone for forward_iterator_tag {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct bidirectional_iterator_tag {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_bidirectional_iterator_tag() {
assert_eq!(::std::mem::size_of::<bidirectional_iterator_tag>() ,
1usize , concat ! (
"Size of: " , stringify ! ( bidirectional_iterator_tag
) ));
assert_eq! (::std::mem::align_of::<bidirectional_iterator_tag>() ,
1usize , concat ! (
"Alignment of " , stringify ! (
bidirectional_iterator_tag ) ));
}
impl Clone for bidirectional_iterator_tag {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct random_access_iterator_tag {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_random_access_iterator_tag() {
assert_eq!(::std::mem::size_of::<random_access_iterator_tag>() ,
1usize , concat ! (
"Size of: " , stringify ! ( random_access_iterator_tag
) ));
assert_eq! (::std::mem::align_of::<random_access_iterator_tag>() ,
1usize , concat ! (
"Alignment of " , stringify ! (
random_access_iterator_tag ) ));
}
impl Clone for random_access_iterator_tag {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct iterator<_Category, _Tp, _Distance, _Pointer, _Reference> {
pub _address: u8,
@ -8274,22 +8208,22 @@ pub mod root {
pub _phantom_3: ::std::marker::PhantomData<_Pointer>,
pub _phantom_4: ::std::marker::PhantomData<_Reference>,
}
pub type iterator_iterator_category<_Category> = _Category;
pub type iterator_value_type<_Tp> = _Tp;
pub type iterator_difference_type<_Distance> = _Distance;
pub type iterator_pointer<_Pointer> = _Pointer;
pub type iterator_reference<_Reference> = _Reference;
pub type iterator_iterator_category<_Category> = _Category;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct __bit_const_reference<_Cp> {
pub __seg_: root::std::__bit_const_reference___storage_pointer<_Cp>,
pub __mask_: root::std::__bit_const_reference___storage_type<_Cp>,
#[derive(Debug)]
pub struct atomic<_Tp> {
pub _M_i: _Tp,
}
pub type __bit_const_reference___storage_type<_Cp> = _Cp;
pub type __bit_const_reference___storage_pointer<_Cp> = _Cp;
}
pub type __darwin_va_list = root::__builtin_va_list;
pub type va_list = root::__darwin_va_list;
pub mod __gnu_cxx {
#[allow(unused_imports)]
use self::super::super::root;
}
pub type va_list = root::__builtin_va_list;
/**
* MozRefCountType is Mozilla's reference count type.
*
@ -11754,7 +11688,7 @@ pub mod root {
eImageBitmapRenderingContext_TransferImageBitmap = 39,
eURLCreateObjectURL_MediaStream = 40,
eXMLBaseAttribute = 41,
eXMLBaseAttributeWithStyledElement = 42,
eXMLBaseAttributeForStyleAttr = 42,
eDeprecatedOperationCount = 43,
}
#[repr(u32)]
@ -12257,30 +12191,6 @@ pub mod root {
#[derive(Debug, Copy, Clone)]
pub struct nsISelection([u8; 0]);
#[repr(C)]
#[derive(Debug, Copy)]
pub struct mozIDOMWindowProxy {
pub _base: root::nsISupports,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct mozIDOMWindowProxy_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
#[test]
fn bindgen_test_layout_mozIDOMWindowProxy() {
assert_eq!(::std::mem::size_of::<mozIDOMWindowProxy>() , 8usize ,
concat ! ( "Size of: " , stringify ! ( mozIDOMWindowProxy )
));
assert_eq! (::std::mem::align_of::<mozIDOMWindowProxy>() , 8usize ,
concat ! (
"Alignment of " , stringify ! ( mozIDOMWindowProxy ) ));
}
impl Clone for mozIDOMWindowProxy {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug)]
pub struct nsPresContext {
pub _base: root::nsIObserver,
@ -13303,125 +13213,12 @@ pub mod root {
! ( "Alignment of " , stringify ! ( ErrorNote ) ));
}
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsIChannel {
pub _base: root::nsIRequest,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsIChannel_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
pub const nsIChannel_LOAD_DOCUMENT_URI: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_DOCUMENT_URI;
pub const nsIChannel_LOAD_RETARGETED_DOCUMENT_URI:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_RETARGETED_DOCUMENT_URI;
pub const nsIChannel_LOAD_REPLACE: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_REPLACE;
pub const nsIChannel_LOAD_INITIAL_DOCUMENT_URI:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_INITIAL_DOCUMENT_URI;
pub const nsIChannel_LOAD_TARGETED: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_TARGETED;
pub const nsIChannel_LOAD_CALL_CONTENT_SNIFFERS:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_CALL_CONTENT_SNIFFERS;
pub const nsIChannel_LOAD_CLASSIFY_URI: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_CLASSIFY_URI;
pub const nsIChannel_LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE;
pub const nsIChannel_LOAD_EXPLICIT_CREDENTIALS:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_EXPLICIT_CREDENTIALS;
pub const nsIChannel_LOAD_BYPASS_SERVICE_WORKER:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_BYPASS_SERVICE_WORKER;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsIChannel__bindgen_ty_1 {
LOAD_DOCUMENT_URI = 65536,
LOAD_RETARGETED_DOCUMENT_URI = 131072,
LOAD_REPLACE = 262144,
LOAD_INITIAL_DOCUMENT_URI = 524288,
LOAD_TARGETED = 1048576,
LOAD_CALL_CONTENT_SNIFFERS = 2097152,
LOAD_CLASSIFY_URI = 4194304,
LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE = 8388608,
LOAD_EXPLICIT_CREDENTIALS = 16777216,
LOAD_BYPASS_SERVICE_WORKER = 33554432,
}
pub const nsIChannel_DISPOSITION_INLINE: root::nsIChannel__bindgen_ty_2 =
nsIChannel__bindgen_ty_2::DISPOSITION_INLINE;
pub const nsIChannel_DISPOSITION_ATTACHMENT:
root::nsIChannel__bindgen_ty_2 =
nsIChannel__bindgen_ty_2::DISPOSITION_ATTACHMENT;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsIChannel__bindgen_ty_2 {
DISPOSITION_INLINE = 0,
DISPOSITION_ATTACHMENT = 1,
}
#[test]
fn bindgen_test_layout_nsIChannel() {
assert_eq!(::std::mem::size_of::<nsIChannel>() , 8usize , concat ! (
"Size of: " , stringify ! ( nsIChannel ) ));
assert_eq! (::std::mem::align_of::<nsIChannel>() , 8usize , concat ! (
"Alignment of " , stringify ! ( nsIChannel ) ));
}
impl Clone for nsIChannel {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsILoadContext {
pub _base: root::nsISupports,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsILoadContext_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
#[test]
fn bindgen_test_layout_nsILoadContext() {
assert_eq!(::std::mem::size_of::<nsILoadContext>() , 8usize , concat !
( "Size of: " , stringify ! ( nsILoadContext ) ));
assert_eq! (::std::mem::align_of::<nsILoadContext>() , 8usize , concat
! ( "Alignment of " , stringify ! ( nsILoadContext ) ));
}
impl Clone for nsILoadContext {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsIInterfaceRequestor {
pub _base: root::nsISupports,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsIInterfaceRequestor_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
#[test]
fn bindgen_test_layout_nsIInterfaceRequestor() {
assert_eq!(::std::mem::size_of::<nsIInterfaceRequestor>() , 8usize ,
concat ! (
"Size of: " , stringify ! ( nsIInterfaceRequestor ) ));
assert_eq! (::std::mem::align_of::<nsIInterfaceRequestor>() , 8usize ,
concat ! (
"Alignment of " , stringify ! ( nsIInterfaceRequestor )
));
}
impl Clone for nsIInterfaceRequestor {
fn clone(&self) -> Self { *self }
pub enum nsCompatibility {
eCompatibility_FullStandards = 1,
eCompatibility_AlmostStandards = 2,
eCompatibility_NavQuirks = 3,
}
#[repr(C)]
#[derive(Debug, Copy)]
@ -13770,6 +13567,82 @@ pub mod root {
"Alignment of field: " , stringify ! ( nsINode ) , "::" ,
stringify ! ( mSlots ) ));
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsIChannel {
pub _base: root::nsIRequest,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsIChannel_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
pub const nsIChannel_LOAD_DOCUMENT_URI: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_DOCUMENT_URI;
pub const nsIChannel_LOAD_RETARGETED_DOCUMENT_URI:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_RETARGETED_DOCUMENT_URI;
pub const nsIChannel_LOAD_REPLACE: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_REPLACE;
pub const nsIChannel_LOAD_INITIAL_DOCUMENT_URI:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_INITIAL_DOCUMENT_URI;
pub const nsIChannel_LOAD_TARGETED: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_TARGETED;
pub const nsIChannel_LOAD_CALL_CONTENT_SNIFFERS:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_CALL_CONTENT_SNIFFERS;
pub const nsIChannel_LOAD_CLASSIFY_URI: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_CLASSIFY_URI;
pub const nsIChannel_LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE;
pub const nsIChannel_LOAD_EXPLICIT_CREDENTIALS:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_EXPLICIT_CREDENTIALS;
pub const nsIChannel_LOAD_BYPASS_SERVICE_WORKER:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_BYPASS_SERVICE_WORKER;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsIChannel__bindgen_ty_1 {
LOAD_DOCUMENT_URI = 65536,
LOAD_RETARGETED_DOCUMENT_URI = 131072,
LOAD_REPLACE = 262144,
LOAD_INITIAL_DOCUMENT_URI = 524288,
LOAD_TARGETED = 1048576,
LOAD_CALL_CONTENT_SNIFFERS = 2097152,
LOAD_CLASSIFY_URI = 4194304,
LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE = 8388608,
LOAD_EXPLICIT_CREDENTIALS = 16777216,
LOAD_BYPASS_SERVICE_WORKER = 33554432,
}
pub const nsIChannel_DISPOSITION_INLINE: root::nsIChannel__bindgen_ty_2 =
nsIChannel__bindgen_ty_2::DISPOSITION_INLINE;
pub const nsIChannel_DISPOSITION_ATTACHMENT:
root::nsIChannel__bindgen_ty_2 =
nsIChannel__bindgen_ty_2::DISPOSITION_ATTACHMENT;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsIChannel__bindgen_ty_2 {
DISPOSITION_INLINE = 0,
DISPOSITION_ATTACHMENT = 1,
}
#[test]
fn bindgen_test_layout_nsIChannel() {
assert_eq!(::std::mem::size_of::<nsIChannel>() , 8usize , concat ! (
"Size of: " , stringify ! ( nsIChannel ) ));
assert_eq! (::std::mem::align_of::<nsIChannel>() , 8usize , concat ! (
"Alignment of " , stringify ! ( nsIChannel ) ));
}
impl Clone for nsIChannel {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsILoadContext([u8; 0]);
pub type nsSecurityFlags = u32;
#[repr(C)]
#[derive(Debug, Copy)]
@ -13878,6 +13751,31 @@ pub mod root {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsIInterfaceRequestor {
pub _base: root::nsISupports,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsIInterfaceRequestor_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
#[test]
fn bindgen_test_layout_nsIInterfaceRequestor() {
assert_eq!(::std::mem::size_of::<nsIInterfaceRequestor>() , 8usize ,
concat ! (
"Size of: " , stringify ! ( nsIInterfaceRequestor ) ));
assert_eq! (::std::mem::align_of::<nsIInterfaceRequestor>() , 8usize ,
concat ! (
"Alignment of " , stringify ! ( nsIInterfaceRequestor )
));
}
impl Clone for nsIInterfaceRequestor {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsIInputStream([u8; 0]);
#[repr(C)]
@ -13904,13 +13802,6 @@ pub mod root {
impl Clone for nsIStreamListener {
fn clone(&self) -> Self { *self }
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsCompatibility {
eCompatibility_FullStandards = 1,
eCompatibility_AlmostStandards = 2,
eCompatibility_NavQuirks = 3,
}
#[repr(C)]
#[derive(Debug)]
pub struct nsAttrValue {
@ -15159,63 +15050,66 @@ pub mod root {
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsDOMMutationObserver([u8; 0]);
pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_LISTENERMANAGER;
pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_PROPERTIES;
pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_ANONYMOUS_ROOT;
pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS_ROOT;
pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_FORCE_XBL_BINDINGS;
pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_MAY_BE_IN_BINDING_MNGR;
pub const NODE_IS_EDITABLE: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_EDITABLE;
pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS;
pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_IN_SHADOW_TREE;
pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_EMPTY_SELECTOR;
pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_SLOW_SELECTOR;
pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_EDGE_CHILD_SELECTOR;
pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS;
pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_ALL_SELECTOR_FLAGS;
pub const NODE_NEEDS_FRAME: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_NEEDS_FRAME;
pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_DESCENDANTS_NEED_FRAMES;
pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_ACCESSKEY;
pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_DIRECTION_RTL;
pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_DIRECTION_LTR;
pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_ALL_DIRECTION_FLAGS;
pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_CHROME_ONLY_ACCESS;
pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS;
pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1;
pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_2;
pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1;
pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_TYPE_SPECIFIC_BITS_OFFSET;
pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_LISTENERMANAGER;
pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_PROPERTIES;
pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_ANONYMOUS_ROOT;
pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_NATIVE_ANONYMOUS_ROOT;
pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_FORCE_XBL_BINDINGS;
pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_MAY_BE_IN_BINDING_MNGR;
pub const NODE_IS_EDITABLE: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_EDITABLE;
pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_NATIVE_ANONYMOUS;
pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_IN_SHADOW_TREE;
pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_EMPTY_SELECTOR;
pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_SLOW_SELECTOR;
pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_EDGE_CHILD_SELECTOR;
pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS;
pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_ALL_SELECTOR_FLAGS;
pub const NODE_NEEDS_FRAME: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_NEEDS_FRAME;
pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_DESCENDANTS_NEED_FRAMES;
pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_ACCESSKEY;
pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_DIRECTION_RTL;
pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_DIRECTION_LTR;
pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_ALL_DIRECTION_FLAGS;
pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_CHROME_ONLY_ACCESS;
pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS;
pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_1;
pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_2;
pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_1;
pub const NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO:
root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_2;
pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_TYPE_SPECIFIC_BITS_OFFSET;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_28 {
pub enum _bindgen_ty_105 {
NODE_HAS_LISTENERMANAGER = 4,
NODE_HAS_PROPERTIES = 8,
NODE_IS_ANONYMOUS_ROOT = 16,
@ -22096,7 +21990,7 @@ pub mod root {
pub type imgRequest_HasThreadSafeRefCnt = root::mozilla::TrueType;
#[test]
fn bindgen_test_layout_imgRequest() {
assert_eq!(::std::mem::size_of::<imgRequest>() , 400usize , concat ! (
assert_eq!(::std::mem::size_of::<imgRequest>() , 376usize , concat ! (
"Size of: " , stringify ! ( imgRequest ) ));
assert_eq! (::std::mem::align_of::<imgRequest>() , 8usize , concat ! (
"Alignment of " , stringify ! ( imgRequest ) ));

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

@ -17,7 +17,7 @@ use data::{ComputedStyle, ElementData, ElementStyles, RestyleData};
use dom::{AnimationRules, SendElement, TElement, TNode};
use properties::{CascadeFlags, ComputedValues, SHAREABLE, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade};
use properties::longhands::display::computed_value as display;
use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RestyleHint};
use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RESTYLE_CSS_ANIMATIONS, RestyleHint};
use rule_tree::{CascadeLevel, RuleTree, StrongRuleNode};
use selector_parser::{PseudoElement, RestyleDamage, SelectorImpl};
use selectors::MatchAttr;
@ -954,30 +954,54 @@ pub trait MatchMethods : TElement {
context: &StyleContext<Self>,
data: &mut AtomicRefMut<ElementData>)
-> bool {
let primary_rules = &mut data.styles_mut().primary.rules;
use properties::PropertyDeclarationBlock;
use shared_lock::Locked;
let element_styles = &mut data.styles_mut();
let primary_rules = &mut element_styles.primary.rules;
let mut rule_node_changed = false;
if hint.contains(RESTYLE_STYLE_ATTRIBUTE) {
let style_attribute = self.style_attribute();
{
let mut replace_rule_node = |level: CascadeLevel,
pdb: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
path: &mut StrongRuleNode| {
let new_node = context.shared.stylist.rule_tree
.update_rule_at_level(level, pdb, path, &context.shared.guards);
if let Some(n) = new_node {
*path = n;
rule_node_changed = true;
}
};
let new_node = context.shared.stylist.rule_tree
.update_rule_at_level(CascadeLevel::StyleAttributeNormal,
style_attribute,
primary_rules,
&context.shared.guards);
if let Some(n) = new_node {
*primary_rules = n;
rule_node_changed = true;
}
// RESTYLE_CSS_ANIMATIONS is processed prior to other restyle hints
// in the name of animation-only traversal. Rest of restyle hints
// will be processed in a subsequent normal traversal.
if hint.contains(RESTYLE_CSS_ANIMATIONS) {
debug_assert!(context.shared.animation_only_restyle);
let new_node = context.shared.stylist.rule_tree
.update_rule_at_level(CascadeLevel::StyleAttributeImportant,
style_attribute,
primary_rules,
&context.shared.guards);
if let Some(n) = new_node {
*primary_rules = n;
rule_node_changed = true;
let animation_rule = self.get_animation_rule(None);
replace_rule_node(CascadeLevel::Animations,
animation_rule.as_ref(),
primary_rules);
let iter = element_styles.pseudos.iter_mut().filter(|&(p, _)|
<Self as MatchAttr>::Impl::pseudo_is_before_or_after(p));
for (pseudo, ref mut computed) in iter {
let animation_rule = self.get_animation_rule(Some(pseudo));
let pseudo_rules = &mut computed.rules;
replace_rule_node(CascadeLevel::Animations,
animation_rule.as_ref(),
pseudo_rules);
}
} else if hint.contains(RESTYLE_STYLE_ATTRIBUTE) {
let style_attribute = self.style_attribute();
replace_rule_node(CascadeLevel::StyleAttributeNormal,
style_attribute,
primary_rules);
replace_rule_node(CascadeLevel::StyleAttributeImportant,
style_attribute,
primary_rules);
// The per-pseudo rule nodes never change in this path.
}
}

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

@ -269,6 +269,10 @@
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
if self.0.is_empty() {
return dest.write_str("none");
}
let mut first = true;
for pair in &self.0 {
if !first {
@ -278,6 +282,7 @@
try!(serialize_identifier(&pair.0, dest));
try!(write!(dest, " {}", pair.1));
}
Ok(())
}
}

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

@ -92,7 +92,9 @@ ${helpers.predefined_type("stroke-opacity", "Opacity", "1.0",
products="gecko", animatable=False,
spec="https://www.w3.org/TR/SVG11/painting.html#StrokeOpacityProperty")}
${helpers.predefined_type("stroke-dasharray", "LoPOrNumber", "Either::Second(0.0)",
${helpers.predefined_type("stroke-dasharray",
"LengthOrPercentageOrNumber",
"Either::Second(0.0)",
"parse_non_negative",
vector="True",
products="gecko",

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

@ -47,6 +47,11 @@ bitflags! {
/// of their descendants.
const RESTYLE_LATER_SIBLINGS = 0x08,
/// Replace the style data coming from CSS animations without updating
/// any other style data. This hint is only processed in animation-only
/// traversal which is prior to normal traversal.
const RESTYLE_CSS_ANIMATIONS = 0x20,
/// Don't re-run selector-matching on the element, only the style
/// attribute has changed, and this change didn't have any other
/// dependencies.
@ -81,6 +86,7 @@ pub fn assert_restyle_hints_match() {
// (RESTYLE_SELF | RESTYLE_DESCENDANTS).
nsRestyleHint_eRestyle_Subtree => RESTYLE_DESCENDANTS,
nsRestyleHint_eRestyle_LaterSiblings => RESTYLE_LATER_SIBLINGS,
nsRestyleHint_eRestyle_CSSAnimations => RESTYLE_CSS_ANIMATIONS,
nsRestyleHint_eRestyle_StyleAttribute => RESTYLE_STYLE_ATTRIBUTE,
}
}
@ -89,7 +95,7 @@ impl RestyleHint {
/// The subset hints that affect the styling of a single element during the
/// traversal.
pub fn for_self() -> Self {
RESTYLE_SELF | RESTYLE_STYLE_ATTRIBUTE
RESTYLE_SELF | RESTYLE_STYLE_ATTRIBUTE | RESTYLE_CSS_ANIMATIONS
}
}

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

@ -31,6 +31,28 @@ pub struct PerLevelTraversalData {
pub current_dom_depth: Option<usize>,
}
bitflags! {
/// Represents that target elements of the traversal.
pub flags TraversalFlags: u8 {
/// Traverse only unstyled children.
const UNSTYLED_CHILDREN_ONLY = 0x01,
/// Traverse only elements for animation restyles
const ANIMATION_ONLY = 0x02,
}
}
impl TraversalFlags {
/// Returns true if the traversal is for animation-only restyles.
pub fn for_animation_only(&self) -> bool {
self.contains(ANIMATION_ONLY)
}
/// Returns true if the traversal is for unstyled children.
pub fn for_unstyled_children_only(&self) -> bool {
self.contains(UNSTYLED_CHILDREN_ONLY)
}
}
/// This structure exists to enforce that callers invoke pre_traverse, and also
/// to pass information from the pre-traversal into the primary traversal.
pub struct PreTraverseToken {
@ -109,12 +131,15 @@ pub trait DomTraversal<E: TElement> : Sync {
/// a traversal is needed. Returns a token that allows the caller to prove
/// that the call happened.
///
/// The unstyled_children_only parameter is used in Gecko to style newly-
/// The traversal_flag is used in Gecko.
/// If traversal_flag::UNSTYLED_CHILDREN_ONLY is specified, style newly-
/// appended children without restyling the parent.
fn pre_traverse(root: E, stylist: &Stylist, unstyled_children_only: bool)
/// If traversal_flag::ANIMATION_ONLY is specified, style only elements for
/// animations.
fn pre_traverse(root: E, stylist: &Stylist, traversal_flags: TraversalFlags)
-> PreTraverseToken
{
if unstyled_children_only {
if traversal_flags.for_unstyled_children_only() {
return PreTraverseToken {
traverse: true,
unstyled_children_only: true,
@ -135,7 +160,7 @@ pub trait DomTraversal<E: TElement> : Sync {
}
PreTraverseToken {
traverse: Self::node_needs_traversal(root.as_node()),
traverse: Self::node_needs_traversal(root.as_node(), traversal_flags.for_animation_only()),
unstyled_children_only: false,
}
}
@ -149,7 +174,7 @@ pub trait DomTraversal<E: TElement> : Sync {
}
/// Returns true if traversal is needed for the given node and subtree.
fn node_needs_traversal(node: E::ConcreteNode) -> bool {
fn node_needs_traversal(node: E::ConcreteNode, animation_only: bool) -> bool {
// Non-incremental layout visits every node.
if cfg!(feature = "servo") && opts::get().nonincremental_layout {
return true;
@ -158,6 +183,22 @@ pub trait DomTraversal<E: TElement> : Sync {
match node.as_element() {
None => Self::text_node_needs_traversal(node),
Some(el) => {
// In case of animation-only traversal we need to traverse
// the element if the element has animation only dirty
// descendants bit, animation-only restyle hint or recascade.
if animation_only {
if el.has_animation_only_dirty_descendants() {
return true;
}
let data = match el.borrow_data() {
Some(d) => d,
None => return false,
};
return data.get_restyle()
.map_or(false, |r| r.hint.has_animation_hint() || r.recascade);
}
// If the dirty descendants bit is set, we need to traverse no
// matter what. Skip examining the ElementData.
if el.has_dirty_descendants() {
@ -270,7 +311,7 @@ pub trait DomTraversal<E: TElement> : Sync {
}
for kid in parent.as_node().children() {
if Self::node_needs_traversal(kid) {
if Self::node_needs_traversal(kid, self.shared_context().animation_only_restyle) {
let el = kid.as_element();
if el.as_ref().and_then(|el| el.borrow_data())
.map_or(false, |d| d.has_styles())
@ -448,21 +489,38 @@ pub fn recalc_style_at<E, D>(traversal: &D,
None => empty_hint,
Some(r) => {
r.recascade = false;
mem::replace(&mut r.hint, empty_hint).propagate()
if r.hint.has_animation_hint() {
debug_assert!(context.shared.animation_only_restyle,
"animation restyle hint should be handled during animation-only restyles");
// Drop animation restyle hint.
let propagated_hint = r.hint.propagate();
r.hint.remove_animation_hint();
propagated_hint
} else {
mem::replace(&mut r.hint, empty_hint).propagate()
}
},
};
debug_assert!(data.has_current_styles());
debug_assert!(data.has_current_styles() || context.shared.animation_only_restyle,
"Should have computed style or haven't yet valid computed style in case of animation-only restyle");
trace!("propagated_hint={:?}, inherited_style_changed={:?}", propagated_hint, inherited_style_changed);
// Preprocess children, propagating restyle hints and handling sibling relationships.
if traversal.should_traverse_children(&mut context.thread_local, element, &data, DontLog) &&
(element.has_dirty_descendants() || !propagated_hint.is_empty() || inherited_style_changed) {
((!context.shared.animation_only_restyle && element.has_dirty_descendants()) ||
(context.shared.animation_only_restyle && element.has_animation_only_dirty_descendants()) ||
!propagated_hint.is_empty() ||
inherited_style_changed) {
let damage_handled = data.get_restyle().map_or(RestyleDamage::empty(), |r| {
r.damage_handled() | r.damage.handled_for_descendants()
});
preprocess_children(traversal, element, propagated_hint, damage_handled, inherited_style_changed);
}
if context.shared.animation_only_restyle {
unsafe { element.unset_animation_only_dirty_descendants(); }
}
// Make sure the dirty descendants bit is not set for the root of a
// display:none subtree, even if the style didn't change (since, if
// the style did change, we'd have already cleared it above).

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

@ -400,7 +400,7 @@ impl ToCss for SVGPaint {
}
/// <length> | <percentage> | <number>
pub type LoPOrNumber = Either<LengthOrPercentage, Number>;
pub type LengthOrPercentageOrNumber = Either<LengthOrPercentage, Number>;
#[derive(Clone, PartialEq, Eq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]

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

@ -909,15 +909,26 @@ impl ToCss for Percentage {
}
}
impl Percentage {
fn parse_internal(input: &mut Parser, context: AllowedNumericType) -> Result<Self, ()> {
match try!(input.next()) {
Token::Percentage(ref value) if context.is_ok(value.unit_value) => {
Ok(Percentage(value.unit_value))
}
_ => Err(())
}
}
/// Parses a percentage token, but rejects it if it's negative.
pub fn parse_non_negative(input: &mut Parser) -> Result<Self, ()> {
Self::parse_internal(input, AllowedNumericType::NonNegative)
}
}
impl Parse for Percentage {
#[inline]
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
let context = AllowedNumericType::All;
match try!(input.next()) {
Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
Ok(Percentage(value.unit_value)),
_ => Err(())
}
Self::parse_internal(input, AllowedNumericType::All)
}
}

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

@ -538,8 +538,8 @@ impl Parse for Number {
impl Number {
fn parse_with_minimum(input: &mut Parser, min: CSSFloat) -> Result<Number, ()> {
match parse_number(input) {
Ok(value) if value < min => Err(()),
value => value.map(Number),
Ok(value) if value >= min => Ok(Number(value)),
_ => Err(()),
}
}
@ -585,13 +585,12 @@ pub enum NumberOrPercentage {
no_viewport_percentage!(NumberOrPercentage);
impl Parse for NumberOrPercentage {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
if let Ok(per) = input.try(|input| Percentage::parse(context, input)) {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
if let Ok(per) = input.try(Percentage::parse_non_negative) {
return Ok(NumberOrPercentage::Percentage(per));
}
let num = try!(Number::parse_non_negative(input));
Ok(NumberOrPercentage::Number(num))
Number::parse_non_negative(input).map(NumberOrPercentage::Number)
}
}
@ -980,18 +979,18 @@ impl ToComputedValue for SVGPaintKind {
}
/// <length> | <percentage> | <number>
pub type LoPOrNumber = Either<LengthOrPercentage, Number>;
pub type LengthOrPercentageOrNumber = Either<LengthOrPercentage, Number>;
impl LoPOrNumber {
impl LengthOrPercentageOrNumber {
/// parse a <length-percentage> | <number> enforcing that the contents aren't negative
pub fn parse_non_negative(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
if let Ok(lop) = input.try(LengthOrPercentage::parse_non_negative) {
Ok(Either::First(lop))
} else if let Ok(num) = input.try(Number::parse_non_negative) {
Ok(Either::Second(num))
} else {
Err(())
// NB: Parse numbers before Lengths so we are consistent about how to
// recognize and serialize "0".
if let Ok(num) = input.try(Number::parse_non_negative) {
return Ok(Either::Second(num))
}
LengthOrPercentage::parse_non_negative(input).map(Either::First)
}
}

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

@ -117,7 +117,12 @@ macro_rules! __define_css_keyword_enum__actual {
/// Parse this property from a CSS input stream.
pub fn parse(input: &mut ::cssparser::Parser) -> Result<$name, ()> {
let ident = input.expect_ident()?;
match_ignore_ascii_case! { &ident,
Self::from_ident(&ident)
}
/// Parse this property from an already-tokenized identifier.
pub fn from_ident(ident: &str) -> Result<$name, ()> {
match_ignore_ascii_case! { ident,
$( $css => Ok($name::$variant), )+
_ => Err(())
}

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

@ -47,10 +47,8 @@ impl ServoUrl {
Arc::try_unwrap(self.0).unwrap_or_else(|s| (*s).clone()).into_string()
}
// NOTE: These methods return options that are always true temporarily until
// we special-case some urls to avoid going through rust-url.
pub fn into_url(self) -> Option<Url> {
Some(Arc::try_unwrap(self.0).unwrap_or_else(|s| (*s).clone()))
pub fn into_url(self) -> Url {
Arc::try_unwrap(self.0).unwrap_or_else(|s| (*s).clone())
}
pub fn as_url(&self) -> &Url {
@ -94,24 +92,24 @@ impl ServoUrl {
self.0.as_str()
}
pub fn as_mut_url(&mut self) -> Option<&mut Url> {
Some(Arc::make_mut(&mut self.0))
pub fn as_mut_url(&mut self) -> &mut Url {
Arc::make_mut(&mut self.0)
}
pub fn set_username(&mut self, user: &str) -> Result<(), ()> {
Arc::make_mut(&mut self.0).set_username(user)
self.as_mut_url().set_username(user)
}
pub fn set_ip_host(&mut self, addr: IpAddr) -> Result<(), ()> {
Arc::make_mut(&mut self.0).set_ip_host(addr)
self.as_mut_url().set_ip_host(addr)
}
pub fn set_password(&mut self, pass: Option<&str>) -> Result<(), ()> {
Arc::make_mut(&mut self.0).set_password(pass)
self.as_mut_url().set_password(pass)
}
pub fn set_fragment(&mut self, fragment: Option<&str>) {
Arc::make_mut(&mut self.0).set_fragment(fragment)
self.as_mut_url().set_fragment(fragment)
}
pub fn username(&self) -> &str {

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

@ -10,6 +10,7 @@ name = "webdriver_server"
path = "lib.rs"
[dependencies]
base64 = "0.4.1"
cookie = "0.2.5"
euclid = "0.11"
hyper = "0.9.9"

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

@ -7,6 +7,7 @@
#![deny(unsafe_code)]
extern crate base64;
extern crate cookie as cookie_rs;
extern crate euclid;
extern crate hyper;
@ -34,7 +35,6 @@ use keys::keycodes_to_keys;
use msg::constellation_msg::{FrameId, PipelineId, TraversalDirection};
use net_traits::image::base::PixelFormat;
use regex::Captures;
use rustc_serialize::base64::{CharacterSet, Config, Newline, ToBase64};
use rustc_serialize::json::{Json, ToJson};
use script_traits::{ConstellationMsg, LoadData, WebDriverCommandMsg};
use script_traits::webdriver_msg::{LoadStatus, WebDriverCookieError, WebDriverFrameId};
@ -831,13 +831,7 @@ impl Handler {
let mut png_data = Vec::new();
DynamicImage::ImageRgb8(rgb).save(&mut png_data, ImageFormat::PNG).unwrap();
let config = Config {
char_set: CharacterSet::Standard,
newline: Newline::LF,
pad: true,
line_length: None
};
let encoded = png_data.to_base64(config);
let encoded = base64::encode(&png_data);
Ok(WebDriverResponse::Generic(ValueResponse::new(encoded.to_json())))
}

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

@ -83,7 +83,8 @@ use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::supports::parse_condition_or_declaration;
use style::thread_state;
use style::timer::Timer;
use style::traversal::{resolve_style, DomTraversal, TraversalDriver};
use style::traversal::{ANIMATION_ONLY, UNSTYLED_CHILDREN_ONLY};
use style::traversal::{resolve_style, DomTraversal, TraversalDriver, TraversalFlags};
use style_traits::ToCss;
use super::stylesheet_loader::StylesheetLoader;
@ -124,7 +125,8 @@ pub extern "C" fn Servo_Shutdown() {
}
fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard,
per_doc_data: &PerDocumentStyleDataImpl) -> SharedStyleContext<'a> {
per_doc_data: &PerDocumentStyleDataImpl,
animation_only: bool) -> SharedStyleContext<'a> {
let local_context_data =
ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
@ -139,11 +141,12 @@ fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard,
timer: Timer::new(),
// FIXME Find the real QuirksMode information for this document
quirks_mode: QuirksMode::NoQuirks,
animation_only_restyle: animation_only,
}
}
fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
unstyled_children_only: bool) {
traversal_flags: TraversalFlags) {
// When new content is inserted in a display:none subtree, we will call into
// servo to try to style it. Detect that here and bail out.
if let Some(parent) = element.parent_element() {
@ -155,7 +158,7 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
let token = RecalcStyleOnly::pre_traverse(element, &per_doc_data.stylist, unstyled_children_only);
let token = RecalcStyleOnly::pre_traverse(element, &per_doc_data.stylist, traversal_flags);
if !token.should_traverse() {
return;
}
@ -165,7 +168,8 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let shared_style_context = create_shared_context(&guard, &per_doc_data);
let shared_style_context = create_shared_context(&guard, &per_doc_data,
traversal_flags.for_animation_only());
let traversal_driver = if global_style_data.style_thread_pool.is_none() {
TraversalDriver::Sequential
@ -192,8 +196,18 @@ pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed,
behavior: structs::TraversalRootBehavior) -> bool {
let element = GeckoElement(root);
debug!("Servo_TraverseSubtree: {:?}", element);
traverse_subtree(element, raw_data,
behavior == structs::TraversalRootBehavior::UnstyledChildrenOnly);
let traversal_flags = match behavior {
structs::TraversalRootBehavior::UnstyledChildrenOnly => UNSTYLED_CHILDREN_ONLY,
_ => TraversalFlags::empty(),
};
if element.has_animation_only_dirty_descendants() ||
element.has_animation_restyle_hints() {
traverse_subtree(element, raw_data, traversal_flags | ANIMATION_ONLY);
}
traverse_subtree(element, raw_data, traversal_flags);
element.has_dirty_descendants() || element.mutate_data().unwrap().has_restyle()
}
@ -1359,7 +1373,9 @@ pub extern "C" fn Servo_CSSSupports(cond: *const nsACString) -> bool {
/// Only safe to call on the main thread, with exclusive access to the element and
/// its ancestors.
unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut<ElementData>, element: GeckoElement)
unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut<ElementData>,
element: GeckoElement,
animation_only: bool)
-> Option<&'a mut RestyleData>
{
// Don't generate a useless RestyleData if the element hasn't been styled.
@ -1371,8 +1387,13 @@ unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut<ElementData>, element: Ge
let mut curr = element;
while let Some(parent) = curr.parent_element() {
curr = parent;
if curr.has_dirty_descendants() { break; }
curr.set_dirty_descendants();
if animation_only {
if curr.has_animation_only_dirty_descendants() { break; }
curr.set_animation_only_dirty_descendants();
} else {
if curr.has_dirty_descendants() { break; }
curr.set_dirty_descendants();
}
}
bindings::Gecko_SetOwnerDocumentNeedsStyleFlush(element.0);
@ -1387,7 +1408,7 @@ pub extern "C" fn Servo_Element_GetSnapshot(element: RawGeckoElementBorrowed) ->
let snapshot = match element.mutate_data() {
None => ptr::null_mut(),
Some(mut data) => {
if let Some(restyle_data) = unsafe { maybe_restyle(&mut data, element) } {
if let Some(restyle_data) = unsafe { maybe_restyle(&mut data, element, false) } {
restyle_data.snapshot.ensure(|| element.create_snapshot()).borrow_mut_raw()
} else {
ptr::null_mut()
@ -1407,10 +1428,14 @@ pub extern "C" fn Servo_NoteExplicitHints(element: RawGeckoElementBorrowed,
let damage = GeckoRestyleDamage::new(change_hint);
debug!("Servo_NoteExplicitHints: {:?}, restyle_hint={:?}, change_hint={:?}",
element, restyle_hint, change_hint);
debug_assert!(restyle_hint == structs::nsRestyleHint_eRestyle_CSSAnimations ||
(restyle_hint.0 & structs::nsRestyleHint_eRestyle_CSSAnimations.0) == 0,
"eRestyle_CSSAnimations should only appear by itself");
let mut maybe_data = element.mutate_data();
let maybe_restyle_data =
maybe_data.as_mut().and_then(|d| unsafe { maybe_restyle(d, element) });
let maybe_restyle_data = maybe_data.as_mut().and_then(|d| unsafe {
maybe_restyle(d, element, restyle_hint == structs::nsRestyleHint_eRestyle_CSSAnimations)
});
if let Some(restyle_data) = maybe_restyle_data {
let restyle_hint: RestyleHint = restyle_hint.into();
restyle_data.hint.insert(&restyle_hint.into());
@ -1492,7 +1517,7 @@ pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
}
// We don't have the style ready. Go ahead and compute it as necessary.
let shared = create_shared_context(&guard, &mut doc_data.borrow_mut());
let shared = create_shared_context(&guard, &mut doc_data.borrow_mut(), false);
let mut tlc = ThreadLocalStyleContext::new(&shared);
let mut context = StyleContext {
shared: &shared,
@ -1592,7 +1617,7 @@ pub extern "C" fn Servo_AssertTreeIsClean(root: RawGeckoElementBorrowed) {
let root = GeckoElement(root);
fn assert_subtree_is_clean<'le>(el: GeckoElement<'le>) {
debug_assert!(!el.has_dirty_descendants());
debug_assert!(!el.has_dirty_descendants() && !el.has_animation_only_dirty_descendants());
for child in el.as_node().children() {
if let Some(child) = child.as_element() {
assert_subtree_is_clean(child);

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

@ -1 +1 @@
8c72b7651f231f589bc81d78fb9602d5a0899213
7dd4e2db785c8ec360a989f69891b1e97dd4d369

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

@ -151,11 +151,11 @@ fn test_replace_hosts() {
host_table.insert("servo.test.server".to_owned(), ip("127.0.0.2"));
let url = ServoUrl::parse("http://foo.bar.com:8000/foo").unwrap();
assert_eq!(host_replacement(&host_table, &url).host_str().unwrap(), "127.0.0.1");
assert_eq!(host_replacement(&host_table, url).host_str().unwrap(), "127.0.0.1");
let url = ServoUrl::parse("http://servo.test.server").unwrap();
assert_eq!(host_replacement(&host_table, &url).host_str().unwrap(), "127.0.0.2");
assert_eq!(host_replacement(&host_table, url).host_str().unwrap(), "127.0.0.2");
let url = ServoUrl::parse("http://a.foo.bar.com").unwrap();
assert_eq!(host_replacement(&host_table, &url).host_str().unwrap(), "a.foo.bar.com");
assert_eq!(host_replacement(&host_table, url).host_str().unwrap(), "a.foo.bar.com");
}

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

@ -1170,4 +1170,30 @@ mod shorthand_serialization {
assert_eq!(shadow.to_css_string(), shadow_css);
}
}
mod counter_increment {
pub use super::*;
pub use style::properties::longhands::counter_increment::SpecifiedValue as CounterIncrement;
#[test]
fn counter_increment_with_properties_should_serialize_correctly() {
let mut properties = Vec::new();
properties.push(("counter1".to_owned(), 1));
properties.push(("counter2".to_owned(), -4));
let counter_increment = CounterIncrement(properties);
let counter_increment_css = "counter1 1 counter2 -4";
assert_eq!(counter_increment.to_css_string(), counter_increment_css);
}
#[test]
fn counter_increment_without_properties_should_serialize_correctly() {
let counter_increment = CounterIncrement(Vec::new());
let counter_increment_css = "none";
assert_eq!(counter_increment.to_css_string(), counter_increment_css);
}
}
}

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

@ -71,7 +71,7 @@ class GeckoInstance(object):
"hangmonitor.timeout": 0,
"javascript.options.showInConsole": True,
"marionette.defaultPrefs.enabled": True,
"marionette.enabled": True,
"media.volume_scale": "0.01",
# Make sure the disk cache doesn't get auto disabled

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

@ -36,7 +36,10 @@ class Timeouts(object):
self._marionette._send_message("timeouts", {"type": name, "ms": ms})
def _get(self, name):
ms = self._marionette._send_message("getTimeouts", key=name)
ts = self._marionette._send_message("getTimeouts")
if name not in ts:
raise KeyError()
ms = ts[name]
return ms / 1000
@property
@ -63,7 +66,11 @@ class Timeouts(object):
minutes (or 300 seconds).
"""
return self._get("page load")
# remove fallback when Firefox 56 is stable
try:
return self._get("pageLoad")
except KeyError:
return self._get("page load")
@page_load.setter
def page_load(self, sec):
@ -71,7 +78,11 @@ class Timeouts(object):
to wait for the page loading to complete.
"""
self._set("page load", sec)
# remove fallback when Firefox 56 is stable
try:
self._set("pageLoad", sec)
except errors.InvalidArgumentException:
return self._set("page load", sec)
@property
def implicit(self):

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

@ -6,80 +6,76 @@
const {Constructor: CC, interfaces: Ci, utils: Cu, classes: Cc} = Components;
const MARIONETTE_CONTRACTID = "@mozilla.org/marionette;1";
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const MARIONETTE_CONTRACT_ID = "@mozilla.org/marionette;1";
const MARIONETTE_CID = Components.ID("{786a1369-dca5-4adc-8486-33d23c88010a}");
const DEFAULT_PORT = 2828;
const ENABLED_PREF = "marionette.defaultPrefs.enabled";
const PORT_PREF = "marionette.defaultPrefs.port";
const FORCELOCAL_PREF = "marionette.force-local";
const LOG_PREF = "marionette.logging";
const PREF_ENABLED = "marionette.enabled";
const PREF_ENABLED_FALLBACK = "marionette.defaultPrefs.enabled";
const PREF_PORT = "marionette.port";
const PREF_PORT_FALLBACK = "marionette.defaultPrefs.port";
const PREF_LOG_LEVEL = "marionette.log.level";
const PREF_LOG_LEVEL_FALLBACK = "marionette.logging";
const PREF_FORCE_LOCAL = "marionette.forcelocal";
const PREF_FORCE_LOCAL_FALLBACK = "marionette.force-local";
/**
* Besides starting based on existing prefs in a profile and a commandline flag,
* we also support inheriting prefs out of an env var, and to start marionette
* that way.
* This allows marionette prefs to persist when we do a restart into a
* different profile in order to test things like Firefox refresh.
* The env var itself, if present, is interpreted as a JSON structure, with the
* keys mapping to preference names in the "marionette." branch, and the values
* to the values of those prefs. So something like {"defaultPrefs.enabled": true}
* in the env var would result in the marionette.defaultPrefs.enabled pref being
* set to true, thus triggering marionette being enabled for that startup.
*/
const DEFAULT_PORT = 2828;
const DEFAULT_LOG_LEVEL = "info";
const LOG_LEVELS = new Map([
["fatal", Log.Level.Fatal],
["error", Log.Level.Error],
["warn", Log.Level.Warn],
["info", Log.Level.Info],
["config", Log.Level.Config],
["debug", Log.Level.Debug],
["trace", Log.Level.Trace],
]);
// Besides starting based on existing prefs in a profile and a command
// line flag, we also support inheriting prefs out of an env var, and to
// start Marionette that way.
//
// This allows marionette prefs to persist when we do a restart into
// a different profile in order to test things like Firefox refresh.
// The environment variable itself, if present, is interpreted as a
// JSON structure, with the keys mapping to preference names in the
// "marionette." branch, and the values to the values of those prefs. So
// something like {"enabled": true} would result in the marionette.enabled
// pref being set to true, thus triggering marionette being enabled for
// that startup.
const ENV_PREF_VAR = "MOZ_MARIONETTE_PREF_STATE_ACROSS_RESTARTS";
const ServerSocket = CC("@mozilla.org/network/server-socket;1",
"nsIServerSocket",
"initSpecialConnection");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
// Marionette preferences recently changed names. This is an abstraction
// that first looks for the new name, but falls back to using the old name
// if the new does not exist.
//
// This shim can be removed when Firefox 55 ships.
const prefs = {
get port () {
let fallback = Preferences.get(PREF_PORT_FALLBACK, DEFAULT_PORT);
return Preferences.get(PREF_PORT, fallback);
},
function MarionetteComponent() {
this.loaded_ = false;
this.observerService = Services.obs;
this.logger = this.setupLogger_(this.determineLoggingLevel_());
}
MarionetteComponent.prototype = {
classDescription: "Marionette component",
classID: MARIONETTE_CID,
contractID: MARIONETTE_CONTRACTID,
QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler, Ci.nsIObserver]),
_xpcom_categories: [
{category: "command-line-handler", entry: "b-marionette"},
{category: "profile-after-change", service: true}
],
enabled: false,
finalUiStartup: false,
gfxWindow: null,
server: null,
};
MarionetteComponent.prototype.setupLogger_ = function (level) {
let log = Log.repository.getLogger("Marionette");
log.level = level;
log.addAppender(new Log.DumpAppender());
return log;
};
MarionetteComponent.prototype.determineLoggingLevel_ = function() {
let level = Log.Level.Info;
// marionette.logging pref can override default
// with an entry from the Log.Level enum
if (Preferences.has(LOG_PREF)) {
let p = Preferences.get(LOG_PREF);
get logLevel () {
let level = DEFAULT_LOG_LEVEL;
let fallback = Preferences.get(PREF_LOG_LEVEL_FALLBACK, level);
let p = Preferences.get(PREF_LOG_LEVEL, fallback);
switch (typeof p) {
// Gecko >= 46
case "string":
let s = p.toLowerCase();
s = s.charAt(0).toUpperCase() + s.slice(1);
level = Log.Level[s];
if (LOG_LEVELS.has(s)) {
level = LOG_LEVELS.get(s);
}
break;
// Gecko <= 45
@ -89,13 +85,81 @@ MarionetteComponent.prototype.determineLoggingLevel_ = function() {
}
break;
}
}
return level;
return level;
},
get forceLocal () {
let fallback = Preferences.get(PREF_FORCE_LOCAL_FALLBACK, true);
return Preferences.get(PREF_FORCE_LOCAL, fallback);
},
readFromEnvironment (key) {
const env = Cc["@mozilla.org/process/environment;1"]
.getService(Ci.nsIEnvironment);
if (env.exists(key)) {
let prefs;
try {
prefs = JSON.parse(env.get(key));
} catch (e) {
Cu.reportError(
"Invalid Marionette preferences in environment; " +
"preferences will not have been applied");
Cu.reportError(e);
}
if (prefs) {
for (let prefName of Object.keys(prefs)) {
Preferences.set("marionette." + prefName, prefs[prefName]);
}
}
}
},
};
MarionetteComponent.prototype.onSocketAccepted = function(
socket, transport) {
function MarionetteComponent() {
// guards against this component
// being initialised multiple times
this.running = false;
// holds a reference to server.TCPListener
this.server = null;
// holds reference to ChromeWindow
// used to run GFX sanity tests on Windows
this.gfxWindow = null;
// indicates that all pending window checks have been completed
// and that we are ready to start the Marionette server
this.finalUIStartup = false;
this.logger = this.setupLogger(prefs.logLevel);
Services.prefs.addObserver(PREF_ENABLED, this, false);
if (Preferences.isSet(PREF_ENABLED_FALLBACK)) {
this.logger.warn(`Deprecated preference ${PREF_ENABLED_FALLBACK} detected, ` +
`please use ${PREF_ENABLED}`);
Preferences.set(PREF_ENABLED, Preferences.get(PREF_ENABLED_FALLBACK));
}
}
MarionetteComponent.prototype = {
classDescription: "Marionette component",
classID: MARIONETTE_CID,
contractID: MARIONETTE_CONTRACT_ID,
QueryInterface: XPCOMUtils.generateQI([
Ci.nsICommandLineHandler,
Ci.nsIObserver,
]),
_xpcom_categories: [
{category: "command-line-handler", entry: "b-marionette"},
{category: "profile-after-change", service: true},
],
helpInfo: " --marionette Enable remote control server.\n",
};
MarionetteComponent.prototype.onSocketAccepted = function (socket, transport) {
this.logger.info("onSocketAccepted for Marionette dummy socket");
};
@ -104,59 +168,70 @@ MarionetteComponent.prototype.onStopListening = function (socket, status) {
socket.close();
};
/** Check cmdLine argument for {@code --marionette}. */
// Handle --marionette flag
MarionetteComponent.prototype.handle = function (cmdLine) {
// if the CLI is there then lets do work otherwise nothing to see
if (cmdLine.handleFlag("marionette", false)) {
this.enabled = true;
this.logger.debug("Marionette enabled via command-line flag");
this.init();
}
};
Object.defineProperty(MarionetteComponent.prototype, "enabled", {
set (value) {
Preferences.set(PREF_ENABLED, value);
},
get () {
return Preferences.get(PREF_ENABLED);
},
});
MarionetteComponent.prototype.observe = function (subject, topic, data) {
switch (topic) {
case "nsPref:changed":
if (Preferences.get(PREF_ENABLED)) {
this.init();
} else {
this.uninit();
}
break;
case "profile-after-change":
// Using sessionstore-windows-restored as the xpcom category doesn't seem to work,
// so we wait for that by adding an observer here.
this.observerService.addObserver(this, "sessionstore-windows-restored", false);
// Using sessionstore-windows-restored as the xpcom category doesn't
// seem to work, so we wait for that by adding an observer here.
Services.obs.addObserver(this, "sessionstore-windows-restored", false);
this.maybeReadPrefsFromEnvironment();
prefs.readFromEnvironment(ENV_PREF_VAR);
#ifdef ENABLE_MARIONETTE
this.enabled = Preferences.get(ENABLED_PREF, false);
if (this.enabled) {
this.logger.debug("Marionette enabled via build flag and pref");
// We want to suppress the modal dialog that's shown
// when starting up in safe-mode to enable testing.
if (Services.appinfo.inSafeMode) {
this.observerService.addObserver(this, "domwindowopened", false);
Services.obs.addObserver(this, "domwindowopened", false);
}
}
#endif
break;
case "domwindowclosed":
if (this.gfxWindow === null || subject === this.gfxWindow) {
this.observerService.removeObserver(this, topic);
Services.obs.removeObserver(this, topic);
this.observerService.addObserver(this, "xpcom-shutdown", false);
this.finalUiStartup = true;
Services.obs.addObserver(this, "xpcom-shutdown", false);
this.finalUIStartup = true;
this.init();
}
break;
case "domwindowopened":
this.observerService.removeObserver(this, topic);
this.suppressSafeModeDialog_(subj);
Services.obs.removeObserver(this, topic);
this.suppressSafeModeDialog(subject);
break;
case "sessionstore-windows-restored":
this.observerService.removeObserver(this, topic);
Services.obs.removeObserver(this, topic);
// When Firefox starts on Windows, an additional GFX sanity test window
// may appear off-screen. Marionette should wait for it to close.
// When Firefox starts on Windows, an additional GFX sanity test
// window may appear off-screen. Marionette should wait for it
// to close.
let winEn = Services.wm.getEnumerator(null);
while (winEn.hasMoreElements()) {
let win = winEn.getNext();
@ -167,46 +242,33 @@ MarionetteComponent.prototype.observe = function (subject, topic, data) {
}
if (this.gfxWindow) {
this.observerService.addObserver(this, "domwindowclosed", false);
Services.obs.addObserver(this, "domwindowclosed", false);
} else {
this.observerService.addObserver(this, "xpcom-shutdown", false);
this.finalUiStartup = true;
Services.obs.addObserver(this, "xpcom-shutdown", false);
this.finalUIStartup = true;
this.init();
}
break;
case "xpcom-shutdown":
this.observerService.removeObserver(this, "xpcom-shutdown");
Services.obs.removeObserver(this, "xpcom-shutdown");
this.uninit();
break;
}
};
MarionetteComponent.prototype.maybeReadPrefsFromEnvironment = function() {
let env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
if (env.exists(ENV_PREF_VAR)) {
let prefStr = env.get(ENV_PREF_VAR);
let prefs;
try {
prefs = JSON.parse(prefStr);
} catch (ex) {
Cu.reportError("Invalid marionette prefs in environment; prefs won't have been applied.");
Cu.reportError(ex);
}
if (prefs) {
for (let prefName of Object.keys(prefs)) {
Preferences.set("marionette." + prefName, prefs[prefName]);
}
}
}
}
MarionetteComponent.prototype.setupLogger = function (level) {
let logger = Log.repository.getLogger("Marionette");
logger.level = level;
logger.addAppender(new Log.DumpAppender());
return logger;
};
MarionetteComponent.prototype.suppressSafeModeDialog_ = function (win) {
// Wait for the modal dialog to finish loading.
win.addEventListener("load", function() {
MarionetteComponent.prototype.suppressSafeModeDialog = function (win) {
win.addEventListener("load", () => {
if (win.document.getElementById("safeModeDialog")) {
// Accept the dialog to start in safe-mode
// accept the dialog to start in safe-mode
win.setTimeout(() => {
win.document.documentElement.getButton("accept").click();
});
@ -214,18 +276,12 @@ MarionetteComponent.prototype.suppressSafeModeDialog_ = function (win) {
}, {once: true});
};
MarionetteComponent.prototype.init = function() {
if (this.loaded_ || !this.enabled || !this.finalUiStartup) {
MarionetteComponent.prototype.init = function () {
if (this.running || !this.enabled || !this.finalUIStartup) {
return;
}
this.loaded_ = true;
let forceLocal = Preferences.get(FORCELOCAL_PREF,
Services.appinfo.name == "B2G" ? false : true);
Preferences.set(FORCELOCAL_PREF, forceLocal);
if (!forceLocal) {
if (!prefs.forceLocal) {
// See bug 800138. Because the first socket that opens with
// force-local=false fails, we open a dummy socket that will fail.
// keepWhenOffline=true so that it still work when offline (local).
@ -236,30 +292,30 @@ MarionetteComponent.prototype.init = function() {
insaneSacrificialGoat.asyncListen(this);
}
let port = Preferences.get(PORT_PREF, DEFAULT_PORT);
let s;
try {
Cu.import("chrome://marionette/content/server.js");
s = new MarionetteServer(port, forceLocal);
s = new server.TCPListener(prefs.port, prefs.forceLocal);
s.start();
this.logger.info(`Listening on port ${s.port}`);
} catch (e) {
this.logger.error(`Error on starting server: ${e}`);
dump(e.toString() + "\n" + e.stack + "\n");
dump(`${e.toString()}\n${e.stack}\n`);
} finally {
if (s) {
this.server = s;
this.running = true;
}
}
};
MarionetteComponent.prototype.uninit = function() {
if (!this.loaded_) {
MarionetteComponent.prototype.uninit = function () {
if (!this.running) {
return;
}
this.server.stop();
this.loaded_ = false;
this.logger.info("Ceased listening");
this.running = false;
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MarionetteComponent]);

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

@ -2,8 +2,7 @@
# 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/.
EXTRA_COMPONENTS += ["marionette.manifest"]
EXTRA_PP_COMPONENTS += ["marionette.js"]
if CONFIG["ENABLE_MARIONETTE"]:
DEFINES["ENABLE_MARIONETTE"] = 1
EXTRA_COMPONENTS += [
"marionette.js",
"marionette.manifest",
]

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

@ -1,228 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("chrome://marionette/content/assert.js");
Cu.import("chrome://marionette/content/driver.js");
Cu.import("chrome://marionette/content/error.js");
Cu.import("chrome://marionette/content/message.js");
this.EXPORTED_SYMBOLS = ["Dispatcher"];
const PROTOCOL_VERSION = 3;
const logger = Log.repository.getLogger("Marionette");
/**
* Manages a Marionette connection, and dispatches packets received to
* their correct destinations.
*
* @param {number} connId
* Unique identifier of the connection this dispatcher should handle.
* @param {DebuggerTransport} transport
* Debugger transport connection to the client.
* @param {function(): GeckoDriver} driverFactory
* A factory function that produces a GeckoDriver.
*/
this.Dispatcher = function (connId, transport, driverFactory) {
this.connId = connId;
this.conn = transport;
// transport hooks are Dispatcher#onPacket
// and Dispatcher#onClosed
this.conn.hooks = this;
// callback for when connection is closed
this.onclose = null;
// last received/sent message ID
this.lastId = 0;
this.driver = driverFactory();
// lookup of commands sent by server to client by message ID
this.commands_ = new Map();
};
/**
* Debugger transport callback that cleans up
* after a connection is closed.
*/
Dispatcher.prototype.onClosed = function (reason) {
this.driver.deleteSession();
if (this.onclose) {
this.onclose(this);
}
};
/**
* Callback that receives data packets from the client.
*
* If the message is a Response, we look up the command previously issued
* to the client and run its callback, if any. In case of a Command,
* the corresponding is executed.
*
* @param {Array.<number, number, ?, ?>} data
* A four element array where the elements, in sequence, signifies
* message type, message ID, method name or error, and parameters
* or result.
*/
Dispatcher.prototype.onPacket = function (data) {
let msg = Message.fromMsg(data);
msg.origin = MessageOrigin.Client;
this.log_(msg);
if (msg instanceof Response) {
let cmd = this.commands_.get(msg.id);
this.commands_.delete(msg.id);
cmd.onresponse(msg);
} else if (msg instanceof Command) {
this.lastId = msg.id;
this.execute(msg);
}
};
/**
* Executes a WebDriver command and sends back a response when it has
* finished executing.
*
* Commands implemented in GeckoDriver and registered in its
* {@code GeckoDriver.commands} attribute. The return values from
* commands are expected to be Promises. If the resolved value of said
* promise is not an object, the response body will be wrapped in an object
* under a "value" field.
*
* If the command implementation sends the response itself by calling
* {@code resp.send()}, the response is guaranteed to not be sent twice.
*
* Errors thrown in commands are marshaled and sent back, and if they
* are not WebDriverError instances, they are additionally propagated and
* reported to {@code Components.utils.reportError}.
*
* @param {Command} cmd
* The requested command to execute.
*/
Dispatcher.prototype.execute = function (cmd) {
let resp = new Response(cmd.id, this.send.bind(this));
let sendResponse = () => resp.sendConditionally(resp => !resp.sent);
let sendError = resp.sendError.bind(resp);
let req = Task.spawn(function*() {
let fn = this.driver.commands[cmd.name];
if (typeof fn == "undefined") {
throw new UnknownCommandError(cmd.name);
}
if (cmd.name !== "newSession") {
assert.session(this.driver);
}
let rv = yield fn.bind(this.driver)(cmd, resp);
if (typeof rv != "undefined") {
if (typeof rv != "object") {
resp.body = {value: rv};
} else {
resp.body = rv;
}
}
}.bind(this));
req.then(sendResponse, sendError).catch(error.report);
};
Dispatcher.prototype.sendError = function (err, cmdId) {
let resp = new Response(cmdId, this.send.bind(this));
resp.sendError(err);
};
// Convenience methods:
/**
* When a client connects we send across a JSON Object defining the
* protocol level.
*
* This is the only message sent by Marionette that does not follow
* the regular message format.
*/
Dispatcher.prototype.sayHello = function() {
let whatHo = {
applicationType: "gecko",
marionetteProtocol: PROTOCOL_VERSION,
};
this.sendRaw(whatHo);
};
/**
* Delegates message to client based on the provided {@code cmdId}.
* The message is sent over the debugger transport socket.
*
* The command ID is a unique identifier assigned to the client's request
* that is used to distinguish the asynchronous responses.
*
* Whilst responses to commands are synchronous and must be sent in the
* correct order.
*
* @param {Command,Response} msg
* The command or response to send.
*/
Dispatcher.prototype.send = function (msg) {
msg.origin = MessageOrigin.Server;
if (msg instanceof Command) {
this.commands_.set(msg.id, msg);
this.sendToEmulator(msg);
} else if (msg instanceof Response) {
this.sendToClient(msg);
}
};
// Low-level methods:
/**
* Send given response to the client over the debugger transport socket.
*
* @param {Response} resp
* The response to send back to the client.
*/
Dispatcher.prototype.sendToClient = function (resp) {
this.driver.responseCompleted();
this.sendMessage(resp);
};
/**
* Marshal message to the Marionette message format and send it.
*
* @param {Command,Response} msg
* The message to send.
*/
Dispatcher.prototype.sendMessage = function (msg) {
this.log_(msg);
let payload = msg.toMsg();
this.sendRaw(payload);
};
/**
* Send the given payload over the debugger transport socket to the
* connected client.
*
* @param {Object} payload
* The payload to ship.
*/
Dispatcher.prototype.sendRaw = function (payload) {
this.conn.send(payload);
};
Dispatcher.prototype.log_ = function (msg) {
let a = (msg.origin == MessageOrigin.Client ? " -> " : " <- ");
let s = JSON.stringify(msg.toMsg());
logger.trace(this.connId + a + s);
};

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

@ -35,7 +35,7 @@ class TestCapabilities(MarionetteTestCase):
self.assertFalse(self.caps["acceptInsecureCerts"])
self.assertDictEqual(self.caps["timeouts"],
{"implicit": 0,
"page load": 300000,
"pageLoad": 300000,
"script": 30000})
def test_supported_features(self):
@ -245,7 +245,7 @@ class TestCapabilityMatching(MarionetteTestCase):
self.assertEqual(self.marionette.get_pref("network.proxy.type"), 1)
def test_timeouts(self):
timeouts = {u"implicit": 123, u"page load": 456, u"script": 789}
timeouts = {u"implicit": 123, u"pageLoad": 456, u"script": 789}
caps = {"desiredCapabilities": {"timeouts": timeouts}}
self.marionette.start_session(caps)
self.assertIn("timeouts", self.marionette.session_capabilities)

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

@ -20,7 +20,6 @@ marionette.jar:
content/error.js (error.js)
content/wait.js (wait.js)
content/message.js (message.js)
content/dispatcher.js (dispatcher.js)
content/modal.js (modal.js)
content/proxy.js (proxy.js)
content/capture.js (capture.js)

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

@ -4,6 +4,8 @@
DIRS += ["components"]
JS_PREFERENCE_FILES += ["prefs.js"]
JAR_MANIFESTS += ["jar.mn"]
MARIONETTE_UNIT_MANIFESTS += ["harness/marionette_harness/tests/unit/unit-tests.ini"]
MARIONETTE_WEBAPI_MANIFESTS += ["harness/marionette_harness/tests/webapi-tests.ini"]

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

@ -0,0 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// Whether or not Marionette is enabled.
pref("marionette.enabled", false);
// Port to start Marionette server on.
pref("marionette.port", 2828);
// Forces client connections to come from a loopback device.
pref("marionette.forcelocal", true);
// Marionette logging verbosity. Allowed values are "fatal", "error",
// "warn", "info", "config", "debug", and "trace".
pref("marionette.log.level", "info");
// Sets preferences recommended when using Firefox in automation with
// Marionette.
pref("marionette.prefs.recommended", true);

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

@ -4,141 +4,585 @@
"use strict";
var {Constructor: CC, classes: Cc, interfaces: Ci, utils: Cu} = Components;
const {Constructor: CC, classes: Cc, interfaces: Ci, utils: Cu} = Components;
var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader);
const loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader);
const ServerSocket = CC("@mozilla.org/network/server-socket;1", "nsIServerSocket", "initSpecialConnection");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("chrome://marionette/content/dispatcher.js");
Cu.import("chrome://marionette/content/assert.js");
Cu.import("chrome://marionette/content/driver.js");
Cu.import("chrome://marionette/content/element.js");
Cu.import("chrome://marionette/content/simpletest.js");
Cu.import("chrome://marionette/content/error.js");
Cu.import("chrome://marionette/content/message.js");
// Bug 1083711: Load transport.js as an SDK module instead of subscript
loader.loadSubScript("resource://devtools/shared/transport/transport.js");
const logger = Log.repository.getLogger("Marionette");
this.EXPORTED_SYMBOLS = ["MarionetteServer"];
this.EXPORTED_SYMBOLS = ["server"];
this.server = {};
const CONTENT_LISTENER_PREF = "marionette.contentListener";
const MANAGE_OFFLINE_STATUS_PREF = "network.gonk.manage-offline-status";
const PROTOCOL_VERSION = 3;
const PREF_CONTENT_LISTENER = "marionette.contentListener";
const PREF_RECOMMENDED = "marionette.prefs.recommended";
// Marionette sets preferences recommended for automation when it starts,
// unless |marionette.prefs.recommended| has been set to false.
// Where noted, some prefs should also be set in the profile passed to
// Marionette to prevent them from affecting startup, since some of these
// are checked before Marionette initialises.
const RECOMMENDED_PREFS = new Map([
// Disable automatic downloading of new releases.
//
// This should also be set in the profile prior to starting Firefox,
// as it is picked up at runtime.
["app.update.auto", false],
// Disable automatically upgrading Firefox.
//
// This should also be set in the profile prior to starting Firefox,
// as it is picked up at runtime.
["app.update.enabled", false],
// Increase the APZ content response timeout in tests to 1 minute.
// This is to accommodate the fact that test environments tends to be
// slower than production environments (with the b2g emulator being
// the slowest of them all), resulting in the production timeout value
// sometimes being exceeded and causing false-positive test failures.
//
// (bug 1176798, bug 1177018, bug 1210465)
["apz.content_response_timeout", 60000],
// Indicate that the download panel has been shown once so that
// whichever download test runs first doesn't show the popup
// inconsistently.
["browser.download.panel.shown", true],
// Do not show the EULA notification.
//
// This should also be set in the profile prior to starting Firefox,
// as it is picked up at runtime.
["browser.EULA.override", true],
// Turn off about:newtab and make use of about:blank instead for new
// opened tabs.
//
// This should also be set in the profile prior to starting Firefox,
// as it is picked up at runtime.
["browser.newtabpage.enabled", false],
// Assume the about:newtab page's intro panels have been shown to not
// depend on which test runs first and happens to open about:newtab
["browser.newtabpage.introShown", true],
// Never start the browser in offline mode
//
// This should also be set in the profile prior to starting Firefox,
// as it is picked up at runtime.
["browser.offline", false],
// Background thumbnails in particular cause grief, and disabling
// thumbnails in general cannot hurt
["browser.pagethumbnails.capturing_disabled", true],
// Avoid performing Reader Mode intros during tests
["browser.reader.detectedFirstArticle", true],
// Disable safebrowsing components.
//
// These should also be set in the profile prior to starting Firefox,
// as it is picked up at runtime.
["browser.safebrowsing.blockedURIs.enabled", false],
["browser.safebrowsing.downloads.enabled", false],
["browser.safebrowsing.enabled", false],
["browser.safebrowsing.forbiddenURIs.enabled", false],
["browser.safebrowsing.malware.enabled", false],
["browser.safebrowsing.phishing.enabled", false],
// Disable updates to search engines.
//
// Should be set in profile.
["browser.search.update", false],
// Do not restore the last open set of tabs if the browser has crashed
["browser.sessionstore.resume_from_crash", false],
// Don't check for the default web browser during startup.
//
// These should also be set in the profile prior to starting Firefox,
// as it is picked up at runtime.
["browser.shell.checkDefaultBrowser", false],
// Start with a blank page (about:blank)
["browser.startup.page", 0],
// Disable tab animation
["browser.tabs.animate", false],
// Do not allow background tabs to be zombified, otherwise for tests
// that open additional tabs, the test harness tab itself might get
// unloaded
["browser.tabs.disableBackgroundZombification", false],
// Do not warn when closing all other open tabs
["browser.tabs.warnOnCloseOtherTabs", false],
// Do not warn when multiple tabs will be opened
["browser.tabs.warnOnOpen", false],
// Disable first run splash page on Windows 10
["browser.usedOnWindows10.introURL", ""],
// Disable the UI tour.
//
// Should be set in profile.
["browser.uitour.enabled", false],
// Do not show datareporting policy notifications which can
// interfere with tests
["datareporting.healthreport.about.reportUrl", "http://%(server)s/dummy/abouthealthreport/"],
["datareporting.healthreport.documentServerURI", "http://%(server)s/dummy/healthreport/"],
["datareporting.healthreport.logging.consoleEnabled", false],
["datareporting.healthreport.service.enabled", false],
["datareporting.healthreport.service.firstRun", false],
["datareporting.healthreport.uploadEnabled", false],
["datareporting.policy.dataSubmissionEnabled", false],
["datareporting.policy.dataSubmissionPolicyAccepted", false],
["datareporting.policy.dataSubmissionPolicyBypassNotification", true],
// Disable popup-blocker
["dom.disable_open_during_load", false],
// Disable the ProcessHangMonitor
["dom.ipc.reportProcessHangs", false],
// Disable slow script dialogues
["dom.max_chrome_script_run_time", 0],
["dom.max_script_run_time", 0],
// Only load extensions from the application and user profile
// AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
//
// Should be set in profile.
["extensions.autoDisableScopes", 0],
["extensions.enabledScopes", 5],
// Do not block add-ons for e10s
["extensions.e10sBlocksEnabling", false],
// Disable metadata caching for installed add-ons by default
["extensions.getAddons.cache.enabled", false],
// Disable intalling any distribution extensions or add-ons.
// Should be set in profile.
["extensions.installDistroAddons", false],
["extensions.showMismatchUI", false],
// Turn off extension updates so they do not bother tests
["extensions.update.enabled", false],
["extensions.update.notifyUser", false],
// Make sure opening about:addons will not hit the network
["extensions.webservice.discoverURL", "http://%(server)s/dummy/discoveryURL"],
// Allow the application to have focus even it runs in the background
["focusmanager.testmode", true],
// Disable useragent updates
["general.useragent.updates.enabled", false],
// Always use network provider for geolocation tests so we bypass the
// macOS dialog raised by the corelocation provider
["geo.provider.testing", true],
// Do not scan Wifi
["geo.wifi.scan", false],
// No hang monitor
["hangmonitor.timeout", 0],
// Show chrome errors and warnings in the error console
["javascript.options.showInConsole", true],
// Make sure the disk cache doesn't get auto disabled
["network.http.bypass-cachelock-threshold", 200000],
// Do not prompt for temporary redirects
["network.http.prompt-temp-redirect", false],
// Disable speculative connections so they are not reported as leaking
// when they are hanging around
["network.http.speculative-parallel-limit", 0],
// Do not automatically switch between offline and online
["network.manage-offline-status", false],
// Make sure SNTP requests do not hit the network
["network.sntp.pools", "%(server)s"],
// Local documents have access to all other local documents,
// including directory listings
["security.fileuri.strict_origin_policy", false],
// Tests do not wait for the notification button security delay
["security.notification_enable_delay", 0],
// Ensure blocklist updates do not hit the network
["services.settings.server", "http://%(server)s/dummy/blocklist/"],
// Do not automatically fill sign-in forms with known usernames and
// passwords
["signon.autofillForms", false],
// Disable password capture, so that tests that include forms are not
// influenced by the presence of the persistent doorhanger notification
["signon.rememberSignons", false],
// Disable first-run welcome page
["startup.homepage_welcome_url", "about:blank"],
["startup.homepage_welcome_url.additional", ""],
// Prevent starting into safe mode after application crashes
["toolkit.startup.max_resumed_crashes", -1],
]);
/**
* Bootstraps Marionette and handles incoming client connections.
*
* Once started, it opens a TCP socket sporting the debugger transport
* protocol on the provided port. For every new client a Dispatcher is
* created.
*
* @param {number} port
* Port for server to listen to.
* @param {boolean} forceLocal
* Listen only to connections from loopback if true. If false,
* accept all connections.
* Starting the Marionette server will open a TCP socket sporting the
* debugger transport interface on the provided |port|. For every new
* connection, a |server.TCPConnection| is created.
*/
this.MarionetteServer = function (port, forceLocal) {
this.port = port;
this.forceLocal = forceLocal;
this.conns = {};
this.nextConnId = 0;
this.alive = false;
this._acceptConnections = false;
server.TCPListener = class {
/**
* @param {number} port
* Port for server to listen to.
* @param {boolean=} forceLocal
* Listen only to connections from loopback if true (default).
* When false, accept all connections.
*/
constructor (port, forceLocal = true) {
this.port = port;
this.forceLocal = forceLocal;
this.conns = new Set();
this.nextConnID = 0;
this.alive = false;
this._acceptConnections = false;
this.alteredPrefs = new Set();
}
/**
* Function produces a GeckoDriver.
*
* Determines application nameto initialise the driver with.
*
* @return {GeckoDriver}
* A driver instance.
*/
driverFactory () {
Preferences.set(PREF_CONTENT_LISTENER, false);
return new GeckoDriver(Services.appinfo.name, this);
}
set acceptConnections (value) {
if (!value) {
logger.info("New connections will no longer be accepted");
} else {
logger.info("New connections are accepted again");
}
this._acceptConnections = value;
}
start () {
if (this.alive) {
return;
}
if (Preferences.get(PREF_RECOMMENDED)) {
// set recommended prefs if they are not already user-defined
for (let [k, v] of RECOMMENDED_PREFS) {
if (!Preferences.isSet(k)) {
logger.debug(`Setting recommended pref ${k} to ${v}`);
Preferences.set(k, v);
this.alteredPrefs.add(k);
}
}
}
let flags = Ci.nsIServerSocket.KeepWhenOffline;
if (this.forceLocal) {
flags |= Ci.nsIServerSocket.LoopbackOnly;
}
this.listener = new ServerSocket(this.port, flags, 1);
this.listener.asyncListen(this);
this.alive = true;
this._acceptConnections = true;
}
stop () {
if (!this.alive) {
return;
}
for (let k of this.alteredPrefs) {
logger.debug(`Resetting recommended pref ${k}`);
Preferences.reset(k);
}
this.closeListener();
this.alteredPrefs.clear();
this.alive = false;
this._acceptConnections = false;
}
closeListener () {
this.listener.close();
this.listener = null;
}
onSocketAccepted (serverSocket, clientSocket) {
if (!this._acceptConnections) {
logger.warn("New connections are currently not accepted");
return;
}
let input = clientSocket.openInputStream(0, 0, 0);
let output = clientSocket.openOutputStream(0, 0, 0);
let transport = new DebuggerTransport(input, output);
let conn = new server.TCPConnection(
this.nextConnID++, transport, this.driverFactory.bind(this));
conn.onclose = this.onConnectionClosed.bind(this);
this.conns.add(conn);
logger.debug(`Accepted connection ${conn.id} from ${clientSocket.host}:${clientSocket.port}`);
conn.sayHello();
transport.ready();
}
onConnectionClosed (conn) {
logger.debug(`Closed connection ${conn.id}`);
this.conns.delete(conn);
}
};
/**
* Function produces a GeckoDriver.
* Marionette client connection.
*
* Determines application nameto initialise the driver with.
* Dispatches packets received to their correct service destinations
* and sends back the service endpoint's return values.
*
* @return {GeckoDriver}
* A driver instance.
* @param {number} connID
* Unique identifier of the connection this dispatcher should handle.
* @param {DebuggerTransport} transport
* Debugger transport connection to the client.
* @param {function(): GeckoDriver} driverFactory
* Factory function that produces a |GeckoDriver|.
*/
MarionetteServer.prototype.driverFactory = function() {
let appName = isMulet() ? "B2G" : Services.appinfo.name;
let bypassOffline = false;
server.TCPConnection = class {
constructor (connID, transport, driverFactory) {
this.id = connID;
this.conn = transport;
Preferences.set(CONTENT_LISTENER_PREF, false);
// transport hooks are TCPConnection#onPacket
// and TCPConnection#onClosed
this.conn.hooks = this;
if (bypassOffline) {
logger.debug("Bypassing offline status");
Preferences.set(MANAGE_OFFLINE_STATUS_PREF, false);
Services.io.manageOfflineStatus = false;
Services.io.offline = false;
// callback for when connection is closed
this.onclose = null;
// last received/sent message ID
this.lastID = 0;
this.driver = driverFactory();
// lookup of commands sent by server to client by message ID
this.commands_ = new Map();
}
return new GeckoDriver(appName, this);
};
MarionetteServer.prototype.__defineSetter__("acceptConnections", function (value) {
if (!value) {
logger.info("New connections will no longer be accepted");
} else {
logger.info("New connections are accepted again");
/**
* Debugger transport callback that cleans up
* after a connection is closed.
*/
onClosed (reason) {
this.driver.deleteSession();
if (this.onclose) {
this.onclose(this);
}
}
this._acceptConnections = value;
});
/**
* Callback that receives data packets from the client.
*
* If the message is a Response, we look up the command previously
* issued to the client and run its callback, if any. In case of
* a Command, the corresponding is executed.
*
* @param {Array.<number, number, ?, ?>} data
* A four element array where the elements, in sequence, signifies
* message type, message ID, method name or error, and parameters
* or result.
*/
onPacket (data) {
let msg = Message.fromMsg(data);
msg.origin = MessageOrigin.Client;
this.log_(msg);
MarionetteServer.prototype.start = function() {
if (this.alive) {
return;
}
let flags = Ci.nsIServerSocket.KeepWhenOffline;
if (this.forceLocal) {
flags |= Ci.nsIServerSocket.LoopbackOnly;
}
this.listener = new ServerSocket(this.port, flags, 1);
this.listener.asyncListen(this);
this.alive = true;
this._acceptConnections = true;
};
MarionetteServer.prototype.stop = function() {
if (!this.alive) {
return;
}
this.closeListener();
this.alive = false;
this._acceptConnections = false;
};
MarionetteServer.prototype.closeListener = function() {
this.listener.close();
this.listener = null;
};
MarionetteServer.prototype.onSocketAccepted = function (
serverSocket, clientSocket) {
if (!this._acceptConnections) {
logger.warn("New connections are currently not accepted");
return;
if (msg instanceof Response) {
let cmd = this.commands_.get(msg.id);
this.commands_.delete(msg.id);
cmd.onresponse(msg);
} else if (msg instanceof Command) {
this.lastID = msg.id;
this.execute(msg);
}
}
let input = clientSocket.openInputStream(0, 0, 0);
let output = clientSocket.openOutputStream(0, 0, 0);
let transport = new DebuggerTransport(input, output);
let connId = "conn" + this.nextConnId++;
/**
* Executes a WebDriver command and sends back a response when it has
* finished executing.
*
* Commands implemented in GeckoDriver and registered in its
* {@code GeckoDriver.commands} attribute. The return values from
* commands are expected to be Promises. If the resolved value of said
* promise is not an object, the response body will be wrapped in
* an object under a "value" field.
*
* If the command implementation sends the response itself by calling
* {@code resp.send()}, the response is guaranteed to not be sent twice.
*
* Errors thrown in commands are marshaled and sent back, and if they
* are not WebDriverError instances, they are additionally propagated
* and reported to {@code Components.utils.reportError}.
*
* @param {Command} cmd
* The requested command to execute.
*/
execute (cmd) {
let resp = new Response(cmd.id, this.send.bind(this));
let sendResponse = () => resp.sendConditionally(resp => !resp.sent);
let sendError = resp.sendError.bind(resp);
let dispatcher = new Dispatcher(connId, transport, this.driverFactory.bind(this));
dispatcher.onclose = this.onConnectionClosed.bind(this);
this.conns[connId] = dispatcher;
let req = Task.spawn(function*() {
let fn = this.driver.commands[cmd.name];
if (typeof fn == "undefined") {
throw new UnknownCommandError(cmd.name);
}
logger.debug(`Accepted connection ${connId} from ${clientSocket.host}:${clientSocket.port}`);
dispatcher.sayHello();
transport.ready();
if (cmd.name !== "newSession") {
assert.session(this.driver);
}
let rv = yield fn.bind(this.driver)(cmd, resp);
if (typeof rv != "undefined") {
if (typeof rv != "object") {
resp.body = {value: rv};
} else {
resp.body = rv;
}
}
}.bind(this));
req.then(sendResponse, sendError).catch(error.report);
}
sendError (err, cmdID) {
let resp = new Response(cmdID, this.send.bind(this));
resp.sendError(err);
}
/**
* When a client connects we send across a JSON Object defining the
* protocol level.
*
* This is the only message sent by Marionette that does not follow
* the regular message format.
*/
sayHello () {
let whatHo = {
applicationType: "gecko",
marionetteProtocol: PROTOCOL_VERSION,
};
this.sendRaw(whatHo);
};
/**
* Delegates message to client based on the provided {@code cmdID}.
* The message is sent over the debugger transport socket.
*
* The command ID is a unique identifier assigned to the client's request
* that is used to distinguish the asynchronous responses.
*
* Whilst responses to commands are synchronous and must be sent in the
* correct order.
*
* @param {Command,Response} msg
* The command or response to send.
*/
send (msg) {
msg.origin = MessageOrigin.Server;
if (msg instanceof Command) {
this.commands_.set(msg.id, msg);
this.sendToEmulator(msg);
} else if (msg instanceof Response) {
this.sendToClient(msg);
}
}
// Low-level methods:
/**
* Send given response to the client over the debugger transport socket.
*
* @param {Response} resp
* The response to send back to the client.
*/
sendToClient (resp) {
this.driver.responseCompleted();
this.sendMessage(resp);
};
/**
* Marshal message to the Marionette message format and send it.
*
* @param {Command,Response} msg
* The message to send.
*/
sendMessage (msg) {
this.log_(msg);
let payload = msg.toMsg();
this.sendRaw(payload);
}
/**
* Send the given payload over the debugger transport socket to the
* connected client.
*
* @param {Object} payload
* The payload to ship.
*/
sendRaw (payload) {
this.conn.send(payload);
}
log_ (msg) {
let a = (msg.origin == MessageOrigin.Client ? " -> " : " <- ");
let s = JSON.stringify(msg.toMsg());
logger.trace(this.id + a + s);
}
toString () {
return `[object server.TCPConnection ${this.id}]`;
}
};
MarionetteServer.prototype.onConnectionClosed = function (conn) {
let id = conn.connId;
delete this.conns[id];
logger.debug(`Closed connection ${id}`);
};
function isMulet() {
return Preferences.get("b2g.is_mulet", false);
}

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

@ -42,9 +42,9 @@ session.Timeouts = class {
toJSON () {
return {
"implicit": this.implicit,
"page load": this.pageLoad,
"script": this.script,
implicit: this.implicit,
pageLoad: this.pageLoad,
script: this.script,
};
}
@ -64,7 +64,7 @@ session.Timeouts = class {
t.script = ms;
break;
case "page load":
case "pageLoad":
t.pageLoad = ms;
break;

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

@ -29,21 +29,21 @@ add_test(function test_Timeouts_toString() {
add_test(function test_Timeouts_toJSON() {
let ts = new session.Timeouts();
deepEqual(ts.toJSON(), {"implicit": 0, "page load": 300000, "script": 30000});
deepEqual(ts.toJSON(), {"implicit": 0, "pageLoad": 300000, "script": 30000});
run_next_test();
});
add_test(function test_Timeouts_fromJSON() {
let json = {
"implicit": 10,
"page load": 20,
"script": 30,
implicit: 10,
pageLoad: 20,
script: 30,
};
let ts = session.Timeouts.fromJSON(json);
equal(ts.implicit, json["implicit"]);
equal(ts.pageLoad, json["page load"]);
equal(ts.script, json["script"]);
equal(ts.implicit, json.implicit);
equal(ts.pageLoad, json.pageLoad);
equal(ts.script, json.script);
run_next_test();
});

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

@ -365,3 +365,8 @@ user_pref("signon.rememberSignons", false);
// Enable form autofill feature testing.
user_pref("browser.formautofill.experimental", true);
// Disable all recommended Marionette preferences for Gecko tests.
// The prefs recommended by Marionette are typically geared towards
// consumer automation; not vendor testing.
user_pref("marionette.prefs.recommended", false);

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

@ -148,8 +148,8 @@ class FirefoxBrowser(Browser):
self.profile = FirefoxProfile(locations=locations,
preferences=preferences)
self.profile.set_preferences({"marionette.defaultPrefs.enabled": True,
"marionette.defaultPrefs.port": self.marionette_port,
self.profile.set_preferences({"marionette.enabled": True,
"marionette.port": self.marionette_port,
"dom.disable_open_during_load": False,
"network.dns.localDomains": ",".join(hostnames),
"network.proxy.type": 0,

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

@ -55,7 +55,7 @@
"dbg-server.jsm": ["DebuggerServer", "ActorPool", "OriginalLocation"],
"debug.js": ["NS_ASSERT"],
"declined.js": ["DeclinedEngines"],
"dispatcher.js": ["Dispatcher"],
"dispatcher.js": ["dispatcher"],
"distribution.js": ["DistributionCustomizer"],
"DNSTypes.jsm": ["DNS_QUERY_RESPONSE_CODES", "DNS_AUTHORITATIVE_ANSWER_CODES", "DNS_CLASS_CODES", "DNS_RECORD_TYPES"],
"doctor.js": ["Doctor"],
@ -193,7 +193,7 @@
"require.js": ["require"],
"RTCStatsReport.jsm": ["convertToRTCStatsReport"],
"scratchpad-manager.jsm": ["ScratchpadManager"],
"server.js": ["MarionetteServer"],
"server.js": ["server"],
"service.js": ["Service"],
"SharedPromptUtils.jsm": ["PromptUtils", "EnableDelayHelper"],
"ShutdownLeaksCollector.jsm": ["ContentCollector"],

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

@ -1357,13 +1357,6 @@ PuppetWidget::GetScreenDimensions()
return nsIntSize(r.width, r.height);
}
NS_IMETHODIMP
PuppetScreen::GetId(uint32_t *outId)
{
*outId = 1;
return NS_OK;
}
NS_IMETHODIMP
PuppetScreen::GetRect(int32_t *outLeft, int32_t *outTop,
int32_t *outWidth, int32_t *outHeight)
@ -1397,20 +1390,6 @@ PuppetScreen::GetColorDepth(int32_t *aColorDepth)
return NS_OK;
}
NS_IMETHODIMP
PuppetScreen::GetRotation(uint32_t* aRotation)
{
NS_WARNING("Attempt to get screen rotation through nsIScreen::GetRotation(). Nothing should know or care this in sandboxed contexts. If you want *orientation*, use hal.");
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
PuppetScreen::SetRotation(uint32_t aRotation)
{
NS_WARNING("Attempt to set screen rotation through nsIScreen::GetRotation(). Nothing should know or care this in sandboxed contexts. If you want *orientation*, use hal.");
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMPL_ISUPPORTS(PuppetScreenManager, nsIScreenManager)
PuppetScreenManager::PuppetScreenManager()
@ -1422,14 +1401,6 @@ PuppetScreenManager::~PuppetScreenManager()
{
}
NS_IMETHODIMP
PuppetScreenManager::ScreenForId(uint32_t aId,
nsIScreen** outScreen)
{
NS_IF_ADDREF(*outScreen = mOneScreen.get());
return NS_OK;
}
NS_IMETHODIMP
PuppetScreenManager::GetPrimaryScreen(nsIScreen** outScreen)
{
@ -1447,20 +1418,6 @@ PuppetScreenManager::ScreenForRect(int32_t inLeft,
return GetPrimaryScreen(outScreen);
}
NS_IMETHODIMP
PuppetScreenManager::ScreenForNativeWidget(void* aWidget,
nsIScreen** outScreen)
{
return GetPrimaryScreen(outScreen);
}
NS_IMETHODIMP
PuppetScreenManager::GetNumberOfScreens(uint32_t* aNumberOfScreens)
{
*aNumberOfScreens = 1;
return NS_OK;
}
NS_IMETHODIMP
PuppetScreenManager::GetSystemDefaultScale(float *aDefaultScale)
{

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

@ -443,13 +443,10 @@ public:
explicit PuppetScreen(void* nativeScreen);
~PuppetScreen();
NS_IMETHOD GetId(uint32_t* aId) override;
NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override;
NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override;
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override;
NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override;
NS_IMETHOD GetRotation(uint32_t* aRotation) override;
NS_IMETHOD SetRotation(uint32_t aRotation) override;
};
class PuppetScreenManager final : public nsIScreenManager

144
widget/Screen.cpp Normal file
Просмотреть файл

@ -0,0 +1,144 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Screen.h"
#include "mozilla/dom/DOMTypes.h"
namespace mozilla {
namespace widget {
NS_IMPL_ISUPPORTS(Screen, nsIScreen)
Screen::Screen(LayoutDeviceIntRect aRect, LayoutDeviceIntRect aAvailRect,
uint32_t aPixelDepth, uint32_t aColorDepth,
DesktopToLayoutDeviceScale aContentsScale,
CSSToLayoutDeviceScale aDefaultCssScale)
: mRect(aRect)
, mAvailRect(aAvailRect)
, mRectDisplayPix(RoundedToInt(aRect / aContentsScale))
, mAvailRectDisplayPix(RoundedToInt(aAvailRect / aContentsScale))
, mPixelDepth(aPixelDepth)
, mColorDepth(aColorDepth)
, mContentsScale(aContentsScale)
, mDefaultCssScale(aDefaultCssScale)
{
}
Screen::Screen(const mozilla::dom::ScreenDetails& aScreen)
: mRect(aScreen.rect())
, mAvailRect(aScreen.availRect())
, mRectDisplayPix(aScreen.rectDisplayPix())
, mAvailRectDisplayPix(aScreen.availRectDisplayPix())
, mPixelDepth(aScreen.pixelDepth())
, mColorDepth(aScreen.colorDepth())
, mContentsScale(aScreen.contentsScaleFactor())
, mDefaultCssScale(aScreen.defaultCSSScaleFactor())
{
}
Screen::Screen(const Screen& aOther)
: mRect(aOther.mRect)
, mAvailRect(aOther.mAvailRect)
, mRectDisplayPix(aOther.mRectDisplayPix)
, mAvailRectDisplayPix(aOther.mAvailRectDisplayPix)
, mPixelDepth(aOther.mPixelDepth)
, mColorDepth(aOther.mColorDepth)
, mContentsScale(aOther.mContentsScale)
, mDefaultCssScale(aOther.mDefaultCssScale)
{
}
mozilla::dom::ScreenDetails
Screen::ToScreenDetails()
{
return mozilla::dom::ScreenDetails(
mRect, mRectDisplayPix, mAvailRect, mAvailRectDisplayPix,
mPixelDepth, mColorDepth, mContentsScale, mDefaultCssScale);
}
NS_IMETHODIMP
Screen::GetRect(int32_t* aOutLeft,
int32_t* aOutTop,
int32_t* aOutWidth,
int32_t* aOutHeight)
{
*aOutLeft = mRect.x;
*aOutTop = mRect.y;
*aOutWidth = mRect.width;
*aOutHeight = mRect.height;
return NS_OK;
}
NS_IMETHODIMP
Screen::GetRectDisplayPix(int32_t* aOutLeft,
int32_t* aOutTop,
int32_t* aOutWidth,
int32_t* aOutHeight)
{
*aOutLeft = mRectDisplayPix.x;
*aOutTop = mRectDisplayPix.y;
*aOutWidth = mRectDisplayPix.width;
*aOutHeight = mRectDisplayPix.height;
return NS_OK;
}
NS_IMETHODIMP
Screen::GetAvailRect(int32_t* aOutLeft,
int32_t* aOutTop,
int32_t* aOutWidth,
int32_t* aOutHeight)
{
*aOutLeft = mAvailRect.x;
*aOutTop = mAvailRect.y;
*aOutWidth = mAvailRect.width;
*aOutHeight = mAvailRect.height;
return NS_OK;
}
NS_IMETHODIMP
Screen::GetAvailRectDisplayPix(int32_t* aOutLeft,
int32_t* aOutTop,
int32_t* aOutWidth,
int32_t* aOutHeight)
{
*aOutLeft = mAvailRectDisplayPix.x;
*aOutTop = mAvailRectDisplayPix.y;
*aOutWidth = mAvailRectDisplayPix.width;
*aOutHeight = mAvailRectDisplayPix.height;
return NS_OK;
}
NS_IMETHODIMP
Screen::GetPixelDepth(int32_t* aPixelDepth)
{
*aPixelDepth = mPixelDepth;
return NS_OK;
}
NS_IMETHODIMP
Screen::GetColorDepth(int32_t* aColorDepth)
{
*aColorDepth = mColorDepth;
return NS_OK;
}
NS_IMETHODIMP
Screen::GetContentsScaleFactor(double *aOutScale)
{
*aOutScale = mContentsScale.scale;
return NS_OK;
}
NS_IMETHODIMP
Screen::GetDefaultCSSScaleFactor(double *aOutScale)
{
*aOutScale = mDefaultCssScale.scale;
return NS_OK;
}
} // namespace widget
} // namespace mozilla

55
widget/Screen.h Normal file
Просмотреть файл

@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_widget_Screen_h
#define mozilla_widget_Screen_h
#include "nsIScreen.h"
#include "Units.h"
namespace mozilla {
namespace dom {
class ScreenDetails;
} // namespace dom
} // namespace mozilla
namespace mozilla {
namespace widget {
class Screen final : public nsIScreen
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISCREEN
Screen(LayoutDeviceIntRect aRect, LayoutDeviceIntRect aAvailRect,
uint32_t aPixelDepth, uint32_t aColorDepth,
DesktopToLayoutDeviceScale aContentsScale,
CSSToLayoutDeviceScale aDefaultCssScale);
explicit Screen(const mozilla::dom::ScreenDetails& aScreenDetails);
Screen(const Screen& aOther);
mozilla::dom::ScreenDetails ToScreenDetails();
private:
virtual ~Screen() {}
LayoutDeviceIntRect mRect;
LayoutDeviceIntRect mAvailRect;
DesktopIntRect mRectDisplayPix;
DesktopIntRect mAvailRectDisplayPix;
uint32_t mPixelDepth;
uint32_t mColorDepth;
DesktopToLayoutDeviceScale mContentsScale;
CSSToLayoutDeviceScale mDefaultCssScale;
};
} // namespace widget
} // namespace mozilla
#endif

203
widget/ScreenManager.cpp Normal file
Просмотреть файл

@ -0,0 +1,203 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ScreenManager.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/Logging.h"
#include "mozilla/StaticPtr.h"
static LazyLogModule sScreenLog("WidgetScreen");
NS_IMPL_ISUPPORTS(ScreenManager, nsIScreenManager)
namespace mozilla {
namespace widget {
ScreenManager::ScreenManager()
{
}
ScreenManager::~ScreenManager()
{
}
static StaticRefPtr<ScreenManager> sSingleton;
ScreenManager&
ScreenManager::GetSingleton()
{
if (!sSingleton) {
sSingleton = new ScreenManager();
ClearOnShutdown(&sSingleton);
}
return *sSingleton;
}
already_AddRefed<ScreenManager>
ScreenManager::GetAddRefedSingleton()
{
RefPtr<ScreenManager> sm = &GetSingleton();
return sm.forget();
}
void
ScreenManager::SetHelper(UniquePtr<Helper> aHelper)
{
mHelper = Move(aHelper);
}
void
ScreenManager::Refresh(nsTArray<RefPtr<Screen>>&& aScreens)
{
MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refresh screens"));
mScreenList = Move(aScreens);
CopyScreensToAllRemotesIfIsParent();
}
void
ScreenManager::Refresh(nsTArray<mozilla::dom::ScreenDetails>&& aScreens)
{
MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refresh screens from IPC"));
mScreenList.Clear();
for (auto& screen : aScreens) {
mScreenList.AppendElement(new Screen(screen));
}
CopyScreensToAllRemotesIfIsParent();
}
template<class Range>
void
ScreenManager::CopyScreensToRemoteRange(Range aRemoteRange)
{
AutoTArray<ScreenDetails, 4> screens;
for (auto& screen : mScreenList) {
screens.AppendElement(screen->ToScreenDetails());
}
for (auto cp : aRemoteRange) {
MOZ_LOG(sScreenLog, LogLevel::Debug, ("Send screens to [Pid %d]", cp->Pid()));
if (!cp->SendRefreshScreens(screens)) {
MOZ_LOG(sScreenLog, LogLevel::Error,
("SendRefreshScreens to [Pid %d] failed", cp->Pid()));
}
}
}
void
ScreenManager::CopyScreensToRemote(ContentParent* aContentParent)
{
MOZ_ASSERT(aContentParent);
MOZ_ASSERT(XRE_IsParentProcess());
auto range = { aContentParent };
CopyScreensToRemoteRange(range);
}
void
ScreenManager::CopyScreensToAllRemotesIfIsParent()
{
if (XRE_IsContentProcess()) {
return;
}
MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refreshing all ContentParents"));
CopyScreensToRemoteRange(ContentParent::AllProcesses(ContentParent::eLive));
}
// Returns the screen that contains the rectangle. If the rect overlaps
// multiple screens, it picks the screen with the greatest area of intersection.
//
// The coordinates are in desktop pixels.
//
NS_IMETHODIMP
ScreenManager::ScreenForRect(int32_t aX, int32_t aY,
int32_t aWidth, int32_t aHeight,
nsIScreen** aOutScreen)
{
if (mScreenList.IsEmpty()) {
MOZ_LOG(sScreenLog, LogLevel::Warning,
("No screen available. This can happen in xpcshell."));
RefPtr<Screen> ret = new Screen(LayoutDeviceIntRect(), LayoutDeviceIntRect(),
0, 0,
DesktopToLayoutDeviceScale(),
CSSToLayoutDeviceScale());
ret.forget(aOutScreen);
return NS_OK;
}
// Optimize for the common case. If the number of screens is only
// one then just return the primary screen.
if (mScreenList.Length() == 1) {
return GetPrimaryScreen(aOutScreen);
}
// which screen should we return?
Screen* which = mScreenList[0].get();
// walk the list of screens and find the one that has the most
// surface area.
uint32_t area = 0;
DesktopIntRect windowRect(aX, aY, aWidth, aHeight);
for (auto& screen : mScreenList) {
int32_t x, y, width, height;
x = y = width = height = 0;
screen->GetRectDisplayPix(&x, &y, &width, &height);
// calculate the surface area
DesktopIntRect screenRect(x, y, width, height);
screenRect.IntersectRect(screenRect, windowRect);
uint32_t tempArea = screenRect.width * screenRect.height;
if (tempArea >= area) {
which = screen.get();
area = tempArea;
}
}
RefPtr<Screen> ret = which;
ret.forget(aOutScreen);
return NS_OK;
}
// The screen with the menubar/taskbar. This shouldn't be needed very
// often.
//
NS_IMETHODIMP
ScreenManager::GetPrimaryScreen(nsIScreen** aPrimaryScreen)
{
if (mScreenList.IsEmpty()) {
MOZ_LOG(sScreenLog, LogLevel::Warning,
("No screen available. This can happen in xpcshell."));
RefPtr<Screen> ret = new Screen(LayoutDeviceIntRect(), LayoutDeviceIntRect(),
0, 0,
DesktopToLayoutDeviceScale(),
CSSToLayoutDeviceScale());
ret.forget(aPrimaryScreen);
return NS_OK;
}
RefPtr<Screen> ret = mScreenList[0];
ret.forget(aPrimaryScreen);
return NS_OK;
}
NS_IMETHODIMP
ScreenManager::GetSystemDefaultScale(float* aDefaultScale)
{
if (mHelper) {
*aDefaultScale = mHelper->GetSystemDefaultScale();
return NS_OK;
}
*aDefaultScale = 1;
return NS_OK;
}
} // namespace widget
} // namespace mozilla

65
widget/ScreenManager.h Normal file
Просмотреть файл

@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_widget_ScreenManager_h
#define mozilla_widget_ScreenManager_h
#include "nsIScreenManager.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/widget/Screen.h"
#include "nsTArray.h"
namespace mozilla {
namespace dom {
class ContentParent;
class ScreenDetails;
}
}
namespace mozilla {
namespace widget {
class ScreenManager final : public nsIScreenManager
{
public:
class Helper
{
public:
virtual float GetSystemDefaultScale() = 0;
virtual ~Helper() {};
};
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISCREENMANAGER
static ScreenManager& GetSingleton();
static already_AddRefed<ScreenManager> GetAddRefedSingleton();
void SetHelper(UniquePtr<Helper> aHelper);
void Refresh(nsTArray<RefPtr<Screen>>&& aScreens);
void Refresh(nsTArray<mozilla::dom::ScreenDetails>&& aScreens);
void CopyScreensToRemote(mozilla::dom::ContentParent* aContentParent);
private:
ScreenManager();
virtual ~ScreenManager();
template<class Range>
void CopyScreensToRemoteRange(Range aRemoteRange);
void CopyScreensToAllRemotesIfIsParent();
AutoTArray<RefPtr<Screen>, 4> mScreenList;
UniquePtr<Helper> mHelper;
};
} // namespace widget
} // namespace mozilla
#endif // mozilla_widget_ScreenManager_h

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

@ -1,213 +0,0 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Unused.h"
#include "nsContentUtils.h"
#include "nsIAppShell.h"
#include "nsScreenManagerProxy.h"
#include "nsServiceManagerUtils.h"
#include "nsWidgetsCID.h"
#include "ScreenProxy.h"
namespace mozilla {
namespace widget {
using namespace mozilla::dom;
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
ScreenProxy::ScreenProxy(nsScreenManagerProxy* aScreenManager, ScreenDetails aDetails)
: mContentsScaleFactor(0)
, mDefaultCSSScaleFactor(0)
, mScreenManager(aScreenManager)
, mId(0)
, mPixelDepth(0)
, mColorDepth(0)
, mCacheValid(false)
, mCacheWillInvalidate(false)
{
PopulateByDetails(aDetails);
}
NS_IMETHODIMP
ScreenProxy::GetId(uint32_t *outId)
{
*outId = mId;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetRect(int32_t *outLeft,
int32_t *outTop,
int32_t *outWidth,
int32_t *outHeight)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*outLeft = mRect.x;
*outTop = mRect.y;
*outWidth = mRect.width;
*outHeight = mRect.height;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetRectDisplayPix(int32_t *outLeft,
int32_t *outTop,
int32_t *outWidth,
int32_t *outHeight)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*outLeft = mRectDisplayPix.x;
*outTop = mRectDisplayPix.y;
*outWidth = mRectDisplayPix.width;
*outHeight = mRectDisplayPix.height;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetAvailRect(int32_t *outLeft,
int32_t *outTop,
int32_t *outWidth,
int32_t *outHeight)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*outLeft = mAvailRect.x;
*outTop = mAvailRect.y;
*outWidth = mAvailRect.width;
*outHeight = mAvailRect.height;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetAvailRectDisplayPix(int32_t *outLeft,
int32_t *outTop,
int32_t *outWidth,
int32_t *outHeight)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*outLeft = mAvailRectDisplayPix.x;
*outTop = mAvailRectDisplayPix.y;
*outWidth = mAvailRectDisplayPix.width;
*outHeight = mAvailRectDisplayPix.height;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetPixelDepth(int32_t *aPixelDepth)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*aPixelDepth = mPixelDepth;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetColorDepth(int32_t *aColorDepth)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*aColorDepth = mColorDepth;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetContentsScaleFactor(double* aContentsScaleFactor)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*aContentsScaleFactor = mContentsScaleFactor;
return NS_OK;
}
NS_IMETHODIMP
ScreenProxy::GetDefaultCSSScaleFactor(double* aScaleFactor)
{
if (!EnsureCacheIsValid()) {
return NS_ERROR_FAILURE;
}
*aScaleFactor = mDefaultCSSScaleFactor;
return NS_OK;
}
void
ScreenProxy::PopulateByDetails(ScreenDetails aDetails)
{
mId = aDetails.id();
mRect = nsIntRect(aDetails.rect());
mRectDisplayPix = nsIntRect(aDetails.rectDisplayPix());
mAvailRect = nsIntRect(aDetails.availRect());
mAvailRectDisplayPix = nsIntRect(aDetails.availRectDisplayPix());
mPixelDepth = aDetails.pixelDepth();
mColorDepth = aDetails.colorDepth();
mContentsScaleFactor = aDetails.contentsScaleFactor();
mDefaultCSSScaleFactor = aDetails.defaultCSSScaleFactor();
}
bool
ScreenProxy::EnsureCacheIsValid()
{
if (mCacheValid) {
return true;
}
bool success = false;
// Kick off a synchronous IPC call to the parent to get the
// most up-to-date information.
ScreenDetails details;
Unused << mScreenManager->SendScreenRefresh(mId, &details, &success);
if (!success) {
NS_WARNING("Updating a ScreenProxy in the child process failed on parent side.");
return false;
}
PopulateByDetails(details);
mCacheValid = true;
InvalidateCacheOnNextTick();
return true;
}
void
ScreenProxy::InvalidateCacheOnNextTick()
{
if (mCacheWillInvalidate) {
return;
}
mCacheWillInvalidate = true;
nsContentUtils::RunInStableState(NewRunnableMethod(this, &ScreenProxy::InvalidateCache));
}
void
ScreenProxy::InvalidateCache()
{
mCacheValid = false;
mCacheWillInvalidate = false;
}
} // namespace widget
} // namespace mozilla

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

@ -1,75 +0,0 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_widget_ScreenProxy_h
#define mozilla_widget_ScreenProxy_h
#include "nsBaseScreen.h"
#include "mozilla/dom/PScreenManagerChild.h"
#include "mozilla/dom/TabChild.h"
class nsScreenManagerProxy;
namespace mozilla {
namespace widget {
class ScreenProxy : public nsBaseScreen
{
public:
ScreenProxy(nsScreenManagerProxy* aScreenManager,
mozilla::dom::ScreenDetails aDetails);
~ScreenProxy() {};
NS_IMETHOD GetId(uint32_t* aId) override;
NS_IMETHOD GetRect(int32_t* aLeft,
int32_t* aTop,
int32_t* aWidth,
int32_t* aHeight) override;
NS_IMETHOD GetRectDisplayPix(int32_t* aLeft,
int32_t* aTop,
int32_t* aWidth,
int32_t* aHeight) override;
NS_IMETHOD GetAvailRect(int32_t* aLeft,
int32_t* aTop,
int32_t* aWidth,
int32_t* aHeight) override;
NS_IMETHOD GetAvailRectDisplayPix(int32_t* aLeft,
int32_t* aTop,
int32_t* aWidth,
int32_t* aHeight) override;
NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override;
NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override;
NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) override;
NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) override;
private:
void PopulateByDetails(mozilla::dom::ScreenDetails aDetails);
bool EnsureCacheIsValid();
void InvalidateCacheOnNextTick();
void InvalidateCache();
double mContentsScaleFactor;
double mDefaultCSSScaleFactor;
RefPtr<nsScreenManagerProxy> mScreenManager;
uint32_t mId;
int32_t mPixelDepth;
int32_t mColorDepth;
nsIntRect mRect;
nsIntRect mRectDisplayPix;
nsIntRect mAvailRect;
nsIntRect mAvailRectDisplayPix;
bool mCacheValid;
bool mCacheWillInvalidate;
};
} // namespace widget
} // namespace mozilla
#endif

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

@ -16,6 +16,8 @@
#include "ProfilerMarkers.h"
#endif
using namespace mozilla::layers;
namespace mozilla {
CompositorVsyncDispatcher::CompositorVsyncDispatcher()

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

@ -728,7 +728,8 @@ NS_IMPL_ISUPPORTS(nsAndroidBridge,
nsIAndroidBridge,
nsIObserver)
nsAndroidBridge::nsAndroidBridge()
nsAndroidBridge::nsAndroidBridge() :
mAudibleWindowsNum(0)
{
if (jni::IsAvailable()) {
RefPtr<widget::EventDispatcher> dispatcher = new widget::EventDispatcher();
@ -803,45 +804,28 @@ nsAndroidBridge::Observe(nsISupports* aSubject, const char* aTopic,
{
if (!strcmp(aTopic, "xpcom-shutdown")) {
RemoveObservers();
} else if (!strcmp(aTopic, "media-playback")) {
ALOG_BRIDGE("nsAndroidBridge::Observe, get media-playback event.");
nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
if (!wrapper) {
return NS_OK;
}
uint64_t windowId = 0;
nsresult rv = wrapper->GetData(&windowId);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else if (!strcmp(aTopic, "audio-playback")) {
ALOG_BRIDGE("nsAndroidBridge::Observe, get audio-playback event.");
nsAutoString activeStr(aData);
bool isPlaying = activeStr.EqualsLiteral("active");
UpdateAudioPlayingWindows(windowId, isPlaying);
UpdateAudioPlayingWindows(isPlaying);
}
return NS_OK;
}
void
nsAndroidBridge::UpdateAudioPlayingWindows(uint64_t aWindowId,
bool aPlaying)
nsAndroidBridge::UpdateAudioPlayingWindows(bool aPlaying)
{
// Request audio focus for the first audio playing window and abandon focus
// for the last audio playing window.
if (aPlaying && !mAudioPlayingWindows.Contains(aWindowId)) {
mAudioPlayingWindows.AppendElement(aWindowId);
if (mAudioPlayingWindows.Length() == 1) {
ALOG_BRIDGE("nsAndroidBridge, request audio focus.");
AudioFocusAgent::NotifyStartedPlaying();
}
} else if (!aPlaying && mAudioPlayingWindows.Contains(aWindowId)) {
mAudioPlayingWindows.RemoveElement(aWindowId);
if (mAudioPlayingWindows.Length() == 0) {
ALOG_BRIDGE("nsAndroidBridge, abandon audio focus.");
AudioFocusAgent::NotifyStoppedPlaying();
}
MOZ_ASSERT(mAudibleWindowsNum >= 0);
if (aPlaying && mAudibleWindowsNum++ == 0) {
ALOG_BRIDGE("nsAndroidBridge, request audio focus.");
AudioFocusAgent::NotifyStartedPlaying();
} else if (!aPlaying && --mAudibleWindowsNum == 0) {
ALOG_BRIDGE("nsAndroidBridge, abandon audio focus.");
AudioFocusAgent::NotifyStoppedPlaying();
}
}
@ -852,7 +836,7 @@ nsAndroidBridge::AddObservers()
if (obs) {
obs->AddObserver(this, "xpcom-shutdown", false);
if (jni::IsFennec()) { // No AudioFocusAgent in non-Fennec environment.
obs->AddObserver(this, "media-playback", false);
obs->AddObserver(this, "audio-playback", false);
}
}
}
@ -864,7 +848,7 @@ nsAndroidBridge::RemoveObservers()
if (obs) {
obs->RemoveObserver(this, "xpcom-shutdown");
if (jni::IsFennec()) { // No AudioFocusAgent in non-Fennec environment.
obs->RemoveObserver(this, "media-playback");
obs->RemoveObserver(this, "audio-playback");
}
}
}

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