/* -*- 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/. */ #include "ExtensionBrowser.h" #include "mozilla/dom/ExtensionBrowserBinding.h" #include "mozilla/dom/ExtensionPortBinding.h" // ExtensionPortDescriptor #include "mozilla/dom/WorkerPrivate.h" // GetWorkerPrivateFromContext #include "mozilla/extensions/ExtensionAlarms.h" #include "mozilla/extensions/ExtensionMockAPI.h" #include "mozilla/extensions/ExtensionPort.h" #include "mozilla/extensions/ExtensionRuntime.h" #include "mozilla/extensions/ExtensionTest.h" #include "mozilla/extensions/WebExtensionPolicy.h" namespace mozilla { namespace extensions { NS_IMPL_CYCLE_COLLECTION_CLASS(ExtensionBrowser) NS_IMPL_CYCLE_COLLECTING_ADDREF(ExtensionBrowser) NS_IMPL_CYCLE_COLLECTING_RELEASE(ExtensionBrowser) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ExtensionBrowser) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ExtensionBrowser) NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal) NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionAlarms) NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionMockAPI) NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionRuntime) NS_IMPL_CYCLE_COLLECTION_UNLINK(mExtensionTest) tmp->mLastError.setUndefined(); tmp->mPortsLookup.Clear(); NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ExtensionBrowser) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionAlarms) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionMockAPI) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionRuntime) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExtensionTest) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ExtensionBrowser) NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLastError) NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_TRACE_END ExtensionBrowser::ExtensionBrowser(nsIGlobalObject* aGlobal) : mGlobal(aGlobal) { MOZ_DIAGNOSTIC_ASSERT(mGlobal); } JSObject* ExtensionBrowser::WrapObject(JSContext* aCx, JS::Handle aGivenProto) { return dom::ExtensionBrowser_Binding::Wrap(aCx, this, aGivenProto); } nsIGlobalObject* ExtensionBrowser::GetParentObject() const { return mGlobal; } bool ExtensionAPIAllowed(JSContext* aCx, JSObject* aGlobal) { #ifdef MOZ_WEBEXT_WEBIDL_ENABLED // Only expose the Extension API bindings if: // - the context is related to a worker where the Extension API are allowed // (currently only the extension service worker declared in the extension // manifest met this condition) // - the global is an extension window or an extension content script sandbox // TODO: // - the support for the extension window is deferred to a followup. // - support for the content script sandboxes is also deferred to follow-ups // - lock native Extension API in an extension window or sandbox behind a // separate pref. MOZ_DIAGNOSTIC_ASSERT( !NS_IsMainThread(), "ExtensionAPI webidl bindings does not yet support main thread globals"); // Verify if the Extensions API should be allowed on a worker thread. if (!StaticPrefs::extensions_backgroundServiceWorker_enabled_AtStartup()) { return false; } auto* workerPrivate = mozilla::dom::GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(workerPrivate); MOZ_ASSERT(workerPrivate->IsServiceWorker()); return workerPrivate->ExtensionAPIAllowed(); #else // Always return false on build where MOZ_WEBEXT_WEBIDL_ENABLED is set to // false (currently on all channels but nightly). return false; #endif } void ExtensionBrowser::SetLastError(JS::Handle aLastError) { mLastError.set(aLastError); mCheckedLastError = false; } void ExtensionBrowser::GetLastError(JS::MutableHandle aRetVal) { aRetVal.set(mLastError); mCheckedLastError = true; } bool ExtensionBrowser::ClearLastError() { bool shouldReport = !mCheckedLastError; mLastError.setUndefined(); return shouldReport; } already_AddRefed ExtensionBrowser::GetPort( JS::Handle aDescriptorValue, ErrorResult& aRv) { // Get a port descriptor from the js value got from the API request // handler. UniquePtr portDescriptor = ExtensionPort::ToPortDescriptor(aDescriptorValue, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } auto portId = portDescriptor->mPortId; auto maybePort = mPortsLookup.MaybeGet(portId); if (maybePort.isSome() && maybePort.value().get()) { RefPtr existingPort = maybePort.value().get(); return existingPort.forget(); } RefPtr newPort = ExtensionPort::Create(mGlobal, this, std::move(portDescriptor)); mPortsLookup.InsertOrUpdate(portId, newPort); return newPort.forget(); } void ExtensionBrowser::ForgetReleasedPort(const nsAString& aPortId) { mPortsLookup.Remove(aPortId); } ExtensionAlarms* ExtensionBrowser::GetExtensionAlarms() { if (!mExtensionAlarms) { mExtensionAlarms = new ExtensionAlarms(mGlobal, this); } return mExtensionAlarms; } ExtensionMockAPI* ExtensionBrowser::GetExtensionMockAPI() { if (!mExtensionMockAPI) { mExtensionMockAPI = new ExtensionMockAPI(mGlobal, this); } return mExtensionMockAPI; } ExtensionRuntime* ExtensionBrowser::GetExtensionRuntime() { if (!mExtensionRuntime) { mExtensionRuntime = new ExtensionRuntime(mGlobal, this); } return mExtensionRuntime; } ExtensionTest* ExtensionBrowser::GetExtensionTest() { if (!mExtensionTest) { mExtensionTest = new ExtensionTest(mGlobal, this); } return mExtensionTest; } } // namespace extensions } // namespace mozilla