1/* 2 * Copyright (C) 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#ifndef WebContext_h 27#define WebContext_h 28 29#include "APIObject.h" 30#include "DownloadProxyMap.h" 31#include "GenericCallback.h" 32#include "ImmutableArray.h" 33#include "ImmutableDictionary.h" 34#include "MessageReceiver.h" 35#include "MessageReceiverMap.h" 36#include "PlugInAutoStartProvider.h" 37#include "PluginInfoStore.h" 38#include "ProcessModel.h" 39#include "StatisticsRequest.h" 40#include "StorageManager.h" 41#include "VisitedLinkProvider.h" 42#include "WebContextClient.h" 43#include "WebContextConnectionClient.h" 44#include "WebContextInjectedBundleClient.h" 45#include "WebDownloadClient.h" 46#include "WebHistoryClient.h" 47#include "WebProcessProxy.h" 48#include <WebCore/LinkHash.h> 49#include <wtf/Forward.h> 50#include <wtf/HashMap.h> 51#include <wtf/HashSet.h> 52#include <wtf/PassRefPtr.h> 53#include <wtf/RefPtr.h> 54#include <wtf/text/StringHash.h> 55#include <wtf/text/WTFString.h> 56 57#if ENABLE(NETWORK_PROCESS) 58#include "NetworkProcessProxy.h" 59#endif 60 61#if PLATFORM(MAC) 62OBJC_CLASS NSObject; 63OBJC_CLASS NSString; 64#endif 65 66namespace WebKit { 67 68class DownloadProxy; 69class WebContextSupplement; 70class WebIconDatabase; 71class WebPageGroup; 72class WebPageProxy; 73struct StatisticsData; 74struct WebProcessCreationParameters; 75 76typedef GenericCallback<WKDictionaryRef> DictionaryCallback; 77 78#if ENABLE(NETWORK_INFO) 79class WebNetworkInfoManagerProxy; 80#endif 81#if ENABLE(NETWORK_PROCESS) 82struct NetworkProcessCreationParameters; 83#endif 84 85#if PLATFORM(MAC) 86extern NSString *SchemeForCustomProtocolRegisteredNotificationName; 87extern NSString *SchemeForCustomProtocolUnregisteredNotificationName; 88#endif 89 90class WebContext : public TypedAPIObject<APIObject::TypeContext>, private CoreIPC::MessageReceiver 91#if ENABLE(NETSCAPE_PLUGIN_API) 92 , private PluginInfoStoreClient 93#endif 94 { 95public: 96 static PassRefPtr<WebContext> create(const String& injectedBundlePath); 97 virtual ~WebContext(); 98 99 static const Vector<WebContext*>& allContexts(); 100 101 template <typename T> 102 T* supplement() 103 { 104 return static_cast<T*>(m_supplements.get(T::supplementName())); 105 } 106 107 template <typename T> 108 void addSupplement() 109 { 110 m_supplements.add(T::supplementName(), T::create(this)); 111 } 112 113 void addMessageReceiver(CoreIPC::StringReference messageReceiverName, CoreIPC::MessageReceiver*); 114 void addMessageReceiver(CoreIPC::StringReference messageReceiverName, uint64_t destinationID, CoreIPC::MessageReceiver*); 115 void removeMessageReceiver(CoreIPC::StringReference messageReceiverName, uint64_t destinationID); 116 117 bool dispatchMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&); 118 bool dispatchSyncMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&); 119 120 void initializeClient(const WKContextClient*); 121 void initializeInjectedBundleClient(const WKContextInjectedBundleClient*); 122 void initializeConnectionClient(const WKContextConnectionClient*); 123 void initializeHistoryClient(const WKContextHistoryClient*); 124 void initializeDownloadClient(const WKContextDownloadClient*); 125 126 void setProcessModel(ProcessModel); // Can only be called when there are no processes running. 127 ProcessModel processModel() const { return m_processModel; } 128 129 void setMaximumNumberOfProcesses(unsigned); // Can only be called when there are no processes running. 130 unsigned maximumNumberOfProcesses() const { return m_webProcessCountLimit; } 131 132 // WebProcess or NetworkProcess as approporiate for current process model. The connection must be non-null. 133 CoreIPC::Connection* networkingProcessConnection(); 134 135 template<typename U> void sendToAllProcesses(const U& message); 136 template<typename U> void sendToAllProcessesRelaunchingThemIfNecessary(const U& message); 137 template<typename U> void sendToOneProcess(const U& message); 138 139 // Sends the message to WebProcess or NetworkProcess as approporiate for current process model. 140 template<typename U> void sendToNetworkingProcess(const U& message); 141 template<typename U> void sendToNetworkingProcessRelaunchingIfNecessary(const U& message); 142 143 void processWillOpenConnection(WebProcessProxy*); 144 void processWillCloseConnection(WebProcessProxy*); 145 void processDidFinishLaunching(WebProcessProxy*); 146 147 // Disconnect the process from the context. 148 void disconnectProcess(WebProcessProxy*); 149 150 StorageManager& storageManager() const { return *m_storageManager; } 151 152 PassRefPtr<WebPageProxy> createWebPage(PageClient*, WebPageGroup*, WebPageProxy* relatedPage = 0); 153 154 const String& injectedBundlePath() const { return m_injectedBundlePath; } 155 156 DownloadProxy* download(WebPageProxy* initiatingPage, const WebCore::ResourceRequest&); 157 158 void setInjectedBundleInitializationUserData(PassRefPtr<APIObject> userData) { m_injectedBundleInitializationUserData = userData; } 159 160 void postMessageToInjectedBundle(const String&, APIObject*); 161 162 // InjectedBundle client 163 void didReceiveMessageFromInjectedBundle(const String&, APIObject*); 164 void didReceiveSynchronousMessageFromInjectedBundle(const String&, APIObject*, RefPtr<APIObject>& returnData); 165 166 void populateVisitedLinks(); 167 168#if ENABLE(NETSCAPE_PLUGIN_API) 169 void setAdditionalPluginsDirectory(const String&); 170 171 PluginInfoStore& pluginInfoStore() { return m_pluginInfoStore; } 172#endif 173 174 void setAlwaysUsesComplexTextCodePath(bool); 175 void setShouldUseFontSmoothing(bool); 176 177 void registerURLSchemeAsEmptyDocument(const String&); 178 void registerURLSchemeAsSecure(const String&); 179 void setDomainRelaxationForbiddenForURLScheme(const String&); 180 void registerURLSchemeAsLocal(const String&); 181 void registerURLSchemeAsNoAccess(const String&); 182 void registerURLSchemeAsDisplayIsolated(const String&); 183 void registerURLSchemeAsCORSEnabled(const String&); 184 185 void addVisitedLink(const String&); 186 void addVisitedLinkHash(WebCore::LinkHash); 187 188 // MessageReceiver. 189 virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&) OVERRIDE; 190 virtual void didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&) OVERRIDE; 191 192 void setCacheModel(CacheModel); 193 CacheModel cacheModel() const { return m_cacheModel; } 194 195 void setDefaultRequestTimeoutInterval(double); 196 197 void startMemorySampler(const double interval); 198 void stopMemorySampler(); 199 200#if USE(SOUP) 201 void setInitialHTTPCookieAcceptPolicy(HTTPCookieAcceptPolicy policy) { m_initialHTTPCookieAcceptPolicy = policy; } 202#endif 203 void setEnhancedAccessibility(bool); 204 205 // Downloads. 206 DownloadProxy* createDownloadProxy(); 207 WebDownloadClient& downloadClient() { return m_downloadClient; } 208 209 WebHistoryClient& historyClient() { return m_historyClient; } 210 WebContextClient& client() { return m_client; } 211 212 WebIconDatabase* iconDatabase() const { return m_iconDatabase.get(); } 213#if ENABLE(NETSCAPE_PLUGIN_API) 214 WebPluginSiteDataManager* pluginSiteDataManager() const { return m_pluginSiteDataManager.get(); } 215#endif 216 217 struct Statistics { 218 unsigned wkViewCount; 219 unsigned wkPageCount; 220 unsigned wkFrameCount; 221 }; 222 static Statistics& statistics(); 223 224 void setApplicationCacheDirectory(const String& dir) { m_overrideApplicationCacheDirectory = dir; } 225 void setDatabaseDirectory(const String& dir) { m_overrideDatabaseDirectory = dir; } 226 void setIconDatabasePath(const String&); 227 String iconDatabasePath() const; 228 void setLocalStorageDirectory(const String&); 229 void setDiskCacheDirectory(const String& dir) { m_overrideDiskCacheDirectory = dir; } 230 void setCookieStorageDirectory(const String& dir) { m_overrideCookieStorageDirectory = dir; } 231 232 void allowSpecificHTTPSCertificateForHost(const WebCertificateInfo*, const String& host); 233 234 WebProcessProxy* ensureSharedWebProcess(); 235 WebProcessProxy* createNewWebProcessRespectingProcessCountLimit(); // Will return an existing one if limit is met. 236 void warmInitialProcess(); 237 238 bool shouldTerminate(WebProcessProxy*); 239 240 void disableProcessTermination() { m_processTerminationEnabled = false; } 241 void enableProcessTermination(); 242 243 // Defaults to false. 244 void setHTTPPipeliningEnabled(bool); 245 bool httpPipeliningEnabled() const; 246 247 void getStatistics(uint32_t statisticsMask, PassRefPtr<DictionaryCallback>); 248 249 void garbageCollectJavaScriptObjects(); 250 void setJavaScriptGarbageCollectorTimerEnabled(bool flag); 251 252#if PLATFORM(MAC) 253 static bool omitPDFSupport(); 254#endif 255 256 void fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled); 257 258 void textCheckerStateChanged(); 259 260 PassRefPtr<ImmutableDictionary> plugInAutoStartOriginHashes() const; 261 void setPlugInAutoStartOriginHashes(ImmutableDictionary&); 262 void setPlugInAutoStartOrigins(ImmutableArray&); 263 264 // Network Process Management 265 266 void setUsesNetworkProcess(bool); 267 bool usesNetworkProcess() const; 268 269#if ENABLE(NETWORK_PROCESS) 270 void ensureNetworkProcess(); 271 NetworkProcessProxy* networkProcess() { return m_networkProcess.get(); } 272 void networkProcessCrashed(NetworkProcessProxy*); 273 274 void getNetworkProcessConnection(PassRefPtr<Messages::WebProcessProxy::GetNetworkProcessConnection::DelayedReply>); 275#endif 276 277 278#if PLATFORM(MAC) 279 void setProcessSuppressionEnabled(bool); 280 bool processSuppressionEnabled() const { return m_processSuppressionEnabled; } 281 bool canEnableProcessSuppressionForNetworkProcess() const; 282 bool canEnableProcessSuppressionForWebProcess(const WebProcessProxy*) const; 283 static bool canEnableProcessSuppressionForGlobalChildProcesses(); 284 void updateProcessSuppressionStateOfChildProcesses(); 285#endif 286 287 static void willStartUsingPrivateBrowsing(); 288 static void willStopUsingPrivateBrowsing(); 289 290#if USE(SOUP) 291 void setIgnoreTLSErrors(bool); 292 bool ignoreTLSErrors() const { return m_ignoreTLSErrors; } 293#endif 294 295 static void setInvalidMessageCallback(void (*)(WKStringRef)); 296 static void didReceiveInvalidMessage(const CoreIPC::StringReference& messageReceiverName, const CoreIPC::StringReference& messageName); 297 298 void processDidCachePage(WebProcessProxy*); 299 300 bool isURLKnownHSTSHost(const String& urlString, bool privateBrowsingEnabled) const; 301 void resetHSTSHosts(); 302 303 void setMemoryCacheDisabled(bool); 304 305private: 306 WebContext(ProcessModel, const String& injectedBundlePath); 307 void platformInitialize(); 308 309 void platformInitializeWebProcess(WebProcessCreationParameters&); 310 void platformInvalidateContext(); 311 312 WebProcessProxy* createNewWebProcess(); 313 314 void requestWebContentStatistics(StatisticsRequest*); 315 void requestNetworkingStatistics(StatisticsRequest*); 316 317#if ENABLE(NETWORK_PROCESS) 318 void platformInitializeNetworkProcess(NetworkProcessCreationParameters&); 319#endif 320 321#if PLATFORM(MAC) 322 void getPasteboardTypes(const String& pasteboardName, Vector<String>& pasteboardTypes); 323 void getPasteboardPathnamesForType(const String& pasteboardName, const String& pasteboardType, Vector<String>& pathnames); 324 void getPasteboardStringForType(const String& pasteboardName, const String& pasteboardType, String&); 325 void getPasteboardBufferForType(const String& pasteboardName, const String& pasteboardType, SharedMemory::Handle&, uint64_t& size); 326 void pasteboardCopy(const String& fromPasteboard, const String& toPasteboard); 327 void getPasteboardChangeCount(const String& pasteboardName, uint64_t& changeCount); 328 void getPasteboardUniqueName(String& pasteboardName); 329 void getPasteboardColor(const String& pasteboardName, WebCore::Color&); 330 void getPasteboardURL(const String& pasteboardName, WTF::String&); 331 void addPasteboardTypes(const String& pasteboardName, const Vector<String>& pasteboardTypes); 332 void setPasteboardTypes(const String& pasteboardName, const Vector<String>& pasteboardTypes); 333 void setPasteboardPathnamesForType(const String& pasteboardName, const String& pasteboardType, const Vector<String>& pathnames); 334 void setPasteboardStringForType(const String& pasteboardName, const String& pasteboardType, const String&); 335 void setPasteboardBufferForType(const String& pasteboardName, const String& pasteboardType, const SharedMemory::Handle&, uint64_t size); 336#endif 337 338#if !PLATFORM(MAC) 339 // FIXME: This a dummy message, to avoid breaking the build for platforms that don't require 340 // any synchronous messages, and should be removed when <rdar://problem/8775115> is fixed. 341 void dummy(bool&); 342#endif 343 344 void didGetStatistics(const StatisticsData&, uint64_t callbackID); 345 346 // Implemented in generated WebContextMessageReceiver.cpp 347 void didReceiveWebContextMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&); 348 void didReceiveSyncWebContextMessage(CoreIPC::Connection*, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&); 349 350 static void languageChanged(void* context); 351 void languageChanged(); 352 353 String applicationCacheDirectory() const; 354 String platformDefaultApplicationCacheDirectory() const; 355 356 String databaseDirectory() const; 357 String platformDefaultDatabaseDirectory() const; 358 359 String platformDefaultIconDatabasePath() const; 360 361 String localStorageDirectory() const; 362 String platformDefaultLocalStorageDirectory() const; 363 364 String diskCacheDirectory() const; 365 String platformDefaultDiskCacheDirectory() const; 366 367 String cookieStorageDirectory() const; 368 String platformDefaultCookieStorageDirectory() const; 369 370#if PLATFORM(MAC) 371 void processSuppressionEnabledChanged(); 372 void registerNotificationObservers(); 373 void unregisterNotificationObservers(); 374#endif 375 376#if ENABLE(CUSTOM_PROTOCOLS) 377 void registerSchemeForCustomProtocol(const String&); 378 void unregisterSchemeForCustomProtocol(const String&); 379#endif 380 381 void addPlugInAutoStartOriginHash(const String& pageOrigin, unsigned plugInOriginHash); 382 void plugInDidReceiveUserInteraction(unsigned plugInOriginHash); 383 384 void setAnyPageGroupMightHavePrivateBrowsingEnabled(bool); 385 386#if ENABLE(NETSCAPE_PLUGIN_API) 387 // PluginInfoStoreClient: 388 virtual void pluginInfoStoreDidLoadPlugins(PluginInfoStore*) OVERRIDE; 389#endif 390 391 CoreIPC::MessageReceiverMap m_messageReceiverMap; 392 393 ProcessModel m_processModel; 394 unsigned m_webProcessCountLimit; // The limit has no effect when process model is ProcessModelSharedSecondaryProcess. 395 396 Vector<RefPtr<WebProcessProxy>> m_processes; 397 bool m_haveInitialEmptyProcess; 398 399 WebProcessProxy* m_processWithPageCache; 400 401 RefPtr<WebPageGroup> m_defaultPageGroup; 402 403 RefPtr<APIObject> m_injectedBundleInitializationUserData; 404 String m_injectedBundlePath; 405 WebContextInjectedBundleClient m_injectedBundleClient; 406 407 WebContextClient m_client; 408 WebContextConnectionClient m_connectionClient; 409 WebDownloadClient m_downloadClient; 410 WebHistoryClient m_historyClient; 411 412#if ENABLE(NETSCAPE_PLUGIN_API) 413 PluginInfoStore m_pluginInfoStore; 414#endif 415 VisitedLinkProvider m_visitedLinkProvider; 416 PlugInAutoStartProvider m_plugInAutoStartProvider; 417 418 HashSet<String> m_schemesToRegisterAsEmptyDocument; 419 HashSet<String> m_schemesToRegisterAsSecure; 420 HashSet<String> m_schemesToSetDomainRelaxationForbiddenFor; 421 HashSet<String> m_schemesToRegisterAsLocal; 422 HashSet<String> m_schemesToRegisterAsNoAccess; 423 HashSet<String> m_schemesToRegisterAsDisplayIsolated; 424 HashSet<String> m_schemesToRegisterAsCORSEnabled; 425 426 bool m_alwaysUsesComplexTextCodePath; 427 bool m_shouldUseFontSmoothing; 428 429 // Messages that were posted before any pages were created. 430 // The client should use initialization messages instead, so that a restarted process would get the same state. 431 Vector<pair<String, RefPtr<APIObject>>> m_messagesToInjectedBundlePostedToEmptyContext; 432 433 CacheModel m_cacheModel; 434 435 bool m_memorySamplerEnabled; 436 double m_memorySamplerInterval; 437 438 RefPtr<WebIconDatabase> m_iconDatabase; 439#if ENABLE(NETSCAPE_PLUGIN_API) 440 RefPtr<WebPluginSiteDataManager> m_pluginSiteDataManager; 441#endif 442 443 RefPtr<StorageManager> m_storageManager; 444 445 typedef HashMap<const char*, RefPtr<WebContextSupplement>, PtrHash<const char*>> WebContextSupplementMap; 446 WebContextSupplementMap m_supplements; 447 448#if USE(SOUP) 449 HTTPCookieAcceptPolicy m_initialHTTPCookieAcceptPolicy; 450#endif 451 452#if PLATFORM(MAC) 453 RetainPtr<NSObject> m_enhancedAccessibilityObserver; 454 RetainPtr<NSObject> m_customSchemeRegisteredObserver; 455 RetainPtr<NSObject> m_customSchemeUnregisteredObserver; 456 457 RetainPtr<NSObject> m_automaticTextReplacementNotificationObserver; 458 RetainPtr<NSObject> m_automaticSpellingCorrectionNotificationObserver; 459#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 460 RetainPtr<NSObject> m_automaticQuoteSubstitutionNotificationObserver; 461 RetainPtr<NSObject> m_automaticDashSubstitutionNotificationObserver; 462#endif 463#endif 464 465 String m_overrideApplicationCacheDirectory; 466 String m_overrideDatabaseDirectory; 467 String m_overrideIconDatabasePath; 468 String m_overrideLocalStorageDirectory; 469 String m_overrideDiskCacheDirectory; 470 String m_overrideCookieStorageDirectory; 471 472 bool m_processTerminationEnabled; 473 474#if ENABLE(NETWORK_PROCESS) 475 bool m_usesNetworkProcess; 476 RefPtr<NetworkProcessProxy> m_networkProcess; 477#endif 478 479 HashMap<uint64_t, RefPtr<DictionaryCallback>> m_dictionaryCallbacks; 480 HashMap<uint64_t, RefPtr<StatisticsRequest>> m_statisticsRequests; 481 482#if PLATFORM(MAC) 483 bool m_processSuppressionEnabled; 484#endif 485 486#if USE(SOUP) 487 bool m_ignoreTLSErrors; 488#endif 489 490 bool m_memoryCacheDisabled; 491}; 492 493template<typename U> inline void WebContext::sendToNetworkingProcess(const U& message) 494{ 495 switch (m_processModel) { 496 case ProcessModelSharedSecondaryProcess: 497 if (!m_processes.isEmpty() && m_processes[0]->canSendMessage()) 498 m_processes[0]->send(message, 0); 499 return; 500 case ProcessModelMultipleSecondaryProcesses: 501#if ENABLE(NETWORK_PROCESS) 502 if (m_networkProcess->canSendMessage()) 503 m_networkProcess->send(message, 0); 504 return; 505#else 506 break; 507#endif 508 } 509 ASSERT_NOT_REACHED(); 510} 511 512template<typename U> void WebContext::sendToNetworkingProcessRelaunchingIfNecessary(const U& message) 513{ 514 switch (m_processModel) { 515 case ProcessModelSharedSecondaryProcess: 516 ensureSharedWebProcess(); 517 m_processes[0]->send(message, 0); 518 return; 519 case ProcessModelMultipleSecondaryProcesses: 520#if ENABLE(NETWORK_PROCESS) 521 ensureNetworkProcess(); 522 m_networkProcess->send(message, 0); 523 return; 524#else 525 break; 526#endif 527 } 528 ASSERT_NOT_REACHED(); 529} 530 531template<typename U> inline void WebContext::sendToAllProcesses(const U& message) 532{ 533 size_t processCount = m_processes.size(); 534 for (size_t i = 0; i < processCount; ++i) { 535 WebProcessProxy* process = m_processes[i].get(); 536 if (process->canSendMessage()) 537 process->send(message, 0); 538 } 539} 540 541template<typename U> void WebContext::sendToAllProcessesRelaunchingThemIfNecessary(const U& message) 542{ 543// FIXME (Multi-WebProcess): WebContext doesn't track processes that have exited, so it cannot relaunch these. Perhaps this functionality won't be needed in this mode. 544 if (m_processModel == ProcessModelSharedSecondaryProcess) 545 ensureSharedWebProcess(); 546 sendToAllProcesses(message); 547} 548 549template<typename U> inline void WebContext::sendToOneProcess(const U& message) 550{ 551 if (m_processModel == ProcessModelSharedSecondaryProcess) 552 ensureSharedWebProcess(); 553 554 bool messageSent = false; 555 size_t processCount = m_processes.size(); 556 for (size_t i = 0; i < processCount; ++i) { 557 WebProcessProxy* process = m_processes[i].get(); 558 if (process->canSendMessage()) { 559 process->send(message, 0); 560 messageSent = true; 561 break; 562 } 563 } 564 565 if (!messageSent && m_processModel == ProcessModelMultipleSecondaryProcesses) { 566 warmInitialProcess(); 567 RefPtr<WebProcessProxy> process = m_processes.last(); 568 if (process->canSendMessage()) 569 process->send(message, 0); 570 } 571} 572 573} // namespace WebKit 574 575#endif // WebContext_h 576