Bug 1167465 - Exposing Allowed Audio Channels in System App's Window, r=alwu, r=fabrice

This commit is contained in:
Andrea Marchesini 2015-09-23 08:12:52 +01:00
parent 71920a9550
commit 5bd948cce6
8 changed files with 195 additions and 51 deletions

View File

@ -498,6 +498,11 @@ this.PermissionsTable = { geolocation: {
privileged: ALLOW_ACTION,
certified: ALLOW_ACTION
},
"system-app-only-audio-channels-in-app": {
app: DENY_ACTION,
privileged: DENY_ACTION,
certified: ALLOW_ACTION
},
"killswitch": {
app: DENY_ACTION,
trusted: DENY_ACTION,

View File

@ -45,6 +45,24 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(BrowserElementAudioChannel,
mTabParent,
mBrowserElementAPI)
/* static */ already_AddRefed<BrowserElementAudioChannel>
BrowserElementAudioChannel::Create(nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
AudioChannel aAudioChannel,
ErrorResult& aRv)
{
nsRefPtr<BrowserElementAudioChannel> ac =
new BrowserElementAudioChannel(aWindow, aFrameLoader, aAPI, aAudioChannel);
aRv = ac->Initialize();
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
return ac.forget();
}
BrowserElementAudioChannel::BrowserElementAudioChannel(
nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
@ -58,7 +76,6 @@ BrowserElementAudioChannel::BrowserElementAudioChannel(
{
MOZ_ASSERT(NS_IsMainThread());
AssertIsInMainProcess();
MOZ_ASSERT(mFrameLoader);
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
@ -94,6 +111,20 @@ BrowserElementAudioChannel::~BrowserElementAudioChannel()
nsresult
BrowserElementAudioChannel::Initialize()
{
if (!mFrameLoader) {
nsCOMPtr<nsPIDOMWindow> window = GetOwner();
if (!window) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMWindow> topWindow;
window->GetScriptableTop(getter_AddRefs(topWindow));
mFrameWindow = do_QueryInterface(topWindow);
mFrameWindow = mFrameWindow->GetOuterWindow();
return NS_OK;
}
nsCOMPtr<nsIDocShell> docShell;
nsresult rv = mFrameLoader->GetDocShell(getter_AddRefs(docShell));
if (NS_WARN_IF(NS_FAILED(rv))) {

View File

@ -35,12 +35,12 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BrowserElementAudioChannel,
DOMEventTargetHelper)
BrowserElementAudioChannel(nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
AudioChannel aAudioChannel);
nsresult Initialize();
static already_AddRefed<BrowserElementAudioChannel>
Create(nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
AudioChannel aAudioChannel,
ErrorResult& aRv);
// WebIDL methods
@ -60,8 +60,15 @@ public:
IMPL_EVENT_HANDLER(activestatechanged);
private:
BrowserElementAudioChannel(nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
AudioChannel aAudioChannel);
~BrowserElementAudioChannel();
nsresult Initialize();
void ProcessStateChanged(const char16_t* aData);
nsCOMPtr<nsIFrameLoader> mFrameLoader;

View File

@ -563,69 +563,84 @@ nsBrowserElement::GetAllowedAudioChannels(
return;
}
nsCOMPtr<nsIAppsService> appsService =
do_GetService("@mozilla.org/AppsService;1");
if (NS_WARN_IF(!appsService)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsCOMPtr<mozIApplication> app;
aRv = appsService->GetAppByManifestURL(manifestURL, getter_AddRefs(app));
GenerateAllowedAudioChannels(window, frameLoader, mBrowserElementAPI,
manifestURL, mBrowserElementAudioChannels,
aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
}
// Normal is always allowed.
nsTArray<nsRefPtr<BrowserElementAudioChannel>> channels;
aAudioChannels.AppendElements(mBrowserElementAudioChannels);
}
nsRefPtr<BrowserElementAudioChannel> ac =
new BrowserElementAudioChannel(window, frameLoader, mBrowserElementAPI,
AudioChannel::Normal);
/* static */ void
nsBrowserElement::GenerateAllowedAudioChannels(
nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
const nsAString& aManifestURL,
nsTArray<nsRefPtr<BrowserElementAudioChannel>>& aAudioChannels,
ErrorResult& aRv)
{
MOZ_ASSERT(aAudioChannels.IsEmpty());
aRv = ac->Initialize();
if (NS_WARN_IF(aRv.Failed())) {
return;
}
nsCOMPtr<nsIAppsService> appsService =
do_GetService("@mozilla.org/AppsService;1");
if (NS_WARN_IF(!appsService)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
channels.AppendElement(ac);
nsCOMPtr<mozIApplication> app;
aRv = appsService->GetAppByManifestURL(aManifestURL, getter_AddRefs(app));
if (NS_WARN_IF(aRv.Failed())) {
return;
}
if (app) {
const nsAttrValue::EnumTable* audioChannelTable =
AudioChannelService::GetAudioChannelTable();
// Normal is always allowed.
nsTArray<nsRefPtr<BrowserElementAudioChannel>> channels;
bool allowed;
nsAutoCString permissionName;
nsRefPtr<BrowserElementAudioChannel> ac =
BrowserElementAudioChannel::Create(aWindow, aFrameLoader, aAPI,
AudioChannel::Normal, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
for (uint32_t i = 0; audioChannelTable && audioChannelTable[i].tag; ++i) {
permissionName.AssignASCII("audio-channel-");
permissionName.AppendASCII(audioChannelTable[i].tag);
channels.AppendElement(ac);
aRv = app->HasPermission(permissionName.get(), &allowed);
if (app) {
const nsAttrValue::EnumTable* audioChannelTable =
AudioChannelService::GetAudioChannelTable();
bool allowed;
nsAutoCString permissionName;
for (uint32_t i = 0; audioChannelTable && audioChannelTable[i].tag; ++i) {
permissionName.AssignASCII("audio-channel-");
permissionName.AppendASCII(audioChannelTable[i].tag);
aRv = app->HasPermission(permissionName.get(), &allowed);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
if (allowed) {
nsRefPtr<BrowserElementAudioChannel> ac =
BrowserElementAudioChannel::Create(aWindow, aFrameLoader, aAPI,
(AudioChannel)audioChannelTable[i].value,
aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
if (allowed) {
nsRefPtr<BrowserElementAudioChannel> ac =
new BrowserElementAudioChannel(window, frameLoader,
mBrowserElementAPI,
(AudioChannel)audioChannelTable[i].value);
aRv = ac->Initialize();
if (NS_WARN_IF(aRv.Failed())) {
return;
}
channels.AppendElement(ac);
}
channels.AppendElement(ac);
}
}
mBrowserElementAudioChannels.AppendElements(channels);
}
aAudioChannels.AppendElements(mBrowserElementAudioChannels);
aAudioChannels.SwapElements(channels);
}
already_AddRefed<DOMRequest>

View File

@ -117,6 +117,15 @@ public:
void SetNFCFocus(bool isFocus,
ErrorResult& aRv);
// Helper
static void GenerateAllowedAudioChannels(
nsPIDOMWindow* aWindow,
nsIFrameLoader* aFrameLoader,
nsIBrowserElementAPI* aAPI,
const nsAString& aManifestURL,
nsTArray<nsRefPtr<dom::BrowserElementAudioChannel>>& aAudioChannels,
ErrorResult& aRv);
protected:
NS_IMETHOD_(already_AddRefed<nsFrameLoader>) GetFrameLoader() = 0;
void InitBrowserElementAPI();

View File

@ -2,6 +2,8 @@
* 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 "nsIAppsService.h"
#include "nsIDocument.h"
#include "nsIDOMClassInfo.h"
#include "nsIDOMEvent.h"
#include "nsIDOMEventListener.h"
@ -11,6 +13,7 @@
#include "nsIInterfaceRequestorUtils.h"
#include "AudioChannelManager.h"
#include "mozilla/dom/AudioChannelManagerBinding.h"
#include "mozilla/dom/nsBrowserElement.h"
#include "mozilla/Services.h"
using namespace mozilla::hal;
@ -149,6 +152,70 @@ AudioChannelManager::HandleEvent(nsIDOMEvent* aEvent)
return NS_OK;
}
void
AudioChannelManager::GetAllowedAudioChannels(
nsTArray<nsRefPtr<BrowserElementAudioChannel>>& aAudioChannels,
ErrorResult& aRv)
{
MOZ_ASSERT(aAudioChannels.IsEmpty());
// Only main process is supported.
if (XRE_GetProcessType() != GeckoProcessType_Default) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsCOMPtr<nsPIDOMWindow> window = GetOwner();
if (NS_WARN_IF(!window)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
if (NS_WARN_IF(!doc)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
MOZ_ASSERT(principal);
uint16_t status;
if (NS_WARN_IF(NS_FAILED(principal->GetAppStatus(&status)))) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
if (status != nsIPrincipal::APP_STATUS_CERTIFIED) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
uint32_t appId;
aRv = principal->GetAppId(&appId);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
nsCOMPtr<nsIAppsService> appsService =
do_GetService("@mozilla.org/AppsService;1");
if (NS_WARN_IF(!appsService)) {
aRv.Throw(NS_ERROR_FAILURE);
return;
}
nsAutoString manifestURL;
aRv = appsService->GetManifestURLByLocalId(appId, manifestURL);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
nsBrowserElement::GenerateAllowedAudioChannels(window, nullptr, nullptr,
manifestURL, aAudioChannels,
aRv);
NS_WARN_IF(aRv.Failed());
}
} // namespace system
} // namespace dom
} // namespace mozilla

View File

@ -5,6 +5,7 @@
#ifndef mozilla_dom_system_AudioChannelManager_h
#define mozilla_dom_system_AudioChannelManager_h
#include "mozilla/dom/BrowserElementAudioChannel.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/Hal.h"
#include "mozilla/HalTypes.h"
@ -65,6 +66,10 @@ public:
IMPL_EVENT_HANDLER(headphoneschange)
void GetAllowedAudioChannels(
nsTArray<nsRefPtr<mozilla::dom::BrowserElementAudioChannel>>& aAudioChannels,
mozilla::ErrorResult& aRv);
protected:
virtual ~AudioChannelManager();

View File

@ -29,4 +29,9 @@ interface AudioChannelManager : EventTarget {
* volume keys.
*/
attribute DOMString volumeControlChannel;
[Pure, Cached, Throws,
Pref="dom.mozBrowserFramesEnabled",
CheckAnyPermissions="system-app-only-audio-channels-in-app"]
readonly attribute sequence<BrowserElementAudioChannel> allowedAudioChannels;
};