nsresult ShutdownXPCOM(nsIServiceManager* aServMgr) { // Make sure the hang monitor is enabled for shutdown. HangMonitor::NotifyActivity(); if (!NS_IsMainThread()) { NS_RUNTIMEABORT("Shutdown on wrong thread"); } nsresult rv; nsCOMPtr<nsISimpleEnumerator> moduleLoaders; // Notify observers of xpcom shutting down { // Block it so that the COMPtr will get deleted before we hit // servicemanager shutdown nsCOMPtr<nsIThread> thread = do_GetCurrentThread(); if (NS_WARN_IF(!thread)) { return NS_ERROR_UNEXPECTED; } RefPtr<nsObserverService> observerService; CallGetService("@mozilla.org/observer-service;1", (nsObserverService**)getter_AddRefs(observerService)); if (observerService) { observerService->NotifyObservers(nullptr, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, nullptr); nsCOMPtr<nsIServiceManager> mgr; rv = NS_GetServiceManager(getter_AddRefs(mgr)); if (NS_SUCCEEDED(rv)) { observerService->NotifyObservers(mgr, NS_XPCOM_SHUTDOWN_OBSERVER_ID, nullptr); } } // This must happen after the shutdown of media and widgets, which // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification. NS_ProcessPendingEvents(thread); gfxPlatform::ShutdownLayersIPC(); mozilla::scache::StartupCache::DeleteSingleton(); if (observerService) observerService->NotifyObservers(nullptr, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, nullptr); gXPCOMThreadsShutDown = true; NS_ProcessPendingEvents(thread); // Shutdown the timer thread and all timers that might still be alive before // shutting down the component manager nsTimerImpl::Shutdown(); NS_ProcessPendingEvents(thread); // Shutdown all remaining threads. This method does not return until // all threads created using the thread manager (with the exception of // the main thread) have exited. nsThreadManager::get()->Shutdown(); NS_ProcessPendingEvents(thread); HangMonitor::NotifyActivity(); // Late-write checks needs to find the profile directory, so it has to // be initialized before mozilla::services::Shutdown or (because of // xpcshell tests replacing the service) modules being unloaded. mozilla::InitLateWriteChecks(); // We save the "xpcom-shutdown-loaders" observers to notify after // the observerservice is gone. if (observerService) { observerService->EnumerateObservers(NS_XPCOM_SHUTDOWN_LOADERS_OBSERVER_ID, getter_AddRefs(moduleLoaders)); observerService->Shutdown(); } } // Free ClearOnShutdown()'ed smart pointers. This needs to happen *after* // we've finished notifying observers of XPCOM shutdown, because shutdown // observers themselves might call ClearOnShutdown(). mozilla::KillClearOnShutdown(); // XPCOM is officially in shutdown mode NOW // Set this only after the observers have been notified as this // will cause servicemanager to become inaccessible. mozilla::services::Shutdown(); #ifdef DEBUG_dougt fprintf(stderr, "* * * * XPCOM shutdown. Access will be denied * * * * \n"); #endif // We may have AddRef'd for the caller of NS_InitXPCOM, so release it // here again: NS_IF_RELEASE(aServMgr); // Shutdown global servicemanager if (nsComponentManagerImpl::gComponentManager) { nsComponentManagerImpl::gComponentManager->FreeServices(); } // Release the directory service NS_IF_RELEASE(nsDirectoryService::gService); free(gGREBinPath); gGREBinPath = nullptr; if (moduleLoaders) { bool more; nsCOMPtr<nsISupports> el; while (NS_SUCCEEDED(moduleLoaders->HasMoreElements(&more)) && more) { moduleLoaders->GetNext(getter_AddRefs(el)); // Don't worry about weak-reference observers here: there is // no reason for weak-ref observers to register for // xpcom-shutdown-loaders // FIXME: This can cause harmless writes from sqlite committing // log files. We have to ignore them before we can move // the mozilla::PoisonWrite call before this point. See bug // 834945 for the details. nsCOMPtr<nsIObserver> obs(do_QueryInterface(el)); if (obs) { obs->Observe(nullptr, NS_XPCOM_SHUTDOWN_LOADERS_OBSERVER_ID, nullptr); } } moduleLoaders = nullptr; } nsCycleCollector_shutdown(); layers::AsyncTransactionTrackersHolder::Finalize(); PROFILER_MARKER("Shutdown xpcom"); // If we are doing any shutdown checks, poison writes. if (gShutdownChecks != SCM_NOTHING) { #ifdef XP_MACOSX mozilla::OnlyReportDirtyWrites(); #endif /* XP_MACOSX */ mozilla::BeginLateWriteChecks(); } // Shutdown nsLocalFile string conversion NS_ShutdownLocalFile(); #ifdef XP_UNIX NS_ShutdownNativeCharsetUtils(); #endif #if defined(XP_WIN) // This exit(0) call is intended to be temporary, to get shutdown leak // checking working on Linux. // On Windows XP debug, there are intermittent failures in // dom/media/tests/mochitest/test_peerConnection_basicH264Video.html // if we don't exit early in a child process. See bug 1073310. if (XRE_IsContentProcess() && !IsVistaOrLater()) { NS_WARNING("Exiting child process early!"); exit(0); } #endif // Shutdown xpcom. This will release all loaders and cause others holding // a refcount to the component manager to release it. if (nsComponentManagerImpl::gComponentManager) { rv = (nsComponentManagerImpl::gComponentManager)->Shutdown(); NS_ASSERTION(NS_SUCCEEDED(rv), "Component Manager shutdown failed."); } else { NS_WARNING("Component Manager was never created ..."); } #ifdef MOZ_ENABLE_PROFILER_SPS // In optimized builds we don't do shutdown collections by default, so // uncollected (garbage) objects may keep the nsXPConnect singleton alive, // and its XPCJSRuntime along with it. However, we still destroy various // bits of state in JS_ShutDown(), so we need to make sure the profiler // can't access them when it shuts down. This call nulls out the // JS pseudo-stack's internal reference to the main thread JSRuntime, // duplicating the call in XPCJSRuntime::~XPCJSRuntime() in case that // never fired. if (PseudoStack* stack = mozilla_get_pseudo_stack()) { stack->sampleRuntime(nullptr); } #endif // Shut down the JS engine. JS_ShutDown(); // Release our own singletons // Do this _after_ shutting down the component manager, because the // JS component loader will use XPConnect to call nsIModule::canUnload, // and that will spin up the InterfaceInfoManager again -- bad mojo XPTInterfaceInfoManager::FreeInterfaceInfoManager(); // Finally, release the component manager last because it unloads the // libraries: if (nsComponentManagerImpl::gComponentManager) { nsrefcnt cnt; NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt); NS_ASSERTION(cnt == 0, "Component Manager being held past XPCOM shutdown."); } nsComponentManagerImpl::gComponentManager = nullptr; nsCategoryManager::Destroy(); NS_PurgeAtomTable(); NS_IF_RELEASE(gDebug); delete sIOThread; sIOThread = nullptr; delete sMessageLoop; sMessageLoop = nullptr; if (sCommandLineWasInitialized) { CommandLine::Terminate(); sCommandLineWasInitialized = false; } delete sExitManager; sExitManager = nullptr; Omnijar::CleanUp(); HangMonitor::Shutdown(); delete sMainHangMonitor; sMainHangMonitor = nullptr; BackgroundHangMonitor::Shutdown(); profiler_shutdown(); NS_LogTerm(); #if defined(MOZ_WIDGET_GONK) // This exit(0) call is intended to be temporary, to get shutdown leak // checking working on Linux. // On debug B2G, the child process crashes very late. Instead, just // give up so at least we exit cleanly. See bug 1071866. if (XRE_IsContentProcess()) { NS_WARNING("Exiting child process early!"); exit(0); } #endif return NS_OK; }
bool ClientLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback, void* aCallbackData, EndTransactionFlags) { PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Rasterization); AutoProfilerTracing tracing("Paint", "Rasterize"); Maybe<TimeStamp> startTime; if (gfxPrefs::LayersDrawFPS()) { startTime = Some(TimeStamp::Now()); } #ifdef WIN32 if (aCallbackData) { // Content processes don't get OnPaint called. So update here whenever we // may do Thebes drawing. gfxDWriteFont::UpdateClearTypeUsage(); } #endif AUTO_PROFILER_LABEL("ClientLayerManager::EndTransactionInternal", GRAPHICS); #ifdef MOZ_LAYERS_HAVE_LOG MOZ_LAYERS_LOG((" ----- (beginning paint)")); Log(); #endif NS_ASSERTION(InConstruction(), "Should be in construction phase"); mPhase = PHASE_DRAWING; ClientLayer* root = ClientLayer::ToClientLayer(GetRoot()); mTransactionIncomplete = false; // Apply pending tree updates before recomputing effective // properties. GetRoot()->ApplyPendingUpdatesToSubtree(); mPaintedLayerCallback = aCallback; mPaintedLayerCallbackData = aCallbackData; GetRoot()->ComputeEffectiveTransforms(Matrix4x4()); // Skip the painting if the device is in device-reset status. if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { if (gfxPrefs::AlwaysPaint() && XRE_IsContentProcess()) { TimeStamp start = TimeStamp::Now(); root->RenderLayer(); mLastPaintTime = TimeStamp::Now() - start; } else { root->RenderLayer(); } } else { gfxCriticalNote << "LayerManager::EndTransaction skip RenderLayer()."; } if (!mRepeatTransaction && !GetRoot()->GetInvalidRegion().IsEmpty()) { GetRoot()->Mutated(); } if (!mIsRepeatTransaction) { mAnimationReadyTime = TimeStamp::Now(); GetRoot()->StartPendingAnimations(mAnimationReadyTime); } mPaintedLayerCallback = nullptr; mPaintedLayerCallbackData = nullptr; // Go back to the construction phase if the transaction isn't complete. // Layout will update the layer tree and call EndTransaction(). mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE; NS_ASSERTION(!aCallback || !mTransactionIncomplete, "If callback is not null, transaction must be complete"); if (gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { FrameLayerBuilder::InvalidateAllLayers(this); } if (startTime) { PaintTiming& pt = mForwarder->GetPaintTiming(); pt.rasterMs() = (TimeStamp::Now() - startTime.value()).ToMilliseconds(); } return !mTransactionIncomplete; }
void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) { AutoProfilerTracing tracing("Paint", "ForwardTransaction"); TimeStamp start = TimeStamp::Now(); // Skip the synchronization for buffer since we also skip the painting during // device-reset status. if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { if (mForwarder->GetSyncObject() && mForwarder->GetSyncObject()->IsSyncObjectValid()) { mForwarder->GetSyncObject()->Synchronize(); } } mPhase = PHASE_FORWARD; mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(!mIsRepeatTransaction); TimeStamp transactionStart; if (!mTransactionIdAllocator->GetTransactionStart().IsNull()) { transactionStart = mTransactionIdAllocator->GetTransactionStart(); } else { transactionStart = mTransactionStart; } if (gfxPrefs::AlwaysPaint() && XRE_IsContentProcess()) { mForwarder->SendPaintTime(mLatestTransactionId, mLastPaintTime); } // forward this transaction's changeset to our LayerManagerComposite bool sent = false; bool ok = mForwarder->EndTransaction( mRegionToClear, mLatestTransactionId, aScheduleComposite, mPaintSequenceNumber, mIsRepeatTransaction, transactionStart, &sent); if (ok) { if (sent) { mNeedsComposite = false; } } else if (HasShadowManager()) { NS_WARNING("failed to forward Layers transaction"); } if (!sent) { // Clear the transaction id so that it doesn't get returned // unless we forwarded to somewhere that doesn't actually // have a compositor. mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId); } mPhase = PHASE_NONE; // this may result in Layers being deleted, which results in // PLayer::Send__delete__() and DeallocShmem() mKeepAlive.Clear(); TabChild* window = mWidget ? mWidget->GetOwningTabChild() : nullptr; if (window) { TimeStamp end = TimeStamp::Now(); window->DidRequestComposite(start, end); } }
IDXGIAdapter1* DeviceManagerDx::GetDXGIAdapter() { if (mAdapter) { return mAdapter; } nsModuleHandle dxgiModule(LoadLibrarySystem32(L"dxgi.dll")); decltype(CreateDXGIFactory1)* createDXGIFactory1 = (decltype(CreateDXGIFactory1)*) GetProcAddress(dxgiModule, "CreateDXGIFactory1"); if (!createDXGIFactory1) { return nullptr; } // Try to use a DXGI 1.1 adapter in order to share resources // across processes. RefPtr<IDXGIFactory1> factory1; HRESULT hr = createDXGIFactory1(__uuidof(IDXGIFactory1), getter_AddRefs(factory1)); if (FAILED(hr) || !factory1) { // This seems to happen with some people running the iZ3D driver. // They won't get acceleration. return nullptr; } if (!mDeviceStatus) { // If we haven't created a device yet, and have no existing device status, // then this must be the compositor device. Pick the first adapter we can. MOZ_ASSERT(ProcessOwnsCompositor()); if (FAILED(factory1->EnumAdapters1(0, getter_AddRefs(mAdapter)))) { return nullptr; } } else { // In the UI and GPU process, we clear mDeviceStatus on device reset, so we // should never reach here. Furthermore, the UI process does not create // devices when using a GPU process. // // So, this should only ever get called on the content process. MOZ_ASSERT(XRE_IsContentProcess()); // In the child process, we search for the adapter that matches the parent // process. The first adapter can be mismatched on dual-GPU systems. for (UINT index = 0; ; index++) { RefPtr<IDXGIAdapter1> adapter; if (FAILED(factory1->EnumAdapters1(index, getter_AddRefs(adapter)))) { break; } const DxgiAdapterDesc& preferred = mDeviceStatus->adapter(); DXGI_ADAPTER_DESC desc; if (SUCCEEDED(adapter->GetDesc(&desc)) && desc.AdapterLuid.HighPart == preferred.AdapterLuid.HighPart && desc.AdapterLuid.LowPart == preferred.AdapterLuid.LowPart && desc.VendorId == preferred.VendorId && desc.DeviceId == preferred.DeviceId) { mAdapter = adapter.forget(); break; } } } if (!mAdapter) { return nullptr; } // We leak this module everywhere, we might as well do so here as well. dxgiModule.disown(); return mAdapter; }
bool ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget) { // Wait for any previous async paints to complete before starting to paint again. GetCompositorBridgeChild()->FlushAsyncPaints(); MOZ_ASSERT(mForwarder, "ClientLayerManager::BeginTransaction without forwarder"); if (!mForwarder->IPCOpen()) { gfxCriticalNote << "ClientLayerManager::BeginTransaction with IPC channel down. GPU process may have died."; return false; } if (XRE_IsContentProcess() && mForwarder->DeviceCanReset() && mDeviceResetSequenceNumber != CompositorBridgeChild::Get()->DeviceResetSequenceNumber()) { // The compositor has informed this process that a device reset occurred, // but it has not finished informing each TabChild of its new // TextureFactoryIdentifier. Until then, it's illegal to paint. Note that // it is also illegal to request a new TIF synchronously, because we're // not guaranteed the UI process has finished acquiring new compositors // for each widget. // // Note that we only do this for accelerated backends, since we do not // perform resets on basic compositors. gfxCriticalNote << "Discarding a paint since a device reset has not yet been acknowledged."; return false; } mInTransaction = true; mTransactionStart = TimeStamp::Now(); #ifdef MOZ_LAYERS_HAVE_LOG MOZ_LAYERS_LOG(("[----- BeginTransaction")); Log(); #endif NS_ASSERTION(!InTransaction(), "Nested transactions not allowed"); mPhase = PHASE_CONSTRUCTION; MOZ_ASSERT(mKeepAlive.IsEmpty(), "uncommitted txn?"); // If the last transaction was incomplete (a failed DoEmptyTransaction), // don't signal a new transaction to ShadowLayerForwarder. Carry on adding // to the previous transaction. dom::ScreenOrientationInternal orientation; if (dom::TabChild* window = mWidget->GetOwningTabChild()) { orientation = window->GetOrientation(); } else { hal::ScreenConfiguration currentConfig; hal::GetCurrentScreenConfiguration(¤tConfig); orientation = currentConfig.orientation(); } LayoutDeviceIntRect targetBounds = mWidget->GetNaturalBounds(); targetBounds.x = targetBounds.y = 0; mForwarder->BeginTransaction(targetBounds.ToUnknownRect(), mTargetRotation, orientation); // If we're drawing on behalf of a context with async pan/zoom // enabled, then the entire buffer of painted layers might be // composited (including resampling) asynchronously before we get // a chance to repaint, so we have to ensure that it's all valid // and not rotated. // // Desktop does not support async zoom yet, so we ignore this for those // platforms. #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT) if (mWidget && mWidget->GetOwningTabChild()) { mCompositorMightResample = AsyncPanZoomEnabled(); } #endif // If we have a non-default target, we need to let our shadow manager draw // to it. This will happen at the end of the transaction. if (aTarget && XRE_IsParentProcess()) { mShadowTarget = aTarget; } else { NS_ASSERTION(!aTarget, "Content-process ClientLayerManager::BeginTransactionWithTarget not supported"); } // If this is a new paint, increment the paint sequence number. if (!mIsRepeatTransaction) { // Increment the paint sequence number even if test logging isn't // enabled in this process; it may be enabled in the parent process, // and the parent process expects unique sequence numbers. ++mPaintSequenceNumber; if (gfxPrefs::APZTestLoggingEnabled()) { mApzTestData.StartNewPaint(mPaintSequenceNumber); } } return true; }
void DataTransfer::CacheExternalClipboardFormats() { NS_ASSERTION(mEventMessage == ePaste, "caching clipboard data for invalid event"); // Called during the constructor for paste events to cache the formats // available on the clipboard. As with CacheExternalDragFormats, the // data will only be retrieved when needed. nsCOMPtr<nsIClipboard> clipboard = do_GetService("@mozilla.org/widget/clipboard;1"); if (!clipboard || mClipboardType < 0) { return; } nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); nsCOMPtr<nsIPrincipal> sysPrincipal; ssm->GetSystemPrincipal(getter_AddRefs(sysPrincipal)); // Check if the clipboard has any files bool hasFileData = false; const char *fileMime[] = { kFileMime }; clipboard->HasDataMatchingFlavors(fileMime, 1, mClipboardType, &hasFileData); // We will be ignoring any application/x-moz-file files found in the paste // datatransfer within e10s, as they will fail to be sent over IPC. Because of // that, we will unset hasFileData, whether or not it would have been set. // (bug 1308007) if (XRE_IsContentProcess()) { hasFileData = false; } // there isn't a way to get a list of the formats that might be available on // all platforms, so just check for the types that can actually be imported. // NOTE: kCustomTypesMime must have index 0, kFileMime index 1 const char* formats[] = { kCustomTypesMime, kFileMime, kHTMLMime, kRTFMime, kURLMime, kURLDataMime, kUnicodeMime, kPNGImageMime }; for (uint32_t f = 0; f < mozilla::ArrayLength(formats); ++f) { // check each format one at a time bool supported; clipboard->HasDataMatchingFlavors(&(formats[f]), 1, mClipboardType, &supported); // if the format is supported, add an item to the array with null as // the data. When retrieved, GetRealData will read the data. if (supported) { if (f == 0) { FillInExternalCustomTypes(0, sysPrincipal); } else { // In non-e10s we support pasting files from explorer.exe. // Unfortunately, we fail to send that data over IPC in e10s, so we // don't want to add the item to the DataTransfer and end up producing a // null `application/x-moz-file`. (bug 1308007) if (XRE_IsContentProcess() && f == 1) { continue; } // If we aren't the file data, and we have file data, we want to be hidden CacheExternalData(formats[f], 0, sysPrincipal, /* hidden = */ f != 1 && hasFileData); } } } }
nsresult nsPluginNativeWindowGtk::CallSetWindow(nsRefPtr<nsNPAPIPluginInstance> &aPluginInstance) { if (aPluginInstance) { if (type == NPWindowTypeWindow && XRE_IsContentProcess()) { // In this case, most of the initialization code here has already happened // in the chrome process. The window we have in content is the XID of the // socket widget we need to hand to plugins. SetWindow((XID)window); } else if (type == NPWindowTypeWindow) { if (!mSocketWidget) { nsresult rv; // The documentation on the types for many variables in NP(N|P)_GetValue // is vague. Often boolean values are NPBool (1 byte), but // https://developer.mozilla.org/en/XEmbed_Extension_for_Mozilla_Plugins // treats NPPVpluginNeedsXEmbed as PRBool (int), and // on x86/32-bit, flash stores to this using |movl 0x1,&needsXEmbed|. // thus we can't use NPBool for needsXEmbed, or the three bytes above // it on the stack would get clobbered. so protect with the larger bool. int needsXEmbed = 0; rv = aPluginInstance->GetValueFromPlugin(NPPVpluginNeedsXEmbed, &needsXEmbed); // If the call returned an error code make sure we still use our default value. if (NS_FAILED(rv)) { needsXEmbed = 0; } #ifdef DEBUG printf("nsPluginNativeWindowGtk: NPPVpluginNeedsXEmbed=%d\n", needsXEmbed); #endif bool isOOPPlugin = aPluginInstance->GetPlugin()->GetLibrary()->IsOOP(); if (needsXEmbed || isOOPPlugin) { bool enableXtFocus = !needsXEmbed; rv = CreateXEmbedWindow(enableXtFocus); } else { #if (MOZ_WIDGET_GTK == 2) rv = CreateXtWindow(); #else return NS_ERROR_FAILURE; #endif } if (NS_FAILED(rv)) { return NS_ERROR_FAILURE; } } if (!mSocketWidget) { return NS_ERROR_FAILURE; } // Make sure to resize and re-place the window if required. SetAllocation(); // Need to reset "window" each time as nsPluginFrame::DidReflow sets it // to the ancestor window. #if (MOZ_WIDGET_GTK == 2) if (GTK_IS_XTBIN(mSocketWidget)) { // Point the NPWindow structures window to the actual X window SetWindow(GTK_XTBIN(mSocketWidget)->xtwindow); } else { // XEmbed or OOP&Xt SetWindow(gtk_socket_get_id(GTK_SOCKET(mSocketWidget))); } #else // Gtk3 supports only OOP by GtkSocket SetWindow(gtk_socket_get_id(GTK_SOCKET(mSocketWidget))); #endif #ifdef DEBUG printf("nsPluginNativeWindowGtk: call SetWindow with xid=%p\n", (void *)window); #endif } // NPWindowTypeWindow aPluginInstance->SetWindow(this); } else if (mPluginInstance) { mPluginInstance->SetWindow(nullptr); } SetPluginInstance(aPluginInstance); return NS_OK; }
void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) { TimeStamp start = TimeStamp::Now(); // Skip the synchronization for buffer since we also skip the painting during // device-reset status. if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { if (mForwarder->GetSyncObject()) { mForwarder->GetSyncObject()->FinalizeFrame(); } } mPhase = PHASE_FORWARD; mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(); TimeStamp transactionStart; if (!mTransactionIdAllocator->GetTransactionStart().IsNull()) { transactionStart = mTransactionIdAllocator->GetTransactionStart(); } else { transactionStart = mTransactionStart; } if (gfxPrefs::AlwaysPaint() && XRE_IsContentProcess()) { mForwarder->SendPaintTime(mLatestTransactionId, mLastPaintTime); } // forward this transaction's changeset to our LayerManagerComposite bool sent; AutoTArray<EditReply, 10> replies; if (mForwarder->EndTransaction(&replies, mRegionToClear, mLatestTransactionId, aScheduleComposite, mPaintSequenceNumber, mIsRepeatTransaction, transactionStart, &sent)) { for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) { const EditReply& reply = replies[i]; switch (reply.type()) { case EditReply::TOpContentBufferSwap: { MOZ_LAYERS_LOG(("[LayersForwarder] DoubleBufferSwap")); const OpContentBufferSwap& obs = reply.get_OpContentBufferSwap(); RefPtr<CompositableClient> compositable = CompositableClient::FromIPDLActor(obs.compositableChild()); ContentClientRemote* contentClient = static_cast<ContentClientRemote*>(compositable.get()); MOZ_ASSERT(contentClient); contentClient->SwapBuffers(obs.frontUpdatedRegion()); break; } default: MOZ_CRASH("not reached"); } } if (sent) { mNeedsComposite = false; } } else if (HasShadowManager()) { NS_WARNING("failed to forward Layers transaction"); } if (!sent) { // Clear the transaction id so that it doesn't get returned // unless we forwarded to somewhere that doesn't actually // have a compositor. mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId); } mPhase = PHASE_NONE; // this may result in Layers being deleted, which results in // PLayer::Send__delete__() and DeallocShmem() mKeepAlive.Clear(); TabChild* window = mWidget ? mWidget->GetOwningTabChild() : nullptr; if (window) { TimeStamp end = TimeStamp::Now(); window->DidRequestComposite(start, end); } }
void InstallSignalHandlers(const char *ProgramName) { PL_strncpy(_progname,ProgramName, (sizeof(_progname)-1) ); const char *gdbSleep = PR_GetEnv("MOZ_GDB_SLEEP"); if (gdbSleep && *gdbSleep) { unsigned int s; if (1 == sscanf(gdbSleep, "%u", &s)) { _gdb_sleep_duration = s; } } #if defined(CRAWL_STACK_ON_SIGSEGV) if (!getenv("XRE_NO_WINDOWS_CRASH_DIALOG")) { void (*crap_handler)(int) = GeckoProcessType_Default != XRE_GetProcessType() ? child_ah_crap_handler : ah_crap_handler; signal(SIGSEGV, crap_handler); signal(SIGILL, crap_handler); signal(SIGABRT, crap_handler); } #endif // CRAWL_STACK_ON_SIGSEGV #ifdef SA_SIGINFO /* Install a handler for floating point exceptions and disable them if they occur. */ struct sigaction sa, osa; sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO; sa.sa_sigaction = fpehandler; sigemptyset(&sa.sa_mask); sigaction(SIGFPE, &sa, &osa); #endif if (XRE_IsContentProcess()) { /* * If the user is debugging a Gecko parent process in gdb and hits ^C to * suspend, a SIGINT signal will be sent to the child. We ignore this signal * so the child isn't killed. */ signal(SIGINT, SIG_IGN); } #if defined(DEBUG) && defined(LINUX) const char *memLimit = PR_GetEnv("MOZ_MEM_LIMIT"); if (memLimit && *memLimit) { long m = atoi(memLimit); m *= (1024*1024); struct rlimit r; r.rlim_cur = m; r.rlim_max = m; setrlimit(RLIMIT_AS, &r); } #endif #if defined(SOLARIS) #define NOFILES 512 // Boost Solaris file descriptors { struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) == 0) if (rl.rlim_cur < NOFILES) { rl.rlim_cur = NOFILES; if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { perror("setrlimit(RLIMIT_NOFILE)"); fprintf(stderr, "Cannot exceed hard limit for open files"); } #if defined(DEBUG) if (getrlimit(RLIMIT_NOFILE, &rl) == 0) printf("File descriptors set to %d\n", rl.rlim_cur); #endif //DEBUG } } #endif //SOLARIS #if defined(MOZ_WIDGET_GTK) && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6)) const char *assertString = PR_GetEnv("XPCOM_DEBUG_BREAK"); if (assertString && (!strcmp(assertString, "suspend") || !strcmp(assertString, "stack") || !strcmp(assertString, "abort") || !strcmp(assertString, "trap") || !strcmp(assertString, "break"))) { // Override the default glib logging function so we get stacks for it too. orig_log_func = g_log_set_default_handler(my_glib_log_func, nullptr); } #endif }
bool ClientLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback, void* aCallbackData, EndTransactionFlags) { PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Rasterization); PROFILER_LABEL("ClientLayerManager", "EndTransactionInternal", js::ProfileEntry::Category::GRAPHICS); #ifdef MOZ_LAYERS_HAVE_LOG MOZ_LAYERS_LOG((" ----- (beginning paint)")); Log(); #endif profiler_tracing("Paint", "Rasterize", TRACING_INTERVAL_START); NS_ASSERTION(InConstruction(), "Should be in construction phase"); mPhase = PHASE_DRAWING; ClientLayer* root = ClientLayer::ToClientLayer(GetRoot()); mTransactionIncomplete = false; // Apply pending tree updates before recomputing effective // properties. GetRoot()->ApplyPendingUpdatesToSubtree(); mPaintedLayerCallback = aCallback; mPaintedLayerCallbackData = aCallbackData; GetRoot()->ComputeEffectiveTransforms(Matrix4x4()); // Skip the painting if the device is in device-reset status. if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { if (gfxPrefs::AlwaysPaint() && XRE_IsContentProcess()) { TimeStamp start = TimeStamp::Now(); root->RenderLayer(); mLastPaintTime = TimeStamp::Now() - start; } else { root->RenderLayer(); } } else { gfxCriticalNote << "LayerManager::EndTransaction skip RenderLayer()."; } if (!mRepeatTransaction && !GetRoot()->GetInvalidRegion().IsEmpty()) { GetRoot()->Mutated(); } if (!mIsRepeatTransaction) { mAnimationReadyTime = TimeStamp::Now(); GetRoot()->StartPendingAnimations(mAnimationReadyTime); } mPaintedLayerCallback = nullptr; mPaintedLayerCallbackData = nullptr; // Go back to the construction phase if the transaction isn't complete. // Layout will update the layer tree and call EndTransaction(). mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE; NS_ASSERTION(!aCallback || !mTransactionIncomplete, "If callback is not null, transaction must be complete"); if (gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) { FrameLayerBuilder::InvalidateAllLayers(this); } return !mTransactionIncomplete; }
bool IsImageExtractionAllowed(Document* aDocument, JSContext* aCx, nsIPrincipal& aPrincipal) { // Do the rest of the checks only if privacy.resistFingerprinting is on. if (!nsContentUtils::ShouldResistFingerprinting(aDocument)) { return true; } // Don't proceed if we don't have a document or JavaScript context. if (!aDocument || !aCx) { return false; } // The system principal can always extract canvas data. if (nsContentUtils::IsSystemPrincipal(&aPrincipal)) { return true; } // Allow extension principals. auto principal = BasePrincipal::Cast(&aPrincipal); if (principal->AddonPolicy() || principal->ContentScriptAddonPolicy()) { return true; } // Get the document URI and its spec. nsIURI* docURI = aDocument->GetDocumentURI(); nsCString docURISpec; docURI->GetSpec(docURISpec); // Allow local files to extract canvas data. bool isFileURL; if (NS_SUCCEEDED(docURI->SchemeIs("file", &isFileURL)) && isFileURL) { return true; } // Don't show canvas prompt for PDF.js JS::AutoFilename scriptFile; if (JS::DescribeScriptedCaller(aCx, &scriptFile) && scriptFile.get() && strcmp(scriptFile.get(), "resource://pdf.js/build/pdf.js") == 0) { return true; } Document* topLevelDocument = aDocument->GetTopLevelContentDocument(); nsIURI* topLevelDocURI = topLevelDocument ? topLevelDocument->GetDocumentURI() : nullptr; nsCString topLevelDocURISpec; if (topLevelDocURI) { topLevelDocURI->GetSpec(topLevelDocURISpec); } // Load Third Party Util service. nsresult rv; nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, false); // Block all third-party attempts to extract canvas. bool isThirdParty = true; rv = thirdPartyUtil->IsThirdPartyURI(topLevelDocURI, docURI, &isThirdParty); NS_ENSURE_SUCCESS(rv, false); if (isThirdParty) { nsAutoString message; message.AppendPrintf("Blocked third party %s from extracting canvas data.", docURISpec.get()); nsContentUtils::ReportToConsoleNonLocalized( message, nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Security"), aDocument); return false; } // Load Permission Manager service. nsCOMPtr<nsIPermissionManager> permissionManager = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, false); // Check if the site has permission to extract canvas data. // Either permit or block extraction if a stored permission setting exists. uint32_t permission; rv = permissionManager->TestPermissionFromPrincipal( principal, PERMISSION_CANVAS_EXTRACT_DATA, &permission); NS_ENSURE_SUCCESS(rv, false); switch (permission) { case nsIPermissionManager::ALLOW_ACTION: return true; case nsIPermissionManager::DENY_ACTION: return false; default: break; } // At this point, permission is unknown // (nsIPermissionManager::UNKNOWN_ACTION). // Check if the request is in response to user input bool isAutoBlockCanvas = StaticPrefs:: privacy_resistFingerprinting_autoDeclineNoUserInputCanvasPrompts() && !EventStateManager::IsHandlingUserInput(); if (isAutoBlockCanvas) { nsAutoString message; message.AppendPrintf( "Blocked %s from extracting canvas data because no user input was " "detected.", docURISpec.get()); nsContentUtils::ReportToConsoleNonLocalized( message, nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Security"), aDocument); } else { // It was in response to user input, so log and display the prompt. nsAutoString message; message.AppendPrintf( "Blocked %s from extracting canvas data, but prompting the user.", docURISpec.get()); nsContentUtils::ReportToConsoleNonLocalized( message, nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Security"), aDocument); } // Prompt the user (asynchronous). nsPIDOMWindowOuter* win = aDocument->GetWindow(); nsAutoCString origin; rv = principal->GetOrigin(origin); NS_ENSURE_SUCCESS(rv, false); if (XRE_IsContentProcess()) { BrowserChild* browserChild = BrowserChild::GetFrom(win); if (browserChild) { browserChild->SendShowCanvasPermissionPrompt(origin, isAutoBlockCanvas); } } else { nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { obs->NotifyObservers(win, isAutoBlockCanvas ? TOPIC_CANVAS_PERMISSIONS_PROMPT_HIDE_DOORHANGER : TOPIC_CANVAS_PERMISSIONS_PROMPT, NS_ConvertUTF8toUTF16(origin).get()); } } // We don't extract the image for now -- user may override at prompt. return false; }
void DriverCrashGuard::Initialize() { #ifdef NIGHTLY_BUILD // We only use the crash guard on non-nightly channels, since the nightly // channel is for development and having graphics features perma-disabled // is rather annoying. return; #endif // Using DriverCrashGuard off the main thread currently does not work. Under // e10s it could conceivably work by dispatching the IPC calls via the main // thread. In the parent process this would be harder. For now, we simply // exit early instead. if (!NS_IsMainThread()) { return; } // Check to see if all guards have been disabled through the environment. if (gfxEnv::DisableCrashGuard()) { return; } mGfxInfo = services::GetGfxInfo(); if (XRE_IsContentProcess()) { // Ask the parent whether or not activating the guard is okay. The parent // won't bother if it detected a crash. dom::ContentChild* cc = dom::ContentChild::GetSingleton(); cc->SendBeginDriverCrashGuard(uint32_t(mType), &mCrashDetected); if (mCrashDetected) { LogFeatureDisabled(); return; } ActivateGuard(); return; } // Always check whether or not the lock file exists. For example, we could // have crashed creating a D3D9 device in the parent process, and on restart // are now requesting one in the child process. We catch everything here. if (RecoverFromCrash()) { mCrashDetected = true; return; } // If the environment has changed, we always activate the guard. In the // parent process this performs main-thread disk I/O. Child process guards // only incur an IPC cost, so if we're proxying for a child process, we // play it safe and activate the guard as long as we don't expect it to // crash. if (CheckOrRefreshEnvironment() || (mMode == Mode::Proxy && GetStatus() != DriverInitStatus::Crashed)) { ActivateGuard(); return; } // If we got here and our status is "crashed", then the environment has not // updated and we do not want to attempt to use the driver again. if (GetStatus() == DriverInitStatus::Crashed) { mCrashDetected = true; LogFeatureDisabled(); } }
JSObject* WrapperFactory::Rewrap(JSContext* cx, HandleObject existing, HandleObject obj) { MOZ_ASSERT(!IsWrapper(obj) || GetProxyHandler(obj) == &XrayWaiver || js::IsWindowProxy(obj), "wrapped object passed to rewrap"); MOZ_ASSERT(!XrayUtils::IsXPCWNHolderClass(JS_GetClass(obj)), "trying to wrap a holder"); MOZ_ASSERT(!js::IsWindow(obj)); // We sometimes end up here after nsContentUtils has been shut down but before // XPConnect has been shut down, so check the context stack the roundabout way. MOZ_ASSERT(XPCJSRuntime::Get()->GetJSContextStack()->Peek() == cx); // Compute the information we need to select the right wrapper. JSCompartment* origin = js::GetObjectCompartment(obj); JSCompartment* target = js::GetContextCompartment(cx); bool originIsChrome = AccessCheck::isChrome(origin); bool targetIsChrome = AccessCheck::isChrome(target); bool originSubsumesTarget = AccessCheck::subsumesConsideringDomain(origin, target); bool targetSubsumesOrigin = AccessCheck::subsumesConsideringDomain(target, origin); bool sameOrigin = targetSubsumesOrigin && originSubsumesTarget; XrayType xrayType = GetXrayType(obj); const Wrapper* wrapper; // // First, handle the special cases. // // If UniversalXPConnect is enabled, this is just some dumb mochitest. Use // a vanilla CCW. if (xpc::IsUniversalXPConnectEnabled(target)) { CrashIfNotInAutomation(); wrapper = &CrossCompartmentWrapper::singleton; } // Let the SpecialPowers scope make its stuff easily accessible to content. else if (CompartmentPrivate::Get(origin)->forcePermissiveCOWs) { CrashIfNotInAutomation(); wrapper = &CrossCompartmentWrapper::singleton; } // Special handling for chrome objects being exposed to content. else if (originIsChrome && !targetIsChrome) { // If this is a chrome function being exposed to content, we need to allow // call (but nothing else). We allow CPOWs that purport to be function's // here, but only in the content process. if ((IdentifyStandardInstance(obj) == JSProto_Function || (jsipc::IsCPOW(obj) && JS::IsCallable(obj) && XRE_IsContentProcess()))) { wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper, OpaqueWithCall>::singleton; } // For Vanilla JSObjects exposed from chrome to content, we use a wrapper // that supports __exposedProps__. We'd like to get rid of these eventually, // but in their current form they don't cause much trouble. else if (IdentifyStandardInstance(obj) == JSProto_Object) { wrapper = &ChromeObjectWrapper::singleton; } // Otherwise we get an opaque wrapper. else { wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper, Opaque>::singleton; } } // // Now, handle the regular cases. // // These are wrappers we can compute using a rule-based approach. In order // to do so, we need to compute some parameters. // else { // The wrapper is a security wrapper (protecting the wrappee) if and // only if the target does not subsume the origin. bool securityWrapper = !targetSubsumesOrigin; // Xrays are warranted if either the target or the origin don't trust // each other. This is generally the case, unless the two are same-origin // and the caller has not requested same-origin Xrays. // // Xrays are a bidirectional protection, since it affords clarity to the // caller and privacy to the callee. bool sameOriginXrays = CompartmentPrivate::Get(origin)->wantXrays || CompartmentPrivate::Get(target)->wantXrays; bool wantXrays = !sameOrigin || sameOriginXrays; // If Xrays are warranted, the caller may waive them for non-security // wrappers (unless explicitly forbidden from doing so). bool waiveXrays = wantXrays && !securityWrapper && CompartmentPrivate::Get(target)->allowWaivers && HasWaiveXrayFlag(obj); // We have slightly different behavior for the case when the object // being wrapped is in an XBL scope. bool originIsContentXBLScope = IsContentXBLScope(origin); wrapper = SelectWrapper(securityWrapper, wantXrays, xrayType, waiveXrays, originIsContentXBLScope, obj); // If we want to apply add-on interposition in the target compartment, // then we try to "upgrade" the wrapper to an interposing one. if (CompartmentPrivate::Get(target)->scope->HasInterposition()) wrapper = SelectAddonWrapper(cx, obj, wrapper); } if (!targetSubsumesOrigin) { // Do a belt-and-suspenders check against exposing eval()/Function() to // non-subsuming content. if (JSFunction* fun = JS_GetObjectFunction(obj)) { if (JS_IsBuiltinEvalFunction(fun) || JS_IsBuiltinFunctionConstructor(fun)) { NS_WARNING("Trying to expose eval or Function to non-subsuming content!"); wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper, Opaque>::singleton; } } } DEBUG_CheckUnwrapSafety(obj, wrapper, origin, target); if (existing) return Wrapper::Renew(cx, existing, obj, wrapper); return Wrapper::New(cx, obj, wrapper); }
NS_IMETHODIMP nsAboutRedirector::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo, nsIChannel** aResult) { NS_ENSURE_ARG_POINTER(aURI); NS_ENSURE_ARG_POINTER(aLoadInfo); NS_ASSERTION(aResult, "must not be null"); nsAutoCString path; nsresult rv = NS_GetAboutModuleName(aURI, path); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); NS_ENSURE_SUCCESS(rv, rv); if (XRE_IsParentProcess() && path.EqualsASCII("crashparent")) { MOZ_CRASH("Crash via about:crashparent"); } if (XRE_IsContentProcess() && path.EqualsASCII("crashcontent")) { MOZ_CRASH("Crash via about:crashcontent"); } #ifdef ABOUT_CONFIG_BLOCKED_GV // We don't want to allow access to about:config from // GeckoView on release or beta, but it's fine for Fennec. if (path.EqualsASCII("config") && !mozilla::jni::IsFennec()) { return NS_ERROR_NOT_AVAILABLE; } #endif for (int i = 0; i < kRedirTotal; i++) { if (!strcmp(path.get(), kRedirMap[i].id)) { nsCOMPtr<nsIChannel> tempChannel; nsCOMPtr<nsIURI> tempURI; rv = NS_NewURI(getter_AddRefs(tempURI), kRedirMap[i].url); NS_ENSURE_SUCCESS(rv, rv); rv = NS_NewChannelInternal(getter_AddRefs(tempChannel), tempURI, aLoadInfo); NS_ENSURE_SUCCESS(rv, rv); // If tempURI links to an external URI (i.e. something other than // chrome:// or resource://) then set result principal URI on the // load info which forces the channel principal to reflect the displayed // URL rather then being the systemPrincipal. bool isUIResource = false; rv = NS_URIChainHasFlags(tempURI, nsIProtocolHandler::URI_IS_UI_RESOURCE, &isUIResource); NS_ENSURE_SUCCESS(rv, rv); bool isAboutBlank = NS_IsAboutBlank(tempURI); if (!isUIResource && !isAboutBlank) { aLoadInfo->SetResultPrincipalURI(tempURI); } tempChannel->SetOriginalURI(aURI); tempChannel.forget(aResult); return rv; } } NS_ERROR("nsAboutRedirector called for unknown case"); return NS_ERROR_ILLEGAL_VALUE; }