/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set ts=2 sw=2 sts=2 et cindent: */ /* 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/dom/PresentationRequestBinding.h" #include "mozilla/dom/PresentationConnectionAvailableEvent.h" #include "mozilla/dom/Promise.h" #include "mozIThirdPartyUtil.h" #include "nsCycleCollectionParticipant.h" #include "nsIPresentationService.h" #include "nsIUUIDGenerator.h" #include "nsServiceManagerUtils.h" #include "PresentationAvailability.h" #include "PresentationCallbacks.h" #include "PresentationRequest.h" using namespace mozilla; using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_INHERITED(PresentationRequest, DOMEventTargetHelper, mAvailability) NS_IMPL_ADDREF_INHERITED(PresentationRequest, DOMEventTargetHelper) NS_IMPL_RELEASE_INHERITED(PresentationRequest, DOMEventTargetHelper) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationRequest) NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) /* static */ already_AddRefed PresentationRequest::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl, ErrorResult& aRv) { nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); if (!window) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } // Ensure the URL is not empty. if (NS_WARN_IF(aUrl.IsEmpty())) { aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); return nullptr; } RefPtr request = new PresentationRequest(window, aUrl); return NS_WARN_IF(!request->Init()) ? nullptr : request.forget(); } PresentationRequest::PresentationRequest(nsPIDOMWindowInner* aWindow, const nsAString& aUrl) : DOMEventTargetHelper(aWindow) , mUrl(aUrl) { } PresentationRequest::~PresentationRequest() { } bool PresentationRequest::Init() { mAvailability = PresentationAvailability::Create(GetOwner()); if (NS_WARN_IF(!mAvailability)) { return false; } return true; } /* virtual */ JSObject* PresentationRequest::WrapObject(JSContext* aCx, JS::Handle aGivenProto) { return PresentationRequestBinding::Wrap(aCx, this, aGivenProto); } already_AddRefed PresentationRequest::Start(ErrorResult& aRv) { return StartWithDevice(NullString(), aRv); } already_AddRefed PresentationRequest::StartWithDevice(const nsAString& aDeviceId, ErrorResult& aRv) { nsCOMPtr global = do_QueryInterface(GetOwner()); if (NS_WARN_IF(!global)) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } // Get the origin. nsAutoString origin; nsresult rv = nsContentUtils::GetUTFOrigin(global->PrincipalOrNull(), origin); if (NS_WARN_IF(NS_FAILED(rv))) { aRv.Throw(rv); return nullptr; } RefPtr promise = Promise::Create(global, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } // Generate a session ID. nsCOMPtr uuidgen = do_GetService("@mozilla.org/uuid-generator;1"); if(NS_WARN_IF(!uuidgen)) { promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR); return promise.forget(); } nsID uuid; uuidgen->GenerateUUIDInPlace(&uuid); char buffer[NSID_LENGTH]; uuid.ToProvidedString(buffer); nsAutoString id; CopyASCIItoUTF16(buffer, id); nsCOMPtr service = do_GetService(PRESENTATION_SERVICE_CONTRACTID); if(NS_WARN_IF(!service)) { promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR); return promise.forget(); } nsCOMPtr callback = new PresentationRequesterCallback(this, mUrl, id, promise); rv = service->StartSession(mUrl, id, origin, aDeviceId, GetOwner()->WindowID(), callback); if (NS_WARN_IF(NS_FAILED(rv))) { promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR); } return promise.forget(); } already_AddRefed PresentationRequest::GetAvailability(ErrorResult& aRv) { nsCOMPtr global = do_QueryInterface(GetOwner()); if (NS_WARN_IF(!global)) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } RefPtr promise = Promise::Create(global, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } promise->MaybeResolve(mAvailability); return promise.forget(); } nsresult PresentationRequest::DispatchConnectionAvailableEvent(PresentationConnection* aConnection) { PresentationConnectionAvailableEventInit init; init.mConnection = aConnection; RefPtr event = PresentationConnectionAvailableEvent::Constructor(this, NS_LITERAL_STRING("connectionavailable"), init); if (NS_WARN_IF(!event)) { return NS_ERROR_FAILURE; } event->SetTrusted(true); RefPtr asyncDispatcher = new AsyncEventDispatcher(this, event); return asyncDispatcher->PostDOMEvent(); }