зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1206581 - Implement notifyChannel() on AudioChannel API. r=kanru, r=baku
--HG-- extra : transplant_source : %25%253%AFA%06%18%7Bz%00%0EZ%E5%E5%D3%3E%0B%EA%DE%DA
This commit is contained in:
Родитель
eb691c83f1
Коммит
6fa70576bd
|
@ -7,15 +7,21 @@
|
|||
#include "mozilla/Services.h"
|
||||
#include "mozilla/dom/BrowserElementAudioChannelBinding.h"
|
||||
#include "mozilla/dom/DOMRequest.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "AudioChannelService.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"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -50,10 +56,12 @@ BrowserElementAudioChannel::Create(nsPIDOMWindow* aWindow,
|
|||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
AudioChannel aAudioChannel,
|
||||
const nsAString& aManifestURL,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<BrowserElementAudioChannel> ac =
|
||||
new BrowserElementAudioChannel(aWindow, aFrameLoader, aAPI, aAudioChannel);
|
||||
new BrowserElementAudioChannel(aWindow, aFrameLoader, aAPI,
|
||||
aAudioChannel, aManifestURL);
|
||||
|
||||
aRv = ac->Initialize();
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
|
@ -64,14 +72,16 @@ BrowserElementAudioChannel::Create(nsPIDOMWindow* aWindow,
|
|||
}
|
||||
|
||||
BrowserElementAudioChannel::BrowserElementAudioChannel(
|
||||
nsPIDOMWindow* aWindow,
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
AudioChannel aAudioChannel)
|
||||
nsPIDOMWindow* aWindow,
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
AudioChannel aAudioChannel,
|
||||
const nsAString& aManifestURL)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mFrameLoader(aFrameLoader)
|
||||
, mBrowserElementAPI(aAPI)
|
||||
, mAudioChannel(aAudioChannel)
|
||||
, mManifestURL(aManifestURL)
|
||||
, mState(eStateUnknown)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -302,6 +312,43 @@ protected:
|
|||
}
|
||||
};
|
||||
|
||||
class RespondSuccessHandler final : public PromiseNativeHandler
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
explicit RespondSuccessHandler(DOMRequest* aRequest)
|
||||
: mDomRequest(aRequest)
|
||||
{};
|
||||
|
||||
virtual void
|
||||
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
virtual void
|
||||
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
private:
|
||||
~RespondSuccessHandler() {};
|
||||
|
||||
RefPtr<DOMRequest> mDomRequest;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS0(RespondSuccessHandler);
|
||||
|
||||
void
|
||||
RespondSuccessHandler::ResolvedCallback(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
mDomRequest->FireSuccess(value);
|
||||
}
|
||||
|
||||
void
|
||||
RespondSuccessHandler::RejectedCallback(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
mDomRequest->FireError(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
already_AddRefed<dom::DOMRequest>
|
||||
|
@ -459,6 +506,62 @@ BrowserElementAudioChannel::IsActive(ErrorResult& aRv)
|
|||
return domRequest.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<dom::DOMRequest>
|
||||
BrowserElementAudioChannel::NotifyChannel(const nsAString& aEvent,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
if (!mFrameWindow) {
|
||||
nsCOMPtr<nsIDOMDOMRequest> request;
|
||||
aRv = mBrowserElementAPI->NotifyChannel(aEvent, mManifestURL,
|
||||
(uint32_t)mAudioChannel,
|
||||
getter_AddRefs(request));
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return request.forget().downcast<DOMRequest>();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
|
||||
do_GetService("@mozilla.org/system-message-internal;1");
|
||||
MOZ_ASSERT(systemMessenger);
|
||||
|
||||
AutoJSAPI jsAPI;
|
||||
if (!jsAPI.Init(GetOwner())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> value(jsAPI.cx());
|
||||
value.setInt32((uint32_t)mAudioChannel);
|
||||
|
||||
nsCOMPtr<nsIURI> manifestURI;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(manifestURI), mManifestURL);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Since the pageURI of the app has been registered to the system messager,
|
||||
// when the app was installed. The system messager can only use the manifest
|
||||
// to send the message to correct page.
|
||||
nsCOMPtr<nsISupports> promise;
|
||||
rv = systemMessenger->SendMessage(aEvent, value, nullptr, manifestURI,
|
||||
JS::UndefinedHandleValue,
|
||||
getter_AddRefs(promise));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<Promise> promiseIns = static_cast<Promise*>(promise.get());
|
||||
RefPtr<DOMRequest> request = new DOMRequest(GetOwner());
|
||||
RefPtr<RespondSuccessHandler> handler = new RespondSuccessHandler(request);
|
||||
promiseIns->AppendNativeHandler(handler);
|
||||
|
||||
return request.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BrowserElementAudioChannel::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData)
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
AudioChannel aAudioChannel,
|
||||
const nsAString& aManifestURL,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// WebIDL methods
|
||||
|
@ -57,13 +58,17 @@ public:
|
|||
|
||||
already_AddRefed<dom::DOMRequest> IsActive(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<dom::DOMRequest> NotifyChannel(const nsAString& aEvent,
|
||||
ErrorResult& aRv);
|
||||
|
||||
IMPL_EVENT_HANDLER(activestatechanged);
|
||||
|
||||
private:
|
||||
BrowserElementAudioChannel(nsPIDOMWindow* aWindow,
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
AudioChannel aAudioChannel);
|
||||
AudioChannel aAudioChannel,
|
||||
const nsAString& aManifestURL);
|
||||
|
||||
~BrowserElementAudioChannel();
|
||||
|
||||
|
@ -76,6 +81,7 @@ private:
|
|||
nsCOMPtr<nsITabParent> mTabParent;
|
||||
nsCOMPtr<nsPIDOMWindow> mFrameWindow;
|
||||
AudioChannel mAudioChannel;
|
||||
nsString mManifestURL;
|
||||
|
||||
enum {
|
||||
eStateActive,
|
||||
|
|
|
@ -23,6 +23,10 @@ XPCOMUtils.defineLazyGetter(this, "DOMApplicationRegistry", function () {
|
|||
return DOMApplicationRegistry;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "systemMessenger",
|
||||
"@mozilla.org/system-message-internal;1",
|
||||
"nsISystemMessagesInternal");
|
||||
|
||||
function debug(msg) {
|
||||
//dump("BrowserElementParent - " + msg + "\n");
|
||||
}
|
||||
|
@ -1208,6 +1212,26 @@ BrowserElementParent.prototype = {
|
|||
{audioChannel: aAudioChannel});
|
||||
},
|
||||
|
||||
notifyChannel: function(aEvent, aManifest, aAudioChannel) {
|
||||
var self = this;
|
||||
var req = Services.DOMRequest.createRequest(self._window);
|
||||
|
||||
// Since the pageURI of the app has been registered to the system messager,
|
||||
// when the app was installed. The system messager can only use the manifest
|
||||
// to send the message to correct page.
|
||||
let manifestURL = Services.io.newURI(aManifest, null, null);
|
||||
systemMessenger.sendMessage(aEvent, aAudioChannel, null, manifestURL)
|
||||
.then(function() {
|
||||
Services.DOMRequest.fireSuccess(req,
|
||||
Cu.cloneInto(true, self._window));
|
||||
}, function() {
|
||||
debug("Error : NotifyChannel fail.");
|
||||
Services.DOMRequest.fireErrorAsync(req,
|
||||
Cu.cloneInto("NotifyChannel fail.", self._window));
|
||||
});
|
||||
return req;
|
||||
},
|
||||
|
||||
getStructuredData: defineDOMRequestMethod('get-structured-data'),
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const { classes: Cc, interfaces: Ci } = Components;
|
||||
const systemMessenger = Cc["@mozilla.org/system-message-internal;1"]
|
||||
.getService(Ci.nsISystemMessagesInternal);
|
||||
const ioService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService);
|
||||
|
||||
var tests = [false /* INPROC */, true /* OOP */];
|
||||
var rootURI = "http://test/chrome/dom/browser-element/mochitest/";
|
||||
var manifestURI = rootURI + "manifest.webapp";
|
||||
var srcURI = rootURI + "file_browserElement_NotifyChannel.html";
|
||||
var generator = runTests();
|
||||
var app = null;
|
||||
|
||||
addLoadEvent(() => {
|
||||
SpecialPowers.pushPermissions(
|
||||
[{ "type": "webapps-manage", "allow": 1, "context": document },
|
||||
{ "type": "browser", "allow": 1, "context": document },
|
||||
{ "type": "embed-apps", "allow": 1, "context": document }],
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{'set': [["dom.mozBrowserFramesEnabled", true],
|
||||
["dom.sysmsg.enabled", true]]},
|
||||
() => { generator.next(); })
|
||||
});
|
||||
});
|
||||
|
||||
function error(message) {
|
||||
ok(false, message);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function continueTest() {
|
||||
try {
|
||||
generator.next();
|
||||
} catch (e if e instanceof StopIteration) {
|
||||
error("Stop test because of exception!");
|
||||
}
|
||||
}
|
||||
|
||||
function registerPage(aEvent) {
|
||||
systemMessenger.registerPage(aEvent,
|
||||
ioService.newURI(srcURI, null, null),
|
||||
ioService.newURI(manifestURI, null, null));
|
||||
}
|
||||
|
||||
function runTest(aEnable) {
|
||||
var request = navigator.mozApps.install(manifestURI, {});
|
||||
request.onerror = () => {
|
||||
error("Install app failed!");
|
||||
};
|
||||
|
||||
request.onsuccess = () => {
|
||||
app = request.result;
|
||||
ok(app, "App is installed. remote = " + aEnable);
|
||||
is(app.manifestURL, manifestURI, "App manifest url is correct.");
|
||||
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', true);
|
||||
iframe.setAttribute('remote', aEnable);
|
||||
iframe.setAttribute('mozapp', manifestURI);
|
||||
iframe.src = srcURI;
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
iframe.addEventListener('mozbrowserloadend', () => {
|
||||
var channels = iframe.allowedAudioChannels;
|
||||
is(channels.length, 1, "1 audio channel by default");
|
||||
|
||||
var ac = channels[0];
|
||||
ok(ac instanceof BrowserElementAudioChannel, "Correct class");
|
||||
ok("notifyChannel" in ac, "ac.notifyChannel exists");
|
||||
|
||||
var message = "audiochannel-interruption-begin";
|
||||
registerPage(message);
|
||||
ac.notifyChannel(message);
|
||||
iframe.addEventListener("mozbrowsershowmodalprompt", function (e) {
|
||||
is(e.detail.message, message,
|
||||
"App got audiochannel-interruption-begin.");
|
||||
|
||||
if (app) {
|
||||
request = navigator.mozApps.mgmt.uninstall(app);
|
||||
app = null;
|
||||
request.onerror = () => {
|
||||
error("Uninstall app failed!");
|
||||
};
|
||||
request.onsuccess = () => {
|
||||
is(request.result, manifestURI, "App uninstalled.");
|
||||
runNextTest();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
if (tests.length) {
|
||||
var isEnabledOOP = tests.shift();
|
||||
runTest(isEnabledOOP);
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
runNextTest();
|
||||
yield undefined;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
[DEFAULT]
|
||||
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
|
||||
|
||||
support-files =
|
||||
browserElement_NotifyChannel.js
|
||||
file_browserElement_NotifyChannel.html
|
||||
manifest.webapp
|
||||
manifest.webapp^headers^
|
||||
|
||||
[test_browserElement_NotifyChannel.html]
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test of browser element audio channel method, notifyChannel</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.8">
|
||||
"use strict";
|
||||
navigator.mozSetMessageHandler('audiochannel-interruption-begin',
|
||||
function (e) {
|
||||
alert("audiochannel-interruption-begin");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "NotifyChannel Test",
|
||||
"launch_path": "/index.html",
|
||||
"messages": [
|
||||
{ "audiochannel-interruption-begin": "./file_browserElement_NotifyChannel.html" }
|
||||
]
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Content-Type: application/manifest+json
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test BrowserElementAudioChannel function : notifyChannel().</title>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/chrome-harness.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7" src="browserElement_NotifyChannel.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -54,6 +54,7 @@ MOCHITEST_MANIFESTS += [
|
|||
'mochitest/mochitest.ini',
|
||||
'mochitest/priority/mochitest.ini',
|
||||
]
|
||||
MOCHITEST_CHROME_MANIFESTS += ['mochitest/chrome.ini']
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
|
|
@ -26,7 +26,7 @@ interface nsIBrowserElementNextPaintListener : nsISupports
|
|||
* Interface to the BrowserElementParent implementation. All methods
|
||||
* but setFrameLoader throw when the remote process is dead.
|
||||
*/
|
||||
[scriptable, uuid(9946695c-1ed3-4abb-bc60-6f8947fd5641)]
|
||||
[scriptable, uuid(57758c10-6036-11e5-a837-0800200c9a66)]
|
||||
interface nsIBrowserElementAPI : nsISupports
|
||||
{
|
||||
const long FIND_CASE_SENSITIVE = 0;
|
||||
|
@ -97,6 +97,10 @@ interface nsIBrowserElementAPI : nsISupports
|
|||
|
||||
nsIDOMDOMRequest isAudioChannelActive(in uint32_t audioChannel);
|
||||
|
||||
nsIDOMDOMRequest notifyChannel(in DOMString event,
|
||||
in DOMString manifest,
|
||||
in uint32_t audioChannel);
|
||||
|
||||
void setNFCFocus(in boolean isFocus);
|
||||
|
||||
nsIDOMDOMRequest executeScript(in DOMString script, in jsval options);
|
||||
|
|
|
@ -603,7 +603,8 @@ nsBrowserElement::GenerateAllowedAudioChannels(
|
|||
|
||||
RefPtr<BrowserElementAudioChannel> ac =
|
||||
BrowserElementAudioChannel::Create(aWindow, aFrameLoader, aAPI,
|
||||
AudioChannel::Normal, aRv);
|
||||
AudioChannel::Normal,
|
||||
aManifestURL, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
@ -630,7 +631,7 @@ nsBrowserElement::GenerateAllowedAudioChannels(
|
|||
RefPtr<BrowserElementAudioChannel> ac =
|
||||
BrowserElementAudioChannel::Create(aWindow, aFrameLoader, aAPI,
|
||||
(AudioChannel)audioChannelTable[i].value,
|
||||
aRv);
|
||||
aManifestURL, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -136,7 +136,9 @@ this.SystemMessagePermissionsTable = {
|
|||
},
|
||||
"first-run-with-sim": {
|
||||
"settings": ["read", "write"]
|
||||
}
|
||||
},
|
||||
"audiochannel-interruption-begin" : {},
|
||||
"audiochannel-interruption-ended" : {}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ interface BrowserElementAudioChannel : EventTarget {
|
|||
|
||||
[Throws]
|
||||
DOMRequest isActive();
|
||||
|
||||
[Throws]
|
||||
DOMRequest notifyChannel(DOMString aEvent);
|
||||
};
|
||||
|
||||
partial interface BrowserElementPrivileged {
|
||||
|
|
Загрузка…
Ссылка в новой задаче