123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* 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/PreallocatedProcessManager.h"
- #include "mozilla/ClearOnShutdown.h"
- #include "mozilla/Preferences.h"
- #include "mozilla/Unused.h"
- #include "mozilla/dom/ContentParent.h"
- #include "mozilla/dom/ScriptSettings.h"
- #include "nsIPropertyBag2.h"
- #include "ProcessPriorityManager.h"
- #include "nsServiceManagerUtils.h"
- // This number is fairly arbitrary ... the intention is to put off
- // launching another app process until the last one has finished
- // loading its content, to reduce CPU/memory/IO contention.
- #define DEFAULT_ALLOCATE_DELAY 1000
- using namespace mozilla;
- using namespace mozilla::hal;
- using namespace mozilla::dom;
- namespace {
- /**
- * This singleton class implements the static methods on
- * PreallocatedProcessManager.
- */
- class PreallocatedProcessManagerImpl final
- : public nsIObserver
- {
- public:
- static PreallocatedProcessManagerImpl* Singleton();
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
- // See comments on PreallocatedProcessManager for these methods.
- void AllocateAfterDelay();
- void AllocateOnIdle();
- void AllocateNow();
- already_AddRefed<ContentParent> Take();
- private:
- static mozilla::StaticRefPtr<PreallocatedProcessManagerImpl> sSingleton;
- PreallocatedProcessManagerImpl();
- ~PreallocatedProcessManagerImpl() {}
- DISALLOW_EVIL_CONSTRUCTORS(PreallocatedProcessManagerImpl);
- void Init();
- void RereadPrefs();
- void Enable();
- void Disable();
- void ObserveProcessShutdown(nsISupports* aSubject);
- bool mEnabled;
- bool mShutdown;
- RefPtr<ContentParent> mPreallocatedAppProcess;
- };
- /* static */ StaticRefPtr<PreallocatedProcessManagerImpl>
- PreallocatedProcessManagerImpl::sSingleton;
- /* static */ PreallocatedProcessManagerImpl*
- PreallocatedProcessManagerImpl::Singleton()
- {
- if (!sSingleton) {
- sSingleton = new PreallocatedProcessManagerImpl();
- sSingleton->Init();
- ClearOnShutdown(&sSingleton);
- }
- return sSingleton;
- }
- NS_IMPL_ISUPPORTS(PreallocatedProcessManagerImpl, nsIObserver)
- PreallocatedProcessManagerImpl::PreallocatedProcessManagerImpl()
- :
- mEnabled(false)
- , mShutdown(false)
- {}
- void
- PreallocatedProcessManagerImpl::Init()
- {
- Preferences::AddStrongObserver(this, "dom.ipc.processPrelaunch.enabled");
- nsCOMPtr<nsIObserverService> os = services::GetObserverService();
- if (os) {
- os->AddObserver(this, "ipc:content-shutdown",
- /* weakRef = */ false);
- os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
- /* weakRef = */ false);
- }
- {
- RereadPrefs();
- }
- }
- NS_IMETHODIMP
- PreallocatedProcessManagerImpl::Observe(nsISupports* aSubject,
- const char* aTopic,
- const char16_t* aData)
- {
- if (!strcmp("ipc:content-shutdown", aTopic)) {
- ObserveProcessShutdown(aSubject);
- } else if (!strcmp("nsPref:changed", aTopic)) {
- // The only other observer we registered was for our prefs.
- RereadPrefs();
- } else if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic)) {
- mShutdown = true;
- } else {
- MOZ_ASSERT(false);
- }
- return NS_OK;
- }
- void
- PreallocatedProcessManagerImpl::RereadPrefs()
- {
- if (Preferences::GetBool("dom.ipc.processPrelaunch.enabled")) {
- Enable();
- } else {
- Disable();
- }
- }
- already_AddRefed<ContentParent>
- PreallocatedProcessManagerImpl::Take()
- {
- return mPreallocatedAppProcess.forget();
- }
- void
- PreallocatedProcessManagerImpl::Enable()
- {
- if (mEnabled) {
- return;
- }
- mEnabled = true;
- AllocateAfterDelay();
- }
- void
- PreallocatedProcessManagerImpl::AllocateAfterDelay()
- {
- if (!mEnabled || mPreallocatedAppProcess) {
- return;
- }
- MessageLoop::current()->PostDelayedTask(
- NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateOnIdle),
- Preferences::GetUint("dom.ipc.processPrelaunch.delayMs",
- DEFAULT_ALLOCATE_DELAY));
- }
- void
- PreallocatedProcessManagerImpl::AllocateOnIdle()
- {
- if (!mEnabled || mPreallocatedAppProcess) {
- return;
- }
- MessageLoop::current()->PostIdleTask(NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateNow));
- }
- void
- PreallocatedProcessManagerImpl::AllocateNow()
- {
- if (!mEnabled || mPreallocatedAppProcess) {
- return;
- }
- mPreallocatedAppProcess = ContentParent::PreallocateAppProcess();
- }
- void
- PreallocatedProcessManagerImpl::Disable()
- {
- if (!mEnabled) {
- return;
- }
- mEnabled = false;
- if (mPreallocatedAppProcess) {
- mPreallocatedAppProcess->Close();
- mPreallocatedAppProcess = nullptr;
- }
- }
- void
- PreallocatedProcessManagerImpl::ObserveProcessShutdown(nsISupports* aSubject)
- {
- if (!mPreallocatedAppProcess) {
- return;
- }
- nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
- NS_ENSURE_TRUE_VOID(props);
- uint64_t childID = CONTENT_PROCESS_ID_UNKNOWN;
- props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID);
- NS_ENSURE_TRUE_VOID(childID != CONTENT_PROCESS_ID_UNKNOWN);
- if (childID == mPreallocatedAppProcess->ChildID()) {
- mPreallocatedAppProcess = nullptr;
- }
- }
- inline PreallocatedProcessManagerImpl* GetPPMImpl()
- {
- return PreallocatedProcessManagerImpl::Singleton();
- }
- } // namespace
- namespace mozilla {
- /* static */ void
- PreallocatedProcessManager::AllocateAfterDelay()
- {
- GetPPMImpl()->AllocateAfterDelay();
- }
- /* static */ void
- PreallocatedProcessManager::AllocateOnIdle()
- {
- GetPPMImpl()->AllocateOnIdle();
- }
- /* static */ void
- PreallocatedProcessManager::AllocateNow()
- {
- GetPPMImpl()->AllocateNow();
- }
- /* static */ already_AddRefed<ContentParent>
- PreallocatedProcessManager::Take()
- {
- return GetPPMImpl()->Take();
- }
- } // namespace mozilla
|