Bug 1069230 - Presentation API implementation. Part 2 - Presentation service and listeners. r=smaug

This commit is contained in:
Sean Lin 2015-03-25 19:47:56 +08:00
parent d2cfdcf0f4
commit 8c65319fc0
8 changed files with 438 additions and 0 deletions

View File

@ -0,0 +1,174 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/Services.h"
#include "nsIObserverService.h"
#include "nsIPresentationListener.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "PresentationService.h"
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_ISUPPORTS(PresentationService, nsIPresentationService, nsIObserver)
PresentationService::PresentationService()
{
}
PresentationService::~PresentationService()
{
}
bool
PresentationService::Init()
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (NS_WARN_IF(!obs)) {
return false;
}
// TODO: Add observers and get available devices.
return true;
}
NS_IMETHODIMP
PresentationService::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
// TODO: Handle device availability changes can call |NotifyAvailableChange|.
return NS_OK;
}
void
PresentationService::NotifyAvailableChange(bool aIsAvailable)
{
nsTObserverArray<nsCOMPtr<nsIPresentationListener> >::ForwardIterator iter(mListeners);
while (iter.HasMore()) {
nsCOMPtr<nsIPresentationListener> listener = iter.GetNext();
NS_WARN_IF(NS_FAILED(listener->NotifyAvailableChange(aIsAvailable)));
}
}
NS_IMETHODIMP
PresentationService::StartSession(const nsAString& aUrl,
const nsAString& aSessionId,
const nsAString& aOrigin,
nsIPresentationServiceCallback* aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aCallback);
MOZ_ASSERT(!aSessionId.IsEmpty());
// TODO: Reply the callback.
return NS_OK;
}
NS_IMETHODIMP
PresentationService::SendSessionMessage(const nsAString& aSessionId,
nsIInputStream* aStream)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aStream);
MOZ_ASSERT(!aSessionId.IsEmpty());
// TODO: Send input stream to the session.
return NS_OK;
}
NS_IMETHODIMP
PresentationService::Terminate(const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aSessionId.IsEmpty());
// TODO: Terminate the session.
return NS_OK;
}
NS_IMETHODIMP
PresentationService::RegisterListener(nsIPresentationListener* aListener)
{
MOZ_ASSERT(NS_IsMainThread());
if (NS_WARN_IF(mListeners.Contains(aListener))) {
return NS_OK;
}
mListeners.AppendElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
PresentationService::UnregisterListener(nsIPresentationListener* aListener)
{
MOZ_ASSERT(NS_IsMainThread());
mListeners.RemoveElement(aListener);
return NS_OK;
}
NS_IMETHODIMP
PresentationService::RegisterSessionListener(const nsAString& aSessionId,
nsIPresentationSessionListener* aListener)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aListener);
PresentationSessionInfo* info = mSessionInfo.Get(aSessionId);
if (NS_WARN_IF(!info)) {
return NS_ERROR_NOT_AVAILABLE;
}
info->SetListener(aListener);
return NS_OK;
}
NS_IMETHODIMP
PresentationService::UnregisterSessionListener(const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
PresentationSessionInfo* info = mSessionInfo.Get(aSessionId);
if (info) {
info->SetListener(nullptr);
}
return NS_OK;
}
NS_IMETHODIMP
PresentationService::GetExistentSessionIdAtLaunch(nsAString& aSessionId)
{
// TODO: Return the value based on it's a sender or a receiver.
return NS_OK;
}
NS_IMETHODIMP
PresentationService::NotifyReceiverReady(const nsAString& aSessionId)
{
// TODO: Notify the correspondent session info.
return NS_OK;
}
already_AddRefed<nsIPresentationService>
NS_CreatePresentationService()
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIPresentationService> service = new PresentationService();
return NS_WARN_IF(!static_cast<PresentationService*>(service.get())->Init()) ?
nullptr : service.forget();
}

View File

@ -0,0 +1,41 @@
/* -*- 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/. */
#ifndef mozilla_dom_PresentationService_h
#define mozilla_dom_PresentationService_h
#include "nsClassHashtable.h"
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsTObserverArray.h"
#include "PresentationSessionInfo.h"
namespace mozilla {
namespace dom {
class PresentationService final : public nsIPresentationService
, public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIPRESENTATIONSERVICE
PresentationService();
bool Init();
private:
~PresentationService();
void NotifyAvailableChange(bool aIsAvailable);
nsClassHashtable<nsStringHashKey, PresentationSessionInfo> mSessionInfo;
nsTObserverArray<nsCOMPtr<nsIPresentationListener> > mListeners;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PresentationService_h

View File

@ -0,0 +1,63 @@
/* -*- 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/. */
#ifndef mozilla_dom_PresentationSessionInfo_h
#define mozilla_dom_PresentationSessionInfo_h
#include "mozilla/nsRefPtr.h"
#include "nsCOMPtr.h"
#include "nsIPresentationListener.h"
#include "nsIPresentationService.h"
#include "nsString.h"
namespace mozilla {
namespace dom {
class PresentationSessionInfo
{
public:
PresentationSessionInfo(const nsAString& aUrl,
const nsAString& aSessionId,
nsIPresentationServiceCallback* aCallback)
: mUrl(aUrl)
, mSessionId(aSessionId)
, mCallback(aCallback)
{
MOZ_ASSERT(!mUrl.IsEmpty());
MOZ_ASSERT(!mSessionId.IsEmpty());
}
const nsAString& GetUrl() const
{
return mUrl;
}
const nsAString& GetSessionId() const
{
return mSessionId;
}
void SetCallback(nsIPresentationServiceCallback* aCallback)
{
mCallback = aCallback;
}
void SetListener(nsIPresentationSessionListener* aListener)
{
mListener = aListener;
}
private:
nsString mUrl;
nsString mSessionId;
nsCOMPtr<nsIPresentationServiceCallback> mCallback;
nsCOMPtr<nsIPresentationSessionListener> mListener;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PresentationSessionInfo_h

View File

@ -10,6 +10,8 @@ XPIDL_SOURCES += [
'nsIPresentationDeviceManager.idl',
'nsIPresentationDevicePrompt.idl',
'nsIPresentationDeviceProvider.idl',
'nsIPresentationListener.idl',
'nsIPresentationService.idl',
'nsIPresentationSessionRequest.idl',
'nsITCPPresentationServer.idl',
]

View File

@ -0,0 +1,34 @@
/* 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 "nsISupports.idl"
[scriptable, uuid(0105f837-4279-4715-9d5b-2dc3f8b65353)]
interface nsIPresentationListener : nsISupports
{
/*
* Called when device availability changes.
*/
void notifyAvailableChange(in bool available);
};
[scriptable, uuid(3b9ae71f-2905-4969-9117-101627c1c2ea)]
interface nsIPresentationSessionListener : nsISupports
{
const unsigned short STATE_CONNECTED = 0;
const unsigned short STATE_DISCONNECTED = 1;
const unsigned short STATE_TERMINATED = 2;
/*
* Called when session state changes.
*/
void notifyStateChange(in DOMString sessionId,
in unsigned short state);
/*
* Called when receive messages.
*/
void notifyMessage(in DOMString sessionId,
in ACString data);
};

View File

@ -0,0 +1,112 @@
/* 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 "nsISupports.idl"
interface nsIInputStream;
interface nsIPresentationListener;
interface nsIPresentationSessionListener;
%{C++
#define PRESENTATION_SERVICE_CID \
{ 0x1d9bb10c, 0xc0ab, 0x4fe8, \
{ 0x9e, 0x4f, 0x40, 0x58, 0xb8, 0x51, 0x98, 0x32 } }
#define PRESENTATION_SERVICE_CONTRACTID \
"@mozilla.org/presentation/presentationservice;1"
%}
[scriptable, uuid(12073206-0065-4b10-9488-a6eb9b23e65b)]
interface nsIPresentationServiceCallback : nsISupports
{
/*
* Called when the operation succeeds.
*/
void notifySuccess();
/*
* Called when the operation fails.
*
* @param error: error message.
*/
void notifyError(in nsresult error);
};
[scriptable, uuid(5801efd9-9dba-4af7-8be9-8fc97c2d54a6)]
interface nsIPresentationService : nsISupports
{
/*
* Start a new presentation session and display a prompt box which asks users
* to select a device.
*
* @param url: The url of presenting page.
* @param sessionId: An ID to identify presentation session.
* @param origin: The url of requesting page.
* @param callback: Invoke the callback when the operation is completed.
* NotifySuccess() is called with |id| if a session is
* established successfully with the selected device.
* Otherwise, NotifyError() is called with a error message.
*/
void startSession(in DOMString url,
in DOMString sessionId,
in DOMString origin,
in nsIPresentationServiceCallback callback);
/*
* Send the message wrapped with an input stream to the session.
*
* @param sessionId: An ID to identify presentation session.
* @param stream: The message is converted to an input stream.
*/
void sendSessionMessage(in DOMString sessionId,
in nsIInputStream stream);
/*
* Terminate the session.
*
* @param sessionId: An ID to identify presentation session.
*/
void terminate(in DOMString sessionId);
/*
* Register a listener. Must be called from the main thread.
*
* @param listener: The listener to register.
*/
void registerListener(in nsIPresentationListener listener);
/*
* Unregister a listener. Must be called from the main thread.
* @param listener: The listener to unregister.
*/
void unregisterListener(in nsIPresentationListener listener);
/*
* Register a session listener. Must be called from the main thread.
*
* @param sessionId: An ID to identify presentation session.
* @param listener: The listener to register.
*/
void registerSessionListener(in DOMString sessionId,
in nsIPresentationSessionListener listener);
/*
* Unregister a session listener. Must be called from the main thread.
*
* @param sessionId: An ID to identify presentation session.
*/
void unregisterSessionListener(in DOMString sessionId);
/*
* Check if the presentation instance has an existent session ID at launch.
* An empty string is returned at sender side; non-empty at receiver side.
*/
DOMString getExistentSessionIdAtLaunch();
/*
* Notify the receiver page is ready for presentation use.
*
* @param sessionId: An ID to identify presentation session.
*/
void notifyReceiverReady(in DOMString sessionId);
};

View File

@ -12,12 +12,15 @@ MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini']
EXPORTS.mozilla.dom += [
'Presentation.h',
'PresentationDeviceManager.h',
'PresentationService.h',
'PresentationSession.h',
'PresentationSessionInfo.h',
]
UNIFIED_SOURCES += [
'Presentation.cpp',
'PresentationDeviceManager.cpp',
'PresentationService.cpp',
'PresentationSession.cpp',
'PresentationSessionRequest.cpp',
]

View File

@ -240,6 +240,7 @@ static void Shutdown();
#include "mozilla/dom/time/TimeService.h"
#include "StreamingProtocolService.h"
#include "nsIPresentationService.h"
#include "nsITelephonyService.h"
#include "nsIVoicemailService.h"
@ -293,6 +294,8 @@ using mozilla::gmp::GeckoMediaPluginService;
#define PRESENTATION_DEVICE_MANAGER_CID \
{ 0xe1e79dec, 0x4085, 0x4994, { 0xac, 0x5b, 0x74, 0x4b, 0x01, 0x66, 0x97, 0xe6 } }
already_AddRefed<nsIPresentationService> NS_CreatePresentationService();
// Factory Constructor
NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor)
NS_GENERIC_FACTORY_CONSTRUCTOR(XPathEvaluator)
@ -401,6 +404,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(TextInputProcessor)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(FakeInputPortService,
InputPortServiceFactory::CreateFakeInputPortService)
NS_GENERIC_FACTORY_CONSTRUCTOR(InputPortData)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPresentationService,
NS_CreatePresentationService)
//-----------------------------------------------------------------------------
static bool gInitialized = false;
@ -857,6 +862,7 @@ NS_DEFINE_NAMED_CID(INPUTPORT_DATA_CID);
NS_DEFINE_NAMED_CID(GECKO_MEDIA_PLUGIN_SERVICE_CID);
NS_DEFINE_NAMED_CID(PRESENTATION_SERVICE_CID);
NS_DEFINE_NAMED_CID(PRESENTATION_DEVICE_MANAGER_CID);
NS_DEFINE_NAMED_CID(TEXT_INPUT_PROCESSOR_CID);
@ -1155,6 +1161,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kTV_TUNER_DATA_CID, false, nullptr, TVTunerDataConstructor },
{ &kTV_CHANNEL_DATA_CID, false, nullptr, TVChannelDataConstructor },
{ &kTV_PROGRAM_DATA_CID, false, nullptr, TVProgramDataConstructor },
{ &kPRESENTATION_SERVICE_CID, false, nullptr, nsIPresentationServiceConstructor },
{ &kPRESENTATION_DEVICE_MANAGER_CID, false, nullptr, PresentationDeviceManagerConstructor },
{ &kTEXT_INPUT_PROCESSOR_CID, false, nullptr, TextInputProcessorConstructor },
{ &kFAKE_INPUTPORT_SERVICE_CID, false, nullptr, FakeInputPortServiceConstructor },
@ -1324,6 +1331,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ "@mozilla.org/gecko-media-plugin-service;1", &kGECKO_MEDIA_PLUGIN_SERVICE_CID },
{ NS_MOBILE_CONNECTION_SERVICE_CONTRACTID, &kNS_MOBILE_CONNECTION_SERVICE_CID },
{ NS_VOICEMAIL_SERVICE_CONTRACTID, &kNS_VOICEMAIL_SERVICE_CID },
{ PRESENTATION_SERVICE_CONTRACTID, &kPRESENTATION_SERVICE_CID },
{ PRESENTATION_DEVICE_MANAGER_CONTRACTID, &kPRESENTATION_DEVICE_MANAGER_CID },
{ "@mozilla.org/text-input-processor;1", &kTEXT_INPUT_PROCESSOR_CID },
{ FAKE_INPUTPORT_SERVICE_CONTRACTID, &kFAKE_INPUTPORT_SERVICE_CID },
@ -1353,6 +1361,7 @@ static const mozilla::Module::CategoryEntry kLayoutCategories[] = {
{ "profile-after-change", "Bluetooth Service", BLUETOOTHSERVICE_CONTRACTID },
#endif
{ "profile-after-change", "PresentationDeviceManager", PRESENTATION_DEVICE_MANAGER_CONTRACTID },
{ "profile-after-change", "PresentationService", PRESENTATION_SERVICE_CONTRACTID },
{ "idle-daily", "ServiceWorker Periodic Updater", SERVICEWORKERPERIODICUPDATER_CONTRACTID },
{ nullptr }
};