widget/windows/winrt/APZController.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "APZController.h"
     6 #include "base/message_loop.h"
     7 #include "mozilla/layers/GeckoContentController.h"
     8 #include "nsThreadUtils.h"
     9 #include "MetroUtils.h"
    10 #include "nsPrintfCString.h"
    11 #include "nsIWidgetListener.h"
    12 #include "mozilla/layers/APZCCallbackHelper.h"
    13 #include "nsIDocument.h"
    14 #include "nsPresContext.h"
    15 #include "nsIDOMElement.h"
    16 #include "mozilla/dom/Element.h"
    17 #include "nsIDOMWindowUtils.h"
    18 #include "nsIInterfaceRequestorUtils.h"
    19 #include "nsLayoutUtils.h"
    20 #include "mozilla/TouchEvents.h"
    22 //#define DEBUG_CONTROLLER 1
    24 #ifdef DEBUG_CONTROLLER
    25 #include "WinUtils.h"
    26 using namespace mozilla::widget;
    27 #endif
    29 namespace mozilla {
    30 namespace widget {
    31 namespace winrt {
    33 nsRefPtr<mozilla::layers::APZCTreeManager> APZController::sAPZC;
    35 /*
    36  * Metro layout specific - test to see if a sub document is a
    37  * tab.
    38  */
    39 static bool
    40 IsTab(nsCOMPtr<nsIDocument>& aSubDocument)
    41 {
    42   nsRefPtr<nsIDocument> parent = aSubDocument->GetParentDocument();
    43   if (!parent) {
    44     NS_WARNING("huh? IsTab should always get a sub document for a parameter");
    45     return false;
    46   }
    47   return parent->IsRootDisplayDocument();
    48 }
    50 /*
    51  * Returns the sub document associated with the scroll id.
    52  */
    53 static bool
    54 GetDOMTargets(uint64_t aScrollId,
    55               nsCOMPtr<nsIDocument>& aSubDocument,
    56               nsCOMPtr<nsIContent>& aTargetContent)
    57 {
    58   // For tabs and subframes this will return the HTML sub document
    59   aTargetContent = nsLayoutUtils::FindContentFor(aScrollId);
    60   if (!aTargetContent) {
    61     return false;
    62   }
    63   nsCOMPtr<mozilla::dom::Element> domElement = do_QueryInterface(aTargetContent);
    64   if (!domElement) {
    65     return false;
    66   }
    68   aSubDocument = domElement->OwnerDoc();
    70   if (!aSubDocument) {
    71     return false;
    72   }
    74   // If the root element equals domElement, FindElementWithViewId found
    75   // a document, vs. an element within a document.
    76   if (aSubDocument->GetRootElement() == domElement && IsTab(aSubDocument)) {
    77     aTargetContent = nullptr;
    78   }
    80   return true;
    81 }
    83 class RequestContentRepaintEvent : public nsRunnable
    84 {
    85   typedef mozilla::layers::FrameMetrics FrameMetrics;
    87 public:
    88   RequestContentRepaintEvent(const FrameMetrics& aFrameMetrics,
    89                              nsIWidgetListener* aListener) :
    90     mFrameMetrics(aFrameMetrics),
    91     mWidgetListener(aListener)
    92   {
    93   }
    95   NS_IMETHOD Run() {
    96     // This must be on the gecko thread since we access the dom
    97     MOZ_ASSERT(NS_IsMainThread());
    99 #ifdef DEBUG_CONTROLLER
   100     WinUtils::Log("APZController: mScrollOffset: %f %f", mFrameMetrics.mScrollOffset.x,
   101       mFrameMetrics.mScrollOffset.y);
   102 #endif
   104     nsCOMPtr<nsIDocument> subDocument;
   105     nsCOMPtr<nsIContent> targetContent;
   106     if (!GetDOMTargets(mFrameMetrics.GetScrollId(),
   107                        subDocument, targetContent)) {
   108       return NS_OK;
   109     }
   111     // If we're dealing with a sub frame or content editable element,
   112     // call UpdateSubFrame.
   113     if (targetContent) {
   114 #ifdef DEBUG_CONTROLLER
   115       WinUtils::Log("APZController: detected subframe or content editable");
   116 #endif
   117       mozilla::layers::APZCCallbackHelper::UpdateSubFrame(targetContent, mFrameMetrics);
   118       return NS_OK;
   119     }
   121 #ifdef DEBUG_CONTROLLER
   122     WinUtils::Log("APZController: detected tab");
   123 #endif
   125     // We're dealing with a tab, call UpdateRootFrame.
   126     nsCOMPtr<nsIDOMWindowUtils> utils;
   127     nsCOMPtr<nsIDOMWindow> window = subDocument->GetDefaultView();
   128     if (window) {
   129       utils = do_GetInterface(window);
   130       if (utils) {
   131         mozilla::layers::APZCCallbackHelper::UpdateRootFrame(utils, mFrameMetrics);
   133 #ifdef DEBUG_CONTROLLER
   134         WinUtils::Log("APZController: %I64d mDisplayPortMargins: %0.2f %0.2f %0.2f %0.2f",
   135           mFrameMetrics.GetScrollId(),
   136           mFrameMetrics.GetDisplayPortMargins().left,
   137           mFrameMetrics.GetDisplayPortMargins().top,
   138           mFrameMetrics.GetDisplayPortMargins().right,
   139           mFrameMetrics.GetDisplayPortMargins().bottom);
   140 #endif
   141       }
   142     }
   143     return NS_OK;
   144   }
   145 protected:
   146   FrameMetrics mFrameMetrics;
   147   nsIWidgetListener* mWidgetListener;
   148 };
   150 void
   151 APZController::SetWidgetListener(nsIWidgetListener* aWidgetListener)
   152 {
   153   mWidgetListener = aWidgetListener;
   154 }
   156 void
   157 APZController::ContentReceivedTouch(const ScrollableLayerGuid& aGuid, bool aPreventDefault)
   158 {
   159   if (!sAPZC) {
   160     return;
   161   }
   162   sAPZC->ContentReceivedTouch(aGuid, aPreventDefault);
   163 }
   165 bool
   166 APZController::HitTestAPZC(ScreenIntPoint& aPoint)
   167 {
   168   if (!sAPZC) {
   169     return false;
   170   }
   171   return sAPZC->HitTestAPZC(aPoint);
   172 }
   174 void
   175 APZController::TransformCoordinateToGecko(const ScreenIntPoint& aPoint,
   176                                           LayoutDeviceIntPoint* aRefPointOut)
   177 {
   178   if (!sAPZC || !aRefPointOut) {
   179     return;
   180   }
   181   sAPZC->TransformCoordinateToGecko(aPoint, aRefPointOut);
   182 }
   184 nsEventStatus
   185 APZController::ReceiveInputEvent(WidgetInputEvent* aEvent,
   186                                  ScrollableLayerGuid* aOutTargetGuid)
   187 {
   188   MOZ_ASSERT(aEvent);
   190   if (!sAPZC) {
   191     return nsEventStatus_eIgnore;
   192   }
   193   return sAPZC->ReceiveInputEvent(*aEvent->AsInputEvent(), aOutTargetGuid);
   194 }
   196 // APZC sends us this request when we need to update the display port on
   197 // the scrollable frame the apzc is managing.
   198 void
   199 APZController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
   200 {
   201   if (!mWidgetListener) {
   202     NS_WARNING("Can't update display port, !mWidgetListener");
   203     return;
   204   }
   206 #ifdef DEBUG_CONTROLLER
   207   WinUtils::Log("APZController::RequestContentRepaint scrollid=%I64d",
   208     aFrameMetrics.GetScrollId());
   209 #endif
   210   nsCOMPtr<nsIRunnable> r1 = new RequestContentRepaintEvent(aFrameMetrics,
   211                                                             mWidgetListener);
   212   if (!NS_IsMainThread()) {
   213     NS_DispatchToMainThread(r1);
   214   } else {
   215     r1->Run();
   216   }
   217 }
   219 void
   220 APZController::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
   221                                        const uint32_t& aScrollGeneration)
   222 {
   223 #ifdef DEBUG_CONTROLLER
   224   WinUtils::Log("APZController::AcknowledgeScrollUpdate scrollid=%I64d gen=%lu",
   225     aScrollId, aScrollGeneration);
   226 #endif
   227   mozilla::layers::APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
   228 }
   230 void
   231 APZController::HandleDoubleTap(const CSSPoint& aPoint,
   232                                int32_t aModifiers,
   233                                const ScrollableLayerGuid& aGuid)
   234 {
   235 }
   237 void
   238 APZController::HandleSingleTap(const CSSPoint& aPoint,
   239                                int32_t aModifiers,
   240                                const ScrollableLayerGuid& aGuid)
   241 {
   242 }
   244 void
   245 APZController::HandleLongTap(const CSSPoint& aPoint,
   246                              int32_t aModifiers,
   247                              const ScrollableLayerGuid& aGuid)
   248 {
   249 }
   251 void
   252 APZController::HandleLongTapUp(const CSSPoint& aPoint,
   253                                int32_t aModifiers,
   254                                const ScrollableLayerGuid& aGuid)
   255 {
   256 }
   258 // requests that we send a mozbrowserasyncscroll domevent. not in use.
   259 void
   260 APZController::SendAsyncScrollDOMEvent(bool aIsRoot,
   261                                        const CSSRect &aContentRect,
   262                                        const CSSSize &aScrollableSize)
   263 {
   264 }
   266 void
   267 APZController::PostDelayedTask(Task* aTask, int aDelayMs)
   268 {
   269   MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
   270 }
   272 bool
   273 APZController::GetRootZoomConstraints(ZoomConstraints* aOutConstraints)
   274 {
   275   if (aOutConstraints) {
   276     // Until we support the meta-viewport tag properly allow zooming
   277     // from 1/4 to 4x by default.
   278     aOutConstraints->mAllowZoom = true;
   279     aOutConstraints->mAllowDoubleTapZoom = false;
   280     aOutConstraints->mMinZoom = CSSToScreenScale(0.25f);
   281     aOutConstraints->mMaxZoom = CSSToScreenScale(4.0f);
   282     return true;
   283   }
   284   return false;
   285 }
   287 // apzc notifications
   289 class TransformedStartEvent : public nsRunnable
   290 {
   291   NS_IMETHOD Run() {
   292     MetroUtils::FireObserver("apzc-transform-start", L"");
   293     return NS_OK;
   294   }
   295 };
   297 class TransformedEndEvent : public nsRunnable
   298 {
   299   NS_IMETHOD Run() {
   300     MetroUtils::FireObserver("apzc-transform-end", L"");
   301     return NS_OK;
   302   }
   303 };
   305 void
   306 APZController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
   307                                     APZStateChange aChange,
   308                                     int aArg)
   309 {
   310   switch (aChange) {
   311     case APZStateChange::TransformBegin:
   312     {
   313       if (NS_IsMainThread()) {
   314         MetroUtils::FireObserver("apzc-transform-begin", L"");
   315         return;
   316       }
   317       nsCOMPtr<nsIRunnable> runnable = new TransformedStartEvent();
   318       NS_DispatchToMainThread(runnable);
   319       break;
   320     }
   321     case APZStateChange::TransformEnd:
   322     {
   323       if (NS_IsMainThread()) {
   324         MetroUtils::FireObserver("apzc-transform-end", L"");
   325         return;
   326       }
   327       nsCOMPtr<nsIRunnable> runnable = new TransformedEndEvent();
   328       NS_DispatchToMainThread(runnable);
   329       break;
   330     }
   331     default:
   332     {
   333       // We don't currently care about other state changes.
   334       break;
   335     }
   336   }
   337 }
   339 } } }

mercurial