Bug 920734 - Part 1: Implement window.orientation and window.onorientationchange. r=baku
authorWilliam Chen <wchen@mozilla.com>
Fri, 23 Oct 2015 21:37:28 -0700
changeset 269383 f8c8a7545833
parent 269382 a120a9c50145
child 269384 b227e94179e2
push id29580
push usercbook@mozilla.com
push dateMon, 26 Oct 2015 09:59:59 +0000
treeherdermozilla-central@5ca03a00d268 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs920734
milestone44.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 920734 - Part 1: Implement window.orientation and window.onorientationchange. r=baku
dom/base/WindowOrientationObserver.cpp
dom/base/WindowOrientationObserver.h
dom/base/moz.build
dom/base/nsGkAtomList.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsPIDOMWindow.h
dom/base/test/mochitest.ini
dom/base/test/test_window_orientation.html
dom/events/EventListenerManager.cpp
dom/events/EventNameList.h
dom/webidl/Window.webidl
widget/EventMessageList.h
new file mode 100644
--- /dev/null
+++ b/dom/base/WindowOrientationObserver.cpp
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 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 "WindowOrientationObserver.h"
+
+#include "nsGlobalWindow.h"
+#include "mozilla/Hal.h"
+
+/**
+ * This class is used by nsGlobalWindow to implement window.orientation
+ * and window.onorientationchange. This class is defined in its own file
+ * because Hal.h pulls in windows.h and can't be included from
+ * nsGlobalWindow.cpp
+ */
+WindowOrientationObserver::WindowOrientationObserver(
+  nsGlobalWindow* aGlobalWindow)
+  : mWindow(aGlobalWindow)
+{
+  MOZ_ASSERT(aGlobalWindow && aGlobalWindow->IsInnerWindow());
+  hal::RegisterScreenConfigurationObserver(this);
+
+  hal::ScreenConfiguration config;
+  hal::GetCurrentScreenConfiguration(&config);
+  mAngle = config.angle();
+}
+
+WindowOrientationObserver::~WindowOrientationObserver()
+{
+  hal::UnregisterScreenConfigurationObserver(this);
+}
+
+void
+WindowOrientationObserver::Notify(
+  const mozilla::hal::ScreenConfiguration& aConfiguration)
+{
+  uint16_t currentAngle = aConfiguration.angle();
+  if (mAngle != currentAngle && mWindow->IsCurrentInnerWindow()) {
+    mAngle = currentAngle;
+    mWindow->GetOuterWindow()->DispatchCustomEvent(NS_LITERAL_STRING("orientationchange"));
+  }
+}
+
+/* static */ int16_t
+WindowOrientationObserver::OrientationAngle()
+{
+  hal::ScreenConfiguration config;
+  hal::GetCurrentScreenConfiguration(&config);
+  int16_t angle = static_cast<int16_t>(config.angle());
+  // config.angle() returns 0, 90, 180 or 270.
+  // window.orientation returns -90, 0, 90 or 180.
+  return angle <= 180 ? angle : angle - 360;
+}
new file mode 100644
--- /dev/null
+++ b/dom/base/WindowOrientationObserver.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 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_dom_WindowOrientationObserver_h
+#define mozilla_dom_WindowOrientationObserver_h
+
+#include "mozilla/HalScreenConfiguration.h"
+
+class nsGlobalWindow;
+
+namespace mozilla {
+namespace dom {
+
+class WindowOrientationObserver final :
+  public mozilla::hal::ScreenConfigurationObserver
+{
+public:
+  explicit WindowOrientationObserver(nsGlobalWindow* aGlobalWindow);
+  ~WindowOrientationObserver();
+  void Notify(const mozilla::hal::ScreenConfiguration& aConfiguration) override;
+  static int16_t OrientationAngle();
+
+private:
+  // Weak pointer, instance is owned by mWindow.
+  nsGlobalWindow* MOZ_NON_OWNING_REF mWindow;
+  uint16_t mAngle;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_WindowOrientationObserver_h
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -204,16 +204,17 @@ EXPORTS.mozilla.dom += [
     'StructuredCloneTags.h',
     'StyleSheetList.h',
     'SubtleCrypto.h',
     'Text.h',
     'TreeWalker.h',
     'URL.h',
     'URLSearchParams.h',
     'WebSocket.h',
+    'WindowOrientationObserver.h',
 ]
 
 UNIFIED_SOURCES += [
     'AnonymousContent.cpp',
     'Attr.cpp',
     'BarProps.cpp',
     'ChildIterator.cpp',
     'ChromeUtils.cpp',
@@ -350,16 +351,17 @@ UNIFIED_SOURCES += [
     'Text.cpp',
     'TextInputProcessor.cpp',
     'ThirdPartyUtil.cpp',
     'TreeWalker.cpp',
     'URL.cpp',
     'URLSearchParams.cpp',
     'WebSocket.cpp',
     'WindowNamedPropertiesHandler.cpp',
+    'WindowOrientationObserver.cpp',
 ]
 
 if CONFIG['MOZ_WEBRTC']:
     UNIFIED_SOURCES += [
         'nsDOMDataChannel.cpp',
     ]
 
 # these files couldn't be in UNIFIED_SOURCES for now for reasons given below:
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -842,16 +842,17 @@ GK_ATOM(onmapsendmessagereq, "onmapsendm
 GK_ATOM(onmapmessageupdatereq, "onmapmessageupdatereq")
 GK_ATOM(onnewrdsgroup, "onnewrdsgroup")
 GK_ATOM(onnotificationclick, "onnotificationclick")
 GK_ATOM(onnoupdate, "onnoupdate")
 GK_ATOM(onobsolete, "onobsolete")
 GK_ATOM(ononline, "ononline")
 GK_ATOM(onoffline, "onoffline")
 GK_ATOM(onopen, "onopen")
+GK_ATOM(onorientationchange, "onorientationchange")
 GK_ATOM(onotastatuschange, "onotastatuschange")
 GK_ATOM(onoverflow, "onoverflow")
 GK_ATOM(onoverflowchanged, "onoverflowchanged")
 GK_ATOM(onpagehide, "onpagehide")
 GK_ATOM(onpageshow, "onpageshow")
 GK_ATOM(onpaint, "onpaint")
 GK_ATOM(onpairingaborted, "onpairingaborted")
 GK_ATOM(onpairingconfirmationreq, "onpairingconfirmationreq")
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -15,16 +15,19 @@
 #include "nsScreen.h"
 #include "nsHistory.h"
 #include "nsPerformance.h"
 #include "nsDOMNavigationTiming.h"
 #include "nsIDOMStorageManager.h"
 #include "mozilla/dom/DOMStorage.h"
 #include "mozilla/dom/StorageEvent.h"
 #include "mozilla/dom/StorageEventBinding.h"
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#include "mozilla/dom/WindowOrientationObserver.h"
+#endif
 #include "nsDOMOfflineResourceList.h"
 #include "nsError.h"
 #include "nsIIdleService.h"
 #include "nsISizeOfEventTarget.h"
 #include "nsDOMJSUtils.h"
 #include "nsArrayUtils.h"
 #include "nsIDOMWindowCollection.h"
 #include "nsDOMWindowList.h"
@@ -1522,16 +1525,20 @@ nsGlobalWindow::CleanUp()
   mMozSelfSupport = nullptr;
 
   mPerformance = nullptr;
 
 #ifdef MOZ_WEBSPEECH
   mSpeechSynthesis = nullptr;
 #endif
 
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+  mOrientationChangeObserver = nullptr;
+#endif
+
   ClearControllers();
 
   mOpener = nullptr;             // Forces Release
   if (mContext) {
     mContext = nullptr;            // Forces Release
   }
   mChromeEventHandler = nullptr; // Forces Release
   mParentTarget = nullptr;
@@ -1636,16 +1643,20 @@ nsGlobalWindow::FreeInnerObjects()
     mNavigator->Invalidate();
     mNavigator = nullptr;
   }
 
   if (mScreen) {
     mScreen = nullptr;
   }
 
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+  mOrientationChangeObserver = nullptr;
+#endif
+
   if (mDoc) {
     // Remember the document's principal and URI.
     mDocumentPrincipal = mDoc->NodePrincipal();
     mDocumentURI = mDoc->GetDocumentURI();
     mDocBaseURI = mDoc->GetDocBaseURI();
 
     while (mDoc->EventHandlingSuppressed()) {
       mDoc->UnsuppressEventHandlingAndFireEvents(nsIDocument::eEvents, false);
@@ -13649,16 +13660,37 @@ nsGlobalWindow::DisableDeviceSensor(uint
   }
 
   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
   if (ac) {
     ac->RemoveWindowListener(aType, this);
   }
 }
 
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+void
+nsGlobalWindow::EnableOrientationChangeListener()
+{
+  MOZ_ASSERT(IsInnerWindow());
+
+  if (!mOrientationChangeObserver) {
+    mOrientationChangeObserver =
+      new WindowOrientationObserver(this);
+  }
+}
+
+void
+nsGlobalWindow::DisableOrientationChangeListener()
+{
+  MOZ_ASSERT(IsInnerWindow());
+
+  mOrientationChangeObserver = nullptr;
+}
+#endif
+
 void
 nsGlobalWindow::SetHasGamepadEventListener(bool aHasGamepad/* = true*/)
 {
   MOZ_ASSERT(IsInnerWindow());
   mHasGamepad = aHasGamepad;
   if (aHasGamepad) {
     EnableGamepadUpdates();
   }
@@ -14496,16 +14528,25 @@ nsGlobalModalWindow::SetReturnValue(nsIV
 
 /* static */
 bool
 nsGlobalWindow::IsModalContentWindow(JSContext* aCx, JSObject* aGlobal)
 {
   return xpc::WindowOrNull(aGlobal)->IsModalContentWindow();
 }
 
+
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+int16_t
+nsGlobalWindow::Orientation() const
+{
+  return WindowOrientationObserver::OrientationAngle();
+}
+#endif
+
 NS_IMETHODIMP
 nsGlobalWindow::GetConsole(JSContext* aCx,
                            JS::MutableHandle<JS::Value> aConsole)
 {
   FORWARD_TO_INNER(GetConsole, (aCx, aConsole), NS_ERROR_FAILURE);
 
   ErrorResult rv;
   RefPtr<Console> console = GetConsole(rv);
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -113,16 +113,19 @@ class Navigator;
 class OwningExternalOrWindowProxy;
 class Promise;
 class PostMessageEvent;
 struct RequestInit;
 class RequestOrUSVString;
 class Selection;
 class SpeechSynthesis;
 class WakeLock;
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+class WindowOrientationObserver;
+#endif
 namespace cache {
 class CacheStorage;
 } // namespace cache
 namespace indexedDB {
 class IDBFactory;
 } // namespace indexedDB
 } // namespace dom
 namespace gfx {
@@ -651,16 +654,21 @@ public:
   virtual void PageHidden() override;
   virtual nsresult DispatchAsyncHashchange(nsIURI *aOldURI, nsIURI *aNewURI) override;
   virtual nsresult DispatchSyncPopState() override;
 
   // Inner windows only.
   virtual void EnableDeviceSensor(uint32_t aType) override;
   virtual void DisableDeviceSensor(uint32_t aType) override;
 
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+  virtual void EnableOrientationChangeListener() override;
+  virtual void DisableOrientationChangeListener() override;
+#endif
+
   virtual void EnableTimeChangeNotifications() override;
   virtual void DisableTimeChangeNotifications() override;
 
 #ifdef MOZ_B2G
   // Inner windows only.
   virtual void EnableNetworkEvent(mozilla::EventMessage aEventMessage) override;
   virtual void DisableNetworkEvent(
                  mozilla::EventMessage aEventMessage) override;
@@ -902,16 +910,20 @@ public:
                                            mozilla::ErrorResult& aError);
   already_AddRefed<nsIDOMWindow> Open(const nsAString& aUrl,
                                       const nsAString& aName,
                                       const nsAString& aOptions,
                                       mozilla::ErrorResult& aError);
   mozilla::dom::Navigator* GetNavigator(mozilla::ErrorResult& aError);
   nsIDOMOfflineResourceList* GetApplicationCache(mozilla::ErrorResult& aError);
 
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+  int16_t Orientation() const;
+#endif
+
   mozilla::dom::Console* GetConsole(mozilla::ErrorResult& aRv);
 
   void GetSidebar(mozilla::dom::OwningExternalOrWindowProxy& aResult,
                   mozilla::ErrorResult& aRv);
   already_AddRefed<mozilla::dom::External> GetExternal(mozilla::ErrorResult& aRv);
 
   // Exposed only for testing
   static bool
@@ -1817,16 +1829,20 @@ protected:
   // This flag keeps track of whether dialogs are
   // currently enabled on this window.
   bool                          mAreDialogsEnabled;
 
   nsTHashtable<nsPtrHashKey<mozilla::DOMEventTargetHelper> > mEventTargetObjects;
 
   nsTArray<uint32_t> mEnabledSensors;
 
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+  nsAutoPtr<mozilla::dom::WindowOrientationObserver> mOrientationChangeObserver;
+#endif
+
 #ifdef MOZ_WEBSPEECH
   // mSpeechSynthesis is only used on inner windows.
   RefPtr<mozilla::dom::SpeechSynthesis> mSpeechSynthesis;
 #endif
 
   // This is the CC generation the last time we called CanSkip.
   uint32_t mCanSkipCCGeneration;
 
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -630,16 +630,21 @@ public:
   /**
    * Tell this window that it should remove itself from sensor change
    * notifications.
    *
    * Inner windows only.
    */
   virtual void DisableDeviceSensor(uint32_t aType) = 0;
 
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+  virtual void EnableOrientationChangeListener() = 0;
+  virtual void DisableOrientationChangeListener() = 0;
+#endif
+
   virtual void EnableTimeChangeNotifications() = 0;
   virtual void DisableTimeChangeNotifications() = 0;
 
 #ifdef MOZ_B2G
   /**
    * Tell the window that it should start to listen to the network event of the
    * given aType.
    *
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -354,16 +354,18 @@ skip-if = buildapp == 'mulet'
 skip-if = buildapp == 'mulet'
 [test_window_constructor.html]
 [test_window_cross_origin_props.html]
 [test_window_define_symbol.html]
 [test_window_enumeration.html]
 [test_window_extensible.html]
 [test_window_indexing.html]
 [test_window_named_frame_enumeration.html]
+[test_window_orientation.html]
+skip-if = toolkit != 'gonk'
 [test_writable-replaceable.html]
 [test_navigatorPrefOverride.html]
 [test_EventSource_redirects.html]
 [test_NodeIterator_basics_filters.xhtml]
 [test_NodeIterator_mutations_1.xhtml]
 [test_NodeIterator_mutations_2.html]
 [test_NodeIterator_mutations_3.html]
 [test_XHR.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_window_orientation.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test for window.orientation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="orientationcommon.js"></script>
+<div id="log"></div>
+<script>
+async_test(function(t) {
+  var originalOrientation = screen.orientation.type;
+  var alternateOrientation = originalOrientation == "portrait-primary" ?
+    "landscape-primary" : "portrait-primary";
+
+  var originalWindowOrientation = window.orientation;
+  window.onorientationchange = function() {
+    t.step(function() { assert_not_equals(window.orientation, originalWindowOrientation); });
+
+    var p2 = specialPowersUnlock();
+    p2.then(function() {
+      t.done();
+    }).catch(t.step_func(function(err) {
+      assert_unreached("Error unlocking orientation: " + err);
+      t.done();
+    }));
+  }
+
+  var p1 = specialPowersLock(alternateOrientation);
+  p1.catch(t.step_func(function(err) {
+    assert_unreached("Error locking orientation: " + err);
+    t.done();
+  }));
+}, "Test window.orientation and orientationchange.");
+</script>
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -320,16 +320,20 @@ EventListenerManager::AddEventListenerIn
   } else if (aTypeAtom == nsGkAtoms::ondeviceorientation) {
     EnableDevice(eDeviceOrientation);
   } else if (aTypeAtom == nsGkAtoms::ondeviceproximity || aTypeAtom == nsGkAtoms::onuserproximity) {
     EnableDevice(eDeviceProximity);
   } else if (aTypeAtom == nsGkAtoms::ondevicelight) {
     EnableDevice(eDeviceLight);
   } else if (aTypeAtom == nsGkAtoms::ondevicemotion) {
     EnableDevice(eDeviceMotion);
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+  } else if (aTypeAtom == nsGkAtoms::onorientationchange) {
+    EnableDevice(eOrientationChange);
+#endif
 #ifdef MOZ_B2G
   } else if (aTypeAtom == nsGkAtoms::onmoztimechange) {
     nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
     if (window) {
       window->EnableTimeChangeNotifications();
     }
   } else if (aTypeAtom == nsGkAtoms::onmoznetworkupload) {
     nsCOMPtr<nsPIDOMWindow> window = GetTargetAsInnerWindow();
@@ -426,16 +430,19 @@ bool
 EventListenerManager::IsDeviceType(EventMessage aEventMessage)
 {
   switch (aEventMessage) {
     case eDeviceOrientation:
     case eDeviceMotion:
     case eDeviceLight:
     case eDeviceProximity:
     case eUserProximity:
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+    case eOrientationChange:
+#endif
       return true;
     default:
       break;
   }
   return false;
 }
 
 void
@@ -457,16 +464,21 @@ EventListenerManager::EnableDevice(Event
     case eDeviceLight:
       window->EnableDeviceSensor(SENSOR_LIGHT);
       break;
     case eDeviceMotion:
       window->EnableDeviceSensor(SENSOR_ACCELERATION);
       window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION);
       window->EnableDeviceSensor(SENSOR_GYROSCOPE);
       break;
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+    case eOrientationChange:
+      window->EnableOrientationChangeListener();
+      break;
+#endif
     default:
       NS_WARNING("Enabling an unknown device sensor.");
       break;
   }
 }
 
 void
 EventListenerManager::DisableDevice(EventMessage aEventMessage)
@@ -487,16 +499,21 @@ EventListenerManager::DisableDevice(Even
       break;
     case eDeviceProximity:
     case eUserProximity:
       window->DisableDeviceSensor(SENSOR_PROXIMITY);
       break;
     case eDeviceLight:
       window->DisableDeviceSensor(SENSOR_LIGHT);
       break;
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+    case eOrientationChange:
+      window->DisableOrientationChangeListener();
+      break;
+#endif
     default:
       NS_WARNING("Disabling an unknown device sensor.");
       break;
   }
 }
 
 void
 EventListenerManager::RemoveEventListenerInternal(
--- a/dom/events/EventNameList.h
+++ b/dom/events/EventNameList.h
@@ -502,16 +502,22 @@ WINDOW_EVENT(message,
 WINDOW_EVENT(offline,
              eOffline,
              EventNameType_XUL | EventNameType_HTMLBodyOrFramesetOnly,
              eBasicEventClass)
 WINDOW_EVENT(online,
              eOnline,
              EventNameType_XUL | EventNameType_HTMLBodyOrFramesetOnly,
              eBasicEventClass)
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+WINDOW_EVENT(orientationchange,
+             eOrientationChange,
+             EventNameType_HTMLBodyOrFramesetOnly,
+             eBasicEventClass)
+#endif
 WINDOW_EVENT(pagehide,
              ePageHide,
              EventNameType_HTMLBodyOrFramesetOnly,
              eBasicEventClass)
 WINDOW_EVENT(pageshow,
              ePageShow,
              EventNameType_HTMLBodyOrFramesetOnly,
              eBasicEventClass)
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -393,16 +393,24 @@ partial interface Window {
   [ChromeOnly, Throws]
   readonly attribute WindowRoot? windowRoot;
 };
 
 Window implements TouchEventHandlers;
 
 Window implements OnErrorEventHandlerForWindow;
 
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+// https://compat.spec.whatwg.org/#windoworientation-interface
+partial interface Window {
+  readonly attribute short orientation;
+           attribute EventHandler onorientationchange;
+};
+#endif
+
 // ConsoleAPI
 partial interface Window {
   [Replaceable, GetterThrows]
   readonly attribute Console console;
 };
 
 #ifdef HAVE_SIDEBAR
 // Mozilla extension
--- a/widget/EventMessageList.h
+++ b/widget/EventMessageList.h
@@ -337,16 +337,19 @@ NS_EVENT_MESSAGE(eMessage)
 NS_EVENT_MESSAGE(eOpen)
 
 // Device motion and orientation
 NS_EVENT_MESSAGE(eDeviceOrientation)
 NS_EVENT_MESSAGE(eDeviceMotion)
 NS_EVENT_MESSAGE(eDeviceProximity)
 NS_EVENT_MESSAGE(eUserProximity)
 NS_EVENT_MESSAGE(eDeviceLight)
+#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+NS_EVENT_MESSAGE(eOrientationChange)
+#endif
 
 NS_EVENT_MESSAGE(eShow)
 
 // Fullscreen DOM API
 NS_EVENT_MESSAGE(eFullscreenChange)
 NS_EVENT_MESSAGE(eFullscreenError)
 
 NS_EVENT_MESSAGE(eTouchStart)