LCOV - code coverage report
Current view: top level - layout/base - ZoomConstraintsClient.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 89 114 78.1 %
Date: 2017-07-14 16:53:18 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "ZoomConstraintsClient.h"
       7             : 
       8             : #include <inttypes.h>
       9             : #include "FrameMetrics.h"
      10             : #include "gfxPrefs.h"
      11             : #include "LayersLogging.h"
      12             : #include "mozilla/layers/APZCCallbackHelper.h"
      13             : #include "mozilla/Preferences.h"
      14             : #include "mozilla/PresShell.h"
      15             : #include "mozilla/dom/Event.h"
      16             : #include "nsDocument.h"
      17             : #include "nsIFrame.h"
      18             : #include "nsLayoutUtils.h"
      19             : #include "nsPoint.h"
      20             : #include "nsView.h"
      21             : #include "nsViewportInfo.h"
      22             : #include "Units.h"
      23             : #include "UnitTransforms.h"
      24             : 
      25             : #define ZCC_LOG(...)
      26             : // #define ZCC_LOG(...) printf_stderr("ZCC: " __VA_ARGS__)
      27             : 
      28         110 : NS_IMPL_ISUPPORTS(ZoomConstraintsClient, nsIDOMEventListener, nsIObserver)
      29             : 
      30           3 : static const nsLiteralString DOM_META_ADDED = NS_LITERAL_STRING("DOMMetaAdded");
      31           3 : static const nsLiteralString DOM_META_CHANGED = NS_LITERAL_STRING("DOMMetaChanged");
      32           3 : static const nsLiteralString FULLSCREEN_CHANGED = NS_LITERAL_STRING("fullscreenchange");
      33           3 : static const nsLiteralCString BEFORE_FIRST_PAINT = NS_LITERAL_CSTRING("before-first-paint");
      34           3 : static const nsLiteralCString NS_PREF_CHANGED = NS_LITERAL_CSTRING("nsPref:changed");
      35             : 
      36             : using namespace mozilla;
      37             : using namespace mozilla::layers;
      38             : 
      39           3 : ZoomConstraintsClient::ZoomConstraintsClient() :
      40             :   mDocument(nullptr),
      41           3 :   mPresShell(nullptr)
      42             : {
      43           3 : }
      44             : 
      45           2 : ZoomConstraintsClient::~ZoomConstraintsClient()
      46             : {
      47           2 : }
      48             : 
      49             : static nsIWidget*
      50           5 : GetWidget(nsIPresShell* aShell)
      51             : {
      52           5 :   if (!aShell) {
      53           0 :     return nullptr;
      54             :   }
      55           5 :   if (nsIFrame* rootFrame = aShell->GetRootFrame()) {
      56             : #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT)
      57             :     return rootFrame->GetNearestWidget();
      58             : #else
      59           1 :     if (nsView* view = rootFrame->GetView()) {
      60           1 :       return view->GetWidget();
      61             :     }
      62             : #endif
      63             :   }
      64           4 :   return nullptr;
      65             : }
      66             : 
      67             : void
      68           2 : ZoomConstraintsClient::Destroy()
      69             : {
      70           2 :   if (!(mPresShell && mDocument)) {
      71           0 :     return;
      72             :   }
      73             : 
      74             :   ZCC_LOG("Destroying %p\n", this);
      75             : 
      76           2 :   if (mEventTarget) {
      77           2 :     mEventTarget->RemoveEventListener(DOM_META_ADDED, this, false);
      78           2 :     mEventTarget->RemoveEventListener(DOM_META_CHANGED, this, false);
      79           2 :     mEventTarget->RemoveSystemEventListener(FULLSCREEN_CHANGED, this, false);
      80           2 :     mEventTarget = nullptr;
      81             :   }
      82             : 
      83           4 :   nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
      84           2 :   if (observerService) {
      85           2 :     observerService->RemoveObserver(this, BEFORE_FIRST_PAINT.Data());
      86             :   }
      87             : 
      88           2 :   Preferences::RemoveObserver(this, "browser.ui.zoom.force-user-scalable");
      89             : 
      90           2 :   if (mGuid) {
      91           0 :     if (nsIWidget* widget = GetWidget(mPresShell)) {
      92             :       ZCC_LOG("Sending null constraints in %p for { %u, %" PRIu64 " }\n",
      93             :         this, mGuid->mPresShellId, mGuid->mScrollId);
      94           0 :       widget->UpdateZoomConstraints(mGuid->mPresShellId, mGuid->mScrollId, Nothing());
      95           0 :       mGuid = Nothing();
      96             :     }
      97             :   }
      98             : 
      99           2 :   mDocument = nullptr;
     100           2 :   mPresShell = nullptr;
     101             : }
     102             : 
     103             : void
     104           3 : ZoomConstraintsClient::Init(nsIPresShell* aPresShell, nsIDocument* aDocument)
     105             : {
     106           3 :   if (!(aPresShell && aDocument)) {
     107           0 :     return;
     108             :   }
     109             : 
     110           3 :   mPresShell = aPresShell;
     111           3 :   mDocument = aDocument;
     112             : 
     113           6 :   if (nsCOMPtr<nsPIDOMWindowOuter> window = mDocument->GetWindow()) {
     114           3 :     mEventTarget = window->GetParentTarget();
     115             :   }
     116           3 :   if (mEventTarget) {
     117           3 :     mEventTarget->AddEventListener(DOM_META_ADDED, this, false);
     118           3 :     mEventTarget->AddEventListener(DOM_META_CHANGED, this, false);
     119           3 :     mEventTarget->AddSystemEventListener(FULLSCREEN_CHANGED, this, false);
     120             :   }
     121             : 
     122           6 :   nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
     123           3 :   if (observerService) {
     124           3 :     observerService->AddObserver(this, BEFORE_FIRST_PAINT.Data(), false);
     125             :   }
     126             : 
     127           3 :   Preferences::AddStrongObserver(this, "browser.ui.zoom.force-user-scalable");
     128             : }
     129             : 
     130             : NS_IMETHODIMP
     131           2 : ZoomConstraintsClient::HandleEvent(nsIDOMEvent* event)
     132             : {
     133           4 :   nsAutoString type;
     134           2 :   event->GetType(type);
     135             : 
     136           2 :   if (type.Equals(DOM_META_ADDED)) {
     137             :     ZCC_LOG("Got a dom-meta-added event in %p\n", this);
     138           2 :     RefreshZoomConstraints();
     139           0 :   } else if (type.Equals(DOM_META_CHANGED)) {
     140             :     ZCC_LOG("Got a dom-meta-changed event in %p\n", this);
     141           0 :     RefreshZoomConstraints();
     142           0 :   } else if (type.Equals(FULLSCREEN_CHANGED)) {
     143             :     ZCC_LOG("Got a fullscreen-change event in %p\n", this);
     144           0 :     RefreshZoomConstraints();
     145             :   }
     146             : 
     147           4 :   return NS_OK;
     148             : }
     149             : 
     150             : NS_IMETHODIMP
     151           1 : ZoomConstraintsClient::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
     152             : {
     153           1 :   if (SameCOMIdentity(aSubject, mDocument) && BEFORE_FIRST_PAINT.EqualsASCII(aTopic)) {
     154             :     ZCC_LOG("Got a before-first-paint event in %p\n", this);
     155           1 :     RefreshZoomConstraints();
     156           0 :   } else if (NS_PREF_CHANGED.EqualsASCII(aTopic)) {
     157             :     ZCC_LOG("Got a pref-change event in %p\n", this);
     158             :     // We need to run this later because all the pref change listeners need
     159             :     // to execute before we can be guaranteed that gfxPrefs::ForceUserScalable()
     160             :     // returns the updated value.
     161             : 
     162             :     RefPtr<nsRunnableMethod<ZoomConstraintsClient>> event =
     163           0 :       NewRunnableMethod("ZoomConstraintsClient::RefreshZoomConstraints",
     164             :                         this,
     165           0 :                         &ZoomConstraintsClient::RefreshZoomConstraints);
     166           0 :     mDocument->Dispatch("ZoomConstraintsClient::RefreshZoomConstraints",
     167             :                         TaskCategory::Other,
     168           0 :                         event.forget());
     169             :   }
     170           1 :   return NS_OK;
     171             : }
     172             : 
     173             : void
     174           2 : ZoomConstraintsClient::ScreenSizeChanged()
     175             : {
     176             :   ZCC_LOG("Got a screen-size change notification in %p\n", this);
     177           2 :   RefreshZoomConstraints();
     178           2 : }
     179             : 
     180             : mozilla::layers::ZoomConstraints
     181           1 : ComputeZoomConstraintsFromViewportInfo(const nsViewportInfo& aViewportInfo)
     182             : {
     183           1 :   mozilla::layers::ZoomConstraints constraints;
     184           1 :   constraints.mAllowZoom = aViewportInfo.IsZoomAllowed() && gfxPrefs::APZAllowZooming();
     185           1 :   constraints.mAllowDoubleTapZoom = constraints.mAllowZoom;
     186           1 :   if (constraints.mAllowZoom) {
     187           0 :     constraints.mMinZoom.scale = aViewportInfo.GetMinZoom().scale;
     188           0 :     constraints.mMaxZoom.scale = aViewportInfo.GetMaxZoom().scale;
     189             :   } else {
     190           1 :     constraints.mMinZoom.scale = aViewportInfo.GetDefaultZoom().scale;
     191           1 :     constraints.mMaxZoom.scale = aViewportInfo.GetDefaultZoom().scale;
     192             :   }
     193           1 :   return constraints;
     194             : }
     195             : 
     196             : void
     197           5 : ZoomConstraintsClient::RefreshZoomConstraints()
     198             : {
     199           5 :   nsIWidget* widget = GetWidget(mPresShell);
     200           5 :   if (!widget) {
     201           8 :     return;
     202             :   }
     203             : 
     204           1 :   uint32_t presShellId = 0;
     205           1 :   FrameMetrics::ViewID viewId = FrameMetrics::NULL_SCROLL_ID;
     206             :   bool scrollIdentifiersValid = APZCCallbackHelper::GetOrCreateScrollIdentifiers(
     207           1 :         mDocument->GetDocumentElement(),
     208           1 :         &presShellId, &viewId);
     209           1 :   if (!scrollIdentifiersValid) {
     210           0 :     return;
     211             :   }
     212             : 
     213           1 :   LayoutDeviceIntSize screenSize;
     214           1 :   if (!nsLayoutUtils::GetContentViewerSize(mPresShell->GetPresContext(), screenSize)) {
     215           0 :     return;
     216             :   }
     217             : 
     218           1 :   nsViewportInfo viewportInfo = mDocument->GetViewportInfo(
     219           1 :     ViewAs<ScreenPixel>(screenSize, PixelCastJustification::LayoutDeviceIsScreenForBounds));
     220             : 
     221             :   mozilla::layers::ZoomConstraints zoomConstraints =
     222           2 :     ComputeZoomConstraintsFromViewportInfo(viewportInfo);
     223             : 
     224           1 :   if (mDocument->Fullscreen()) {
     225             :     ZCC_LOG("%p is in fullscreen, disallowing zooming\n", this);
     226           0 :     zoomConstraints.mAllowZoom = false;
     227           0 :     zoomConstraints.mAllowDoubleTapZoom = false;
     228             :   }
     229             : 
     230           1 :   if (zoomConstraints.mAllowDoubleTapZoom) {
     231             :     // If the CSS viewport is narrower than the screen (i.e. width <= device-width)
     232             :     // then we disable double-tap-to-zoom behaviour.
     233             :     CSSToLayoutDeviceScale scale =
     234           0 :         mPresShell->GetPresContext()->CSSToDevPixelScale();
     235           0 :     if ((viewportInfo.GetSize() * scale).width <= screenSize.width) {
     236           0 :       zoomConstraints.mAllowDoubleTapZoom = false;
     237             :     }
     238             :   }
     239             : 
     240             :   // We only ever create a ZoomConstraintsClient for an RCD, so the RSF of
     241             :   // the presShell must be the RCD-RSF (if it exists).
     242           1 :   MOZ_ASSERT(mPresShell->GetPresContext()->IsRootContentDocument());
     243           1 :   if (nsIScrollableFrame* rcdrsf = mPresShell->GetRootScrollFrameAsScrollable()) {
     244             :     ZCC_LOG("Notifying RCD-RSF that it is zoomable: %d\n", zoomConstraints.mAllowZoom);
     245           1 :     rcdrsf->SetZoomableByAPZ(zoomConstraints.mAllowZoom);
     246             :   }
     247             : 
     248           2 :   ScrollableLayerGuid newGuid(0, presShellId, viewId);
     249           1 :   if (mGuid && mGuid.value() != newGuid) {
     250             :     ZCC_LOG("Clearing old constraints in %p for { %u, %" PRIu64 " }\n",
     251             :       this, mGuid->mPresShellId, mGuid->mScrollId);
     252             :     // If the guid changes, send a message to clear the old one
     253           0 :     widget->UpdateZoomConstraints(mGuid->mPresShellId, mGuid->mScrollId, Nothing());
     254             :   }
     255           1 :   mGuid = Some(newGuid);
     256             :   ZCC_LOG("Sending constraints %s in %p for { %u, %" PRIu64 " }\n",
     257             :     Stringify(zoomConstraints).c_str(), this, presShellId, viewId);
     258           1 :   widget->UpdateZoomConstraints(presShellId, viewId, Some(zoomConstraints));
     259             : }

Generated by: LCOV version 1.13