Bug 1232348 - adjust nested-frame checking condition. r=baku.
--- a/dom/browser-element/BrowserElementAudioChannel.cpp
+++ b/dom/browser-element/BrowserElementAudioChannel.cpp
@@ -1,23 +1,25 @@
/* 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 "BrowserElementAudioChannel.h"
+#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/dom/BrowserElementAudioChannelBinding.h"
#include "mozilla/dom/DOMRequest.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/dom/ToJSValue.h"
#include "AudioChannelService.h"
+#include "nsIAppsService.h"
#include "nsIBrowserElementAPI.h"
#include "nsIDocShell.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDOMRequest.h"
#include "nsIObserverService.h"
#include "nsISupportsPrimitives.h"
#include "nsISystemMessagesInternal.h"
#include "nsITabParent.h"
@@ -571,35 +573,24 @@ BrowserElementAudioChannel::Observe(nsIS
if (mTabParent == aSubject) {
ProcessStateChanged(aData);
}
return NS_OK;
}
nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
- // This can be a nested iframe.
if (!wrapper) {
- nsCOMPtr<nsITabParent> iTabParent = do_QueryInterface(aSubject);
- if (!iTabParent) {
- return NS_ERROR_FAILURE;
+ bool isNested = false;
+ nsresult rv = IsFromNestedFrame(aSubject, isNested);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
}
- RefPtr<TabParent> tabParent = TabParent::GetFrom(iTabParent);
- if (!tabParent) {
- return NS_ERROR_FAILURE;
- }
-
- Element* element = tabParent->GetOwnerElement();
- if (!element) {
- return NS_ERROR_FAILURE;
- }
-
- nsCOMPtr<nsPIDOMWindow> window = element->OwnerDoc()->GetWindow();
- if (window == mFrameWindow) {
+ if (isNested) {
ProcessStateChanged(aData);
}
return NS_OK;
}
uint64_t windowID;
nsresult rv = wrapper->GetData(&windowID);
@@ -622,10 +613,83 @@ BrowserElementAudioChannel::ProcessState
("BrowserElementAudioChannel, ProcessStateChanged, this = %p, "
"type = %d\n", this, mAudioChannel));
nsAutoString value(aData);
mState = value.EqualsASCII("active") ? eStateActive : eStateInactive;
DispatchTrustedEvent(NS_LITERAL_STRING("activestatechanged"));
}
+bool
+BrowserElementAudioChannel::IsSystemAppWindow(nsPIDOMWindow* aWindow) const
+{
+ nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
+ if (!doc) {
+ return false;
+ }
+
+ uint32_t appId;
+ nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
+ nsresult rv = principal->GetAppId(&appId);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return false;
+ }
+
+ if (appId == nsIScriptSecurityManager::NO_APP_ID ||
+ appId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
+ return false;
+ }
+
+ nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
+ if (NS_WARN_IF(!appsService)) {
+ return false;
+ }
+
+ nsAdoptingString systemAppManifest =
+ mozilla::Preferences::GetString("b2g.system_manifest_url");
+ if (!systemAppManifest) {
+ return false;
+ }
+
+ uint32_t systemAppId;
+ appsService->GetAppLocalIdByManifestURL(systemAppManifest, &systemAppId);
+
+ if (systemAppId == appId) {
+ return true;
+ }
+
+ return false;
+}
+
+nsresult
+BrowserElementAudioChannel::IsFromNestedFrame(nsISupports* aSubject,
+ bool& aIsNested) const
+{
+ aIsNested = false;
+ nsCOMPtr<nsITabParent> iTabParent = do_QueryInterface(aSubject);
+ if (!iTabParent) {
+ return NS_ERROR_FAILURE;
+ }
+
+ RefPtr<TabParent> tabParent = TabParent::GetFrom(iTabParent);
+ if (!tabParent) {
+ return NS_ERROR_FAILURE;
+ }
+
+ Element* element = tabParent->GetOwnerElement();
+ if (!element) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // Since the normal OOP processes are opened out from b2g process, the owner
+ // of their tabParent are the same - system app window. Therefore, in order
+ // to find the case of nested MozFrame, we need to exclude this situation.
+ nsCOMPtr<nsPIDOMWindow> window = element->OwnerDoc()->GetWindow();
+ if (window == mFrameWindow && !IsSystemAppWindow(window)) {
+ aIsNested = true;
+ return NS_OK;
+ }
+
+ return NS_OK;
+}
+
} // dom namespace
} // mozilla namespace
--- a/dom/browser-element/BrowserElementAudioChannel.h
+++ b/dom/browser-element/BrowserElementAudioChannel.h
@@ -65,16 +65,23 @@ public:
private:
BrowserElementAudioChannel(nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
AudioChannel aAudioChannel,
const nsAString& aManifestURL);
+ bool IsSystemAppWindow(nsPIDOMWindow* aWindow) const;
+
+ // This method is used to check whether we're in the nested-mozbrower-frame
+ // situation, see bug1214148.
+ nsresult IsFromNestedFrame(nsISupports* aSubject,
+ bool& aIsNested) const;
+
~BrowserElementAudioChannel();
nsresult Initialize();
void ProcessStateChanged(const char16_t* aData);
nsCOMPtr<nsIFrameLoader> mFrameLoader;
nsCOMPtr<nsIBrowserElementAPI> mBrowserElementAPI;