Bug 1478576 - A mochitest for system font change notification. r?karlt,froydnj,jimm draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Tue, 07 Aug 2018 11:58:36 +0900
changeset 827108 cb0206cdef1c2b9e5512d048e909451833f5c87e
parent 827106 5b8a35c265a09672f0d06004f23e58e498bb6ad8
push id118468
push userhikezoe@mozilla.com
push dateTue, 07 Aug 2018 02:59:10 +0000
reviewerskarlt, froydnj, jimm
bugs1478576, 1478212
milestone63.0a1
Bug 1478576 - A mochitest for system font change notification. r?karlt,froydnj,jimm The test case in this patch fails without the proper fix in the first patch in this patch series. In this patch two new nsIDOMWindowUtils APIs are introduced to change the system font settins in tests. Currently the APIs work only on GTK+ platform. Also to work the test case properly we need to open a new XUL window because we don't propagate font changes into descendant documents yet (bug 1478212). MozReview-Commit-ID: 4OLxEkEuF8d
dom/base/nsDOMWindowUtils.cpp
dom/interfaces/base/nsIDOMWindowUtils.idl
dom/ipc/PBrowser.ipdl
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
ipc/ipdl/sync-messages.ini
widget/PuppetWidget.cpp
widget/PuppetWidget.h
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
widget/nsIWidget.h
widget/tests/chrome.ini
widget/tests/system_font_changes.xul
widget/tests/test_system_font_changes.xul
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -4402,8 +4402,35 @@ nsTranslationNodeList::GetLength(uint32_
 NS_IMETHODIMP
 nsDOMWindowUtils::WrCapture()
 {
   if (WebRenderBridgeChild* wrbc = GetWebRenderBridge()) {
     wrbc->Capture();
   }
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsDOMWindowUtils::SetSystemFont(const nsACString& aFontName)
+{
+  nsIWidget* widget = GetWidget();
+  if (!widget) {
+    return NS_OK;
+  }
+
+  nsAutoCString fontName(aFontName);
+  return widget->SetSystemFont(fontName);
+}
+
+NS_IMETHODIMP
+nsDOMWindowUtils::GetSystemFont(nsACString& aFontName)
+{
+  nsIWidget* widget = GetWidget();
+  if (!widget) {
+    return NS_OK;
+  }
+
+  nsAutoCString fontName;
+  widget->GetSystemFont(fontName);
+  aFontName.Assign(fontName);
+  return NS_OK;
+}
+
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1926,16 +1926,21 @@ interface nsIDOMWindowUtils : nsISupport
   void ensureDirtyRootFrame();
 
   /**
    * Capture the contents of the current WebRender frame and
    * save them to a folder relative to the current working directory.
    */
   void wrCapture();
 
+  /**
+   * NOTE: Currently works only on GTK+.
+   */
+  attribute ACString systemFont;
+
   // These consts are only for testing purposes.
   const long DEFAULT_MOUSE_POINTER_ID = 0;
   const long DEFAULT_PEN_POINTER_ID   = 1;
   const long DEFAULT_TOUCH_POINTER_ID = 2;
 
   // Match WidgetMouseEventBase::buttonType.
   const long MOUSE_BUTTON_LEFT_BUTTON   = 0;
   const long MOUSE_BUTTON_MIDDLE_BUTTON = 1;
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -571,16 +571,19 @@ parent:
     /**
      * This function is used to notify the parent that it should display a
      * canvas permission prompt.
      *
      * @param aFirstPartyURI first party of the tab that is requesting access.
      */
     async ShowCanvasPermissionPrompt(nsCString aFirstPartyURI);
 
+    sync SetSystemFont(nsCString aFontName);
+    sync GetSystemFont() returns (nsCString retval);
+
 child:
     /**
      * Notify the remote browser that it has been Show()n on this
      * side, with the given |visibleRect|.  This message is expected
      * to trigger creation of the remote browser's "widget".
      *
      * |Show()| and |Move()| take IntSizes rather than Rects because
      * content processes always render to a virtual <0, 0> top-left
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -3601,16 +3601,36 @@ void
 TabParent::SetIsActiveRecordReplayTab(bool aIsActive)
 {
   if (aIsActive != mIsActiveRecordReplayTab) {
     gNumActiveRecordReplayTabs += aIsActive ? 1 : -1;
     mIsActiveRecordReplayTab = aIsActive;
   }
 }
 
+mozilla::ipc::IPCResult
+TabParent::RecvSetSystemFont(const nsCString& aFontName)
+{
+  nsCOMPtr<nsIWidget> widget = GetWidget();
+  if (widget) {
+    widget->SetSystemFont(aFontName);
+  }
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+TabParent::RecvGetSystemFont(nsCString* aFontName)
+{
+  nsCOMPtr<nsIWidget> widget = GetWidget();
+  if (widget) {
+    widget->GetSystemFont(*aFontName);
+  }
+  return IPC_OK();
+}
+
 NS_IMETHODIMP
 FakeChannel::OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo)
 {
   nsAuthInformationHolder* holder =
     static_cast<nsAuthInformationHolder*>(aAuthInfo);
 
   if (!net::gNeckoChild->SendOnAuthAvailable(mCallbackId,
                                              holder->User(),
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -623,16 +623,21 @@ protected:
   virtual mozilla::ipc::IPCResult RecvPaintWhileInterruptingJSNoOp(const LayersObserverEpoch& aEpoch) override;
 
   virtual mozilla::ipc::IPCResult RecvSetDimensions(const uint32_t& aFlags,
                                                     const int32_t& aX, const int32_t& aY,
                                                     const int32_t& aCx, const int32_t& aCy) override;
 
   virtual mozilla::ipc::IPCResult RecvShowCanvasPermissionPrompt(const nsCString& aFirstPartyURI) override;
 
+  mozilla::ipc::IPCResult
+  RecvSetSystemFont(const nsCString& aFontName) override;
+  mozilla::ipc::IPCResult
+  RecvGetSystemFont(nsCString* aFontName) override;
+
   ContentCacheInParent mContentCache;
 
   nsIntRect mRect;
   ScreenIntSize mDimensions;
   ScreenOrientationInternal mOrientation;
   float mDPI;
   int32_t mRounding;
   CSSToLayoutDeviceScale mDefaultScale;
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -833,16 +833,20 @@ description =
 [PBrowser::DispatchWheelEvent]
 description =
 [PBrowser::DispatchMouseEvent]
 description =
 [PBrowser::DispatchKeyboardEvent]
 description =
 [PBrowser::EnsureLayersConnected]
 description =
+[PBrowser::SetSystemFont]
+description = test only
+[PBrowser::GetSystemFont]
+description = test only
 [PContent::SyncMessage]
 description =
 [PContent::CreateChildProcess]
 description =
 [PContent::BridgeToChildProcess]
 description =
 [PContent::OpenRecordReplayChannel]
 description = bug 1475898 this could be async
--- a/widget/PuppetWidget.cpp
+++ b/widget/PuppetWidget.cpp
@@ -1567,10 +1567,31 @@ PuppetWidget::WillDispatchKeyboardEvent(
                 TextEventDispatcher* aTextEventDispatcher,
                 WidgetKeyboardEvent& aKeyboardEvent,
                 uint32_t aIndexOfKeypress,
                 void* aData)
 {
   MOZ_ASSERT(aTextEventDispatcher == mTextEventDispatcher);
 }
 
+nsresult
+PuppetWidget::SetSystemFont(const nsCString& aFontName)
+{
+  if (!mTabChild) {
+    return NS_ERROR_FAILURE;
+  }
+
+  mTabChild->SendSetSystemFont(aFontName);
+  return NS_OK;
+}
+
+nsresult
+PuppetWidget::GetSystemFont(nsCString& aFontName)
+{
+  if (!mTabChild) {
+    return NS_ERROR_FAILURE;
+  }
+  mTabChild->SendGetSystemFont(&aFontName);
+  return NS_OK;
+}
+
 } // namespace widget
 } // namespace mozilla
--- a/widget/PuppetWidget.h
+++ b/widget/PuppetWidget.h
@@ -304,16 +304,19 @@ public:
                      nsIKeyEventInPluginCallback* aCallback) override;
 
   virtual void LookUpDictionary(
                  const nsAString& aText,
                  const nsTArray<mozilla::FontRange>& aFontRangeArray,
                  const bool aIsVertical,
                  const LayoutDeviceIntPoint& aPoint) override;
 
+  nsresult SetSystemFont(const nsCString& aFontName) override;
+  nsresult GetSystemFont(nsCString& aFontName) override;
+
   // TextEventDispatcherListener
   using nsBaseWidget::NotifyIME;
   NS_IMETHOD NotifyIME(TextEventDispatcher* aTextEventDispatcher,
                        const IMENotification& aNotification) override;
   NS_IMETHOD_(IMENotificationRequests) GetIMENotificationRequests() override;
   NS_IMETHOD_(void) OnRemovedFrom(
                       TextEventDispatcher* aTextEventDispatcher) override;
   NS_IMETHOD_(void) WillDispatchKeyboardEvent(
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -7312,8 +7312,32 @@ nsWindow::SetCompositorHint(WindowCompos
                             cardinal_atom,
                             32, // format
                             GDK_PROP_MODE_REPLACE,
                             (guchar*)&value,
                             1);
     }
 }
 #endif
+
+nsresult
+nsWindow::SetSystemFont(const nsCString& aFontName)
+{
+    GtkSettings* settings = gtk_settings_get_default();
+    g_object_set(settings, "gtk-font-name", aFontName.get(), nullptr);
+    return NS_OK;
+}
+
+nsresult
+nsWindow::GetSystemFont(nsCString& aFontName)
+{
+    GtkSettings* settings = gtk_settings_get_default();
+    gchar* fontName = nullptr;
+    g_object_get(settings,
+                 "gtk-font-name", &fontName,
+                 nullptr);
+    if (fontName) {
+        aFontName.Assign(fontName);
+        g_free(fontName);
+    }
+    return NS_OK;
+}
+
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -409,16 +409,19 @@ public:
     // From GDK
     int GdkCoordToDevicePixels(gint coord);
     LayoutDeviceIntPoint GdkPointToDevicePixels(GdkPoint point);
     LayoutDeviceIntPoint GdkEventCoordsToDevicePixels(gdouble x, gdouble y);
     LayoutDeviceIntRect GdkRectToDevicePixels(GdkRectangle rect);
 
     virtual bool WidgetTypeSupportsAcceleration() override;
 
+    nsresult SetSystemFont(const nsCString& aFontName) override;
+    nsresult GetSystemFont(nsCString& aFontName) override;
+
     typedef enum { CSD_SUPPORT_SYSTEM,    // CSD including shadows
                    CSD_SUPPORT_CLIENT,    // CSD without shadows
                    CSD_SUPPORT_NONE,      // WM does not support CSD at all
                    CSD_SUPPORT_UNKNOWN
     } CSDSupportLevel;
     /**
      * Get the support of Client Side Decoration by checking
      * the XDG_CURRENT_DESKTOP environment variable.
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1691,16 +1691,28 @@ class nsIWidget : public nsISupports
      */
     virtual void StopAsyncAutoscroll(const ScrollableLayerGuid& aGuid) = 0;
 
     // If this widget supports out-of-process compositing, it can override
     // this method to provide additional information to the compositor.
     virtual void GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData)
     {}
 
+    /**
+     * Setter/Getter of the system font setting for testing.
+     */
+    virtual nsresult SetSystemFont(const nsCString& aFontName)
+    {
+      return NS_ERROR_NOT_IMPLEMENTED;
+    }
+    virtual nsresult GetSystemFont(nsCString& aFontName)
+    {
+      return NS_ERROR_NOT_IMPLEMENTED;
+    }
+
 private:
   class LongTapInfo
   {
   public:
     LongTapInfo(int32_t aPointerId, LayoutDeviceIntPoint& aPoint,
                 mozilla::TimeDuration aDuration,
                 nsIObserver* aObserver) :
       mPointerId(aPointerId),
--- a/widget/tests/chrome.ini
+++ b/widget/tests/chrome.ini
@@ -85,16 +85,20 @@ skip-if = toolkit != "cocoa"
 [test_secure_input.html]
 support-files = file_secure_input.html
 skip-if = toolkit != "cocoa"
 [test_native_key_bindings_mac.html]
 skip-if = toolkit != "cocoa" || verify
 [test_system_status_bar.xul]
 skip-if = toolkit != "cocoa"
 
+[test_system_font_changes.xul]
+support-files = system_font_changes.xul
+run-if = toolkit == 'gtk3' # Currently the test works on only gtk3
+
 # Windows
 # taskbar_previews.xul
 # window_state_windows.xul
 [test_chrome_context_menus_win.xul]
 skip-if = toolkit != "windows"
 support-files = chrome_context_menus_win.xul
 [test_plugin_input_event.html]
 skip-if = toolkit != "windows"
new file mode 100644
--- /dev/null
+++ b/widget/tests/system_font_changes.xul
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="system_font_changes_window"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        width="300"
+        height="300"
+        onload="start();">
+
+<span id="target" style="font:menu">Hello world</span>
+
+<script type="application/javascript"><![CDATA[
+  function is(condition, message) {
+    window.opener.wrappedJSObject.SimpleTest.is(condition, message);
+  }
+  function registerCleanupFunction(func) {
+    window.opener.wrappedJSObject.SimpleTest.registerCleanupFunction(func);
+  }
+
+  async function waitForFrame() {
+    return new Promise(resolve => {
+      requestAnimationFrame(resolve);
+    });
+  }
+
+  async function start() {
+    await waitForFrame();
+
+    const originalSystemFont = windowUtils.systemFont;
+    registerCleanupFunction(() => {
+      windowUtils.systemFont = originalSystemFont;
+    });
+
+    windowUtils.systemFont = 'Sans 11';
+    is(windowUtils.systemFont, 'Sans 11');
+
+    // Wait for two frames for the safety since the notification for system
+    // font changes is asynchronously processed.
+    await waitForFrame();
+    await waitForFrame();
+
+    const target = document.getElementById('target');
+    is(getComputedStyle(target).fontFamily, 'Sans');
+
+    windowUtils.systemFont = 'Serif 11';
+    is(windowUtils.systemFont, 'Serif 11');
+
+    await waitForFrame();
+    await waitForFrame();
+
+    is(getComputedStyle(target).fontFamily, 'Serif');
+
+    window.close();
+    window.opener.wrappedJSObject.SimpleTest.finish();
+  }
+]]></script>
+</window>
new file mode 100644
--- /dev/null
+++ b/widget/tests/test_system_font_changes.xul
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+<window title="Native menu system tests"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+<body  xmlns="http://www.w3.org/1999/xhtml">
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+<script class="testbody" type="application/javascript">
+<![CDATA[
+
+SimpleTest.waitForExplicitFinish();
+window.open("system_font_changes.xul", "system_font_changes_window",
+            "chrome,width=600,height=600");
+
+]]>
+</script>
+
+</window>