Bug 864484 - Part 3: Move MozCellBroadcastMessage to webidl implementation. r=vyang, r=smaug
authorBevis Tseng <btseng@mozilla.com>
Fri, 15 Aug 2014 13:13:05 +0800
changeset 230975 4090b8c651ab9bf642abeaee2ebe20563adac1ad
parent 230974 fe5ef66ed15d1e3174a4ac2d88a9ad434ab838a0
child 230976 2fe6e70071fff89764ac7a4955b6cfaa29495b94
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvyang, smaug
bugs864484
milestone35.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 864484 - Part 3: Move MozCellBroadcastMessage to webidl implementation. r=vyang, r=smaug
dom/bindings/Bindings.conf
dom/cellbroadcast/CellBroadcast.cpp
dom/cellbroadcast/CellBroadcastMessage.cpp
dom/cellbroadcast/CellBroadcastMessage.h
dom/cellbroadcast/gonk/CellBroadcastService.js
dom/cellbroadcast/interfaces/moz.build
dom/cellbroadcast/interfaces/nsICellBroadcastService.idl
dom/cellbroadcast/interfaces/nsIDOMMozCellBroadcastMessage.idl
dom/cellbroadcast/interfaces/nsIGonkCellBroadcastService.idl
dom/cellbroadcast/moz.build
dom/cellbroadcast/tests/marionette/test_cellbroadcast_etws.js
dom/cellbroadcast/tests/marionette/test_cellbroadcast_gsm.js
dom/cellbroadcast/tests/marionette/test_cellbroadcast_umts.js
dom/tests/mochitest/general/test_interfaces.html
dom/webidl/MozCellBroadcastEvent.webidl
dom/webidl/MozCellBroadcastMessage.webidl
dom/webidl/moz.build
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -697,16 +697,25 @@ DOMInterfaces = {
     'nativeType': 'nsIChannel',
     'notflattened': True
 },
 
 'MozCellBroadcast': {
     'nativeType': 'mozilla::dom::CellBroadcast',
 },
 
+'MozCellBroadcastEtwsInfo': {
+    'nativeType': 'mozilla::dom::CellBroadcastEtwsInfo',
+    'headerFile': 'CellBroadcastMessage.h'
+},
+
+'MozCellBroadcastMessage': {
+    'nativeType': 'mozilla::dom::CellBroadcastMessage',
+},
+
 'MozIcc': {
     'nativeType': 'mozilla::dom::Icc',
 },
 
 'MozIccManager': {
     'nativeType': 'mozilla::dom::IccManager',
 },
 
--- a/dom/cellbroadcast/CellBroadcast.cpp
+++ b/dom/cellbroadcast/CellBroadcast.cpp
@@ -1,22 +1,23 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "CellBroadcast.h"
+#include "mozilla/dom/CellBroadcast.h"
+#include "mozilla/dom/CellBroadcastMessage.h"
 #include "mozilla/dom/MozCellBroadcastBinding.h"
 #include "mozilla/dom/MozCellBroadcastEvent.h"
-#include "nsIDOMMozCellBroadcastMessage.h"
 #include "nsServiceManagerUtils.h"
 
 #define NS_CELLBROADCASTSERVICE_CONTRACTID "@mozilla.org/cellbroadcast/gonkservice;1"
 
 using namespace mozilla::dom;
+using mozilla::ErrorResult;
 
 /**
  * CellBroadcast::Listener Implementation.
  */
 
 class CellBroadcast::Listener MOZ_FINAL : public nsICellBroadcastListener
 {
 private:
@@ -99,19 +100,43 @@ JSObject*
 CellBroadcast::WrapObject(JSContext* aCx)
 {
   return MozCellBroadcastBinding::Wrap(aCx, this);
 }
 
 // Forwarded nsICellBroadcastListener methods
 
 NS_IMETHODIMP
-CellBroadcast::NotifyMessageReceived(nsIDOMMozCellBroadcastMessage* aMessage)
-{
+CellBroadcast::NotifyMessageReceived(uint32_t aServiceId,
+                                     const nsAString& aGsmGeographicalScope,
+                                     uint16_t aMessageCode,
+                                     uint16_t aMessageId,
+                                     const nsAString& aLanguage,
+                                     const nsAString& aBody,
+                                     const nsAString& aMessageClass,
+                                     DOMTimeStamp aTimestamp,
+                                     uint32_t aCdmaServiceCategory,
+                                     bool aHasEtwsInfo,
+                                     const nsAString& aEtwsWarningType,
+                                     bool aEtwsEmergencyUserAlert,
+                                     bool aEtwsPopup) {
   MozCellBroadcastEventInit init;
   init.mBubbles = true;
   init.mCancelable = false;
-  init.mMessage = aMessage;
+  init.mMessage = new CellBroadcastMessage(GetOwner(),
+                                           aServiceId,
+                                           aGsmGeographicalScope,
+                                           aMessageCode,
+                                           aMessageId,
+                                           aLanguage,
+                                           aBody,
+                                           aMessageClass,
+                                           aTimestamp,
+                                           aCdmaServiceCategory,
+                                           aHasEtwsInfo,
+                                           aEtwsWarningType,
+                                           aEtwsEmergencyUserAlert,
+                                           aEtwsPopup);
 
   nsRefPtr<MozCellBroadcastEvent> event =
     MozCellBroadcastEvent::Constructor(this, NS_LITERAL_STRING("received"), init);
   return DispatchTrustedEvent(event);
 }
new file mode 100644
--- /dev/null
+++ b/dom/cellbroadcast/CellBroadcastMessage.cpp
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "CellBroadcastMessage.h"
+#include "mozilla/dom/MozCellBroadcastMessageBinding.h"
+#include "nsPIDOMWindow.h"
+
+#define CONVERT_STRING_TO_NULLABLE_ENUM(_string, _enumType, _enum)      \
+{                                                                       \
+  _enum.SetNull();                                                      \
+                                                                        \
+  uint32_t i = 0;                                                       \
+  for (const EnumEntry* entry = _enumType##Values::strings;             \
+       entry->value;                                                    \
+       ++entry, ++i) {                                                  \
+    if (_string.EqualsASCII(entry->value)) {                            \
+      _enum.SetValue(static_cast<_enumType>(i));                        \
+    }                                                                   \
+  }                                                                     \
+}
+
+namespace mozilla {
+namespace dom {
+
+/**
+ * CellBroadcastMessage Implementation.
+ */
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CellBroadcastMessage, mWindow, mEtwsInfo)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(CellBroadcastMessage)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(CellBroadcastMessage)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CellBroadcastMessage)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+CellBroadcastMessage::CellBroadcastMessage(nsPIDOMWindow* aWindow,
+                                           uint32_t aServiceId,
+                                           const nsAString& aGsmGeographicalScope,
+                                           uint16_t aMessageCode,
+                                           uint16_t aMessageId,
+                                           const nsAString& aLanguage,
+                                           const nsAString& aBody,
+                                           const nsAString& aMessageClass,
+                                           uint64_t aTimestamp,
+                                           uint32_t aCdmaServiceCategory,
+                                           bool aHasEtwsInfo,
+                                           const nsAString& aEtwsWarningType,
+                                           bool aEtwsEmergencyUserAlert,
+                                           bool aEtwsPopup)
+  : mWindow(aWindow)
+  , mServiceId(aServiceId)
+  , mMessageCode(aMessageCode)
+  , mMessageId(aMessageId)
+  , mLanguage(aLanguage)
+  , mBody(aBody)
+  , mTimestamp(aTimestamp)
+  , mEtwsInfo(aHasEtwsInfo ? new CellBroadcastEtwsInfo(aWindow,
+                                                       aEtwsWarningType,
+                                                       aEtwsEmergencyUserAlert,
+                                                       aEtwsPopup)
+                           : nullptr)
+{
+  CONVERT_STRING_TO_NULLABLE_ENUM(aGsmGeographicalScope,
+                                  CellBroadcastGsmGeographicalScope,
+                                  mGsmGeographicalScope)
+
+  CONVERT_STRING_TO_NULLABLE_ENUM(aMessageClass,
+                                  CellBroadcastMessageClass,
+                                  mMessageClass)
+
+  // CdmaServiceCategory represents a 16bit unsigned value.
+  if (aCdmaServiceCategory > 0xFFFFU) {
+    mCdmaServiceCategory.SetNull();
+  } else {
+    mCdmaServiceCategory.SetValue(static_cast<uint16_t>(aCdmaServiceCategory));
+  }
+
+  SetIsDOMBinding();
+}
+
+JSObject*
+CellBroadcastMessage::WrapObject(JSContext* aCx)
+{
+  return MozCellBroadcastMessageBinding::Wrap(aCx, this);
+}
+
+already_AddRefed<CellBroadcastEtwsInfo>
+CellBroadcastMessage::GetEtws() const
+{
+  nsRefPtr<CellBroadcastEtwsInfo> etwsInfo = mEtwsInfo;
+  return etwsInfo.forget();
+}
+
+/**
+ * CellBroadcastEtwsInfo Implementation.
+ */
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CellBroadcastEtwsInfo, mWindow)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(CellBroadcastEtwsInfo)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(CellBroadcastEtwsInfo)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CellBroadcastEtwsInfo)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+CellBroadcastEtwsInfo::CellBroadcastEtwsInfo(nsPIDOMWindow* aWindow,
+                                             const nsAString& aWarningType,
+                                             bool aEmergencyUserAlert,
+                                             bool aPopup)
+  : mWindow(aWindow)
+  , mEmergencyUserAlert(aEmergencyUserAlert)
+  , mPopup(aPopup)
+{
+  CONVERT_STRING_TO_NULLABLE_ENUM(aWarningType,
+                                  CellBroadcastEtwsWarningType,
+                                  mWarningType)
+
+  SetIsDOMBinding();
+}
+
+JSObject*
+CellBroadcastEtwsInfo::WrapObject(JSContext* aCx)
+{
+  return MozCellBroadcastEtwsInfoBinding::Wrap(aCx, this);
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/cellbroadcast/CellBroadcastMessage.h
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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_cellbroadcast_CellBroadcastMessage_h
+#define mozilla_dom_cellbroadcast_CellBroadcastMessage_h
+
+#include "mozilla/dom/MozCellBroadcastMessageBinding.h"
+#include "nsAutoPtr.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsWrapperCache.h"
+
+class nsPIDOMWindow;
+
+namespace mozilla {
+namespace dom {
+
+class CellBroadcastEtwsInfo;
+
+class CellBroadcastMessage MOZ_FINAL : public nsISupports
+                                     , public nsWrapperCache
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CellBroadcastMessage)
+
+  CellBroadcastMessage(nsPIDOMWindow* aWindow,
+                       uint32_t aServiceId,
+                       const nsAString& aGsmGeographicalScope,
+                       uint16_t aMessageCode,
+                       uint16_t aMessageId,
+                       const nsAString& aLanguage,
+                       const nsAString& aBody,
+                       const nsAString& aMessageClass,
+                       uint64_t aTimestamp,
+                       uint32_t aCdmaServiceCategory,
+                       bool aHasEtwsInfo,
+                       const nsAString& aEtwsWarningType,
+                       bool aEtwsEmergencyUserAlert,
+                       bool aEtwsPopup);
+
+  nsPIDOMWindow*
+  GetParentObject() const { return mWindow; }
+
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  // WebIDL interface
+
+  uint32_t ServiceId() const { return mServiceId; }
+
+  const Nullable<CellBroadcastGsmGeographicalScope>&
+  GetGsmGeographicalScope() { return mGsmGeographicalScope; }
+
+  uint16_t MessageCode() const { return mMessageCode; }
+
+  uint16_t MessageId() const { return mMessageId; }
+
+  void GetLanguage(nsString& aLanguage) const { aLanguage = mLanguage; }
+
+  void GetBody(nsString& aBody) const { aBody = mBody; }
+
+  const Nullable<CellBroadcastMessageClass>&
+  GetMessageClass() { return mMessageClass; }
+
+  uint64_t Timestamp() const { return mTimestamp; }
+
+  // Mark this as resultNotAddRefed to return raw pointers
+  already_AddRefed<CellBroadcastEtwsInfo> GetEtws() const;
+
+  const Nullable<uint16_t>& GetCdmaServiceCategory() { return mCdmaServiceCategory; };
+
+private:
+  // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
+  ~CellBroadcastMessage() {};
+
+  // Don't try to use the default constructor.
+  CellBroadcastMessage();
+
+  nsCOMPtr<nsPIDOMWindow> mWindow;
+  uint32_t mServiceId;
+  Nullable<CellBroadcastGsmGeographicalScope> mGsmGeographicalScope;
+  uint16_t mMessageCode;
+  uint16_t mMessageId;
+  nsString mLanguage;
+  nsString mBody;
+  Nullable<CellBroadcastMessageClass> mMessageClass;
+  uint64_t mTimestamp;
+  Nullable<uint16_t> mCdmaServiceCategory;
+  nsRefPtr<CellBroadcastEtwsInfo> mEtwsInfo;
+};
+
+class CellBroadcastEtwsInfo MOZ_FINAL : public nsISupports
+                                      , public nsWrapperCache
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CellBroadcastEtwsInfo)
+
+  CellBroadcastEtwsInfo(nsPIDOMWindow* aWindow,
+                        const nsAString& aWarningType,
+                        bool aEmergencyUserAlert,
+                        bool aPopup);
+
+  nsPIDOMWindow*
+  GetParentObject() const { return mWindow; }
+
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  // WebIDL interface
+
+  const Nullable<CellBroadcastEtwsWarningType>&
+  GetWarningType()  { return mWarningType; }
+
+  bool EmergencyUserAlert() const { return mEmergencyUserAlert; }
+
+  bool Popup() const { return mPopup; }
+
+private:
+  // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
+  ~CellBroadcastEtwsInfo() {};
+
+  // Don't try to use the default constructor.
+  CellBroadcastEtwsInfo();
+
+  nsCOMPtr<nsPIDOMWindow> mWindow;
+  Nullable<CellBroadcastEtwsWarningType> mWarningType;
+  bool mEmergencyUserAlert;
+  bool mPopup;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_cellbroadcast_CellBroadcastMessage_h
--- a/dom/cellbroadcast/gonk/CellBroadcastService.js
+++ b/dom/cellbroadcast/gonk/CellBroadcastService.js
@@ -27,95 +27,16 @@ const CELLBROADCASTETWSINFO_CID =
 
 const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
 
 let DEBUG;
 function debug(s) {
   dump("CellBroadcastService: " + s);
 }
 
-function CellBroadcastMessage(aServiceId,
-                              aGsmGeographicalScope,
-                              aMessageCode,
-                              aMessageId,
-                              aLanguage,
-                              aBody,
-                              aMessageClass,
-                              aTimestamp,
-                              aCdmaServiceCategory,
-                              aHasEtwsInfo,
-                              aEtwsWarningType,
-                              aEtwsEmergencyUserAlert,
-                              aEtwsPopup) {
-  this.serviceId = aServiceId;
-  this.gsmGeographicalScope = aGsmGeographicalScope;
-  this.messageCode = aMessageCode;
-  this.messageId = aMessageId;
-  this.language = aLanguage;
-  this.body = aBody;
-  this.messageClass = aMessageClass;
-  this.timestamp = aTimestamp;
-
-  this.cdmaServiceCategory = aCdmaServiceCategory;
-
-  if (aHasEtwsInfo) {
-    this.etws = new CellBroadcastEtwsInfo(aEtwsWarningType,
-                                          aEtwsEmergencyUserAlert,
-                                          aEtwsPopup);
-  }
-}
-CellBroadcastMessage.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCellBroadcastMessage]),
-  classID:        CELLBROADCASTMESSAGE_CID,
-  classInfo:      XPCOMUtils.generateCI({
-    classID:          CELLBROADCASTMESSAGE_CID,
-    classDescription: "CellBroadcastMessage",
-    flags:            Ci.nsIClassInfo.DOM_OBJECT,
-    interfaces:       [Ci.nsIDOMMozCellBroadcastMessage]
-  }),
-
-  // nsIDOMMozCellBroadcastMessage
-  serviceId: -1,
-
-  gsmGeographicalScope: null,
-  messageCode: null,
-  messageId: null,
-  language: null,
-  body: null,
-  messageClass: null,
-  timestamp: null,
-
-  etws: null,
-  cdmaServiceCategory: null
-};
-
-function CellBroadcastEtwsInfo(aEtwsWarningType,
-                               aEtwsEmergencyUserAlert,
-                               aEtwsPopup) {
-  this.warningType = aEtwsWarningType;
-  this.emergencyUserAlert = aEtwsEmergencyUserAlert;
-  this.popup = aEtwsPopup;
-}
-CellBroadcastEtwsInfo.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCellBroadcastEtwsInfo]),
-  classID:        CELLBROADCASTETWSINFO_CID,
-  classInfo:      XPCOMUtils.generateCI({
-    classID:          CELLBROADCASTETWSINFO_CID,
-    classDescription: "CellBroadcastEtwsInfo",
-    flags:            Ci.nsIClassInfo.DOM_OBJECT,
-    interfaces:       [Ci.nsIDOMMozCellBroadcastEtwsInfo]
-  }),
-
-  // nsIDOMMozCellBroadcastEtwsInfo
-
-  warningType: null,
-  emergencyUserAlert: null,
-  popup: null
-};
-
 function CellBroadcastService() {
   this._listeners = [];
 
   this._updateDebugFlag();
 
   Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 }
 CellBroadcastService.prototype = {
@@ -174,36 +95,31 @@ CellBroadcastService.prototype = {
                                   aBody,
                                   aMessageClass,
                                   aTimestamp,
                                   aCdmaServiceCategory,
                                   aHasEtwsInfo,
                                   aEtwsWarningType,
                                   aEtwsEmergencyUserAlert,
                                   aEtwsPopup) {
-    let message = new CellBroadcastMessage(aServiceId,
-                                           aGsmGeographicalScope,
-                                           aMessageCode,
-                                           aMessageId,
-                                           aLanguage,
-                                           aBody,
-                                           aMessageClass,
-                                           aTimestamp,
-                                           aCdmaServiceCategory,
-                                           aHasEtwsInfo,
-                                           aEtwsWarningType,
-                                           aEtwsEmergencyUserAlert,
-                                           aEtwsPopup);
-
     for (let listener of this._listeners) {
       try {
-        // TODO:
-        // Deflate 'message' object to multiple parameters by redefining
-        // nsICellBroadcastListener for IPC implementation.
-        listener.notifyMessageReceived(message);
+        listener.notifyMessageReceived(aServiceId,
+                                       aGsmGeographicalScope,
+                                       aMessageCode,
+                                       aMessageId,
+                                       aLanguage,
+                                       aBody,
+                                       aMessageClass,
+                                       aTimestamp,
+                                       aCdmaServiceCategory,
+                                       aHasEtwsInfo,
+                                       aEtwsWarningType,
+                                       aEtwsEmergencyUserAlert,
+                                       aEtwsPopup);
       } catch (e) {
         debug("listener threw an exception: " + e);
       }
     }
   },
 
   /**
    * nsIObserver interface.
--- a/dom/cellbroadcast/interfaces/moz.build
+++ b/dom/cellbroadcast/interfaces/moz.build
@@ -1,17 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 XPIDL_SOURCES += [
     'nsICellBroadcastService.idl',
-    'nsIDOMMozCellBroadcastMessage.idl',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
     XPIDL_SOURCES += [
         'nsIGonkCellBroadcastService.idl',
     ]
 
 XPIDL_MODULE = 'dom_cellbroadcast'
--- a/dom/cellbroadcast/interfaces/nsICellBroadcastService.idl
+++ b/dom/cellbroadcast/interfaces/nsICellBroadcastService.idl
@@ -1,26 +1,34 @@
 /* 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 "domstubs.idl"
 #include "nsISupports.idl"
 
-interface nsIDOMMozCellBroadcastMessage;
-
-[scriptable, uuid(e70bb4cc-2297-11e4-aecd-9f8fb3d2b646)]
+[scriptable, uuid(fd1f9efa-3d6c-11e4-a7be-e3b99e7f903b)]
 interface nsICellBroadcastListener : nsISupports
 {
   /**
    * Called when a Cell Broadcast message has been received by the network.
-   *
-   * @param message
-   *        The received Cell Broadcast Message.
    */
-  void notifyMessageReceived(in nsIDOMMozCellBroadcastMessage message);
+  void notifyMessageReceived(in unsigned long aServiceId,
+                             in DOMString aGsmGeographicalScope,
+                             in unsigned short aMessageCode,
+                             in unsigned short aMessageId,
+                             in DOMString aLanguage,
+                             in DOMString aBody,
+                             in DOMString aMessageClass,
+                             in DOMTimeStamp aTimestamp,
+                             in unsigned long aCdmaServiceCategory,
+                             in boolean aHasEtwsInfo,
+                             in DOMString aEtwsWarningType,
+                             in boolean aEtwsEmergencyUserAlert,
+                             in boolean aEtwsPopup);
 };
 
 /**
  * XPCOM component that provides the cell broadcast information.
  */
 [scriptable, uuid(05099b34-21f7-11e4-b3b9-1b1b03487cab)]
 interface nsICellBroadcastService : nsISupports
 {
--- a/dom/cellbroadcast/interfaces/nsIGonkCellBroadcastService.idl
+++ b/dom/cellbroadcast/interfaces/nsIGonkCellBroadcastService.idl
@@ -1,13 +1,12 @@
 /* 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 "domstubs.idl"
 #include "nsICellBroadcastService.idl"
 
 [scriptable, uuid(f72ced60-21f9-11e4-8896-6fdff2f5c909)]
 interface nsIGonkCellBroadcastService : nsICellBroadcastService
 {
   /**
    * Called when a cellbroadcast message has been received by the network.
    */
--- a/dom/cellbroadcast/moz.build
+++ b/dom/cellbroadcast/moz.build
@@ -3,20 +3,22 @@
 # 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/.
 
 DIRS += ['interfaces']
 
 EXPORTS.mozilla.dom += [
     'CellBroadcast.h',
+    'CellBroadcastMessage.h',
 ]
 
 SOURCES += [
     'CellBroadcast.cpp',
+    'CellBroadcastMessage.cpp',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
     EXTRA_COMPONENTS += [
         'gonk/CellBroadcastService.js',
         'gonk/CellBroadcastService.manifest',
     ]
 
--- a/dom/cellbroadcast/tests/marionette/test_cellbroadcast_etws.js
+++ b/dom/cellbroadcast/tests/marionette/test_cellbroadcast_etws.js
@@ -18,17 +18,19 @@ function testReceiving_ETWS_MessageAttri
     ok(aMessage.body == null, "aMessage.body");
     is(aMessage.messageClass, "normal", "aMessage.messageClass");
     ok(aMessage.timestamp != null, "aMessage.timestamp");
     ok(aMessage.etws != null, "aMessage.etws");
     ok(aMessage.etws.warningType != null, "aMessage.etws.warningType");
     ok(aMessage.etws.emergencyUserAlert != null,
        "aMessage.etws.emergencyUserAlert");
     ok(aMessage.etws.popup != null, "aMessage.etws.popup");
-    ok(aMessage.cdmaServiceCategory != null, "aMessage.cdmaServiceCategory");
+
+    // cdmaServiceCategory shall always be unavailable in GMS/UMTS CB message.
+    ok(aMessage.cdmaServiceCategory == null, "aMessage.cdmaServiceCategory");
   };
 
   // Here we use a simple ETWS message for test.
   let pdu = buildHexStr(0, CB_MESSAGE_SIZE_ETWS * 2); // 6 octets
 
   return sendMultipleRawCbsToEmulatorAndWait([pdu])
     .then((aMessage) => verifyCBMessage(aMessage));
 }
--- a/dom/cellbroadcast/tests/marionette/test_cellbroadcast_gsm.js
+++ b/dom/cellbroadcast/tests/marionette/test_cellbroadcast_gsm.js
@@ -17,17 +17,19 @@ function testReceiving_GSM_MessageAttrib
     ok(aMessage.messageClass != null, "aMessage.messageClass");
     ok(aMessage.timestamp != null, "aMessage.timestamp");
     ok('etws' in aMessage, "aMessage.etws");
     if (aMessage.etws) {
       ok('warningType' in aMessage.etws, "aMessage.etws.warningType");
       ok(aMessage.etws.emergencyUserAlert != null, "aMessage.etws.emergencyUserAlert");
       ok(aMessage.etws.popup != null, "aMessage.etws.popup");
     }
-    ok(aMessage.cdmaServiceCategory != null, "aMessage.cdmaServiceCategory");
+
+    // cdmaServiceCategory shall always be unavailable in GMS/UMTS CB message.
+    ok(aMessage.cdmaServiceCategory == null, "aMessage.cdmaServiceCategory");
   };
 
   // Here we use a simple GSM message for test.
   let pdu = buildHexStr(0, CB_MESSAGE_SIZE_GSM * 2);
 
   return sendMultipleRawCbsToEmulatorAndWait([pdu])
     .then((aMessage) => verifyCBMessage(aMessage));
 }
@@ -291,30 +293,16 @@ function testReceiving_GSM_Multipart() {
     promise = promise
       .then(() => sendMultipleRawCbsToEmulatorAndWait(pdus))
       .then((aMessage) => verifyCBMessage(aMessage, aNumParts));
   });
 
   return promise;
 }
 
-function testReceiving_GSM_ServiceCategory() {
-  log("Test receiving GSM Cell Broadcast - Service Category");
-
-  let verifyCBMessage = (aMessage) => {
-    // Bug 910091
-    // "Service Category" is not defined in GSM.  We should always get '0' here.
-    is(aMessage.cdmaServiceCategory, 0, "aMessage.cdmaServiceCategory");
-  };
-
-  let pdu = buildHexStr(0, CB_MESSAGE_SIZE_GSM * 2);
-  return sendMultipleRawCbsToEmulatorAndWait([pdu])
-    .then((aMessage) => verifyCBMessage(aMessage));
-}
-
 function testReceiving_GSM_PaddingCharacters() {
   log("Test receiving GSM Cell Broadcast - Padding Characters <CR>");
 
   let promise = Promise.resolve();
 
   let testContents = [
     { pdu:
         // CB PDU with GSM 7bit encoded text of
@@ -364,11 +352,10 @@ startTestCommon(function testCaseMain() 
     .then(() => testReceiving_GSM_MessageCode())
     .then(() => testReceiving_GSM_MessageId())
     .then(() => testReceiving_GSM_Language_and_Body())
     .then(() => testReceiving_GSM_Timestamp())
     .then(() => testReceiving_GSM_WarningType())
     .then(() => testReceiving_GSM_EmergencyUserAlert())
     .then(() => testReceiving_GSM_Popup())
     .then(() => testReceiving_GSM_Multipart())
-    .then(() => testReceiving_GSM_ServiceCategory())
     .then(() => testReceiving_GSM_PaddingCharacters());
 });
--- a/dom/cellbroadcast/tests/marionette/test_cellbroadcast_umts.js
+++ b/dom/cellbroadcast/tests/marionette/test_cellbroadcast_umts.js
@@ -15,17 +15,19 @@ function testReceiving_UMTS_MessageAttri
     ok(aMessage.messageClass != null, "aMessage.messageClass");
     ok(aMessage.timestamp != null, "aMessage.timestamp");
     ok('etws' in aMessage, "aMessage.etws");
     if (aMessage.etws) {
       ok('warningType' in aMessage.etws, "aMessage.etws.warningType");
       ok(aMessage.etws.emergencyUserAlert != null, "aMessage.etws.emergencyUserAlert");
       ok(aMessage.etws.popup != null, "aMessage.etws.popup");
     }
-    ok(aMessage.cdmaServiceCategory != null, "aMessage.cdmaServiceCategory");
+
+    // cdmaServiceCategory shall always be unavailable in GMS/UMTS CB message.
+    ok(aMessage.cdmaServiceCategory == null, "aMessage.cdmaServiceCategory");
   };
 
   // Here we use a single UMTS message for test.
   let pdu = buildHexStr(CB_UMTS_MESSAGE_TYPE_CBS, 2) // msg_type
           + buildHexStr(0, 10) // skip msg_id, sn, dcs
           + buildHexStr(1, 2)  // set num_of_pages to 1
           + buildHexStr(0, CB_UMTS_MESSAGE_PAGE_SIZE * 2)
           + buildHexStr(CB_UMTS_MESSAGE_PAGE_SIZE, 2); // msg_info_length
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -672,16 +672,20 @@ var interfaceNamesInGlobalScope =
     "MouseScrollEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozActivity", b2g: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozCellBroadcast", b2g: true, pref: "dom.cellbroadcast.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozCellBroadcastEvent", b2g: true, pref: "dom.cellbroadcast.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MozCellBroadcastEtwsInfo", b2g: true, pref: "dom.cellbroadcast.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MozCellBroadcastMessage", b2g: true, pref: "dom.cellbroadcast.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozClirModeEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "mozContact",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MozContactChangeEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MozCSSKeyframeRule",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/webidl/MozCellBroadcastEvent.webidl
+++ b/dom/webidl/MozCellBroadcastEvent.webidl
@@ -1,14 +1,13 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/.
  */
-interface MozCellBroadcastMessage;
 
 [Constructor(DOMString type, optional MozCellBroadcastEventInit eventInitDict), Pref="dom.cellbroadcast.enabled"]
 interface MozCellBroadcastEvent : Event
 {
   readonly attribute MozCellBroadcastMessage? message;
 };
 
 dictionary MozCellBroadcastEventInit : EventInit
rename from dom/cellbroadcast/interfaces/nsIDOMMozCellBroadcastMessage.idl
rename to dom/webidl/MozCellBroadcastMessage.webidl
--- a/dom/cellbroadcast/interfaces/nsIDOMMozCellBroadcastMessage.idl
+++ b/dom/webidl/MozCellBroadcastMessage.webidl
@@ -1,36 +1,36 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=40: */
 /* 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 "domstubs.idl"
-#include "nsISupports.idl"
-
-interface nsIDOMMozCellBroadcastEtwsInfo;
+enum CellBroadcastGsmGeographicalScope {"cell-immediate", "plmn",
+                                        "location-area", "cell"};
+enum CellBroadcastMessageClass {"normal", "class-0", "class-1", "class-2",
+                                "class-3", "user-1", "user-2"};
+enum CellBroadcastEtwsWarningType {"earthquake", "tsunami",
+                                   "earthquake-tsunami", "test", "other"};
 
-/**
- * MozCellBroadcastMessage encapsulates Cell Broadcast short message service
- * (CBS) messages.
- */
-[scriptable, uuid(dc729df4-f1d8-11e3-b00d-d3332542c557)]
-interface nsIDOMMozCellBroadcastMessage : nsISupports
+[Pref="dom.cellbroadcast.enabled"]
+interface MozCellBroadcastMessage
 {
   /**
    * The Service Id in the device where the message is received from.
    */
   readonly attribute unsigned long serviceId;
 
   /**
    * Indication of the geographical area over which the Message Code is unique,
    * and the display mode.
    *
    * Possible values are: "cell-immediate", "plmn", "location-area" and "cell".
    */
-  readonly attribute DOMString gsmGeographicalScope;
+  readonly attribute CellBroadcastGsmGeographicalScope? gsmGeographicalScope;
 
   /**
    * The Message Code differentiates between messages from the same source and
    * type (e.g., with the same Message Identifier).
    */
   readonly attribute unsigned short messageCode;
 
   /**
@@ -38,64 +38,59 @@ interface nsIDOMMozCellBroadcastMessage 
    * (= source), "Traffic Reports" (= type) could correspond to one value. The
    * Message Identifier is coded in binary.
    */
   readonly attribute unsigned short messageId;
 
   /**
    * ISO-639-1 language code for this message. Null if unspecified.
    */
-  readonly attribute DOMString language;
+  readonly attribute DOMString? language;
 
   /**
    * Text message carried by the message.
    */
-  readonly attribute DOMString body;
+  readonly attribute DOMString? body;
 
   /**
    * Possible values are "normal", "class-0", "class-1", "class-2", "class-3",
    * "user-1", and "user-2".
    */
-  readonly attribute DOMString messageClass;
+  readonly attribute CellBroadcastMessageClass? messageClass;
 
   /**
    * System time stamp at receival.
    */
   readonly attribute DOMTimeStamp timestamp;
 
   /**
    * Additional ETWS-specific info.
    */
-  readonly attribute nsIDOMMozCellBroadcastEtwsInfo etws;
+  readonly attribute MozCellBroadcastEtwsInfo? etws;
 
   /**
    * Service Category.
    */
-  readonly attribute long cdmaServiceCategory;
+  readonly attribute unsigned short? cdmaServiceCategory;
 };
 
-/**
- * ETWS (Earthquake and Tsunami Warning service) Primary Notification message
- * specific information.
- */
-[scriptable, uuid(af009d9a-f5e8-4573-a6ee-a85118465bed)]
-interface nsIDOMMozCellBroadcastEtwsInfo : nsISupports
+[Pref="dom.cellbroadcast.enabled"]
+interface MozCellBroadcastEtwsInfo
 {
   /**
    * Warning type. Possible values are "earthquake", "tsunami",
    * "earthquake-tsunami", "test" and "other".
    */
-  readonly attribute ACString warningType;
+  readonly attribute CellBroadcastEtwsWarningType? warningType;
 
   /**
    * Emergency user alert indication. It is used to command mobile terminals to
    * activate emergency user alert upon the reception of ETWS primary
    * notification.
    */
   readonly attribute boolean emergencyUserAlert;
 
   /**
    * Message popup indication. It is used to command mobile terminals to
    * activate message popup upon the reception of ETWS primary notification.
    */
   readonly attribute boolean popup;
 };
-
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -259,16 +259,17 @@ WEBIDL_FILES = [
     'MessageEvent.webidl',
     'MessagePort.webidl',
     'MessagePortList.webidl',
     'MimeType.webidl',
     'MimeTypeArray.webidl',
     'MouseEvent.webidl',
     'MouseScrollEvent.webidl',
     'MozActivity.webidl',
+    'MozCellBroadcastMessage.webidl',
     'MozMmsMessage.webidl',
     'MozMobileCellInfo.webidl',
     'MozMobileConnection.webidl',
     'MozMobileConnectionArray.webidl',
     'MozMobileConnectionInfo.webidl',
     'MozMobileMessageManager.webidl',
     'MozMobileNetworkInfo.webidl',
     'MozPowerManager.webidl',