Bug 1214148 - patch 3 - correct window for nested iframes, r=alwu
☠☠ backed out by 87e625f2b847 ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 09 Dec 2015 16:46:25 -0500
changeset 310157 e716d9ac93d7099a167dacccbae3e2a1c0664cd5
parent 310156 5f693237c8c1b7c4e632d25dac02c0fb3f156c03
child 310158 f6bdd322412546677d539ec064b68214fd9fc1a6
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersalwu
bugs1214148
milestone45.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 1214148 - patch 3 - correct window for nested iframes, r=alwu
dom/audiochannel/AudioChannelAgent.cpp
dom/audiochannel/AudioChannelAgent.h
--- a/dom/audiochannel/AudioChannelAgent.cpp
+++ b/dom/audiochannel/AudioChannelAgent.cpp
@@ -1,17 +1,21 @@
 /* -*- 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 "AudioChannelAgent.h"
 #include "AudioChannelService.h"
+#include "mozilla/Preferences.h"
+#include "nsIAppsService.h"
+#include "nsIDocument.h"
 #include "nsIDOMWindow.h"
+#include "nsIPrincipal.h"
 #include "nsPIDOMWindow.h"
 #include "nsXULAppAPI.h"
 
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(AudioChannelAgent)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioChannelAgent)
@@ -73,16 +77,91 @@ AudioChannelAgent::InitWithWeakCallback(
                                         int32_t aChannelType,
                                         nsIAudioChannelAgentCallback *aCallback)
 {
   return InitInternal(aWindow, aChannelType, aCallback,
                       /* useWeakRef = */ true);
 }
 
 nsresult
+AudioChannelAgent::FindCorrectWindow(nsIDOMWindow* aWindow)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
+  MOZ_ASSERT(window->IsInnerWindow());
+
+  mWindow = window->GetScriptableTop();
+  if (NS_WARN_IF(!mWindow)) {
+    return NS_OK;
+  }
+
+  mWindow = mWindow->GetOuterWindow();
+  if (NS_WARN_IF(!mWindow)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // From here we do an hack for nested iframes.
+  // The system app doesn't have access to the nested iframe objects so it
+  // cannot control the volume of the agents running in nested apps. What we do
+  // here is to assign those Agents to the top scriptable window of the parent
+  // iframe (what is controlled by the system app).
+  // For doing this we go recursively back into the chain of windows until we
+  // find apps that are not the system one.
+  window = mWindow->GetParent();
+  if (!window || window == mWindow) {
+    return NS_OK;
+  }
+
+  window = window->GetCurrentInnerWindow();
+  if (!window) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
+  if (!doc) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
+
+  uint32_t appId;
+  nsresult rv = principal->GetAppId(&appId);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (appId == nsIScriptSecurityManager::NO_APP_ID ||
+      appId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
+  if (NS_WARN_IF(!appsService)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsAdoptingString systemAppManifest =
+    mozilla::Preferences::GetString("b2g.system_manifest_url");
+  if (!systemAppManifest) {
+    return NS_OK;
+  }
+
+  uint32_t systemAppId;
+  rv = appsService->GetAppLocalIdByManifestURL(systemAppManifest, &systemAppId);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (systemAppId == appId) {
+    return NS_OK;
+  }
+
+  return FindCorrectWindow(window);
+}
+
+nsresult
 AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
                                 nsIAudioChannelAgentCallback *aCallback,
                                 bool aUseWeakRef)
 {
   // We syncd the enum of channel type between nsIAudioChannelAgent.idl and
   // AudioChannelBinding.h the same.
   MOZ_ASSERT(int(AUDIO_AGENT_CHANNEL_NORMAL) == int(AudioChannel::Normal) &&
              int(AUDIO_AGENT_CHANNEL_CONTENT) == int(AudioChannel::Content) &&
@@ -103,28 +182,19 @@ AudioChannelAgent::InitInternal(nsIDOMWi
   if (NS_WARN_IF(!aWindow)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsPIDOMWindow> pInnerWindow = do_QueryInterface(aWindow);
   MOZ_ASSERT(pInnerWindow->IsInnerWindow());
   mInnerWindowID = pInnerWindow->WindowID();
 
-  nsCOMPtr<nsPIDOMWindow> topWindow = pInnerWindow->GetScriptableTop();
-  if (NS_WARN_IF(!topWindow)) {
-    return NS_OK;
-  }
-
-  mWindow = do_QueryInterface(topWindow);
-  if (mWindow) {
-    mWindow = mWindow->GetOuterWindow();
-  }
-
-  if (NS_WARN_IF(!mWindow)) {
-    return NS_ERROR_FAILURE;
+  nsresult rv = FindCorrectWindow(aWindow);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
   }
 
   mAudioChannelType = aChannelType;
 
   if (aUseWeakRef) {
     mWeakCallback = do_GetWeakReference(aCallback);
   } else {
     mCallback = aCallback;
--- a/dom/audiochannel/AudioChannelAgent.h
+++ b/dom/audiochannel/AudioChannelAgent.h
@@ -51,16 +51,18 @@ private:
   already_AddRefed<nsIAudioChannelAgentCallback> GetCallback();
 
   nsresult InitInternal(nsIDOMWindow* aWindow, int32_t aAudioAgentType,
                         nsIAudioChannelAgentCallback* aCallback,
                         bool aUseWeakRef);
 
   void Shutdown();
 
+  nsresult FindCorrectWindow(nsIDOMWindow* aWindow);
+
   nsCOMPtr<nsPIDOMWindow> mWindow;
   nsCOMPtr<nsIAudioChannelAgentCallback> mCallback;
 
   nsWeakPtr mWeakCallback;
 
   int32_t mAudioChannelType;
   uint64_t mInnerWindowID;
   bool mIsRegToService;