void ScriptExecutionContext::stopActiveDOMObjects() { checkConsistency(); if (m_activeDOMObjectsAreStopped) return; m_activeDOMObjectsAreStopped = true; // Make a frozen copy of the objects so we can iterate while new ones might be destroyed. Vector<ActiveDOMObject*> possibleActiveDOMObjects; copyToVector(m_activeDOMObjects, possibleActiveDOMObjects); m_activeDOMObjectAdditionForbidden = true; // We assume that new objects will not be added to m_activeDOMObjects during iteration: // stop functions should not add new active DOM objects, nor execute arbitrary JavaScript. // An ASSERT_WITH_SECURITY_IMPLICATION or RELEASE_ASSERT will fire if this happens, but it's important to code stop functions // so it will not happen! NoEventDispatchAssertion assertNoEventDispatch; for (auto* activeDOMObject : possibleActiveDOMObjects) { // Check if this object was deleted already. If so, just skip it. // Calling contains on a possibly-already-deleted object is OK because we guarantee // no new object can be added, so even if a new object ends up allocated with the // same address, that will be *after* this function exits. if (!m_activeDOMObjects.contains(activeDOMObject)) continue; activeDOMObject->stop(); } m_activeDOMObjectAdditionForbidden = false; // FIXME: Make message ports be active DOM objects and let them implement stop instead // of having this separate mechanism just for them. for (auto* messagePort : m_messagePorts) messagePort->close(); }
void Geolocation::stopTimersForOneShots() { auto copy = copyToVector(m_oneShots); stopTimer(copy); }
void Geolocation::Watchers::getNotifiersVector(GeoNotifierVector& copy) const { copy = copyToVector(m_idToNotifierMap.values()); }
void ApplicationCacheGroup::checkIfLoadIsComplete() { if (m_manifestHandle || !m_pendingEntries.isEmpty() || m_downloadingPendingMasterResourceLoadersCount) return; // We're done, all resources have finished downloading (successfully or not). bool isUpgradeAttempt = m_newestCache; switch (m_completionType) { case None: ASSERT_NOT_REACHED(); return; case NoUpdate: ASSERT(isUpgradeAttempt); ASSERT(!m_cacheBeingUpdated); // The storage could have been manually emptied by the user. if (!m_storageID) cacheStorage().storeNewestCache(this); postListenerTask(ApplicationCacheHost::NOUPDATE_EVENT, m_associatedDocumentLoaders); break; case Failure: ASSERT(!m_cacheBeingUpdated); postListenerTask(ApplicationCacheHost::ERROR_EVENT, m_associatedDocumentLoaders); if (m_caches.isEmpty()) { ASSERT(m_associatedDocumentLoaders.isEmpty()); delete this; return; } break; case Completed: { // FIXME: Fetch the resource from manifest URL again, and check whether it is identical to the one used for update (in case the application was upgraded server-side in the meanwhile). (<rdar://problem/6467625>) ASSERT(m_cacheBeingUpdated); if (m_manifestResource) m_cacheBeingUpdated->setManifestResource(m_manifestResource.release()); else { // We can get here as a result of retrying the Complete step, following // a failure of the cache storage to save the newest cache due to hitting // the maximum size. In such a case, m_manifestResource may be 0, as // the manifest was already set on the newest cache object. ASSERT(cacheStorage().isMaximumSizeReached() && m_calledReachedMaxAppCacheSize); } RefPtr<ApplicationCache> oldNewestCache = (m_newestCache == m_cacheBeingUpdated) ? RefPtr<ApplicationCache>() : m_newestCache; // If we exceeded the origin quota while downloading we can request a quota // increase now, before we attempt to store the cache. int64_t totalSpaceNeeded; if (!cacheStorage().checkOriginQuota(this, oldNewestCache.get(), m_cacheBeingUpdated.get(), totalSpaceNeeded)) didReachOriginQuota(totalSpaceNeeded); ApplicationCacheStorage::FailureReason failureReason; setNewestCache(m_cacheBeingUpdated.release()); if (cacheStorage().storeNewestCache(this, oldNewestCache.get(), failureReason)) { // New cache stored, now remove the old cache. if (oldNewestCache) cacheStorage().remove(oldNewestCache.get()); // Fire the final progress event. ASSERT(m_progressDone == m_progressTotal); postListenerTask(ApplicationCacheHost::PROGRESS_EVENT, m_progressTotal, m_progressDone, m_associatedDocumentLoaders); // Fire the success event. postListenerTask(isUpgradeAttempt ? ApplicationCacheHost::UPDATEREADY_EVENT : ApplicationCacheHost::CACHED_EVENT, m_associatedDocumentLoaders); // It is clear that the origin quota was not reached, so clear the flag if it was set. m_originQuotaExceededPreviously = false; } else { if (failureReason == ApplicationCacheStorage::OriginQuotaReached) { // We ran out of space for this origin. Fall down to the normal error handling // after recording this state. m_originQuotaExceededPreviously = true; m_frame->document()->addConsoleMessage(OtherMessageSource, ErrorMessageLevel, "Application Cache update failed, because size quota was exceeded."); } if (failureReason == ApplicationCacheStorage::TotalQuotaReached && !m_calledReachedMaxAppCacheSize) { // FIXME: Should this be handled more like Origin Quotas? Does this fail properly? // We ran out of space. All the changes in the cache storage have // been rolled back. We roll back to the previous state in here, // as well, call the chrome client asynchronously and retry to // save the new cache. // Save a reference to the new cache. m_cacheBeingUpdated = m_newestCache.release(); if (oldNewestCache) { // Reinstate the oldNewestCache. setNewestCache(oldNewestCache.release()); } scheduleReachedMaxAppCacheSizeCallback(); return; } // Run the "cache failure steps" // Fire the error events to all pending master entries, as well any other cache hosts // currently associated with a cache in this group. postListenerTask(ApplicationCacheHost::ERROR_EVENT, m_associatedDocumentLoaders); // Disassociate the pending master entries from the failed new cache. Note that // all other loaders in the m_associatedDocumentLoaders are still associated with // some other cache in this group. They are not associated with the failed new cache. // Need to copy loaders, because the cache group may be destroyed at the end of iteration. Vector<DocumentLoader*> loaders; copyToVector(m_pendingMasterResourceLoaders, loaders); size_t count = loaders.size(); for (size_t i = 0; i != count; ++i) disassociateDocumentLoader(loaders[i]); // This can delete this group. // Reinstate the oldNewestCache, if there was one. if (oldNewestCache) { // This will discard the failed new cache. setNewestCache(oldNewestCache.release()); } else { // We must have been deleted by the last call to disassociateDocumentLoader(). return; } } break; } } // Empty cache group's list of pending master entries. m_pendingMasterResourceLoaders.clear(); m_completionType = None; setUpdateStatus(Idle); m_frame = 0; m_availableSpaceInQuota = ApplicationCacheStorage::unknownQuota(); m_calledReachedMaxAppCacheSize = false; }
void SMILTimeContainer::updateAnimations(SMILTime elapsed, double nextManualSampleTime, const String& nextSamplingTarget) { SMILTime earliersFireTime = SMILTime::unresolved(); Vector<SVGSMILElement*> toAnimate; copyToVector(m_scheduledAnimations, toAnimate); if (nextManualSampleTime) { SMILTime samplingDiff; for (unsigned n = 0; n < toAnimate.size(); ++n) { SVGSMILElement* animation = toAnimate[n]; ASSERT(animation->timeContainer() == this); SVGElement* targetElement = animation->targetElement(); // FIXME: This should probably be using getIdAttribute instead of idForStyleResolution. if (!targetElement || !targetElement->hasID() || targetElement->idForStyleResolution() != nextSamplingTarget) continue; samplingDiff = animation->intervalBegin(); break; } elapsed = SMILTime(nextManualSampleTime) + samplingDiff; } // Sort according to priority. Elements with later begin time have higher priority. // In case of a tie, document order decides. // FIXME: This should also consider timing relationships between the elements. Dependents // have higher priority. sortByPriority(toAnimate, elapsed); // Calculate animation contributions. typedef HashMap<ElementAttributePair, RefPtr<SVGSMILElement> > ResultElementMap; ResultElementMap resultsElements; for (unsigned n = 0; n < toAnimate.size(); ++n) { SVGSMILElement* animation = toAnimate[n]; ASSERT(animation->timeContainer() == this); SVGElement* targetElement = animation->targetElement(); if (!targetElement) continue; QualifiedName attributeName = animation->attributeName(); if (attributeName == anyQName()) { if (animation->hasTagName(SVGNames::animateMotionTag)) attributeName = SVGNames::animateMotionTag; else continue; } // Results are accumulated to the first animation that animates a particular element/attribute pair. ElementAttributePair key(targetElement, attributeName); SVGSMILElement* resultElement = resultsElements.get(key).get(); if (!resultElement) { if (!animation->hasValidAttributeType()) continue; resultElement = animation; resultElement->resetToBaseValue(baseValueFor(key)); resultsElements.add(key, resultElement); } // This will calculate the contribution from the animation and add it to the resultsElement. animation->progress(elapsed, resultElement); SMILTime nextFireTime = animation->nextProgressTime(); if (nextFireTime.isFinite()) earliersFireTime = min(nextFireTime, earliersFireTime); } Vector<SVGSMILElement*> animationsToApply; ResultElementMap::iterator end = resultsElements.end(); for (ResultElementMap::iterator it = resultsElements.begin(); it != end; ++it) animationsToApply.append(it->second.get()); // Sort <animateTranform> to be the last one to be applied. <animate> may change transform attribute as // well (directly or indirectly by modifying <use> x/y) and this way transforms combine properly. sortByApplyOrder(animationsToApply); // Apply results to target elements. for (unsigned n = 0; n < animationsToApply.size(); ++n) animationsToApply[n]->applyResultsToTarget(); startTimer(earliersFireTime, animationFrameDelay); Document::updateStyleForAllDocuments(); }
void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime) { SMILTime earliersFireTime = SMILTime::unresolved(); Vector<SVGSMILElement*> toAnimate; copyToVector(m_scheduledAnimations, toAnimate); // Sort according to priority. Elements with later begin time have higher priority. // In case of a tie, document order decides. // FIXME: This should also consider timing relationships between the elements. Dependents // have higher priority. sortByPriority(toAnimate, elapsed); // Calculate animation contributions. typedef pair<SVGElement*, QualifiedName> ElementAttributePair; typedef HashMap<ElementAttributePair, RefPtr<SVGSMILElement> > ResultElementMap; ResultElementMap resultsElements; HashSet<SVGSMILElement*> contributingElements; for (unsigned n = 0; n < toAnimate.size(); ++n) { SVGSMILElement* animation = toAnimate[n]; ASSERT(animation->timeContainer() == this); SVGElement* targetElement = animation->targetElement(); if (!targetElement) continue; QualifiedName attributeName = animation->attributeName(); if (attributeName == anyQName()) { if (animation->hasTagName(SVGNames::animateMotionTag)) attributeName = SVGNames::animateMotionTag; else continue; } // Results are accumulated to the first animation that animates and contributes to a particular element/attribute pair. ElementAttributePair key(targetElement, attributeName); SVGSMILElement* resultElement = resultsElements.get(key).get(); bool accumulatedResultElement = false; if (!resultElement) { if (!animation->hasValidAttributeType()) continue; resultElement = animation; resultsElements.add(key, resultElement); accumulatedResultElement = true; } // This will calculate the contribution from the animation and add it to the resultsElement. if (animation->progress(elapsed, resultElement, seekToTime)) contributingElements.add(resultElement); else if (accumulatedResultElement) resultsElements.remove(key); SMILTime nextFireTime = animation->nextProgressTime(); if (nextFireTime.isFinite()) earliersFireTime = min(nextFireTime, earliersFireTime); } Vector<SVGSMILElement*> animationsToApply; ResultElementMap::iterator end = resultsElements.end(); for (ResultElementMap::iterator it = resultsElements.begin(); it != end; ++it) { SVGSMILElement* animation = it->second.get(); if (contributingElements.contains(animation)) animationsToApply.append(animation); } unsigned animationsToApplySize = animationsToApply.size(); if (!animationsToApplySize) { startTimer(earliersFireTime, animationFrameDelay); return; } // Sort <animateTranform> to be the last one to be applied. <animate> may change transform attribute as // well (directly or indirectly by modifying <use> x/y) and this way transforms combine properly. sortByApplyOrder(animationsToApply); // Apply results to target elements. for (unsigned i = 0; i < animationsToApplySize; ++i) animationsToApply[i]->applyResultsToTarget(); startTimer(earliersFireTime, animationFrameDelay); Document::updateStyleForAllDocuments(); }
void TableSectionPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) { LayoutRect localPaintInvalidationRect = LayoutRect(paintInfo.rect); localPaintInvalidationRect.moveBy(-paintOffset); LayoutRect tableAlignedRect = m_layoutTableSection.logicalRectForWritingModeAndDirection(localPaintInvalidationRect); CellSpan dirtiedRows = m_layoutTableSection.dirtiedRows(tableAlignedRect); CellSpan dirtiedColumns = m_layoutTableSection.dirtiedColumns(tableAlignedRect); HashSet<LayoutTableCell*> overflowingCells = m_layoutTableSection.overflowingCells(); if (dirtiedColumns.start() < dirtiedColumns.end()) { if (!m_layoutTableSection.hasMultipleCellLevels() && !overflowingCells.size()) { if (paintInfo.phase == PaintPhaseCollapsedTableBorders) { // Collapsed borders are painted from the bottom right to the top left so that precedence // due to cell position is respected. for (unsigned r = dirtiedRows.end(); r > dirtiedRows.start(); r--) { unsigned row = r - 1; for (unsigned c = dirtiedColumns.end(); c > dirtiedColumns.start(); c--) { unsigned col = c - 1; LayoutTableSection::CellStruct& current = m_layoutTableSection.cellAt(row, col); LayoutTableCell* cell = current.primaryCell(); if (!cell || (row > dirtiedRows.start() && m_layoutTableSection.primaryCellAt(row - 1, col) == cell) || (col > dirtiedColumns.start() && m_layoutTableSection.primaryCellAt(row, col - 1) == cell)) continue; LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(cell, paintOffset); TableCellPainter(*cell).paintCollapsedBorders(paintInfo, cellPoint); } } } else { // Draw the dirty cells in the order that they appear. for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r); if (row && !row->hasSelfPaintingLayer()) TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, paintOffset); for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) { LayoutTableSection::CellStruct& current = m_layoutTableSection.cellAt(r, c); LayoutTableCell* cell = current.primaryCell(); if (!cell || (r > dirtiedRows.start() && m_layoutTableSection.primaryCellAt(r - 1, c) == cell) || (c > dirtiedColumns.start() && m_layoutTableSection.primaryCellAt(r, c - 1) == cell)) continue; paintCell(cell, paintInfo, paintOffset); } } } } else { // The overflowing cells should be scarce to avoid adding a lot of cells to the HashSet. #if ENABLE(ASSERT) unsigned totalRows = m_layoutTableSection.numRows(); unsigned totalCols = m_layoutTableSection.table()->columns().size(); ASSERT(overflowingCells.size() < totalRows * totalCols * gMaxAllowedOverflowingCellRatioForFastPaintPath); #endif // To make sure we properly paint invalidate the section, we paint invalidated all the overflowing cells that we collected. Vector<LayoutTableCell*> cells; copyToVector(overflowingCells, cells); HashSet<LayoutTableCell*> spanningCells; for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) { LayoutTableRow* row = m_layoutTableSection.rowLayoutObjectAt(r); if (row && !row->hasSelfPaintingLayer()) TableRowPainter(*row).paintOutlineForRowIfNeeded(paintInfo, paintOffset); for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) { LayoutTableSection::CellStruct& current = m_layoutTableSection.cellAt(r, c); if (!current.hasCells()) continue; for (unsigned i = 0; i < current.cells.size(); ++i) { if (overflowingCells.contains(current.cells[i])) continue; if (current.cells[i]->rowSpan() > 1 || current.cells[i]->colSpan() > 1) { if (!spanningCells.add(current.cells[i]).isNewEntry) continue; } cells.append(current.cells[i]); } } } // Sort the dirty cells by paint order. if (!overflowingCells.size()) std::stable_sort(cells.begin(), cells.end(), compareCellPositions); else std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverflowingCells); if (paintInfo.phase == PaintPhaseCollapsedTableBorders) { for (unsigned i = cells.size(); i > 0; --i) { LayoutPoint cellPoint = m_layoutTableSection.flipForWritingModeForChild(cells[i - 1], paintOffset); TableCellPainter(*cells[i - 1]).paintCollapsedBorders(paintInfo, cellPoint); } } else { for (unsigned i = 0; i < cells.size(); ++i) paintCell(cells[i], paintInfo, paintOffset); } } } }
WebProcessProxy& WebContext::createNewWebProcess() { #if ENABLE(NETWORK_PROCESS) if (m_usesNetworkProcess) ensureNetworkProcess(); #endif RefPtr<WebProcessProxy> process = WebProcessProxy::create(*this); WebProcessCreationParameters parameters; parameters.injectedBundlePath = injectedBundlePath(); if (!parameters.injectedBundlePath.isEmpty()) SandboxExtension::createHandle(parameters.injectedBundlePath, SandboxExtension::ReadOnly, parameters.injectedBundlePathExtensionHandle); parameters.applicationCacheDirectory = applicationCacheDirectory(); if (!parameters.applicationCacheDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.applicationCacheDirectory, parameters.applicationCacheDirectoryExtensionHandle); parameters.databaseDirectory = databaseDirectory(); if (!parameters.databaseDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.databaseDirectory, parameters.databaseDirectoryExtensionHandle); parameters.diskCacheDirectory = diskCacheDirectory(); if (!parameters.diskCacheDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.diskCacheDirectory, parameters.diskCacheDirectoryExtensionHandle); parameters.cookieStorageDirectory = cookieStorageDirectory(); if (!parameters.cookieStorageDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle); parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession; parameters.cacheModel = m_cacheModel; parameters.languages = userPreferredLanguages(); copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegistererdAsEmptyDocument); copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure); copyToVector(m_schemesToSetDomainRelaxationForbiddenFor, parameters.urlSchemesForWhichDomainRelaxationIsForbidden); copyToVector(m_schemesToRegisterAsLocal, parameters.urlSchemesRegisteredAsLocal); copyToVector(m_schemesToRegisterAsNoAccess, parameters.urlSchemesRegisteredAsNoAccess); copyToVector(m_schemesToRegisterAsDisplayIsolated, parameters.urlSchemesRegisteredAsDisplayIsolated); copyToVector(m_schemesToRegisterAsCORSEnabled, parameters.urlSchemesRegisteredAsCORSEnabled); #if ENABLE(CACHE_PARTITIONING) copyToVector(m_schemesToRegisterAsCachePartitioned, parameters.urlSchemesRegisteredAsCachePartitioned); #endif parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath; parameters.shouldUseFontSmoothing = m_shouldUseFontSmoothing; parameters.iconDatabaseEnabled = !iconDatabasePath().isEmpty(); parameters.terminationTimeout = (m_processModel == ProcessModelSharedSecondaryProcess) ? sharedSecondaryProcessShutdownTimeout : 0; parameters.textCheckerState = TextChecker::state(); parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled(); parameters.defaultRequestTimeoutInterval = API::URLRequest::defaultTimeoutInterval(); #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) // FIXME: There should be a generic way for supplements to add to the intialization parameters. supplement<WebNotificationManagerProxy>()->populateCopyOfNotificationPermissions(parameters.notificationPermissions); #endif #if ENABLE(NETWORK_PROCESS) parameters.usesNetworkProcess = m_usesNetworkProcess; #endif parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy(); copyToVector(m_plugInAutoStartProvider.autoStartOrigins(), parameters.plugInAutoStartOrigins); parameters.memoryCacheDisabled = m_memoryCacheDisabled; #if ENABLE(SERVICE_CONTROLS) parameters.hasImageServices = ServicesController::shared().hasImageServices(); parameters.hasSelectionServices = ServicesController::shared().hasSelectionServices(); ServicesController::shared().refreshExistingServices(this); #endif // Add any platform specific parameters platformInitializeWebProcess(parameters); RefPtr<API::Object> injectedBundleInitializationUserData = m_injectedBundleClient.getInjectedBundleInitializationUserData(this); if (!injectedBundleInitializationUserData) injectedBundleInitializationUserData = m_injectedBundleInitializationUserData; process->send(Messages::WebProcess::InitializeWebProcess(parameters, WebContextUserMessageEncoder(injectedBundleInitializationUserData.get(), *process)), 0); #if PLATFORM(COCOA) process->send(Messages::WebProcess::SetQOS(webProcessLatencyQOS(), webProcessThroughputQOS()), 0); #endif if (WebPreferences::anyPagesAreUsingPrivateBrowsing()) process->send(Messages::WebProcess::EnsurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()), 0); m_processes.append(process); if (m_processModel == ProcessModelSharedSecondaryProcess) { for (size_t i = 0; i != m_messagesToInjectedBundlePostedToEmptyContext.size(); ++i) { std::pair<String, RefPtr<API::Object>>& message = m_messagesToInjectedBundlePostedToEmptyContext[i]; IPC::ArgumentEncoder messageData; messageData.encode(message.first); messageData.encode(WebContextUserMessageEncoder(message.second.get(), *process)); process->send(Messages::WebProcess::PostInjectedBundleMessage(IPC::DataReference(messageData.buffer(), messageData.bufferSize())), 0); } m_messagesToInjectedBundlePostedToEmptyContext.clear(); } else ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty()); #if ENABLE(REMOTE_INSPECTOR) // Initialize remote inspector connection now that we have a sub-process that is hosting one of our web views. Inspector::RemoteInspector::shared(); #endif return *process; }
WebProcessProxy& WebProcessPool::createNewWebProcess() { ensureNetworkProcess(); Ref<WebProcessProxy> process = WebProcessProxy::create(*this); WebProcessCreationParameters parameters; parameters.injectedBundlePath = injectedBundlePath(); if (!parameters.injectedBundlePath.isEmpty()) SandboxExtension::createHandle(parameters.injectedBundlePath, SandboxExtension::ReadOnly, parameters.injectedBundlePathExtensionHandle); parameters.applicationCacheDirectory = m_configuration->applicationCacheDirectory(); parameters.applicationCacheFlatFileSubdirectoryName = m_configuration->applicationCacheFlatFileSubdirectoryName(); if (!parameters.applicationCacheDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.applicationCacheDirectory, parameters.applicationCacheDirectoryExtensionHandle); parameters.webSQLDatabaseDirectory = m_configuration->webSQLDatabaseDirectory(); if (!parameters.webSQLDatabaseDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.webSQLDatabaseDirectory, parameters.webSQLDatabaseDirectoryExtensionHandle); parameters.mediaCacheDirectory = m_configuration->mediaCacheDirectory(); if (!parameters.mediaCacheDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.mediaCacheDirectory, parameters.mediaCacheDirectoryExtensionHandle); #if PLATFORM(IOS) String cookieStorageDirectory = this->cookieStorageDirectory(); if (!cookieStorageDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(cookieStorageDirectory, parameters.cookieStorageDirectoryExtensionHandle); String containerCachesDirectory = this->webContentCachesDirectory(); if (!containerCachesDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(containerCachesDirectory, parameters.containerCachesDirectoryExtensionHandle); String containerTemporaryDirectory = this->containerTemporaryDirectory(); if (!containerTemporaryDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(containerTemporaryDirectory, parameters.containerTemporaryDirectoryExtensionHandle); #endif parameters.mediaKeyStorageDirectory = m_configuration->mediaKeysStorageDirectory(); if (!parameters.mediaKeyStorageDirectory.isEmpty()) SandboxExtension::createHandleForReadWriteDirectory(parameters.mediaKeyStorageDirectory, parameters.mediaKeyStorageDirectoryExtensionHandle); parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession; parameters.cacheModel = cacheModel(); parameters.languages = userPreferredLanguages(); copyToVector(m_schemesToRegisterAsEmptyDocument, parameters.urlSchemesRegisteredAsEmptyDocument); copyToVector(m_schemesToRegisterAsSecure, parameters.urlSchemesRegisteredAsSecure); copyToVector(m_schemesToRegisterAsBypassingContentSecurityPolicy, parameters.urlSchemesRegisteredAsBypassingContentSecurityPolicy); copyToVector(m_schemesToSetDomainRelaxationForbiddenFor, parameters.urlSchemesForWhichDomainRelaxationIsForbidden); copyToVector(m_schemesToRegisterAsLocal, parameters.urlSchemesRegisteredAsLocal); copyToVector(m_schemesToRegisterAsNoAccess, parameters.urlSchemesRegisteredAsNoAccess); copyToVector(m_schemesToRegisterAsDisplayIsolated, parameters.urlSchemesRegisteredAsDisplayIsolated); copyToVector(m_schemesToRegisterAsCORSEnabled, parameters.urlSchemesRegisteredAsCORSEnabled); copyToVector(m_schemesToRegisterAsAlwaysRevalidated, parameters.urlSchemesRegisteredAsAlwaysRevalidated); #if ENABLE(CACHE_PARTITIONING) copyToVector(m_schemesToRegisterAsCachePartitioned, parameters.urlSchemesRegisteredAsCachePartitioned); #endif parameters.shouldAlwaysUseComplexTextCodePath = m_alwaysUsesComplexTextCodePath; parameters.shouldUseFontSmoothing = m_shouldUseFontSmoothing; // FIXME: This leaves UI process and WebProcess disagreeing about the state if the client hasn't set the path. // iconDatabasePath is non-empty by default, but m_iconDatabase isn't enabled in UI process unless setDatabasePath is called explicitly. parameters.iconDatabaseEnabled = !iconDatabasePath().isEmpty(); parameters.terminationTimeout = 0; parameters.textCheckerState = TextChecker::state(); parameters.fullKeyboardAccessEnabled = WebProcessProxy::fullKeyboardAccessEnabled(); parameters.defaultRequestTimeoutInterval = API::URLRequest::defaultTimeoutInterval(); #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) // FIXME: There should be a generic way for supplements to add to the intialization parameters. supplement<WebNotificationManagerProxy>()->populateCopyOfNotificationPermissions(parameters.notificationPermissions); #endif parameters.plugInAutoStartOriginHashes = m_plugInAutoStartProvider.autoStartOriginHashesCopy(); copyToVector(m_plugInAutoStartProvider.autoStartOrigins(), parameters.plugInAutoStartOrigins); parameters.memoryCacheDisabled = m_memoryCacheDisabled; #if ENABLE(SERVICE_CONTROLS) auto& serviceController = ServicesController::singleton(); parameters.hasImageServices = serviceController.hasImageServices(); parameters.hasSelectionServices = serviceController.hasSelectionServices(); parameters.hasRichContentServices = serviceController.hasRichContentServices(); serviceController.refreshExistingServices(); #endif #if ENABLE(NETSCAPE_PLUGIN_API) parameters.pluginLoadClientPolicies = m_pluginLoadClientPolicies; #endif #if OS(LINUX) parameters.shouldEnableMemoryPressureReliefLogging = true; #endif parameters.resourceLoadStatisticsEnabled = resourceLoadStatisticsEnabled(); // Add any platform specific parameters platformInitializeWebProcess(parameters); RefPtr<API::Object> injectedBundleInitializationUserData = m_injectedBundleClient.getInjectedBundleInitializationUserData(this); if (!injectedBundleInitializationUserData) injectedBundleInitializationUserData = m_injectedBundleInitializationUserData; parameters.initializationUserData = UserData(process->transformObjectsToHandles(injectedBundleInitializationUserData.get())); process->send(Messages::WebProcess::InitializeWebProcess(parameters), 0); #if PLATFORM(COCOA) process->send(Messages::WebProcess::SetQOS(webProcessLatencyQOS(), webProcessThroughputQOS()), 0); #endif if (WebPreferences::anyPagesAreUsingPrivateBrowsing()) process->send(Messages::WebProcess::EnsurePrivateBrowsingSession(SessionID::legacyPrivateSessionID()), 0); if (m_automationSession) process->send(Messages::WebProcess::EnsureAutomationSessionProxy(m_automationSession->sessionIdentifier()), 0); m_processes.append(process.ptr()); ASSERT(m_messagesToInjectedBundlePostedToEmptyContext.isEmpty()); #if ENABLE(REMOTE_INSPECTOR) // Initialize remote inspector connection now that we have a sub-process that is hosting one of our web views. Inspector::RemoteInspector::singleton(); #endif return process; }
void MemoryIndex::notifyCursorsOfValueChange(const IDBKeyData& indexKey, const IDBKeyData& primaryKey) { for (auto* cursor : copyToVector(m_cleanCursors)) cursor->indexValueChanged(indexKey, primaryKey); }
void NFA::setActions(unsigned node, const ActionSet& actions) { ASSERT_WITH_MESSAGE(m_nodes[node].finalRuleIds.isEmpty(), "The final state should only be defined once."); copyToVector(actions, m_nodes[node].finalRuleIds); }
void Geolocation::stopTimersForOneShots() { GeoNotifierVector copy; copyToVector(m_oneShots, copy); stopTimer(copy); }
SMILTime SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime) { SMILTime earliestFireTime = SMILTime::unresolved(); #if ENABLE(ASSERT) // This boolean will catch any attempts to schedule/unschedule scheduledAnimations during this critical section. // Similarly, any elements removed will unschedule themselves, so this will catch modification of animationsToApply. m_preventScheduledAnimationsChanges = true; #endif if (m_documentOrderIndexesDirty) updateDocumentOrderIndexes(); WillBeHeapHashSet<ElementAttributePair> invalidKeys; using AnimationsVector = WillBeHeapVector<RefPtrWillBeMember<SVGSMILElement>>; AnimationsVector animationsToApply; for (const auto& entry : m_scheduledAnimations) { if (!entry.key.first || entry.value->isEmpty()) { invalidKeys.add(entry.key); continue; } AnimationsLinkedHashSet* scheduled = entry.value.get(); // Sort according to priority. Elements with later begin time have higher priority. // In case of a tie, document order decides. // FIXME: This should also consider timing relationships between the elements. Dependents // have higher priority. AnimationsVector scheduledAnimations; copyToVector(*scheduled, scheduledAnimations); std::sort(scheduledAnimations.begin(), scheduledAnimations.end(), PriorityCompare(elapsed)); SVGSMILElement* resultElement = nullptr; for (const auto& itAnimation : scheduledAnimations) { SVGSMILElement* animation = itAnimation.get(); ASSERT(animation->timeContainer() == this); ASSERT(animation->targetElement()); ASSERT(animation->hasValidAttributeName()); // Results are accumulated to the first animation that animates and contributes to a particular element/attribute pair. // FIXME: we should ensure that resultElement is of an appropriate type. if (!resultElement) { if (!animation->hasValidAttributeType()) continue; resultElement = animation; } // This will calculate the contribution from the animation and add it to the resultsElement. if (!animation->progress(elapsed, resultElement, seekToTime) && resultElement == animation) resultElement = nullptr; SMILTime nextFireTime = animation->nextProgressTime(); if (nextFireTime.isFinite()) earliestFireTime = std::min(nextFireTime, earliestFireTime); } if (resultElement) animationsToApply.append(resultElement); } m_scheduledAnimations.removeAll(invalidKeys); std::sort(animationsToApply.begin(), animationsToApply.end(), PriorityCompare(elapsed)); unsigned animationsToApplySize = animationsToApply.size(); if (!animationsToApplySize) { #if ENABLE(ASSERT) m_preventScheduledAnimationsChanges = false; #endif return earliestFireTime; } // Apply results to target elements. for (unsigned i = 0; i < animationsToApplySize; ++i) animationsToApply[i]->applyResultsToTarget(); #if ENABLE(ASSERT) m_preventScheduledAnimationsChanges = false; #endif for (unsigned i = 0; i < animationsToApplySize; ++i) { if (animationsToApply[i]->inDocument() && animationsToApply[i]->isSVGDiscardElement()) { RefPtrWillBeRawPtr<SVGSMILElement> animDiscard = animationsToApply[i]; RefPtrWillBeRawPtr<SVGElement> targetElement = animDiscard->targetElement(); if (targetElement && targetElement->inDocument()) { targetElement->remove(IGNORE_EXCEPTION); ASSERT(!targetElement->inDocument()); } if (animDiscard->inDocument()) { animDiscard->remove(IGNORE_EXCEPTION); ASSERT(!animDiscard->inDocument()); } } } return earliestFireTime; }