Bug 1020199 - Make sure APZ works with nested oop iframe. r=kats, r=dvander.

This commit is contained in:
Peter Van der Beken 2016-01-08 20:17:39 +01:00
parent 43d19bc9e0
commit b7324aa722
25 changed files with 1244 additions and 751 deletions

View File

@ -44,6 +44,7 @@
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/TestShellChild.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/layers/APZChild.h"
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/PCompositorChild.h"
@ -1260,6 +1261,19 @@ ContentChild::AllocPGMPServiceChild(mozilla::ipc::Transport* aTransport,
return GMPServiceChild::Create(aTransport, aOtherProcess);
}
PAPZChild*
ContentChild::AllocPAPZChild(const TabId& aTabId)
{
return APZChild::Create(aTabId);
}
bool
ContentChild::DeallocPAPZChild(PAPZChild* aActor)
{
delete aActor;
return true;
}
PCompositorChild*
ContentChild::AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)

View File

@ -144,6 +144,11 @@ public:
AllocPGMPServiceChild(mozilla::ipc::Transport* transport,
base::ProcessId otherProcess) override;
PAPZChild*
AllocPAPZChild(const TabId& aTabId) override;
bool
DeallocPAPZChild(PAPZChild* aActor) override;
PCompositorChild*
AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override;

View File

@ -83,6 +83,7 @@
#include "mozilla/ipc/TestShellParent.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/layers/PAPZParent.h"
#include "mozilla/layers/CompositorParent.h"
#include "mozilla/layers/ImageBridgeParent.h"
#include "mozilla/layers/SharedBufferManagerParent.h"
@ -2028,11 +2029,61 @@ NestedBrowserLayerIds()
}
} // namespace
/* static */
bool
ContentParent::RecvAllocateLayerTreeId(uint64_t* aId)
ContentParent::AllocateLayerTreeId(TabParent* aTabParent, uint64_t* aId)
{
return AllocateLayerTreeId(aTabParent->Manager()->AsContentParent(),
aTabParent, aTabParent->GetTabId(), aId);
}
/* static */
bool
ContentParent::AllocateLayerTreeId(ContentParent* aContent,
TabParent* aTopLevel, const TabId& aTabId,
uint64_t* aId)
{
*aId = CompositorParent::AllocateLayerTreeId();
if (!gfxPlatform::AsyncPanZoomEnabled()) {
return true;
}
if (!aContent || !aTopLevel) {
return false;
}
return CompositorParent::UpdateRemoteContentController(*aId, aContent,
aTabId, aTopLevel);
}
bool
ContentParent::RecvAllocateLayerTreeId(const ContentParentId& aCpId,
const TabId& aTabId, uint64_t* aId)
{
// Protect against spoofing by a compromised child. aCpId must either
// correspond to the process that this ContentParent represents or be a
// child of it.
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
if (ChildID() != aCpId) {
ContentParentId parent;
if (!cpm->GetParentProcessId(aCpId, &parent) ||
ChildID() != parent) {
return false;
}
}
// GetTopLevelTabParentByProcessAndTabId will make sure that aTabId
// lives in the process for aCpId.
RefPtr<ContentParent> contentParent = cpm->GetContentProcessById(aCpId);
RefPtr<TabParent> browserParent =
cpm->GetTopLevelTabParentByProcessAndTabId(aCpId, aTabId);
MOZ_ASSERT(contentParent && browserParent);
if (!AllocateLayerTreeId(contentParent, browserParent, aTabId, aId)) {
return false;
}
auto iter = NestedBrowserLayerIds().find(this);
if (iter == NestedBrowserLayerIds().end()) {
std::set<uint64_t> ids;
@ -3398,6 +3449,21 @@ ContentParent::AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
return GMPServiceParent::Create(aTransport, aOtherProcess);
}
PAPZParent*
ContentParent::AllocPAPZParent(const TabId& aTabId)
{
// The PAPZParent should just be created in the main process and then an IPDL
// constructor message sent to hook it up.
MOZ_CRASH("This shouldn't be called");
return nullptr;
}
bool
ContentParent::DeallocPAPZParent(PAPZParent* aActor)
{
return true;
}
PCompositorParent*
ContentParent::AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess)

View File

@ -506,6 +506,8 @@ public:
InfallibleTArray<FrameScriptInfo>* aFrameScripts,
nsCString* aURLToLoad) override;
static bool AllocateLayerTreeId(TabParent* aTabParent, uint64_t* aId);
protected:
void OnChannelConnected(int32_t pid) override;
@ -650,10 +652,19 @@ private:
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
static bool AllocateLayerTreeId(ContentParent* aContent,
TabParent* aTopLevel, const TabId& aTabId,
uint64_t* aId);
PGMPServiceParent*
AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override;
PAPZParent*
AllocPAPZParent(const TabId& aTabId) override;
bool
DeallocPAPZParent(PAPZParent* aActor) override;
PCompositorParent*
AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
base::ProcessId aOtherProcess) override;
@ -1004,7 +1015,9 @@ private:
virtual void ProcessingError(Result aCode, const char* aMsgName) override;
virtual bool RecvAllocateLayerTreeId(uint64_t* aId) override;
virtual bool RecvAllocateLayerTreeId(const ContentParentId& aCpId,
const TabId& aTabId,
uint64_t* aId) override;
virtual bool RecvDeallocateLayerTreeId(const uint64_t& aId) override;

View File

@ -56,13 +56,9 @@ using class mozilla::WidgetPluginEvent from "ipc/nsGUIEventIPC.h";
using struct mozilla::dom::RemoteDOMEvent from "mozilla/dom/TabMessageUtils.h";
using mozilla::dom::ScreenOrientationInternal from "mozilla/dom/ScreenOrientation.h";
using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
using mozilla::CSSPoint from "Units.h";
using mozilla::CSSToScreenScale from "Units.h";
using mozilla::CommandInt from "mozilla/EventForwards.h";
using mozilla::Modifiers from "mozilla/EventForwards.h";
using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.h";
using mozilla::WritingMode from "mozilla/WritingModes.h";
using mozilla::layers::AsyncDragMetrics from "mozilla/layers/AsyncDragMetrics.h";
using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
using nsIWidget::TouchPointerState from "nsIWidget.h";
using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
@ -417,43 +413,6 @@ parent:
nsString aName, nsString aFeatures)
returns (bool windowOpened);
/**
* Instructs the TabParent to forward a request to zoom to a rect given in
* CSS pixels. This rect is relative to the document.
*/
async ZoomToRect(uint32_t aPresShellId, ViewID aViewId, CSSRect aRect, uint32_t aFlags);
/**
* We know for sure that content has either preventDefaulted or not
* preventDefaulted. This applies to an entire batch of touch events. It is
* expected that, if there are any DOM touch listeners, touch events will be
* batched and only processed for panning and zooming if content does not
* preventDefault.
*/
async ContentReceivedInputBlock(ScrollableLayerGuid aGuid, uint64_t aInputBlockId, bool aPreventDefault);
/**
* Notifies the APZ code of the results of the gecko hit-test for a
* particular input block. Each target corresponds to one touch point in the
* touch event.
*/
async SetTargetAPZC(uint64_t aInputBlockId, ScrollableLayerGuid[] aTargets);
/**
* Notifies the APZ code of the allowed touch-behaviours for a particular
* input block. Each item in the aFlags array corresponds to one touch point
* in the touch event.
*/
async SetAllowedTouchBehavior(uint64_t aInputBlockId, TouchBehaviorFlags[] aFlags);
/**
* Updates the zoom constraints for a scrollable frame in this tab.
* The zoom controller code lives on the parent side and so this allows it to
* have up-to-date zoom constraints.
*/
async UpdateZoomConstraints(uint32_t aPresShellId, ViewID aViewId,
MaybeZoomConstraints aConstraints);
/**
* Tells the containing widget whether the given input block results in a
* swipe. Should be called in response to a WidgetWheelEvent that has
@ -538,9 +497,6 @@ parent:
prio(high) sync DispatchMouseEvent(WidgetMouseEvent event);
prio(high) sync DispatchKeyboardEvent(WidgetKeyboardEvent event);
// Start an APZ drag on a scrollbar
async StartScrollbarDrag(AsyncDragMetrics aDragMetrics);
async InvokeDragSession(IPCDataTransfer[] transfers, uint32_t action,
nsCString visualData, uint32_t width, uint32_t height,
uint32_t stride, uint8_t format,
@ -576,20 +532,6 @@ child:
ScreenOrientationInternal orientation,
LayoutDeviceIntPoint chromeDisp) compressall;
async UpdateFrame(FrameMetrics frame);
// The following methods correspond to functions on the GeckoContentController
// interface in gfx/layers/apz/public/GeckoContentController.h. Refer to documentation
// in that file for these functions.
async RequestFlingSnap(ViewID aScrollID, CSSPoint aDestination);
async AcknowledgeScrollUpdate(ViewID aScrollId, uint32_t aScrollGeneration);
async HandleDoubleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid);
async HandleSingleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid);
async HandleLongTap(CSSPoint point, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
async NotifyAPZStateChange(ViewID aViewId, APZStateChange aChange, int aArg);
async NotifyFlushComplete();
/**
* Sending an activate message moves focus to the child.
*/
@ -661,7 +603,7 @@ child:
/**
* APZ notification for mouse scroll testing events.
*/
async MouseScrollTestEvent(ViewID aScrollId, nsString aEvent);
async MouseScrollTestEvent(uint64_t aLayersId, ViewID aScrollId, nsString aEvent);
async CompositionEvent(WidgetCompositionEvent event);

View File

@ -4,6 +4,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/. */
include protocol PAPZ;
include protocol PBackground;
include protocol PBlob;
include protocol PBluetooth;
@ -465,6 +466,7 @@ prio(normal upto urgent) sync protocol PContent
parent opens PVRManager;
child opens PBackground;
manages PAPZ;
manages PBlob;
manages PBluetooth;
manages PBrowser;
@ -575,6 +577,8 @@ child:
async PTestShell();
async PAPZ(TabId tabId);
async RegisterChrome(ChromePackage[] packages, SubstitutionMapping[] substitutions,
OverrideMapping[] overrides, nsCString locale, bool reset);
async RegisterChromeItem(ChromeRegistryItem item);
@ -993,7 +997,7 @@ parent:
async CopyFavicon(URIParams oldURI, URIParams newURI, Principal aLoadingPrincipal, bool isPrivate);
// Tell the compositor to allocate a layer tree id for nested remote mozbrowsers.
sync AllocateLayerTreeId()
sync AllocateLayerTreeId(ContentParentId cpId, TabId tabId)
returns (uint64_t id);
async DeallocateLayerTreeId(uint64_t id);

View File

@ -16,6 +16,7 @@
#include "ContentChild.h"
#include "TabParent.h"
#include "mozilla/Preferences.h"
#include "mozilla/BrowserElementParent.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/dom/workers/ServiceWorkerManager.h"
@ -28,6 +29,7 @@
#include "ipc/Nuwa.h"
#endif
#include "mozilla/ipc/FileDescriptorUtils.h"
#include "mozilla/layers/APZChild.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/APZEventState.h"
@ -37,6 +39,7 @@
#include "mozilla/layers/InputAPZContext.h"
#include "mozilla/layers/ShadowLayers.h"
#include "mozilla/layout/RenderFrameChild.h"
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/Move.h"
@ -589,6 +592,7 @@ TabChild::TabChild(nsIContentChild* aManager,
, mIPCOpen(true)
, mParentIsActive(false)
, mDidSetRealShowInfo(false)
, mAPZChild(nullptr)
{
// In the general case having the TabParent tell us if APZ is enabled or not
// doesn't really work because the TabParent itself may not have a reference
@ -602,7 +606,7 @@ TabChild::TabChild(nsIContentChild* aManager,
const nsTArray<TouchBehaviorFlags>& aFlags)
{
if (nsCOMPtr<nsITabChild> tabChild = do_QueryReferent(weakPtrThis)) {
static_cast<TabChild*>(tabChild.get())->SendSetAllowedTouchBehavior(aInputBlockId, aFlags);
static_cast<TabChild*>(tabChild.get())->SetAllowedTouchBehavior(aInputBlockId, aFlags);
}
};
@ -710,6 +714,35 @@ TabChild::Observe(nsISupports *aSubject,
return NS_OK;
}
void
TabChild::ContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId,
bool aPreventDefault) const
{
if (mAPZChild) {
mAPZChild->SendContentReceivedInputBlock(aGuid, aInputBlockId,
aPreventDefault);
}
}
void
TabChild::SetTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) const
{
if (mAPZChild) {
mAPZChild->SendSetTargetAPZC(aInputBlockId, aTargets);
}
}
void
TabChild::SetAllowedTouchBehavior(uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags>& aTargets) const
{
if (mAPZChild) {
mAPZChild->SendSetAllowedTouchBehavior(aInputBlockId, aTargets);
}
}
bool
TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
@ -722,9 +755,12 @@ TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId,
return true;
}
return SendUpdateZoomConstraints(aPresShellId,
aViewId,
aConstraints);
if (!mAPZChild) {
return false;
}
return mAPZChild->SendUpdateZoomConstraints(aPresShellId, aViewId,
aConstraints);
}
nsresult
@ -811,7 +847,7 @@ TabChild::Init()
bool aPreventDefault)
{
if (nsCOMPtr<nsITabChild> tabChild = do_QueryReferent(weakPtrThis)) {
static_cast<TabChild*>(tabChild.get())->SendContentReceivedInputBlock(aGuid, aInputBlockId, aPreventDefault);
static_cast<TabChild*>(tabChild.get())->ContentReceivedInputBlock(aGuid, aInputBlockId, aPreventDefault);
}
});
mAPZEventState = new APZEventState(mPuppetWidget, Move(callback));
@ -1633,7 +1669,7 @@ TabChild::RecvUpdateDimensions(const CSSRect& rect, const CSSSize& size,
}
bool
TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
TabChild::UpdateFrame(const FrameMetrics& aFrameMetrics)
{
return TabChildBase::UpdateFrameHandler(aFrameMetrics);
}
@ -1652,77 +1688,68 @@ TabChild::RecvSuppressDisplayport(const bool& aEnabled)
return true;
}
bool
TabChild::RecvRequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination)
void
TabChild::HandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid)
{
APZCCallbackHelper::RequestFlingSnap(aScrollId, aDestination);
return true;
TABC_LOG("Handling double tap at %s with %p %p\n",
Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
if (!mGlobal || !mTabChildGlobal) {
return;
}
// Note: there is nothing to do with the modifiers here, as we are not
// synthesizing any sort of mouse event.
CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
nsCOMPtr<nsIDocument> document = GetDocument();
CSSRect zoomToRect = CalculateRectToZoomTo(document, point);
// The double-tap can be dispatched by any scroll frame (so |aGuid| could be
// the guid of any scroll frame), but the zoom-to-rect operation must be
// performed by the root content scroll frame, so query its identifiers
// for the SendZoomToRect() call rather than using the ones from |aGuid|.
uint32_t presShellId;
ViewID viewId;
if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
document->GetDocumentElement(), &presShellId, &viewId) &&
mAPZChild) {
mAPZChild->SendZoomToRect(presShellId, viewId, zoomToRect,
DEFAULT_BEHAVIOR);
}
}
bool
TabChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration)
{
APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
return true;
}
bool
TabChild::RecvHandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid)
{
TABC_LOG("Handling double tap at %s with %p %p\n",
Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
if (!mGlobal || !mTabChildGlobal) {
return true;
}
// Note: there is nothing to do with the modifiers here, as we are not
// synthesizing any sort of mouse event.
CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
nsCOMPtr<nsIDocument> document = GetDocument();
CSSRect zoomToRect = CalculateRectToZoomTo(document, point);
// The double-tap can be dispatched by any scroll frame (so |aGuid| could be
// the guid of any scroll frame), but the zoom-to-rect operation must be
// performed by the root content scroll frame, so query its identifiers
// for the SendZoomToRect() call rather than using the ones from |aGuid|.
uint32_t presShellId;
ViewID viewId;
if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
document->GetDocumentElement(), &presShellId, &viewId)) {
SendZoomToRect(presShellId, viewId, zoomToRect, DEFAULT_BEHAVIOR);
}
return true;
}
bool
TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid)
void
TabChild::HandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
bool aCallTakeFocusForClickFromTap)
{
if (aCallTakeFocusForClickFromTap && mRemoteFrame) {
mRemoteFrame->SendTakeFocusForClickFromTap();
}
if (mGlobal && mTabChildGlobal) {
mAPZEventState->ProcessSingleTap(aPoint, aModifiers, aGuid);
}
return true;
}
bool
TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId)
void
TabChild::HandleLongTap(const CSSPoint& aPoint, const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId)
{
if (mGlobal && mTabChildGlobal) {
mAPZEventState->ProcessLongTap(GetPresShell(), aPoint, aModifiers, aGuid,
aInputBlockId);
}
return true;
}
bool
TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
const APZStateChange& aChange,
const int& aArg)
TabChild::NotifyAPZStateChange(const ViewID& aViewId,
const layers::GeckoContentController::APZStateChange& aChange,
const int& aArg)
{
mAPZEventState->ProcessAPZStateChange(GetDocument(), aViewId, aChange, aArg);
if (aChange == APZStateChange::TransformEnd) {
if (aChange == layers::GeckoContentController::APZStateChange::TransformEnd) {
// This is used by tests to determine when the APZ is done doing whatever
// it's doing. XXX generify this as needed when writing additional tests.
DispatchMessageManagerMessage(
@ -1732,11 +1759,23 @@ TabChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
return true;
}
bool
TabChild::RecvNotifyFlushComplete()
void
TabChild::StartScrollbarDrag(const layers::AsyncDragMetrics& aDragMetrics)
{
APZCCallbackHelper::NotifyFlushComplete();
return true;
if (mAPZChild) {
mAPZChild->SendStartScrollbarDrag(aDragMetrics);
}
}
void
TabChild::ZoomToRect(const uint32_t& aPresShellId,
const FrameMetrics::ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags)
{
if (mAPZChild) {
mAPZChild->SendZoomToRect(aPresShellId, aViewId, aRect, aFlags);
}
}
bool
@ -1854,8 +1893,21 @@ TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent,
}
bool
TabChild::RecvMouseScrollTestEvent(const FrameMetrics::ViewID& aScrollId, const nsString& aEvent)
TabChild::RecvMouseScrollTestEvent(const uint64_t& aLayersId,
const FrameMetrics::ViewID& aScrollId, const nsString& aEvent)
{
if (aLayersId != mLayersId) {
RefPtr<TabParent> browser = TabParent::GetTabParentFromLayersId(aLayersId);
if (!browser) {
return false;
}
NS_DispatchToMainThread(NS_NewRunnableFunction(
[aLayersId, browser, aScrollId, aEvent] () -> void {
Unused << browser->SendMouseScrollTestEvent(aLayersId, aScrollId, aEvent);
}));
return true;
}
APZCCallbackHelper::NotifyMozMouseScrollEvent(aScrollId, aEvent);
return true;
}
@ -2622,7 +2674,10 @@ TabChild::MakeHidden()
void
TabChild::UpdateHitRegion(const nsRegion& aRegion)
{
mRemoteFrame->SendUpdateHitRegion(aRegion);
mRemoteFrame->SendUpdateHitRegion(aRegion);
if (mAPZChild) {
mAPZChild->SendUpdateHitRegion(aRegion);
}
}
NS_IMETHODIMP

View File

@ -37,6 +37,7 @@
#include "mozilla/dom/ipc/IdType.h"
#include "AudioChannelService.h"
#include "PuppetWidget.h"
#include "mozilla/layers/GeckoContentController.h"
class nsICachedFileDescriptorListener;
class nsIDOMWindowUtils;
@ -47,7 +48,9 @@ class RenderFrameChild;
} // namespace layout
namespace layers {
class APZChild;
class APZEventState;
class AsyncDragMetrics;
class ImageCompositeNotification;
} // namespace layers
@ -332,39 +335,6 @@ public:
const ScreenOrientationInternal& aOrientation,
const LayoutDeviceIntPoint& aChromeDisp) override;
virtual bool
RecvUpdateFrame(const layers::FrameMetrics& aFrameMetrics) override;
virtual bool
RecvRequestFlingSnap(const ViewID& aScrollId,
const CSSPoint& aDestination) override;
virtual bool
RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration) override;
virtual bool
RecvHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid) override;
virtual bool
RecvHandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid) override;
virtual bool
RecvHandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId) override;
virtual bool RecvNotifyAPZStateChange(const ViewID& aViewId,
const APZStateChange& aChange,
const int& aArg) override;
virtual bool RecvNotifyFlushComplete() override;
virtual bool RecvActivate() override;
virtual bool RecvDeactivate() override;
@ -418,7 +388,8 @@ public:
const int32_t& aModifiers,
const bool& aPreventDefault) override;
virtual bool RecvMouseScrollTestEvent(const FrameMetrics::ViewID& aScrollId,
virtual bool RecvMouseScrollTestEvent(const uint64_t& aLayersId,
const FrameMetrics::ViewID& aScrollId,
const nsString& aEvent) override;
virtual bool RecvNativeSynthesisResponse(const uint64_t& aObserverId,
@ -622,6 +593,40 @@ public:
PRenderFrameChild* aRenderFrame,
const ShowInfo& aShowInfo);
void ContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId,
bool aPreventDefault) const;
void SetTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) const;
void HandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid);
void HandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid,
bool aCallTakeFocusForClickFromTap);
void HandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const mozilla::layers::ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId);
void SetAllowedTouchBehavior(uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags>& aFlags) const;
bool UpdateFrame(const FrameMetrics& aFrameMetrics);
bool NotifyAPZStateChange(const ViewID& aViewId,
const layers::GeckoContentController::APZStateChange& aChange,
const int& aArg);
void StartScrollbarDrag(const layers::AsyncDragMetrics& aDragMetrics);
void ZoomToRect(const uint32_t& aPresShellId,
const FrameMetrics::ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags);
void SetAPZChild(layers::APZChild* aAPZChild)
{
mAPZChild = aAPZChild;
}
protected:
virtual ~TabChild();
@ -736,6 +741,10 @@ private:
AutoTArray<bool, NUMBER_OF_AUDIO_CHANNELS> mAudioChannelsActive;
// APZChild clears this pointer from its destructor, so it shouldn't be a
// dangling pointer.
layers::APZChild* mAPZChild;
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
};

View File

@ -995,14 +995,6 @@ TabParent::UpdateDimensions(const nsIntRect& rect, const ScreenIntSize& size)
}
}
void
TabParent::UpdateFrame(const FrameMetrics& aFrameMetrics)
{
if (!mIsDestroyed) {
Unused << SendUpdateFrame(aFrameMetrics);
}
}
void
TabParent::UIResolutionChanged()
{
@ -1042,76 +1034,6 @@ TabParent::HandleAccessKey(nsTArray<uint32_t>& aCharCodes,
}
}
void
TabParent::RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination)
{
if (!mIsDestroyed) {
Unused << SendRequestFlingSnap(aScrollId, aDestination);
}
}
void
TabParent::AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration)
{
if (!mIsDestroyed) {
Unused << SendAcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
}
}
void TabParent::HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid &aGuid)
{
if (!mIsDestroyed) {
Unused << SendHandleDoubleTap(aPoint, aModifiers, aGuid);
}
}
void TabParent::HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid &aGuid)
{
if (!mIsDestroyed) {
Unused << SendHandleSingleTap(aPoint, aModifiers, aGuid);
}
}
void TabParent::HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid &aGuid,
uint64_t aInputBlockId)
{
if (!mIsDestroyed) {
Unused << SendHandleLongTap(aPoint, aModifiers, aGuid, aInputBlockId);
}
}
void TabParent::NotifyAPZStateChange(ViewID aViewId,
APZStateChange aChange,
int aArg)
{
if (!mIsDestroyed) {
Unused << SendNotifyAPZStateChange(aViewId, aChange, aArg);
}
}
void
TabParent::NotifyMouseScrollTestEvent(const ViewID& aScrollId, const nsString& aEvent)
{
if (!mIsDestroyed) {
Unused << SendMouseScrollTestEvent(aScrollId, aEvent);
}
}
void
TabParent::NotifyFlushComplete()
{
if (!mIsDestroyed) {
Unused << SendNotifyFlushComplete();
}
}
void
TabParent::Activate()
{
@ -1400,33 +1322,6 @@ CSSPoint TabParent::AdjustTapToChildWidget(const CSSPoint& aPoint)
return aPoint + (LayoutDevicePoint(GetChildProcessOffset()) * GetLayoutDeviceToCSSScale());
}
bool TabParent::SendHandleSingleTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid)
{
if (mIsDestroyed) {
return false;
}
return PBrowserParent::SendHandleSingleTap(AdjustTapToChildWidget(aPoint), aModifiers, aGuid);
}
bool TabParent::SendHandleLongTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId)
{
if (mIsDestroyed) {
return false;
}
return PBrowserParent::SendHandleLongTap(AdjustTapToChildWidget(aPoint), aModifiers, aGuid, aInputBlockId);
}
bool TabParent::SendHandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifiers, const ScrollableLayerGuid& aGuid)
{
if (mIsDestroyed) {
return false;
}
return PBrowserParent::SendHandleDoubleTap(AdjustTapToChildWidget(aPoint), aModifiers, aGuid);
}
bool TabParent::SendMouseWheelEvent(WidgetWheelEvent& event)
{
if (mIsDestroyed) {
@ -2796,29 +2691,6 @@ TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
return true;
}
bool
TabParent::RecvZoomToRect(const uint32_t& aPresShellId,
const ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->ZoomToRect(aPresShellId, aViewId, aRect, aFlags);
}
return true;
}
bool
TabParent::RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const MaybeZoomConstraints& aConstraints)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->UpdateZoomConstraints(aPresShellId, aViewId, aConstraints);
}
return true;
}
bool
TabParent::RecvRespondStartSwipeEvent(const uint64_t& aInputBlockId,
const bool& aStartSwipe)
@ -2829,46 +2701,6 @@ TabParent::RecvRespondStartSwipeEvent(const uint64_t& aInputBlockId,
return true;
}
bool
TabParent::RecvContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const bool& aPreventDefault)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->ContentReceivedInputBlock(aGuid, aInputBlockId, aPreventDefault);
}
return true;
}
bool
TabParent::RecvSetTargetAPZC(const uint64_t& aInputBlockId,
nsTArray<ScrollableLayerGuid>&& aTargets)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->SetTargetAPZC(aInputBlockId, aTargets);
}
return true;
}
bool
TabParent::RecvStartScrollbarDrag(const AsyncDragMetrics& aDragMetrics)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->StartScrollbarDrag(aDragMetrics);
}
return true;
}
bool
TabParent::RecvSetAllowedTouchBehavior(const uint64_t& aInputBlockId,
nsTArray<TouchBehaviorFlags>&& aFlags)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->SetAllowedTouchBehavior(aInputBlockId, aFlags);
}
return true;
}
already_AddRefed<nsILoadContext>
TabParent::GetLoadContext()
{

View File

@ -50,8 +50,6 @@ class CpowHolder;
} // namespace jsipc
namespace layers {
class AsyncDragMetrics;
struct FrameMetrics;
struct TextureFactoryIdentifier;
} // namespace layers
@ -90,7 +88,6 @@ class TabParent final : public PBrowserParent
, public nsIWebBrowserPersistable
{
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
typedef mozilla::layers::AsyncDragMetrics AsyncDragMetrics;
virtual ~TabParent();
@ -297,31 +294,9 @@ public:
virtual bool RecvDispatchFocusToTopLevelWindow() override;
virtual bool RecvZoomToRect(const uint32_t& aPresShellId,
const ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags) override;
virtual bool
RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const MaybeZoomConstraints& aConstraints) override;
virtual bool RecvRespondStartSwipeEvent(const uint64_t& aInputBlockId,
const bool& aStartSwipe) override;
virtual bool
RecvContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const bool& aPreventDefault) override;
virtual bool RecvSetTargetAPZC(const uint64_t& aInputBlockId,
nsTArray<ScrollableLayerGuid>&& aTargets) override;
virtual bool
RecvSetAllowedTouchBehavior(const uint64_t& aInputBlockId,
nsTArray<TouchBehaviorFlags>&& aTargets) override;
virtual bool
RecvDispatchWheelEvent(const mozilla::WidgetWheelEvent& aEvent) override;
@ -331,9 +306,6 @@ public:
virtual bool
RecvDispatchKeyboardEvent(const mozilla::WidgetKeyboardEvent& aEvent) override;
virtual bool
RecvStartScrollbarDrag(const AsyncDragMetrics& aDragMetrics) override;
virtual PColorPickerParent*
AllocPColorPickerParent(const nsString& aTitle,
const nsString& aInitialColor) override;
@ -365,8 +337,6 @@ public:
void UpdateDimensions(const nsIntRect& aRect, const ScreenIntSize& aSize);
void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
void UIResolutionChanged();
void ThemeChanged();
@ -375,34 +345,6 @@ public:
const bool& aIsTrusted,
const int32_t& aModifierMask);
void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination);
void AcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration);
void HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid);
void HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid);
void HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId);
void NotifyAPZStateChange(ViewID aViewId,
APZStateChange aChange,
int aArg);
void NotifyMouseScrollTestEvent(const ViewID& aScrollId,
const nsString& aEvent);
void NotifyFlushComplete();
void Activate();
void Deactivate();
@ -482,19 +424,6 @@ public:
bool SendRealTouchEvent(WidgetTouchEvent& event);
bool SendHandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid);
bool SendHandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId);
bool SendHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid);
virtual PDocumentRendererParent*
AllocPDocumentRendererParent(const nsRect& documentRect,
const gfx::Matrix& transform,

View File

@ -12,6 +12,7 @@
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
#include "mozilla/EventForwards.h" // for Modifiers
#include "nsISupportsImpl.h"
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
class Task;
@ -21,7 +22,12 @@ namespace layers {
class GeckoContentController
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GeckoContentController)
/**
* At least one class deriving from GeckoContentController needs to do
* synchronous cleanup on the main thread, so we use
* NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION.
*/
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(GeckoContentController)
/**
* Requests a paint of the given FrameMetrics |aFrameMetrics| from Gecko.
@ -88,6 +94,7 @@ public:
* controller. This method allows APZ to query the controller for such a
* region. A return value of true indicates that the controller has such a
* region, and it is returned in |aOutRegion|.
* This method needs to be called on the main thread.
* TODO: once bug 928833 is implemented, this should be removed, as
* APZ can then get the correct touch-sensitive region for each frame
* directly from the layer.
@ -148,6 +155,10 @@ public:
virtual void UpdateOverscrollOffset(const float aX,const float aY) {}
GeckoContentController() {}
virtual void ChildAdopted() {}
/**
* Needs to be called on the main thread.
*/
virtual void Destroy() {}
protected:

179
gfx/layers/ipc/APZChild.cpp Normal file
View File

@ -0,0 +1,179 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 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/layers/APZChild.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/layers/APZCCallbackHelper.h"
namespace mozilla {
namespace layers {
/**
* There are cases where we try to create the APZChild before the corresponding
* TabChild has been created, we use an observer for the "tab-child-created"
* topic to set the TabChild in the APZChild when it has been created.
*/
class TabChildCreatedObserver : public nsIObserver
{
public:
TabChildCreatedObserver(APZChild* aAPZChild, const dom::TabId& aTabId)
: mAPZChild(aAPZChild),
mTabId(aTabId)
{}
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
private:
virtual ~TabChildCreatedObserver()
{}
// TabChildCreatedObserver is owned by mAPZChild, and mAPZChild outlives its
// TabChildCreatedObserver, so the raw pointer is fine.
APZChild* mAPZChild;
dom::TabId mTabId;
};
NS_IMPL_ISUPPORTS(TabChildCreatedObserver, nsIObserver)
NS_IMETHODIMP
TabChildCreatedObserver::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
MOZ_ASSERT(strcmp(aTopic, "tab-child-created") == 0);
nsCOMPtr<nsITabChild> tabChild(do_QueryInterface(aSubject));
NS_ENSURE_TRUE(tabChild, NS_ERROR_FAILURE);
dom::TabChild* browser = static_cast<dom::TabChild*>(tabChild.get());
if (browser->GetTabId() == mTabId) {
mAPZChild->SetBrowser(browser);
}
return NS_OK;
}
APZChild*
APZChild::Create(const dom::TabId& aTabId)
{
RefPtr<dom::TabChild> browser = dom::TabChild::FindTabChild(aTabId);
nsAutoPtr<APZChild> apz(new APZChild);
if (browser) {
apz->SetBrowser(browser);
} else {
RefPtr<TabChildCreatedObserver> observer =
new TabChildCreatedObserver(apz, aTabId);
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (!os ||
NS_FAILED(os->AddObserver(observer, "tab-child-created", false))) {
return nullptr;
}
apz->SetObserver(observer);
}
return apz.forget();
}
APZChild::~APZChild()
{
if (mObserver) {
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
os->RemoveObserver(mObserver, "tab-child-created");
} else {
mBrowser->SetAPZChild(nullptr);
}
}
bool
APZChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
{
return mBrowser->UpdateFrame(aFrameMetrics);
}
bool
APZChild::RecvRequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination)
{
APZCCallbackHelper::RequestFlingSnap(aScrollId, aDestination);
return true;
}
bool
APZChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration)
{
APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
return true;
}
bool
APZChild::RecvHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid)
{
mBrowser->HandleDoubleTap(aPoint, aModifiers, aGuid);
return true;
}
bool
APZChild::RecvHandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const bool& aCallTakeFocusForClickFromTap)
{
mBrowser->HandleSingleTap(aPoint, aModifiers, aGuid,
aCallTakeFocusForClickFromTap);
return true;
}
bool
APZChild::RecvHandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId)
{
mBrowser->HandleLongTap(aPoint, aModifiers, aGuid, aInputBlockId);
return true;
}
bool
APZChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
const APZStateChange& aChange,
const int& aArg)
{
return mBrowser->NotifyAPZStateChange(aViewId, aChange, aArg);
}
bool
APZChild::RecvNotifyFlushComplete()
{
APZCCallbackHelper::NotifyFlushComplete();
return true;
}
void
APZChild::SetObserver(nsIObserver* aObserver)
{
MOZ_ASSERT(!mBrowser);
mObserver = aObserver;
}
void
APZChild::SetBrowser(dom::TabChild* aBrowser)
{
MOZ_ASSERT(!mBrowser);
if (mObserver) {
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
os->RemoveObserver(mObserver, "tab-child-created");
mObserver = nullptr;
}
mBrowser = aBrowser;
mBrowser->SetAPZChild(this);
}
} // namespace layers
} // namespace mozilla

72
gfx/layers/ipc/APZChild.h Normal file
View File

@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 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_layers_APZChild_h
#define mozilla_layers_APZChild_h
#include "mozilla/layers/PAPZChild.h"
class nsIObserver;
namespace mozilla {
namespace dom {
class TabChild;
} // namespace dom
namespace layers {
class APZChild final : public PAPZChild
{
public:
static APZChild* Create(const dom::TabId& aTabId);
~APZChild();
virtual bool RecvUpdateFrame(const FrameMetrics& frame) override;
virtual bool RecvRequestFlingSnap(const ViewID& aScrollID,
const CSSPoint& aDestination) override;
virtual bool RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration) override;
virtual bool RecvHandleDoubleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual bool RecvHandleSingleTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const bool& aCallTakeFocusForClickFromTap) override;
virtual bool RecvHandleLongTap(const CSSPoint& aPoint,
const Modifiers& aModifiers,
const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId) override;
virtual bool RecvNotifyAPZStateChange(const ViewID& aViewId,
const APZStateChange& aChange,
const int& aArg) override;
virtual bool RecvNotifyFlushComplete() override;
void SetBrowser(dom::TabChild* aBrowser);
private:
APZChild() {};
void SetObserver(nsIObserver* aObserver);
RefPtr<dom::TabChild> mBrowser;
RefPtr<nsIObserver> mObserver;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_APZChild_h

View File

@ -25,6 +25,7 @@
#include "mozilla/AutoRestore.h" // for AutoRestore
#include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown
#include "mozilla/DebugOnly.h" // for DebugOnly
#include "mozilla/dom/ContentParent.h"
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/Rect.h" // for IntSize
@ -43,7 +44,9 @@
#include "mozilla/layers/LayerManagerComposite.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/PLayerTransactionParent.h"
#include "mozilla/layers/RemoteContentController.h"
#include "mozilla/layers/ShadowLayersManager.h" // for ShadowLayersManager
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/media/MediaSystemResourceService.h" // for MediaSystemResourceService
#include "mozilla/mozalloc.h" // for operator new, etc
#include "mozilla/Telemetry.h"
@ -78,6 +81,10 @@
#include "nsScreenManagerGonk.h"
#endif
#ifdef MOZ_ANDROID_APZ
#include "AndroidBridge.h"
#endif
#include "LayerScope.h"
namespace mozilla {
@ -1654,23 +1661,57 @@ CompositorParent::RecvNotifyChildCreated(const uint64_t& child)
}
void
CompositorParent::NotifyChildCreated(const uint64_t& aChild)
CompositorParent::NotifyChildCreated(uint64_t aChild)
{
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
sIndirectLayerTrees[aChild].mParent = this;
sIndirectLayerTrees[aChild].mLayerManager = mLayerManager;
}
/* static */ bool
CompositorParent::UpdateRemoteContentController(uint64_t aLayersId,
dom::ContentParent* aContent,
const dom::TabId& aTabId,
dom::TabParent* aTopLevel)
{
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock lock(*sIndirectLayerTreesLock);
LayerTreeState& state = sIndirectLayerTrees[aLayersId];
// RemoteContentController needs to know the layers id and the top level
// TabParent, so we pass that to its constructor here and then set up the
// PAPZ protocol by calling SendPAPZConstructor (and pass in the tab id for
// the PBrowser that it corresponds to).
RefPtr<RemoteContentController> controller =
new RemoteContentController(aLayersId, aTopLevel);
if (!aContent->SendPAPZConstructor(controller, aTabId)) {
return false;
}
state.mController = controller;
return true;
}
bool
CompositorParent::RecvAdoptChild(const uint64_t& child)
{
MonitorAutoLock lock(*sIndirectLayerTreesLock);
NotifyChildCreated(child);
if (sIndirectLayerTrees[child].mLayerTree) {
sIndirectLayerTrees[child].mLayerTree->mLayerManager = mLayerManager;
RefPtr<GeckoContentController> controller;
{
MonitorAutoLock lock(*sIndirectLayerTreesLock);
NotifyChildCreated(child);
if (sIndirectLayerTrees[child].mLayerTree) {
sIndirectLayerTrees[child].mLayerTree->mLayerManager = mLayerManager;
}
if (sIndirectLayerTrees[child].mRoot) {
sIndirectLayerTrees[child].mRoot->AsLayerComposite()->SetLayerManager(mLayerManager);
}
controller = sIndirectLayerTrees[child].mController;
}
if (sIndirectLayerTrees[child].mRoot) {
sIndirectLayerTrees[child].mRoot->AsLayerComposite()->SetLayerManager(mLayerManager);
// Calling ChildAdopted on controller will acquire a lock, to avoid a
// potential deadlock between that lock and sIndirectLayerTreesLock we
// release sIndirectLayerTreesLock first before calling ChildAdopted.
if (mApzcTreeManager && controller) {
controller->ChildAdopted();
}
return true;
}

View File

@ -25,6 +25,7 @@
#include "mozilla/Monitor.h" // for Monitor
#include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/TimeStamp.h" // for TimeStamp
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/layers/GeckoContentController.h"
@ -54,6 +55,7 @@ class Compositor;
class CompositorParent;
class LayerManagerComposite;
class LayerTransactionParent;
class PAPZParent;
struct ScopedLayerTreeRegistration
{
@ -283,7 +285,7 @@ public:
static void SetShadowProperties(Layer* aLayer);
void NotifyChildCreated(const uint64_t& aChild);
void NotifyChildCreated(uint64_t aChild);
void AsyncRender();
@ -447,6 +449,20 @@ public:
void ForceComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
/**
* Creates a new RemoteContentController for aTabId. Should only be called on
* the main thread.
*
* aLayersId The layers id for the browser corresponding to aTabId.
* aContentParent The ContentParent for the process that the TabChild for
* aTabId lives in.
* aBrowserParent The toplevel TabParent for aTabId.
*/
static bool UpdateRemoteContentController(uint64_t aLayersId,
dom::ContentParent* aContentParent,
const dom::TabId& aTabId,
dom::TabParent* aBrowserParent);
protected:
// Protected destructor, to discourage deletion outside of Release():
virtual ~CompositorParent();

104
gfx/layers/ipc/PAPZ.ipdl Normal file
View File

@ -0,0 +1,104 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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/GfxMessageUtils.h";
include protocol PContent;
using mozilla::CSSPoint from "Units.h";
using CSSRect from "Units.h";
using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
using mozilla::layers::MaybeZoomConstraints from "FrameMetrics.h";
using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.h";
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
using mozilla::layers::AsyncDragMetrics from "mozilla/layers/AsyncDragMetrics.h";
using mozilla::Modifiers from "mozilla/EventForwards.h";
using class nsRegion from "nsRegion.h";
namespace mozilla {
namespace layers {
/**
* If APZ is enabled then one PAPZ will be opened per PBrowser between the
* process where the PBrowser child actor lives and the main process (the
* PBrowser parent actor doesn't necessarily live in the main process, for
* example with nested browsers). This will typically be set up when the layers
* id is allocated for the PBrowser.
*
* Opened through PContent and runs on the main thread in both parent and child.
*/
sync protocol PAPZ
{
manager PContent;
parent:
async UpdateHitRegion(nsRegion aRegion);
/**
* Instructs the TabParent to forward a request to zoom to a rect given in
* CSS pixels. This rect is relative to the document.
*/
async ZoomToRect(uint32_t aPresShellId, ViewID aViewId, CSSRect aRect, uint32_t aFlags);
/**
* We know for sure that content has either preventDefaulted or not
* preventDefaulted. This applies to an entire batch of touch events. It is
* expected that, if there are any DOM touch listeners, touch events will be
* batched and only processed for panning and zooming if content does not
* preventDefault.
*/
async ContentReceivedInputBlock(ScrollableLayerGuid aGuid, uint64_t aInputBlockId, bool aPreventDefault);
/**
* Notifies the APZ code of the results of the gecko hit-test for a
* particular input block. Each target corresponds to one touch point in the
* touch event.
*/
async SetTargetAPZC(uint64_t aInputBlockId, ScrollableLayerGuid[] aTargets);
// Start an APZ drag on a scrollbar
async StartScrollbarDrag(AsyncDragMetrics aDragMetrics);
/**
* Notifies the APZ code of the allowed touch-behaviours for a particular
* input block. Each item in the aFlags array corresponds to one touch point
* in the touch event.
*/
async SetAllowedTouchBehavior(uint64_t aInputBlockId, TouchBehaviorFlags[] aFlags);
/**
* Updates the zoom constraints for a scrollable frame in this tab.
* The zoom controller code lives on the parent side and so this allows it to
* have up-to-date zoom constraints.
*/
async UpdateZoomConstraints(uint32_t aPresShellId, ViewID aViewId,
MaybeZoomConstraints aConstraints);
child:
async UpdateFrame(FrameMetrics frame);
// The following methods correspond to functions on the GeckoContentController
// interface in gfx/layers/apz/public/GeckoContentController.h. Refer to documentation
// in that file for these functions.
async RequestFlingSnap(ViewID aScrollID, CSSPoint aDestination);
async AcknowledgeScrollUpdate(ViewID aScrollId, uint32_t aScrollGeneration);
async HandleDoubleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid);
async HandleSingleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid, bool aCallTakeFocusForClickFromTap);
async HandleLongTap(CSSPoint point, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
async NotifyAPZStateChange(ViewID aViewId, APZStateChange aChange, int aArg);
async NotifyFlushComplete();
async __delete__();
};
} // layers
} // mozilla

View File

@ -7,16 +7,18 @@
include LayersSurfaces;
include LayersMessages;
include protocol PBrowser;
include protocol PLayer;
include protocol PLayerTransaction;
include "mozilla/GfxMessageUtils.h";
include "nsRegion.h";
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
using mozilla::layers::MaybeZoomConstraints from "FrameMetrics.h";
using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
using mozilla::CrossProcessMutexHandle from "mozilla/ipc/CrossProcessMutex.h";
using mozilla::ipc::SharedMemoryBasic::Handle from "mozilla/ipc/SharedMemoryBasic.h";
using mozilla::LayoutDeviceIntPoint from "Units.h";

View File

@ -0,0 +1,384 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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/layers/RemoteContentController.h"
#include "base/message_loop.h"
#include "base/task.h"
#include "MainThreadUtils.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/APZThreadUtils.h"
#include "mozilla/layers/CompositorParent.h"
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/unused.h"
#include "Units.h"
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#endif
namespace mozilla {
namespace layers {
RemoteContentController::RemoteContentController(uint64_t aLayersId,
dom::TabParent* aBrowserParent)
: mUILoop(MessageLoop::current())
, mLayersId(aLayersId)
, mBrowserParent(aBrowserParent)
, mMutex("RemoteContentController")
{
MOZ_ASSERT(NS_IsMainThread());
}
RemoteContentController::~RemoteContentController()
{
if (mBrowserParent) {
Unused << PAPZParent::Send__delete__(this);
}
}
void
RemoteContentController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
{
MOZ_ASSERT(NS_IsMainThread());
if (CanSend()) {
Unused << SendUpdateFrame(aFrameMetrics);
}
}
void
RemoteContentController::RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::RequestFlingSnap,
aScrollId, aDestination));
return;
}
if (CanSend()) {
Unused << SendRequestFlingSnap(aScrollId, aDestination);
}
}
void
RemoteContentController::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::AcknowledgeScrollUpdate,
aScrollId, aScrollGeneration));
return;
}
if (CanSend()) {
Unused << SendAcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
}
}
void
RemoteContentController::HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::HandleDoubleTap,
aPoint, aModifiers, aGuid));
return;
}
if (CanSend()) {
Unused << SendHandleDoubleTap(aPoint, aModifiers, aGuid);
}
}
void
RemoteContentController::HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::HandleSingleTap,
aPoint, aModifiers, aGuid));
return;
}
bool callTakeFocusForClickFromTap;
layout::RenderFrameParent* frame;
if (mBrowserParent && (frame = mBrowserParent->GetRenderFrame()) &&
mLayersId == frame->GetLayersId()) {
// Avoid going over IPC and back for calling TakeFocusForClickFromTap,
// since the right RenderFrameParent is living in this process.
frame->TakeFocusForClickFromTap();
callTakeFocusForClickFromTap = false;
} else {
callTakeFocusForClickFromTap = true;
}
if (CanSend()) {
Unused << SendHandleSingleTap(aPoint, aModifiers, aGuid,
callTakeFocusForClickFromTap);
}
}
void
RemoteContentController::HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId)
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::HandleLongTap,
aPoint, aModifiers, aGuid, aInputBlockId));
return;
}
if (CanSend()) {
Unused << SendHandleLongTap(aPoint, aModifiers, aGuid, aInputBlockId);
}
}
void
RemoteContentController::PostDelayedTask(Task* aTask, int aDelayMs)
{
#ifdef MOZ_ANDROID_APZ
AndroidBridge::Bridge()->PostTaskToUiThread(aTask, aDelayMs);
#else
(MessageLoop::current() ? MessageLoop::current() : mUILoop)->
PostDelayedTask(FROM_HERE, aTask, aDelayMs);
#endif
}
bool
RemoteContentController::GetTouchSensitiveRegion(CSSRect* aOutRegion)
{
MutexAutoLock lock(mMutex);
if (mTouchSensitiveRegion.IsEmpty()) {
return false;
}
*aOutRegion = CSSRect::FromAppUnits(mTouchSensitiveRegion.GetBounds());
return true;
}
void
RemoteContentController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
APZStateChange aChange,
int aArg)
{
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::NotifyAPZStateChange,
aGuid, aChange, aArg));
return;
}
if (CanSend()) {
Unused << SendNotifyAPZStateChange(aGuid.mScrollId, aChange, aArg);
}
}
void
RemoteContentController::NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
const nsString& aEvent)
{
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::NotifyMozMouseScrollEvent,
aScrollId, aEvent));
return;
}
if (mBrowserParent) {
Unused << mBrowserParent->SendMouseScrollTestEvent(mLayersId, aScrollId, aEvent);
}
}
void
RemoteContentController::NotifyFlushComplete()
{
MOZ_ASSERT(NS_IsMainThread());
if (CanSend()) {
Unused << SendNotifyFlushComplete();
}
}
bool
RemoteContentController::RecvUpdateHitRegion(const nsRegion& aRegion)
{
MutexAutoLock lock(mMutex);
mTouchSensitiveRegion = aRegion;
return true;
}
bool
RemoteContentController::RecvZoomToRect(const uint32_t& aPresShellId,
const ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags)
{
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
apzcTreeManager->ZoomToRect(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId),
aRect, aFlags);
}
return true;
}
bool
RemoteContentController::RecvContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const bool& aPreventDefault)
{
if (aGuid.mLayersId != mLayersId) {
// Guard against bad data from hijacked child processes
NS_ERROR("Unexpected layers id in RecvContentReceivedInputBlock; dropping message...");
return false;
}
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
apzcTreeManager.get(), &APZCTreeManager::ContentReceivedInputBlock,
aInputBlockId, aPreventDefault));
}
return true;
}
bool
RemoteContentController::RecvStartScrollbarDrag(const AsyncDragMetrics& aDragMetrics)
{
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
ScrollableLayerGuid guid(mLayersId, aDragMetrics.mPresShellId,
aDragMetrics.mViewId);
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod(apzcTreeManager.get(),
&APZCTreeManager::StartScrollbarDrag,
guid, aDragMetrics));
}
return true;
}
bool
RemoteContentController::RecvSetTargetAPZC(const uint64_t& aInputBlockId,
nsTArray<ScrollableLayerGuid>&& aTargets)
{
for (size_t i = 0; i < aTargets.Length(); i++) {
if (aTargets[i].mLayersId != mLayersId) {
// Guard against bad data from hijacked child processes
NS_ERROR("Unexpected layers id in SetTargetAPZC; dropping message...");
return false;
}
}
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
// need a local var to disambiguate between the SetTargetAPZC overloads.
void (APZCTreeManager::*setTargetApzcFunc)(uint64_t, const nsTArray<ScrollableLayerGuid>&)
= &APZCTreeManager::SetTargetAPZC;
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
apzcTreeManager.get(), setTargetApzcFunc,
aInputBlockId, aTargets));
}
return true;
}
bool
RemoteContentController::RecvSetAllowedTouchBehavior(const uint64_t& aInputBlockId,
nsTArray<TouchBehaviorFlags>&& aFlags)
{
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
apzcTreeManager.get(), &APZCTreeManager::SetAllowedTouchBehavior,
aInputBlockId, Move(aFlags)));
}
return true;
}
bool
RemoteContentController::RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const MaybeZoomConstraints& aConstraints)
{
if (RefPtr<APZCTreeManager> apzcTreeManager = GetApzcTreeManager()) {
apzcTreeManager->UpdateZoomConstraints(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId),
aConstraints);
}
return true;
}
void
RemoteContentController::ActorDestroy(ActorDestroyReason aWhy)
{
{
MutexAutoLock lock(mMutex);
mApzcTreeManager = nullptr;
}
mBrowserParent = nullptr;
}
// TODO: Remove once upgraded to GCC 4.8+ on linux. Calling a static member
// function (like PAPZParent::Send__delete__) in a lambda leads to a bogus
// error: "'this' was not captured for this lambda function".
//
// (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51494)
static void
DeletePAPZParent(PAPZParent* aPAPZ)
{
Unused << PAPZParent::Send__delete__(aPAPZ);
}
void
RemoteContentController::Destroy()
{
RefPtr<RemoteContentController> controller = this;
NS_DispatchToMainThread(NS_NewRunnableFunction([controller] {
if (controller->CanSend()) {
DeletePAPZParent(controller);
}
}));
}
void
RemoteContentController::ChildAdopted()
{
// Clear the cached APZCTreeManager.
MutexAutoLock lock(mMutex);
mApzcTreeManager = nullptr;
}
already_AddRefed<APZCTreeManager>
RemoteContentController::GetApzcTreeManager()
{
// We can't get a ref to the APZCTreeManager until after the child is
// created and the static getter knows which CompositorParent is
// instantiated with this layers ID. That's why try to fetch it when
// we first need it and cache the result.
MutexAutoLock lock(mMutex);
if (!mApzcTreeManager) {
mApzcTreeManager = CompositorParent::GetAPZCTreeManager(mLayersId);
}
RefPtr<APZCTreeManager> apzcTreeManager(mApzcTreeManager);
return apzcTreeManager.forget();
}
} // namespace layers
} // namespace mozilla

View File

@ -0,0 +1,130 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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_layers_RemoteContentController_h
#define mozilla_layers_RemoteContentController_h
#include "mozilla/layers/GeckoContentController.h"
#include "mozilla/layers/PAPZParent.h"
namespace mozilla {
namespace dom {
class TabParent;
}
namespace layers {
class APZCTreeManager;
/**
* RemoteContentController uses the PAPZ protocol to implement a
* GeckoContentController for a browser living in a remote process.
* Most of the member functions can be called on any thread, exceptions are
* annotated in comments. The PAPZ protocol runs on the main thread (so all the
* Recv* member functions do too).
*/
class RemoteContentController : public GeckoContentController
, public PAPZParent
{
using GeckoContentController::APZStateChange;
public:
explicit RemoteContentController(uint64_t aLayersId,
dom::TabParent* aBrowserParent);
virtual ~RemoteContentController();
// Needs to be called on the main thread.
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override;
virtual void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination) override;
virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration) override;
virtual void HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual void HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override;
virtual void HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId) override;
virtual void PostDelayedTask(Task* aTask, int aDelayMs) override;
virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) override;
virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
APZStateChange aChange,
int aArg) override;
virtual void NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
const nsString& aEvent) override;
// Needs to be called on the main thread.
virtual void NotifyFlushComplete() override;
virtual bool RecvUpdateHitRegion(const nsRegion& aRegion) override;
virtual bool RecvZoomToRect(const uint32_t& aPresShellId,
const ViewID& aViewId,
const CSSRect& aRect,
const uint32_t& aFlags) override;
virtual bool RecvContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
const uint64_t& aInputBlockId,
const bool& aPreventDefault) override;
virtual bool RecvStartScrollbarDrag(const AsyncDragMetrics& aDragMetrics) override;
virtual bool RecvSetTargetAPZC(const uint64_t& aInputBlockId,
nsTArray<ScrollableLayerGuid>&& aTargets) override;
virtual bool RecvSetAllowedTouchBehavior(const uint64_t& aInputBlockId,
nsTArray<TouchBehaviorFlags>&& aFlags) override;
virtual bool RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
const ViewID& aViewId,
const MaybeZoomConstraints& aConstraints) override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual void Destroy() override;
virtual void ChildAdopted() override;
private:
bool CanSend()
{
MOZ_ASSERT(NS_IsMainThread());
return !!mBrowserParent;
}
already_AddRefed<APZCTreeManager> GetApzcTreeManager();
MessageLoop* mUILoop;
uint64_t mLayersId;
RefPtr<dom::TabParent> mBrowserParent;
// Mutex protecting members below accessed from multiple threads.
mozilla::Mutex mMutex;
RefPtr<APZCTreeManager> mApzcTreeManager;
nsRegion mTouchSensitiveRegion;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_RemoteContentController_h

View File

@ -5,6 +5,7 @@
#ifndef THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
#define THREADSAFEREFCOUNTINGWITHMAINTHREADDESTRUCTION_H_
#include "base/message_loop.h"
#include "MainThreadUtils.h"
#include "nsThreadUtils.h"

View File

@ -151,6 +151,7 @@ EXPORTS.mozilla.layers += [
'D3D9SurfaceImage.h',
'Effects.h',
'ImageDataSerializer.h',
'ipc/APZChild.h',
'ipc/AsyncTransactionTracker.h',
'ipc/CompositableForwarder.h',
'ipc/CompositableTransactionParent.h',
@ -167,6 +168,7 @@ EXPORTS.mozilla.layers += [
'ipc/LayerAnimationUtils.h',
'ipc/LayerTransactionChild.h',
'ipc/LayerTransactionParent.h',
'ipc/RemoteContentController.h',
'ipc/ShadowLayerChild.h',
'ipc/ShadowLayers.h',
'ipc/ShadowLayersManager.h',
@ -328,6 +330,7 @@ UNIFIED_SOURCES += [
'GLImages.cpp',
'ImageDataSerializer.cpp',
'ImageLayers.cpp',
'ipc/APZChild.cpp',
'ipc/AsyncTransactionTracker.cpp',
'ipc/CompositableTransactionParent.cpp',
'ipc/CompositorBench.cpp',
@ -342,6 +345,7 @@ UNIFIED_SOURCES += [
'ipc/LayerAnimationUtils.cpp',
'ipc/LayerTransactionChild.cpp',
'ipc/LayerTransactionParent.cpp',
'ipc/RemoteContentController.cpp',
'ipc/ShadowLayerChild.cpp',
'ipc/ShadowLayerParent.cpp',
'ipc/ShadowLayers.cpp',
@ -397,6 +401,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
IPDL_SOURCES = [
'ipc/LayersMessages.ipdlh',
'ipc/LayersSurfaces.ipdlh',
'ipc/PAPZ.ipdl',
'ipc/PCompositable.ipdl',
'ipc/PCompositor.ipdl',
'ipc/PImageBridge.ipdl',

View File

@ -32,6 +32,8 @@ parent:
async UpdateHitRegion(nsRegion aRegion);
sync TakeFocusForClickFromTap();
async __delete__();
};

View File

@ -15,6 +15,8 @@
#include "mozilla/BrowserElementParent.h"
#include "mozilla/EventForwards.h" // for Modifiers
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/APZThreadUtils.h"
@ -34,10 +36,6 @@
#include "ClientLayerManager.h"
#include "FrameLayerBuilder.h"
#ifdef MOZ_ANDROID_APZ
#include "AndroidBridge.h"
#endif
using namespace mozilla::dom;
using namespace mozilla::gfx;
using namespace mozilla::layers;
@ -88,190 +86,6 @@ GetFrom(nsFrameLoader* aFrameLoader)
return nsContentUtils::LayerManagerForDocument(doc);
}
class RemoteContentController : public GeckoContentController {
public:
explicit RemoteContentController(RenderFrameParent* aRenderFrame)
: mUILoop(MessageLoop::current())
, mRenderFrame(aRenderFrame)
{ }
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override
{
MOZ_ASSERT(NS_IsMainThread());
if (mRenderFrame) {
TabParent* browser = TabParent::GetFrom(mRenderFrame->Manager());
browser->UpdateFrame(aFrameMetrics);
}
}
virtual void RequestFlingSnap(const FrameMetrics::ViewID& aScrollId,
const mozilla::CSSPoint& aDestination) override
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::RequestFlingSnap,
aScrollId, aDestination));
return;
}
if (mRenderFrame) {
TabParent* browser = TabParent::GetFrom(mRenderFrame->Manager());
browser->RequestFlingSnap(aScrollId, aDestination);
}
}
virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
const uint32_t& aScrollGeneration) override
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::AcknowledgeScrollUpdate,
aScrollId, aScrollGeneration));
return;
}
if (mRenderFrame) {
TabParent* browser = TabParent::GetFrom(mRenderFrame->Manager());
browser->AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
}
}
virtual void HandleDoubleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::HandleDoubleTap,
aPoint, aModifiers, aGuid));
return;
}
if (mRenderFrame) {
TabParent* browser = TabParent::GetFrom(mRenderFrame->Manager());
browser->HandleDoubleTap(aPoint, aModifiers, aGuid);
}
}
virtual void HandleSingleTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid) override
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::HandleSingleTap,
aPoint, aModifiers, aGuid));
return;
}
if (mRenderFrame) {
mRenderFrame->TakeFocusForClickFromTap();
TabParent* browser = TabParent::GetFrom(mRenderFrame->Manager());
browser->HandleSingleTap(aPoint, aModifiers, aGuid);
}
}
virtual void HandleLongTap(const CSSPoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId) override
{
if (MessageLoop::current() != mUILoop) {
// We have to send this message from the "UI thread" (main
// thread).
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::HandleLongTap,
aPoint, aModifiers, aGuid, aInputBlockId));
return;
}
if (mRenderFrame) {
TabParent* browser = TabParent::GetFrom(mRenderFrame->Manager());
browser->HandleLongTap(aPoint, aModifiers, aGuid, aInputBlockId);
}
}
void ClearRenderFrame() { mRenderFrame = nullptr; }
virtual void PostDelayedTask(Task* aTask, int aDelayMs) override
{
#ifdef MOZ_ANDROID_APZ
AndroidBridge::Bridge()->PostTaskToUiThread(aTask, aDelayMs);
#else
(MessageLoop::current() ? MessageLoop::current() : mUILoop)->
PostDelayedTask(FROM_HERE, aTask, aDelayMs);
#endif
}
virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) override
{
if (mTouchSensitiveRegion.IsEmpty())
return false;
*aOutRegion = CSSRect::FromAppUnits(mTouchSensitiveRegion.GetBounds());
return true;
}
virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
APZStateChange aChange,
int aArg) override
{
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::NotifyAPZStateChange,
aGuid, aChange, aArg));
return;
}
if (mRenderFrame) {
TabParent* browser = TabParent::GetFrom(mRenderFrame->Manager());
browser->NotifyAPZStateChange(aGuid.mScrollId, aChange, aArg);
}
}
void NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId, const nsString& aEvent) override {
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this, &RemoteContentController::NotifyMozMouseScrollEvent, aScrollId, aEvent));
return;
}
if (mRenderFrame) {
TabParent* browser = TabParent::GetFrom(mRenderFrame->Manager());
browser->NotifyMouseScrollTestEvent(aScrollId, aEvent);
}
}
void NotifyFlushComplete() override {
MOZ_ASSERT(NS_IsMainThread());
if (mRenderFrame) {
TabParent* browser = TabParent::GetFrom(mRenderFrame->Manager());
browser->NotifyFlushComplete();
}
}
// Methods used by RenderFrameParent to set fields stored here.
void SetTouchSensitiveRegion(const nsRegion& aRegion)
{
mTouchSensitiveRegion = aRegion;
}
private:
MessageLoop* mUILoop;
RenderFrameParent* mRenderFrame;
nsRegion mTouchSensitiveRegion;
};
RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader,
TextureFactoryIdentifier* aTextureFactoryIdentifier,
uint64_t* aId,
@ -299,44 +113,25 @@ RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader,
*aTextureFactoryIdentifier = TextureFactoryIdentifier();
}
TabParent* browser = TabParent::GetFrom(mFrameLoader);
if (XRE_IsParentProcess()) {
// Our remote frame will push layers updates to the compositor,
// and we'll keep an indirect reference to that tree.
*aId = mLayersId = CompositorParent::AllocateLayerTreeId();
browser->Manager()->AsContentParent()->AllocateLayerTreeId(browser, aId);
mLayersId = *aId;
if (lm && lm->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
ClientLayerManager *clientManager =
static_cast<ClientLayerManager*>(lm.get());
clientManager->GetRemoteRenderer()->SendNotifyChildCreated(mLayersId);
}
if (mAsyncPanZoomEnabled) {
mContentController = new RemoteContentController(this);
CompositorParent::SetControllerForLayerTree(mLayersId, mContentController);
}
} else if (XRE_IsContentProcess()) {
ContentChild::GetSingleton()->SendAllocateLayerTreeId(aId);
ContentChild::GetSingleton()->SendAllocateLayerTreeId(browser->Manager()->ChildID(), browser->GetTabId(), aId);
mLayersId = *aId;
CompositorChild::Get()->SendNotifyChildCreated(mLayersId);
}
*aSuccess = true;
}
APZCTreeManager*
RenderFrameParent::GetApzcTreeManager()
{
// We can't get a ref to the APZCTreeManager until after the child is
// created and the static getter knows which CompositorParent is
// instantiated with this layers ID. That's why try to fetch it when
// we first need it and cache the result.
// Note: the IsParentProcess check is to deal with nested content process
// scenarios, since in those cases we can have RenderFrameParent instances
// in a child process, but the APZC machinery is not in that process. Bug
// 1020199 should fix this more comprehensively.
if (!mApzcTreeManager && mAsyncPanZoomEnabled && XRE_IsParentProcess()) {
mApzcTreeManager = CompositorParent::GetAPZCTreeManager(mLayersId);
}
return mApzcTreeManager.get();
}
RenderFrameParent::~RenderFrameParent()
{}
@ -418,9 +213,6 @@ RenderFrameParent::OwnerContentChanged(nsIContent* aContent)
static_cast<ClientLayerManager*>(lm.get());
clientManager->GetRemoteRenderer()->SendAdoptChild(mLayersId);
}
// The APZCTreeManager associated with this RenderFrameParent may have changed
// so reset it and let GetApzcTreeManager() pick it up again.
mApzcTreeManager = nullptr;
}
void
@ -432,12 +224,6 @@ RenderFrameParent::ActorDestroy(ActorDestroyReason why)
} else {
CompositorParent::DeallocateLayerTreeId(mLayersId);
}
if (mContentController) {
// Stop our content controller from requesting repaints of our
// content.
mContentController->ClearRenderFrame();
// TODO: notify the compositor?
}
}
mFrameLoader = nullptr;
@ -454,13 +240,6 @@ bool
RenderFrameParent::RecvUpdateHitRegion(const nsRegion& aRegion)
{
mTouchRegion = aRegion;
if (mContentController) {
// Tell the content controller about the touch-sensitive region, so
// that it can provide it to APZ. This is required for APZ to do
// correct hit testing for a remote 'mozpasspointerevents' iframe
// until bug 928833 is fixed.
mContentController->SetTouchSensitiveRegion(aRegion);
}
return true;
}
@ -504,98 +283,12 @@ RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder,
new (aBuilder) nsDisplayRemote(aBuilder, aFrame, this));
}
void
RenderFrameParent::ZoomToRect(uint32_t aPresShellId, ViewID aViewId,
const CSSRect& aRect,
const uint32_t aFlags)
{
if (GetApzcTreeManager()) {
GetApzcTreeManager()->ZoomToRect(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId),
aRect, aFlags);
}
}
void
RenderFrameParent::ContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId,
bool aPreventDefault)
{
if (aGuid.mLayersId != mLayersId) {
// Guard against bad data from hijacked child processes
NS_ERROR("Unexpected layers id in ContentReceivedInputBlock; dropping message...");
return;
}
if (GetApzcTreeManager()) {
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
GetApzcTreeManager(), &APZCTreeManager::ContentReceivedInputBlock,
aInputBlockId, aPreventDefault));
}
}
void
RenderFrameParent::SetTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets)
{
for (size_t i = 0; i < aTargets.Length(); i++) {
if (aTargets[i].mLayersId != mLayersId) {
// Guard against bad data from hijacked child processes
NS_ERROR("Unexpected layers id in SetTargetAPZC; dropping message...");
return;
}
}
if (GetApzcTreeManager()) {
// need a local var to disambiguate between the SetTargetAPZC overloads.
void (APZCTreeManager::*setTargetApzcFunc)(uint64_t, const nsTArray<ScrollableLayerGuid>&)
= &APZCTreeManager::SetTargetAPZC;
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
GetApzcTreeManager(), setTargetApzcFunc,
aInputBlockId, aTargets));
}
}
void
RenderFrameParent::SetAllowedTouchBehavior(uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags>& aFlags)
{
if (GetApzcTreeManager()) {
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
GetApzcTreeManager(), &APZCTreeManager::SetAllowedTouchBehavior,
aInputBlockId, aFlags));
}
}
void
RenderFrameParent::UpdateZoomConstraints(uint32_t aPresShellId,
ViewID aViewId,
const Maybe<ZoomConstraints>& aConstraints)
{
if (GetApzcTreeManager()) {
GetApzcTreeManager()->UpdateZoomConstraints(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId),
aConstraints);
}
}
bool
RenderFrameParent::HitTest(const nsRect& aRect)
{
return mTouchRegion.Contains(aRect);
}
void
RenderFrameParent::StartScrollbarDrag(const AsyncDragMetrics& aDragMetrics)
{
if (GetApzcTreeManager()) {
uint64_t layersId = GetLayersId();
ScrollableLayerGuid guid(layersId, aDragMetrics.mPresShellId,
aDragMetrics.mViewId);
APZThreadUtils::RunOnControllerThread(
NewRunnableMethod(GetApzcTreeManager(),
&APZCTreeManager::StartScrollbarDrag,
guid, aDragMetrics));
}
}
void
RenderFrameParent::GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier)
{
@ -629,6 +322,13 @@ RenderFrameParent::TakeFocusForClickFromTap()
nsIFocusManager::FLAG_NOSCROLL);
}
bool
RenderFrameParent::RecvTakeFocusForClickFromTap()
{
TakeFocusForClickFromTap();
return true;
}
} // namespace layout
} // namespace mozilla

View File

@ -33,8 +33,6 @@ struct ScrollableLayerGuid;
namespace layout {
class RemoteContentController;
class RenderFrameParent : public PRenderFrameParent
{
typedef mozilla::layers::AsyncDragMetrics AsyncDragMetrics;
@ -79,24 +77,8 @@ public:
void OwnerContentChanged(nsIContent* aContent);
void ZoomToRect(uint32_t aPresShellId, ViewID aViewId, const CSSRect& aRect, const uint32_t aFlags);
void ContentReceivedInputBlock(const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId,
bool aPreventDefault);
void SetTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets);
void SetAllowedTouchBehavior(uint64_t aInputBlockId,
const nsTArray<TouchBehaviorFlags>& aFlags);
void UpdateZoomConstraints(uint32_t aPresShellId,
ViewID aViewId,
const Maybe<ZoomConstraints>& aConstraints);
bool HitTest(const nsRect& aRect);
void StartScrollbarDrag(const AsyncDragMetrics& aDragMetrics);
void GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier);
inline uint64_t GetLayersId() { return mLayersId; }
@ -110,6 +92,8 @@ protected:
virtual bool RecvUpdateHitRegion(const nsRegion& aRegion) override;
virtual bool RecvTakeFocusForClickFromTap() override;
private:
void TriggerRepaint();
void DispatchEventForPanZoomController(const InputEvent& aEvent);
@ -123,13 +107,6 @@ private:
RefPtr<nsFrameLoader> mFrameLoader;
RefPtr<ContainerLayer> mContainer;
// When our scrolling behavior is ASYNC_PAN_ZOOM, we have a nonnull
// APZCTreeManager. It's used to manipulate the shadow layer tree
// on the compositor thread.
RefPtr<layers::APZCTreeManager> mApzcTreeManager;
RefPtr<RemoteContentController> mContentController;
layers::APZCTreeManager* GetApzcTreeManager();
// True after Destroy() has been called, which is triggered
// originally by nsFrameLoader::Destroy(). After this point, we can

View File

@ -12,7 +12,7 @@
#include "mozilla/dom/TabChild.h"
#include "mozilla/Hal.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/APZChild.h"
#include "mozilla/layers/PLayerTransactionChild.h"
#include "mozilla/Preferences.h"
#include "mozilla/TextComposition.h"
@ -512,7 +512,7 @@ PuppetWidget::SetConfirmedTargetAPZC(uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) const
{
if (mTabChild) {
mTabChild->SendSetTargetAPZC(aInputBlockId, aTargets);
mTabChild->SetTargetAPZC(aInputBlockId, aTargets);
}
}
@ -1261,7 +1261,7 @@ uint32_t PuppetWidget::GetMaxTouchPoints() const
void
PuppetWidget::StartAsyncScrollbarDrag(const AsyncDragMetrics& aDragMetrics)
{
mTabChild->SendStartScrollbarDrag(aDragMetrics);
mTabChild->StartScrollbarDrag(aDragMetrics);
}
PuppetScreen::PuppetScreen(void *nativeScreen)
@ -1434,7 +1434,7 @@ PuppetWidget::ZoomToRect(const uint32_t& aPresShellId,
return;
}
mTabChild->SendZoomToRect(aPresShellId, aViewId, aRect, aFlags);
mTabChild->ZoomToRect(aPresShellId, aViewId, aRect, aFlags);
}
} // namespace widget