/* -*- 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_extensions_ExtensionAPIBase_h #define mozilla_extensions_ExtensionAPIBase_h #include "mozilla/dom/BindingDeclarations.h" #include "mozilla/dom/FunctionBinding.h" #include "mozilla/dom/PromiseNativeHandler.h" #include "mozilla/ErrorResult.h" class nsIGlobalObject; namespace mozilla { namespace dom { class Function; } namespace extensions { #define NS_IMPL_WEBEXT_EVENTMGR_WITH_DATAMEMBER( \ _class, _eventName, _eventGetterName, _eventDataMember) \ ExtensionEventManager* _class::_eventGetterName() { \ if (!(_eventDataMember)) { \ (_eventDataMember) = CreateEventManager(_eventName); \ } \ return (_eventDataMember); \ } #define NS_IMPL_WEBEXT_EVENTMGR(_class, _eventName, _eventGetterName) \ NS_IMPL_WEBEXT_EVENTMGR_WITH_DATAMEMBER( \ _class, _eventName, _eventGetterName, m##_eventGetterName##EventMgr) #define NS_IMPL_WEBEXT_SETTING_WITH_DATAMEMBER( \ _class, _settingName, _settingGetterName, _settingDataMember) \ ExtensionSetting* _class::_settingGetterName() { \ if (!(_settingDataMember)) { \ (_settingDataMember) = CreateSetting(_settingName); \ } \ return (_settingDataMember); \ } #define NS_IMPL_WEBEXT_SETTING(_class, _settingName, _settingGetterName) \ NS_IMPL_WEBEXT_SETTING_WITH_DATAMEMBER(_class, _settingName, \ _settingGetterName, \ m##_settingGetterName##Setting) class ExtensionAPIAddRemoveListener; class ExtensionAPICallFunctionNoReturn; class ExtensionAPICallSyncFunction; class ExtensionAPICallAsyncFunction; class ExtensionAPIGetProperty; class ExtensionBrowser; class ExtensionEventManager; class ExtensionPort; class ExtensionSetting; class ExtensionAPIBase { public: // WebExtensionStub methods shared between multiple API namespaces. virtual void CallWebExtMethodNotImplementedNoReturn( JSContext* aCx, const nsAString& aApiMethod, const dom::Sequence& aArgs, ErrorResult& aRv); virtual void CallWebExtMethodNotImplementedAsync( JSContext* aCx, const nsAString& aApiMethod, const dom::Sequence& aArgs, const dom::Optional>& aCallback, JS::MutableHandle aRetval, ErrorResult& aRv); virtual void CallWebExtMethodNotImplemented( JSContext* aCx, const nsAString& aApiMethod, const dom::Sequence& aArgs, JS::MutableHandle aRetval, ErrorResult& aRv); virtual void CallWebExtMethodNoReturn(JSContext* aCx, const nsAString& aApiMethod, const dom::Sequence& aArgs, ErrorResult& aRv); virtual void CallWebExtMethod(JSContext* aCx, const nsAString& aApiMethod, const dom::Sequence& aArgs, JS::MutableHandle aRetVal, ErrorResult& aRv); virtual void CallWebExtMethodReturnsString( JSContext* aCx, const nsAString& aApiMethod, const dom::Sequence& aArgs, nsAString& aRetVal, ErrorResult& aRv); virtual already_AddRefed CallWebExtMethodReturnsPort( JSContext* aCx, const nsAString& aApiMethod, const dom::Sequence& aArgs, ErrorResult& aRv); virtual void CallWebExtMethodAsync( JSContext* aCx, const nsAString& aApiMethod, const dom::Sequence& aArgs, const dom::Optional>& aCallback, JS::MutableHandle aRetVal, ErrorResult& aRv); virtual void CallWebExtMethodAsyncAmbiguous( JSContext* aCx, const nsAString& aApiMethod, const dom::Sequence& aArgs, JS::MutableHandle aRetVal, ErrorResult& aRv); virtual void GetWebExtPropertyAsString(const nsString& aPropertyName, dom::DOMString& aRetval); virtual void GetWebExtPropertyAsJSValue(JSContext* aCx, const nsAString& aPropertyName, JS::MutableHandle aRetval); // API Requests helpers. already_AddRefed CreateEventManager( const nsAString& aEventName); already_AddRefed CreateSetting( const nsAString& aSettingName); RefPtr CallFunctionNoReturn( const nsAString& aApiMethod); RefPtr CallSyncFunction( const nsAString& aApiMethod); RefPtr CallAsyncFunction( const nsAString& aApiMethod); RefPtr GetProperty(const nsAString& aApiProperty); RefPtr SendAddListener( const nsAString& aEventName); RefPtr SendRemoveListener( const nsAString& aEventName); static void ThrowUnexpectedError(JSContext* aCx, ErrorResult& aRv); protected: virtual nsIGlobalObject* GetGlobalObject() const = 0; virtual ExtensionBrowser* GetExtensionBrowser() const = 0; virtual nsString GetAPINamespace() const = 0; virtual nsString GetAPIObjectType() const = 0; virtual nsString GetAPIObjectId() const = 0; private: void CallWebExtMethodAsyncInternal(JSContext* aCx, const nsAString& aApiMethod, const dom::Sequence& aArgs, const RefPtr& aCallback, JS::MutableHandle aRetval, ErrorResult& aRv); }; class ExtensionAPINamespace : public ExtensionAPIBase { protected: nsString GetAPIObjectType() const override { return VoidString(); } nsString GetAPIObjectId() const override { return VoidString(); }; }; class ChromeCompatCallbackHandler final : public dom::PromiseNativeHandler { public: NS_DECL_THREADSAFE_ISUPPORTS static void Create(ExtensionBrowser* aExtensionBrowser, dom::Promise* aPromise, const RefPtr& aCallback); MOZ_CAN_RUN_SCRIPT void ResolvedCallback(JSContext* aCx, JS::Handle aValue, ErrorResult& aRv) override; MOZ_CAN_RUN_SCRIPT void RejectedCallback(JSContext* aCx, JS::Handle aValue, ErrorResult& aRv) override; private: ChromeCompatCallbackHandler(ExtensionBrowser* aExtensionBrowser, const RefPtr& aCallback) : mCallback(aCallback), mExtensionBrowser(aExtensionBrowser) { MOZ_ASSERT(aCallback); MOZ_ASSERT(aExtensionBrowser); } ~ChromeCompatCallbackHandler() = default; void ReportUncheckedLastError(JSContext* aCx, JS::Handle aValue); RefPtr mCallback; RefPtr mExtensionBrowser; }; } // namespace extensions } // namespace mozilla #endif // mozilla_extensions_ExtensionAPIBase_h