Bug 1401678 - Proxy nsISound::beep() and nsISound::play() calls from the content process to the parent process and beep away there. r=bkelly
☠☠ backed out by ed0bf93e0415 ☠ ☠
authorMike de Boer <mdeboer@mozilla.com>
Fri, 12 Jan 2018 19:14:44 +0100
changeset 453399 19af171d77189ac5a35fd2d471b78884d764bc6a
parent 453398 d40da09bed641cb7638d1e9cc96d6ab1edda8189
child 453405 9da066f5cf32327b5bdfeb66e3e58382428b2bc8
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbkelly
bugs1401678
milestone59.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 1401678 - Proxy nsISound::beep() and nsISound::play() calls from the content process to the parent process and beep away there. r=bkelly MozReview-Commit-ID: J7NwDeVYvQw
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
widget/moz.build
widget/nsContentProcessWidgetFactory.cpp
widget/nsSoundProxy.cpp
widget/nsSoundProxy.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -137,20 +137,22 @@
 #include "nsIMutable.h"
 #include "nsIObserverService.h"
 #include "nsIParentChannel.h"
 #include "nsIPresShell.h"
 #include "nsIRemoteWindowContext.h"
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISiteSecurityService.h"
+#include "nsISound.h"
 #include "nsISpellChecker.h"
 #include "nsISupportsPrimitives.h"
 #include "nsITimer.h"
 #include "nsIURIFixup.h"
+#include "nsIURL.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIXULWindow.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIWindowWatcher.h"
 #include "nsPIWindowWatcher.h"
 #include "nsThread.h"
 #include "nsWindowWatcher.h"
 #include "nsIXULRuntime.h"
@@ -2666,16 +2668,52 @@ ContentParent::RecvClipboardHasType(nsTA
   clipboard->HasDataMatchingFlavors(typesChrs, aTypes.Length(),
                                     aWhichClipboard, aHasType);
 
   delete [] typesChrs;
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
+ContentParent::RecvPlaySound(const URIParams& aURI)
+{
+  nsCOMPtr<nsIURI> soundURI = DeserializeURI(aURI);
+  bool isChrome = false;
+  // If the check here fails, it can only mean that this message was spoofed.
+  if (!soundURI || NS_FAILED(soundURI->SchemeIs("chrome", &isChrome)) || !isChrome) {
+    KillHard("PlaySound only accepts a valid chrome URI.");
+    return IPC_OK();
+  }
+  nsCOMPtr<nsIURL> soundURL(do_QueryInterface(soundURI));
+  if (!soundURL) {
+    return IPC_OK();
+  }
+
+  nsresult rv;
+  nsCOMPtr<nsISound> sound(do_GetService(NS_SOUND_CID, &rv));
+  NS_ENSURE_SUCCESS(rv, IPC_OK());
+
+  sound->Play(soundURL);
+
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+ContentParent::RecvBeep()
+{
+  nsresult rv;
+  nsCOMPtr<nsISound> sound(do_GetService(NS_SOUND_CID, &rv));
+  NS_ENSURE_SUCCESS(rv, IPC_OK());
+
+  sound->Beep();
+
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
 ContentParent::RecvGetSystemColors(const uint32_t& colorsCount,
                                    InfallibleTArray<uint32_t>* colors)
 {
 #ifdef MOZ_WIDGET_ANDROID
   NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
   if (AndroidBridge::Bridge() == nullptr) {
     // Do not fail - the colors won't be right, but it's not critical
     return IPC_OK();
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -985,16 +985,19 @@ private:
                                                    IPCDataTransfer* aDataTransfer) override;
 
   virtual mozilla::ipc::IPCResult RecvEmptyClipboard(const int32_t& aWhichClipboard) override;
 
   virtual mozilla::ipc::IPCResult RecvClipboardHasType(nsTArray<nsCString>&& aTypes,
                                                        const int32_t& aWhichClipboard,
                                                        bool* aHasType) override;
 
+  virtual mozilla::ipc::IPCResult RecvPlaySound(const URIParams& aURI) override;
+  virtual mozilla::ipc::IPCResult RecvBeep() override;
+
   virtual mozilla::ipc::IPCResult RecvGetSystemColors(const uint32_t& colorsCount,
                                                       InfallibleTArray<uint32_t>* colors) override;
 
   virtual mozilla::ipc::IPCResult RecvGetIconForExtension(const nsCString& aFileExt,
                                                           const uint32_t& aIconSize,
                                                           InfallibleTArray<uint8_t>* bits) override;
 
   virtual mozilla::ipc::IPCResult RecvGetShowPasswordSetting(bool* showPassword) override;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -843,16 +843,20 @@ parent:
 
     // Clears the clipboard.
     async EmptyClipboard(int32_t aWhichClipboard);
 
     // Returns true if data of one of the specified types is on the clipboard.
     sync ClipboardHasType(nsCString[] aTypes, int32_t aWhichClipboard)
         returns (bool hasType);
 
+    // 'Play' and 'Beep' are the only nsISound methods used in the content process.
+    async PlaySound(URIParams aURL) compress;
+    async Beep() compress;
+
     sync GetSystemColors(uint32_t colorsCount)
         returns (uint32_t[] colors);
 
     sync GetIconForExtension(nsCString aFileExt, uint32_t aIconSize)
         returns (uint8_t[] bits);
 
     sync GetShowPasswordSetting()
         returns (bool showPassword);
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -185,16 +185,17 @@ UNIFIED_SOURCES += [
     'nsContentProcessWidgetFactory.cpp',
     'nsDragServiceProxy.cpp',
     'nsFilePickerProxy.cpp',
     'nsHTMLFormatConverter.cpp',
     'nsIdleService.cpp',
     'nsIWidgetListener.cpp',
     'nsPrimitiveHelpers.cpp',
     'nsPrintSettingsImpl.cpp',
+    'nsSoundProxy.cpp',
     'nsTransferable.cpp',
     'nsXPLookAndFeel.cpp',
     'PuppetBidiKeyboard.cpp',
     'PuppetWidget.cpp',
     'Screen.cpp',
     'ScreenManager.cpp',
     'SharedWidgetUtils.cpp',
     'TextEventDispatcher.cpp',
--- a/widget/nsContentProcessWidgetFactory.cpp
+++ b/widget/nsContentProcessWidgetFactory.cpp
@@ -6,57 +6,63 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ModuleUtils.h"
 #include "nsWidgetsCID.h"
 #include "nsClipboardProxy.h"
 #include "nsColorPickerProxy.h"
 #include "nsDragServiceProxy.h"
 #include "nsFilePickerProxy.h"
+#include "nsSoundProxy.h"
 #include "mozilla/widget/PuppetBidiKeyboard.h"
 #include "mozilla/widget/ScreenManager.h"
 
 using namespace mozilla;
 using namespace mozilla::widget;
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardProxy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPickerProxy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragServiceProxy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePickerProxy)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsSoundProxy)
 NS_GENERIC_FACTORY_CONSTRUCTOR(PuppetBidiKeyboard)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton)
 
 NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
 NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID);
 NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
+NS_DEFINE_NAMED_CID(NS_SOUND_CID);
 NS_DEFINE_NAMED_CID(PUPPETBIDIKEYBOARD_CID);
 NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
 
 static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
     { &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardProxyConstructor,
       Module::CONTENT_PROCESS_ONLY },
     { &kNS_COLORPICKER_CID, false, nullptr, nsColorPickerProxyConstructor,
       Module::CONTENT_PROCESS_ONLY },
     { &kNS_DRAGSERVICE_CID, false, nullptr, nsDragServiceProxyConstructor,
       Module::CONTENT_PROCESS_ONLY },
     { &kNS_FILEPICKER_CID, false, nullptr, nsFilePickerProxyConstructor,
       Module::CONTENT_PROCESS_ONLY },
+    { &kNS_SOUND_CID, false, nullptr, nsSoundProxyConstructor,
+      Module::CONTENT_PROCESS_ONLY },
     { &kPUPPETBIDIKEYBOARD_CID, false, NULL, PuppetBidiKeyboardConstructor,
       Module::CONTENT_PROCESS_ONLY },
     { &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor,
       Module::CONTENT_PROCESS_ONLY },
     { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
     { "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID, Module::CONTENT_PROCESS_ONLY },
     { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, Module::CONTENT_PROCESS_ONLY },
     { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::CONTENT_PROCESS_ONLY },
     { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID, Module::CONTENT_PROCESS_ONLY },
+    { "@mozilla.org/sound;1", &kNS_SOUND_CID, Module::CONTENT_PROCESS_ONLY },
     { "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, Module::CONTENT_PROCESS_ONLY },
     { "@mozilla.org/widget/bidikeyboard;1", &kPUPPETBIDIKEYBOARD_CID,
       Module::CONTENT_PROCESS_ONLY },
     { nullptr }
 };
 
 static const mozilla::Module kWidgetModule = {
     mozilla::Module::kVersion,
new file mode 100644
--- /dev/null
+++ b/widget/nsSoundProxy.cpp
@@ -0,0 +1,65 @@
+/* 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 "mozilla/dom/ContentChild.h"
+#include "mozilla/ipc/URIUtils.h"
+#include "nsIURL.h"
+#include "nsIURI.h"
+#include "nsSoundProxy.h"
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+NS_IMPL_ISUPPORTS(nsSoundProxy, nsISound)
+
+NS_IMETHODIMP
+nsSoundProxy::Play(nsIURL *aURL)
+{
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
+
+  nsCOMPtr<nsIURI> soundURI(do_QueryInterface(aURL));
+  bool isChrome = false;
+  // Only allow playing a chrome:// URL from the content process.
+  if (!soundURI || NS_FAILED(soundURI->SchemeIs("chrome", &isChrome)) || !isChrome) {
+    return NS_ERROR_FAILURE;
+  }
+
+  mozilla::ipc::URIParams soundParams;
+  mozilla::ipc::SerializeURI(soundURI, soundParams);
+  ContentChild::GetSingleton()->SendPlaySound(soundParams);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSoundProxy::PlaySystemSound(const nsAString &aSoundAlias)
+{
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
+  MOZ_ASSERT(false, "PlaySystemSound is unimplemented.");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsSoundProxy::Beep()
+{
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
+
+  ContentChild::GetSingleton()->SendBeep();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSoundProxy::Init()
+{
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
+  MOZ_ASSERT(false, "Init is unimplemented.");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsSoundProxy::PlayEventSound(uint32_t aEventId)
+{
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
+  MOZ_DIAGNOSTIC_ASSERT(false, "Only called by XUL in the parent process.");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
new file mode 100644
--- /dev/null
+++ b/widget/nsSoundProxy.h
@@ -0,0 +1,23 @@
+/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * 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 NS_SOUND_PROXY_H
+#define NS_SOUND_PROXY_H
+
+#include "nsISound.h"
+
+class nsSoundProxy final : public nsISound
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSISOUND
+
+  nsSoundProxy() = default;
+
+private:
+  ~nsSoundProxy() = default;
+};
+
+#endif