/* -*- 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 "nsIGlobalObject.h" #include "mozilla/dom/ServiceWorker.h" #include "nsContentUtils.h" #include "nsThreadUtils.h" #include "nsHostObjectProtocolHandler.h" using mozilla::Maybe; using mozilla::dom::ClientInfo; using mozilla::dom::ServiceWorker; using mozilla::dom::ServiceWorkerDescriptor; nsIGlobalObject::~nsIGlobalObject() { UnlinkHostObjectURIs(); } nsIPrincipal* nsIGlobalObject::PrincipalOrNull() { JSObject *global = GetGlobalJSObject(); if (NS_WARN_IF(!global)) return nullptr; return nsContentUtils::ObjectPrincipal(global); } void nsIGlobalObject::RegisterHostObjectURI(const nsACString& aURI) { MOZ_ASSERT(!mHostObjectURIs.Contains(aURI)); mHostObjectURIs.AppendElement(aURI); } void nsIGlobalObject::UnregisterHostObjectURI(const nsACString& aURI) { mHostObjectURIs.RemoveElement(aURI); } namespace { class UnlinkHostObjectURIsRunnable final : public mozilla::Runnable { public: explicit UnlinkHostObjectURIsRunnable(nsTArray& aURIs) : mozilla::Runnable("UnlinkHostObjectURIsRunnable") { mURIs.SwapElements(aURIs); } NS_IMETHOD Run() override { MOZ_ASSERT(NS_IsMainThread()); for (uint32_t index = 0; index < mURIs.Length(); ++index) { nsHostObjectProtocolHandler::RemoveDataEntry(mURIs[index]); } return NS_OK; } private: ~UnlinkHostObjectURIsRunnable() {} nsTArray mURIs; }; } // namespace void nsIGlobalObject::UnlinkHostObjectURIs() { if (mHostObjectURIs.IsEmpty()) { return; } if (NS_IsMainThread()) { for (uint32_t index = 0; index < mHostObjectURIs.Length(); ++index) { nsHostObjectProtocolHandler::RemoveDataEntry(mHostObjectURIs[index]); } mHostObjectURIs.Clear(); return; } // nsHostObjectProtocolHandler is main-thread only. RefPtr runnable = new UnlinkHostObjectURIsRunnable(mHostObjectURIs); MOZ_ASSERT(mHostObjectURIs.IsEmpty()); nsresult rv = NS_DispatchToMainThread(runnable); if (NS_FAILED(rv)) { NS_WARNING("Failed to dispatch a runnable to the main-thread."); } } void nsIGlobalObject::TraverseHostObjectURIs(nsCycleCollectionTraversalCallback &aCb) { if (mHostObjectURIs.IsEmpty()) { return; } // Currently we only store BlobImpl objects off the the main-thread and they // are not CCed. if (!NS_IsMainThread()) { return; } for (uint32_t index = 0; index < mHostObjectURIs.Length(); ++index) { nsHostObjectProtocolHandler::Traverse(mHostObjectURIs[index], aCb); } } Maybe nsIGlobalObject::GetClientInfo() const { // By default globals do not expose themselves as a client. Only real // window and worker globals are currently considered clients. return Maybe(); } Maybe nsIGlobalObject::GetController() const { // By default globals do not have a service worker controller. Only real // window and worker globals can currently be controlled as a client. return Maybe(); } RefPtr nsIGlobalObject::GetOrCreateServiceWorker(const ServiceWorkerDescriptor& aDescriptor) { MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service workers"); return nullptr; } void nsIGlobalObject::AddServiceWorker(ServiceWorker* aServiceWorker) { MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service workers"); } void nsIGlobalObject::RemoveServiceWorker(ServiceWorker* aServiceWorker) { MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service workers"); }