Files
tubestation/toolkit/components/extensions/webidl-api/ExtensionBrowser.cpp

177 lines
5.9 KiB
C++

/* -*- 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<JSObject*> 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<JS::Value> aLastError) {
mLastError.set(aLastError);
mCheckedLastError = false;
}
void ExtensionBrowser::GetLastError(JS::MutableHandle<JS::Value> aRetVal) {
aRetVal.set(mLastError);
mCheckedLastError = true;
}
bool ExtensionBrowser::ClearLastError() {
bool shouldReport = !mCheckedLastError;
mLastError.setUndefined();
return shouldReport;
}
already_AddRefed<ExtensionPort> ExtensionBrowser::GetPort(
JS::Handle<JS::Value> aDescriptorValue, ErrorResult& aRv) {
// Get a port descriptor from the js value got from the API request
// handler.
UniquePtr<dom::ExtensionPortDescriptor> 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<ExtensionPort> existingPort = maybePort.value().get();
return existingPort.forget();
}
RefPtr<ExtensionPort> 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