Bug 1171182 - Browser Zoom Query for NPAPI; r=bsmedberg r=jaas
authorKyle Machulis <kyle@nonpolynomial.com>
Thu, 17 Mar 2016 12:00:59 -0700
changeset 289378 e32d4804b6760cc3ab76a83233bd41a044fa7342
parent 289377 a3d994656b2bf373d1deb2cc13f559a4dcf15747
child 289379 4a3d5109a73e0a9297d0607acc07c143fd4917f9
push id30102
push userryanvm@gmail.com
push dateSat, 19 Mar 2016 15:23:17 +0000
treeherdermozilla-central@720fb3d55e28 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, jaas
bugs1171182
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1171182 - Browser Zoom Query for NPAPI; r=bsmedberg r=jaas
dom/plugins/base/npapi.h
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsNPAPIPluginInstance.h
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginInstanceOwner.h
dom/plugins/ipc/PPluginInstance.ipdl
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginInstanceChild.h
dom/plugins/ipc/PluginInstanceParent.cpp
layout/generic/nsPluginFrame.cpp
--- a/dom/plugins/base/npapi.h
+++ b/dom/plugins/base/npapi.h
@@ -407,16 +407,18 @@ typedef enum {
   NPNVSupportsWindowless = 17,
 
   NPNVprivateModeBool = 18,
 
   NPNVsupportsAdvancedKeyHandling = 21,
 
   NPNVdocumentOrigin = 22,
 
+  NPNVCSSZoomFactor = 23,
+
   NPNVpluginDrawingModel = 1000 /* Get the current drawing model (NPDrawingModel) */
 #if defined(XP_MACOSX)
   , NPNVcontentsScaleFactor = 1001
 #ifndef NP_NO_QUICKDRAW
   , NPNVsupportsQuickDrawBool = 2000
 #endif
   , NPNVsupportsCoreGraphicsBool = 2001
   , NPNVsupportsOpenGLBool = 2002
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -2026,16 +2026,24 @@ NPError
     nsNPAPIPluginInstance *inst =
       (nsNPAPIPluginInstance *) (npp ? npp->ndata : nullptr);
     double scaleFactor = inst ? inst->GetContentsScaleFactor() : 1.0;
     *(double*)result = scaleFactor;
     return NPERR_NO_ERROR;
   }
 #endif
 
+  case NPNVCSSZoomFactor: {
+    nsNPAPIPluginInstance *inst =
+      (nsNPAPIPluginInstance *) (npp ? npp->ndata : nullptr);
+    double scaleFactor = inst ? inst->GetCSSZoomFactor() : 1.0;
+    *(double*)result = scaleFactor;
+    return NPERR_NO_ERROR;
+  }
+
 #ifdef MOZ_WIDGET_ANDROID
     case kLogInterfaceV0_ANPGetValue: {
       LOG("get log interface");
       ANPLogInterfaceV0 *i = (ANPLogInterfaceV0 *) result;
       InitLogInterface(i);
       return NPERR_NO_ERROR;
     }
 
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -996,17 +996,18 @@ nsresult nsNPAPIPluginInstance::IsRemote
       return NS_ERROR_FAILURE;
 
   return library->IsRemoteDrawingCoreAnimation(&mNPP, aDrawing);
 #else
   return NS_ERROR_FAILURE;
 #endif
 }
 
-nsresult nsNPAPIPluginInstance::ContentsScaleFactorChanged(double aContentsScaleFactor)
+nsresult
+nsNPAPIPluginInstance::ContentsScaleFactorChanged(double aContentsScaleFactor)
 {
 #ifdef XP_MACOSX
   if (!mPlugin)
       return NS_ERROR_FAILURE;
 
   PluginLibrary* library = mPlugin->GetLibrary();
   if (!library)
       return NS_ERROR_FAILURE;
@@ -1017,16 +1018,41 @@ nsresult nsNPAPIPluginInstance::Contents
 
   return library->ContentsScaleFactorChanged(&mNPP, aContentsScaleFactor);
 #else
   return NS_ERROR_FAILURE;
 #endif
 }
 
 nsresult
+nsNPAPIPluginInstance::CSSZoomFactorChanged(float aCSSZoomFactor)
+{
+  if (RUNNING != mRunning)
+    return NS_OK;
+
+  PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of CSS Zoom Factor change this=%p\n",this));
+
+  if (!mPlugin || !mPlugin->GetLibrary())
+    return NS_ERROR_FAILURE;
+
+  NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
+
+  if (!pluginFunctions->setvalue)
+    return NS_ERROR_FAILURE;
+
+  PluginDestructionGuard guard(this);
+
+  NPError error;
+  double value = static_cast<double>(aCSSZoomFactor);
+  NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setvalue)(&mNPP, NPNVCSSZoomFactor, &value), this,
+                          NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
+  return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult
 nsNPAPIPluginInstance::GetJSObject(JSContext *cx, JSObject** outObject)
 {
   if (mHaveJavaC2PJSObjectQuirk) {
     return NS_ERROR_FAILURE;
   }
 
   NPObject *npobj = nullptr;
   nsresult rv = GetValueFromPlugin(NPPVpluginScriptableNPObject, &npobj);
@@ -1734,16 +1760,26 @@ nsNPAPIPluginInstance::GetContentsScaleF
 {
   double scaleFactor = 1.0;
   if (mOwner) {
     mOwner->GetContentsScaleFactor(&scaleFactor);
   }
   return scaleFactor;
 }
 
+float
+nsNPAPIPluginInstance::GetCSSZoomFactor()
+{
+  float zoomFactor = 1.0;
+  if (mOwner) {
+    mOwner->GetCSSZoomFactor(&zoomFactor);
+  }
+  return zoomFactor;
+}
+
 nsresult
 nsNPAPIPluginInstance::GetRunID(uint32_t* aRunID)
 {
   if (NS_WARN_IF(!aRunID)) {
     return NS_ERROR_INVALID_POINTER;
   }
 
   if (NS_WARN_IF(!mPlugin)) {
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -95,16 +95,17 @@ public:
   nsresult NewStreamFromPlugin(const char* type, const char* target, nsIOutputStream* *result);
   nsresult Print(NPPrint* platformPrint);
   nsresult HandleEvent(void* event, int16_t* result,
                        NSPluginCallReentry aSafeToReenterGecko = NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
   nsresult GetValueFromPlugin(NPPVariable variable, void* value);
   nsresult GetDrawingModel(int32_t* aModel);
   nsresult IsRemoteDrawingCoreAnimation(bool* aDrawing);
   nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
+  nsresult CSSZoomFactorChanged(float aCSSZoomFactor);
   nsresult GetJSObject(JSContext *cx, JSObject** outObject);
   bool ShouldCache();
   nsresult IsWindowless(bool* isWindowless);
   nsresult AsyncSetWindow(NPWindow* window);
   nsresult GetImageContainer(mozilla::layers::ImageContainer **aContainer);
   nsresult GetImageSize(nsIntSize* aSize);
   nsresult NotifyPainted(void);
   nsresult GetIsOOP(bool* aIsOOP);
@@ -301,16 +302,19 @@ public:
 
   // Called when the instance fails to instantiate beceause the Carbon
   // event model is not supported.
   void CarbonNPAPIFailure();
 
   // Returns the contents scale factor of the screen the plugin is drawn on.
   double GetContentsScaleFactor();
 
+  // Returns the css zoom factor of the document the plugin is drawn on.
+  float GetCSSZoomFactor();
+
   nsresult GetRunID(uint32_t *aRunID);
 
   static bool InPluginCallUnsafeForReentry() { return gInUnsafePluginCalls > 0; }
   static void BeginPluginCall(NSPluginCallReentry aReentryState)
   {
     if (aReentryState == NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO) {
       ++gInUnsafePluginCalls;
     }
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -356,16 +356,17 @@ nsPluginInstanceOwner::nsPluginInstanceO
   mWidgetCreationComplete = false;
 #ifdef XP_MACOSX
   mSentInitialTopLevelWindowEvent = false;
   mLastWindowIsActive = false;
   mLastContentFocused = false;
   mLastScaleFactor = 1.0;
   mShouldBlurOnActivate = false;
 #endif
+  mLastCSSZoomFactor = 1.0;
   mContentFocused = false;
   mWidgetVisible = true;
   mPluginWindowVisible = false;
   mPluginDocumentActiveState = true;
   mLastMouseDownButtonType = -1;
 
 #ifdef XP_MACOSX
 #ifndef NP_NO_CARBON
@@ -3531,27 +3532,16 @@ nsPluginInstanceOwner::SendWindowFocusCh
   cocoaEvent.type = NPCocoaEventWindowFocusChanged;
   cocoaEvent.data.focus.hasFocus = aIsActive;
   mInstance->HandleEvent(&cocoaEvent,
                          nullptr,
                          NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
 }
 
 void
-nsPluginInstanceOwner::ResolutionMayHaveChanged()
-{
-  double scaleFactor = 1.0;
-  GetContentsScaleFactor(&scaleFactor);
-  if (scaleFactor != mLastScaleFactor) {
-    ContentsScaleFactorChanged(scaleFactor);
-    mLastScaleFactor = scaleFactor;
-   }
-}
-
-void
 nsPluginInstanceOwner::HidePluginWindow()
 {
   if (!mPluginWindow || !mInstance) {
     return;
   }
 
   mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
   mPluginWindow->clipRect.right  = mPluginWindow->clipRect.left;
@@ -3612,16 +3602,38 @@ void
 nsPluginInstanceOwner::UpdateWindowVisibility(bool aVisible)
 {
   mPluginWindowVisible = aVisible;
   UpdateWindowPositionAndClipRect(true);
 }
 #endif // XP_MACOSX
 
 void
+nsPluginInstanceOwner::ResolutionMayHaveChanged()
+{
+#ifdef XP_MACOSX
+  double scaleFactor = 1.0;
+  GetContentsScaleFactor(&scaleFactor);
+  if (scaleFactor != mLastScaleFactor) {
+    ContentsScaleFactorChanged(scaleFactor);
+    mLastScaleFactor = scaleFactor;
+  }
+#endif
+  float zoomFactor = 1.0;
+  GetCSSZoomFactor(&zoomFactor);
+  if (zoomFactor != mLastCSSZoomFactor) {
+    if (mInstance) {
+      mInstance->CSSZoomFactorChanged(zoomFactor);
+    }
+    mLastCSSZoomFactor = zoomFactor;
+  }
+
+}
+
+void
 nsPluginInstanceOwner::UpdateDocumentActiveState(bool aIsActive)
 {
   PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
 
   mPluginDocumentActiveState = aIsActive;
 #ifndef XP_MACOSX
   UpdateWindowPositionAndClipRect(true);
 
@@ -3690,16 +3702,28 @@ nsPluginInstanceOwner::GetContentsScaleF
     scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/
       presShell->GetPresContext()->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom();
   }
 #endif
   *result = scaleFactor;
   return NS_OK;
 }
 
+void
+nsPluginInstanceOwner::GetCSSZoomFactor(float *result)
+{
+  nsCOMPtr<nsIContent> content = do_QueryReferent(mContent);
+  nsIPresShell* presShell = nsContentUtils::FindPresShellForDocument(content->OwnerDoc());
+  if (presShell) {
+    *result = presShell->GetPresContext()->DeviceContext()->GetFullZoom();
+  } else {
+    *result = 1.0;
+  }
+}
+
 void nsPluginInstanceOwner::SetFrame(nsPluginFrame *aFrame)
 {
   // Don't do anything if the frame situation hasn't changed.
   if (mPluginFrame == aFrame) {
     return;
   }
 
   nsCOMPtr<nsIContent> content = do_QueryReferent(mContent);
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -133,17 +133,16 @@ public:
   void SetWidgetWindowAsParent(HWND aWindowToAdopt);
   nsresult SetNetscapeWindowAsParent(HWND aWindowToAdopt);
 #endif
   
 #ifdef XP_MACOSX
   enum { ePluginPaintEnable, ePluginPaintDisable };
 
   void WindowFocusMayHaveChanged();
-  void ResolutionMayHaveChanged();
 
   bool WindowIsActive();
   void SendWindowFocusChanged(bool aIsActive);
   NPDrawingModel GetDrawingModel();
   bool IsRemoteDrawingCoreAnimation();
   nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
   NPEventModel GetEventModel();
   static void CARefresh(nsITimer *aTimer, void *aClosure);
@@ -155,16 +154,17 @@ public:
   // Set plugin port info in the plugin (in the 'window' member of the
   // NPWindow structure passed to the plugin by SetWindow()).
   void SetPluginPort();
 #else // XP_MACOSX
   void UpdateWindowPositionAndClipRect(bool aSetWindow);
   void UpdateWindowVisibility(bool aVisible);
 #endif // XP_MACOSX
 
+  void ResolutionMayHaveChanged();
   void UpdateDocumentActiveState(bool aIsActive);
 
   void SetFrame(nsPluginFrame *aFrame);
   nsPluginFrame* GetFrame();
 
   uint32_t GetLastEventloopNestingLevel() const {
     return mLastEventloopNestingLevel; 
   }
@@ -273,16 +273,17 @@ public:
   void NotifyDestroyPending();
 
   bool GetCompositionString(uint32_t aIndex, nsTArray<uint8_t>* aString,
                             int32_t* aLength);
   bool SetCandidateWindow(
            const mozilla::widget::CandidateWindowPosition& aPosition);
   bool RequestCommitOrCancel(bool aCommitted);
 
+  void GetCSSZoomFactor(float *result);
 private:
   virtual ~nsPluginInstanceOwner();
 
   // return FALSE if LayerSurface dirty (newly created and don't have valid plugin content yet)
   bool IsUpToDate()
   {
     nsIntSize size;
     return NS_SUCCEEDED(mInstance->GetImageSize(&size)) &&
@@ -323,17 +324,17 @@ private:
   static nsTArray<nsPluginInstanceOwner*>  *sCARefreshListeners;
   bool                                      mSentInitialTopLevelWindowEvent;
   bool                                      mLastWindowIsActive;
   bool                                      mLastContentFocused;
   double                                    mLastScaleFactor;
   // True if, the next time the window is activated, we should blur ourselves.
   bool                                      mShouldBlurOnActivate;
 #endif
-
+  double                                    mLastCSSZoomFactor;
   // Initially, the event loop nesting level we were created on, it's updated
   // if we detect the appshell is on a lower level as long as we're not stopped.
   // We delay DoStopPlugin() until the appshell reaches this level or lower.
   uint32_t                    mLastEventloopNestingLevel;
   bool                        mContentFocused;
   bool                        mWidgetVisible;    // used on Mac to store our widget's visible state
 #ifdef MOZ_X11
   // Used with windowless plugins only, initialized in CreateWidget().
--- a/dom/plugins/ipc/PPluginInstance.ipdl
+++ b/dom/plugins/ipc/PPluginInstance.ipdl
@@ -92,16 +92,18 @@ child:
 
   intr NPP_GetValue_NPPVpluginScriptableNPObject()
     returns (nullable PPluginScriptableObject value, NPError result);
 
   intr NPP_SetValue_NPNVprivateModeBool(bool value) returns (NPError result);
   intr NPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId()
     returns (nsCString plug_id, NPError result);
 
+  intr NPP_SetValue_NPNVCSSZoomFactor(double value) returns (NPError result);
+
   intr NPP_SetValue_NPNVmuteAudioBool(bool muted) returns (NPError result);
 
   intr NPP_HandleEvent(NPRemoteEvent event)
     returns (int16_t handled);
   // special cases where we need to a shared memory buffer
   intr NPP_HandleEvent_Shmem(NPRemoteEvent event, Shmem buffer)
     returns (int16_t handled, Shmem rtnbuffer);
   // special cases where we need an iosurface
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -538,16 +538,20 @@ PluginInstanceChild::NPN_GetValue(NPNVar
 #endif /* NP_NO_QUICKDRAW */
 
     case NPNVcontentsScaleFactor: {
         *static_cast<double*>(aValue) = mContentsScaleFactor;
         return NPERR_NO_ERROR;
     }
 #endif /* XP_MACOSX */
 
+    case NPNVCSSZoomFactor: {
+        *static_cast<double*>(aValue) = mCSSZoomFactor;
+        return NPERR_NO_ERROR;
+    }
 #ifdef DEBUG
     case NPNVjavascriptEnabledBool:
     case NPNVasdEnabledBool:
     case NPNVisOfflineBool:
     case NPNVSupportsXEmbedBool:
     case NPNVSupportsWindowless:
         NS_NOTREACHED("NPNVariable should be handled in PluginModuleChild.");
         MOZ_FALLTHROUGH;
@@ -813,16 +817,31 @@ PluginInstanceChild::AnswerNPP_SetValue_
     }
 
     NPBool v = value;
     *result = mPluginIface->setvalue(GetNPP(), NPNVprivateModeBool, &v);
     return true;
 }
 
 bool
+PluginInstanceChild::AnswerNPP_SetValue_NPNVCSSZoomFactor(const double& value,
+                                                          NPError* result)
+{
+    if (!mPluginIface->setvalue) {
+        *result = NPERR_GENERIC_ERROR;
+        return true;
+    }
+
+    mCSSZoomFactor = value;
+    double v = value;
+    *result = mPluginIface->setvalue(GetNPP(), NPNVCSSZoomFactor, &v);
+    return true;
+}
+
+bool
 PluginInstanceChild::AnswerNPP_SetValue_NPNVmuteAudioBool(const bool& value,
                                                           NPError* result)
 {
     if (!mPluginIface->setvalue) {
         *result = NPERR_GENERIC_ERROR;
         return true;
     }
 
--- a/dom/plugins/ipc/PluginInstanceChild.h
+++ b/dom/plugins/ipc/PluginInstanceChild.h
@@ -84,16 +84,18 @@ protected:
                                                     NPError* result) override;
     virtual bool
     AnswerNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId(nsCString* aPlugId,
                                                            NPError* aResult) override;
     virtual bool
     AnswerNPP_SetValue_NPNVprivateModeBool(const bool& value, NPError* result) override;
     virtual bool
     AnswerNPP_SetValue_NPNVmuteAudioBool(const bool& value, NPError* result) override;
+    virtual bool
+    AnswerNPP_SetValue_NPNVCSSZoomFactor(const double& value, NPError* result) override;
 
     virtual bool
     AnswerNPP_HandleEvent(const NPRemoteEvent& event, int16_t* handled) override;
     virtual bool
     AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
                                 Shmem&& mem,
                                 int16_t* handled,
                                 Shmem* rtnmem) override;
@@ -398,16 +400,17 @@ private:
     uint16_t                    mMode;
     InfallibleTArray<nsCString> mNames;
     InfallibleTArray<nsCString> mValues;
     NPP_t mData;
     NPWindow mWindow;
 #if defined(XP_DARWIN)
     double mContentsScaleFactor;
 #endif
+    double mCSSZoomFactor;
     int16_t               mDrawingModel;
 
     NPAsyncSurface* mCurrentDirectSurface;
 
     // The surface hashtables below serve a few purposes. They let us verify
     // and retain extra information about plugin surfaces, and they let us
     // free shared memory that the plugin might forget to release.
     struct DirectBitmap {
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -1730,16 +1730,23 @@ PluginInstanceParent::NPP_SetValue(NPNVa
 
     case NPNVmuteAudioBool:
         if (!CallNPP_SetValue_NPNVmuteAudioBool(*static_cast<NPBool*>(value),
                                                 &result))
             return NPERR_GENERIC_ERROR;
 
         return result;
 
+    case NPNVCSSZoomFactor:
+        if (!CallNPP_SetValue_NPNVCSSZoomFactor(*static_cast<double*>(value),
+                                                &result))
+            return NPERR_GENERIC_ERROR;
+
+        return result;
+
     default:
         NS_ERROR("Unhandled NPNVariable in NPP_SetValue");
         MOZ_LOG(GetPluginLog(), LogLevel::Warning,
                ("In PluginInstanceParent::NPP_SetValue: Unhandled NPNVariable %i (%s)",
                 (int) variable, NPNVariableToString(variable)));
         return NPERR_GENERIC_ERROR;
     }
 }
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -1213,18 +1213,19 @@ nsPluginFrame::BuildDisplayList(nsDispla
 #ifndef XP_MACOSX
   if (mWidget && aBuilder->IsInTransform()) {
     // Windowed plugins should not be rendered inside a transform.
     return;
   }
 #endif
 
   if (aBuilder->IsForPainting() && mInstanceOwner) {
+    // Update plugin frame for both content scaling and full zoom changes.
+    mInstanceOwner->ResolutionMayHaveChanged();
 #ifdef XP_MACOSX
-    mInstanceOwner->ResolutionMayHaveChanged();
     mInstanceOwner->WindowFocusMayHaveChanged();
 #endif
     if (mInstanceOwner->UseAsyncRendering()) {
       NPWindow* window = nullptr;
       mInstanceOwner->GetWindow(window);
       bool isVisible = window && window->width > 0 && window->height > 0;
       if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
 #ifndef XP_MACOSX