Have NetworkProcess manage resource load scheduling.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 27 Oct 2012 05:59:24 +0000 (05:59 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 27 Oct 2012 05:59:24 +0000 (05:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=100479

Reviewed by Alexey Proskuryakov.

Source/WebCore:

Down in WebCore we need to virtualize a handful of ResourceLoadScheduler methods
to be overridden by WebKit's implementation.

No new tests (No change in Core behavior).

* WebCore.exp.in:
* WebCore.xcodeproj/project.pbxproj:

* loader/ResourceLoadScheduler.cpp:
(WebCore::resourceLoadScheduler): Gracefully handle LoaderStrategies wanting to return the default scheduler.
(WebCore::ResourceLoadScheduler::scheduleLoad): Call notifyDidScheduleResourceRequest.
(WebCore::ResourceLoadScheduler::notifyDidScheduleResourceRequest): Moved InspectorInstrumentation call
  here so derived classes can do it indirectly.
(WebCore::ResourceLoadScheduler::startResourceLoader): To allow derived classes the ability to call
  ResourceLoader::start() which only ResourceLoadScheduler can do.

* loader/ResourceLoadScheduler.h:
(ResourceLoadScheduler): Virtualize some core public methods so they can be overridden.
(WebCore::ResourceLoadScheduler::setSerialLoadingEnabled): Make virtual.
(WebCore::ResourceLoadScheduler::isSuspendingPendingRequests): Make private as it's internal only.

* loader/ResourceLoader.cpp:
(WebCore::ResourceLoader::setIdentifier): Add this setter so outside clients can manually change the identifier.

* loader/ResourceLoader.h:
(WebCore::ResourceLoader::identifier): Change identifier to explicitly be uint64_t.
(WebCore::ResourceLoader::request): Make public.
(ResourceLoader):

Source/WebKit2:

Implement a ResourceLoadScheduler that models the same behavior as WebCore::ResourceLoadScheduler.

The WebProcess scheduler acts as a marshall to the NetworkProcess scheduler via CoreIPC messaging.

Besides MainResourceLoads which are started directly in the WebProcess, all other loads are now
started only when the NetworkProcess tells them to start.

Build-system and messaging related stuff:
* DerivedSources.make:
* Platform/CoreIPC/MessageID.h:
* WebKit2.xcodeproj/project.pbxproj:

Add a new Network logging channel.
* Platform/Logging.cpp:
(WebKit::getChannelFromName):
* Platform/Logging.h:

Modeled after ResourceLoadScheduler::HostInformation but more specifically geared towards what NetworkProcess needs to track:
* NetworkProcess/HostRecord.cpp: Added.
(WebKit::HostRecord::HostRecord):
(WebKit::HostRecord::~HostRecord):
(WebKit::HostRecord::schedule):
(WebKit::HostRecord::addLoadInProgress):
(WebKit::HostRecord::remove):
(WebKit::HostRecord::hasRequests):
(WebKit::HostRecord::limitRequests):
* NetworkProcess/HostRecord.h:
(WebKit::HostRecord::name):
(WebKit::HostRecord::requestsPending):

Gateway messaging from the WebResourceLoadScheduler to the NetworkResourceLoadScheduler:
* NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::NetworkConnectionToWebProcess):
(WebKit::NetworkConnectionToWebProcess::~NetworkConnectionToWebProcess):
(WebKit::NetworkConnectionToWebProcess::registerObserver):
(WebKit::NetworkConnectionToWebProcess::unregisterObserver):
(WebKit::NetworkConnectionToWebProcess::didReceiveMessage):
(WebKit::NetworkConnectionToWebProcess::didReceiveSyncMessage):
(WebKit::NetworkConnectionToWebProcess::didClose):
(WebKit::NetworkConnectionToWebProcess::scheduleNetworkRequest):
(WebKit::NetworkConnectionToWebProcess::addLoadInProgress):
(WebKit::NetworkConnectionToWebProcess::removeLoadIdentifier):
(WebKit::NetworkConnectionToWebProcess::crossOriginRedirectReceived):
(WebKit::NetworkConnectionToWebProcess::servePendingRequests):
(WebKit::NetworkConnectionToWebProcess::suspendPendingRequests):
(WebKit::NetworkConnectionToWebProcess::resumePendingRequests):
(WebKit::NetworkConnectionToWebProcess::setSerialLoadingEnabled):
* NetworkProcess/NetworkConnectionToWebProcess.h:
(NetworkConnectionToWebProcessObserver): Add an observer interface so arbitrary objects can be notified if
  a Network->WebProcess connection closes.
(WebKit::NetworkConnectionToWebProcessObserver::~NetworkConnectionToWebProcessObserver):
(WebKit::NetworkConnectionToWebProcess::isSerialLoadingEnabled):
* NetworkProcess/NetworkConnectionToWebProcess.messages.in:

Represents a request,  ResourceLoadIdentifier, and connection that all correspond to the same pending NetworkLoad:
* NetworkProcess/NetworkRequest.cpp:
(WebKit::NetworkRequest::NetworkRequest):
(WebKit::NetworkRequest::~NetworkRequest):
(WebKit::NetworkRequest::connectionToWebProcessDidClose): Using the NetworkConnectionToWebProcessObserver interface,
  if the connection closes then clear out the connection pointer for this request that is now irrelevant.
* NetworkProcess/NetworkRequest.h:
(WebKit::NetworkRequest::create):
(WebKit::NetworkRequest::identifier):
(WebKit::NetworkRequest::connectionToWebProcess):

Manages connection-per-host scheduling with the same structure as WebCore::ResourceLoadScheduling but also with IPC:
* NetworkProcess/NetworkResourceLoadScheduler.cpp: Added.
(WebKit::NetworkResourceLoadScheduler::NetworkResourceLoadScheduler):
(WebKit::NetworkResourceLoadScheduler::scheduleServePendingRequests):
(WebKit::NetworkResourceLoadScheduler::requestTimerFired):
(WebKit::NetworkResourceLoadScheduler::scheduleNetworkRequest):
(WebKit::NetworkResourceLoadScheduler::addLoadInProgress):
(WebKit::NetworkResourceLoadScheduler::hostForURL):
(WebKit::NetworkResourceLoadScheduler::removeLoadIdentifier):
(WebKit::NetworkResourceLoadScheduler::crossOriginRedirectReceived):
(WebKit::NetworkResourceLoadScheduler::servePendingRequests):
(WebKit::NetworkResourceLoadScheduler::servePendingRequestsForHost): Serve as many requests for the host as we should,
  skipping the NetworkRequests who have lost their connection to their WebProcess.
(WebKit::NetworkResourceLoadScheduler::suspendPendingRequests):
(WebKit::NetworkResourceLoadScheduler::resumePendingRequests):
* NetworkProcess/NetworkResourceLoadScheduler.h: Added.
* NetworkProcess/mac/NetworkResourceLoadSchedulerMac.mm: Added.
(WebKit::NetworkResourceLoadScheduler::platformInitializeMaximumHTTPConnectionCountPerHost):

* NetworkProcess/NetworkProcess.h:
(WebKit::NetworkProcess::networkResourceLoadScheduler): Add a scheduler global to the NetworkProcess.

A thin derivation of WebCore::ResourceLoadScheduler, most of what WebResourceLoadScheduler does is handle IPC to the NetworkProcess:
* WebProcess/Network/WebResourceLoadScheduler.cpp:
(WebKit::WebResourceLoadScheduler::WebResourceLoadScheduler):
(WebKit::WebResourceLoadScheduler::scheduleSubresourceLoad):
(WebKit::WebResourceLoadScheduler::schedulePluginStreamLoad):
(WebKit::WebResourceLoadScheduler::scheduleLoad):
(WebKit::WebResourceLoadScheduler::addMainResourceLoad):
(WebKit::WebResourceLoadScheduler::remove):
(WebKit::WebResourceLoadScheduler::crossOriginRedirectReceived):
(WebKit::WebResourceLoadScheduler::servePendingRequests):
(WebKit::WebResourceLoadScheduler::suspendPendingRequests):
(WebKit::WebResourceLoadScheduler::resumePendingRequests):
(WebKit::WebResourceLoadScheduler::setSerialLoadingEnabled):
(WebKit::WebResourceLoadScheduler::startResourceLoad):
* WebProcess/Network/WebResourceLoadScheduler.h:

Add the ability for the NetworkProcess to message back to the WebProcess telling it to start a resource load:
* WebProcess/Network/NetworkProcessConnection.cpp:
(WebKit::NetworkProcessConnection::didReceiveMessage):
(WebKit::NetworkProcessConnection::didReceiveSyncMessage):
(WebKit::NetworkProcessConnection::startResourceLoad):
* WebProcess/Network/NetworkProcessConnection.h:
* WebProcess/Network/NetworkProcessConnection.messages.in:

* WebProcess/WebCoreSupport/WebPlatformStrategies.cpp:
(WebKit::WebPlatformStrategies::resourceLoadScheduler): Only return the WebResourceLoadScheduler if NetworkProcess is enabled.

* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::ensureNetworkProcessConnection): Actually keep the NetworkProcessConnection around in a member variable.
(WebKit::WebProcess::networkConnection):
* WebProcess/WebProcess.h:
(WebKit::WebProcess::usesNetworkProcess): Expose this for platform strategies sake.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@132721 268f45cc-cd09-0410-ab3c-d52691b4dbfc

32 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/loader/ResourceLoadScheduler.cpp
Source/WebCore/loader/ResourceLoadScheduler.h
Source/WebCore/loader/ResourceLoader.cpp
Source/WebCore/loader/ResourceLoader.h
Source/WebKit2/ChangeLog
Source/WebKit2/DerivedSources.make
Source/WebKit2/NetworkProcess/HostRecord.cpp [new file with mode: 0644]
Source/WebKit2/NetworkProcess/HostRecord.h [new file with mode: 0644]
Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp
Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.h
Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.messages.in
Source/WebKit2/NetworkProcess/NetworkProcess.h
Source/WebKit2/NetworkProcess/NetworkRequest.cpp [new file with mode: 0644]
Source/WebKit2/NetworkProcess/NetworkRequest.h [new file with mode: 0644]
Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.cpp [new file with mode: 0644]
Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.h [new file with mode: 0644]
Source/WebKit2/NetworkProcess/mac/NetworkResourceLoadSchedulerMac.mm [new file with mode: 0644]
Source/WebKit2/Platform/CoreIPC/MessageID.h
Source/WebKit2/Platform/Logging.cpp
Source/WebKit2/Platform/Logging.h
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Source/WebKit2/WebProcess/Network/NetworkProcessConnection.cpp
Source/WebKit2/WebProcess/Network/NetworkProcessConnection.h
Source/WebKit2/WebProcess/Network/NetworkProcessConnection.messages.in [new file with mode: 0644]
Source/WebKit2/WebProcess/Network/WebResourceLoadScheduler.cpp
Source/WebKit2/WebProcess/Network/WebResourceLoadScheduler.h
Source/WebKit2/WebProcess/WebCoreSupport/WebPlatformStrategies.cpp
Source/WebKit2/WebProcess/WebProcess.cpp
Source/WebKit2/WebProcess/WebProcess.h

index 64aec4e..21924d3 100644 (file)
@@ -1,3 +1,39 @@
+2012-10-26  Brady Eidson  <beidson@apple.com>
+
+        Have NetworkProcess manage resource load scheduling.
+        https://bugs.webkit.org/show_bug.cgi?id=100479
+
+        Reviewed by Alexey Proskuryakov.
+
+        Down in WebCore we need to virtualize a handful of ResourceLoadScheduler methods
+        to be overridden by WebKit's implementation.
+
+        No new tests (No change in Core behavior).
+
+        * WebCore.exp.in:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * loader/ResourceLoadScheduler.cpp:
+        (WebCore::resourceLoadScheduler): Gracefully handle LoaderStrategies wanting to return the default scheduler.
+        (WebCore::ResourceLoadScheduler::scheduleLoad): Call notifyDidScheduleResourceRequest.
+        (WebCore::ResourceLoadScheduler::notifyDidScheduleResourceRequest): Moved InspectorInstrumentation call
+          here so derived classes can do it indirectly.
+        (WebCore::ResourceLoadScheduler::startResourceLoader): To allow derived classes the ability to call
+          ResourceLoader::start() which only ResourceLoadScheduler can do.
+
+        * loader/ResourceLoadScheduler.h:
+        (ResourceLoadScheduler): Virtualize some core public methods so they can be overridden.
+        (WebCore::ResourceLoadScheduler::setSerialLoadingEnabled): Make virtual.
+        (WebCore::ResourceLoadScheduler::isSuspendingPendingRequests): Make private as it's internal only.
+
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::setIdentifier): Add this setter so outside clients can manually change the identifier.
+
+        * loader/ResourceLoader.h:
+        (WebCore::ResourceLoader::identifier): Change identifier to explicitly be uint64_t.
+        (WebCore::ResourceLoader::request): Make public.
+        (ResourceLoader):
+
 2012-10-26  Chris Rogers  <crogers@google.com>
 
         Implement AudioBufferSourceNode .loopStart and .loopEnd attributes
index 591df9e..57029ee 100644 (file)
@@ -270,6 +270,7 @@ __ZN7WebCore14ResourceBufferD1Ev
 __ZN7WebCore14ResourceHandle20forceContentSniffingEv
 __ZN7WebCore14ResourceHandle26synchronousLoadRunLoopModeEv
 __ZN7WebCore14ResourceHandle35createPrivateBrowsingStorageSessionEPK10__CFString
+__ZN7WebCore14ResourceLoader13setIdentifierEm
 __ZN7WebCore14ResourceLoader14cancelledErrorEv
 __ZN7WebCore14SchemeRegistry24registerURLSchemeAsLocalERKN3WTF6StringE
 __ZN7WebCore14SchemeRegistry25registerURLSchemeAsSecureERKN3WTF6StringE
@@ -472,6 +473,7 @@ __ZN7WebCore17JSDOMGlobalObject6s_infoE
 __ZN7WebCore17languageDidChangeEv
 __ZN7WebCore17RegularExpressionC1ERKN3WTF6StringENS1_19TextCaseSensitivityE
 __ZN7WebCore17RegularExpressionD1Ev
+__ZN7WebCore17SubresourceLoader6createEPNS_5FrameEPNS_14CachedResourceERKNS_15ResourceRequestERKNS_21ResourceLoaderOptionsE
 __ZN7WebCore17ViewportArguments19deprecatedTargetDPIE
 __ZN7WebCore17cacheDOMStructureEPNS_17JSDOMGlobalObjectEPN3JSC9StructureEPKNS2_9ClassInfoE
 __ZN7WebCore17openTemporaryFileERKN3WTF6StringERi
@@ -559,6 +561,7 @@ __ZN7WebCore21BackForwardController11itemAtIndexEi
 __ZN7WebCore21MemoryPressureHandler7installEv
 __ZN7WebCore21PlatformKeyboardEvent24disambiguateKeyDownEventENS_13PlatformEvent4TypeEb
 __ZN7WebCore21ResourceLoadScheduler19addMainResourceLoadEPNS_14ResourceLoaderE
+__ZN7WebCore21ResourceLoadScheduler19startResourceLoaderEPNS_14ResourceLoaderE
 __ZN7WebCore21ResourceLoadScheduler20servePendingRequestsENS_20ResourceLoadPriorityE
 __ZN7WebCore21ResourceLoadScheduler20servePendingRequestsEPNS0_15HostInformationENS_20ResourceLoadPriorityE
 __ZN7WebCore21ResourceLoadScheduler21resumePendingRequestsEv
@@ -566,6 +569,7 @@ __ZN7WebCore21ResourceLoadScheduler22suspendPendingRequestsEv
 __ZN7WebCore21ResourceLoadScheduler23scheduleSubresourceLoadEPNS_5FrameEPNS_14CachedResourceERKNS_15ResourceRequestENS_20ResourceLoadPriorityERKNS_21ResourceLoaderOptionsE
 __ZN7WebCore21ResourceLoadScheduler24schedulePluginStreamLoadEPNS_5FrameEPNS_32NetscapePlugInStreamLoaderClientERKNS_15ResourceRequestE
 __ZN7WebCore21ResourceLoadScheduler27crossOriginRedirectReceivedEPNS_14ResourceLoaderERKNS_4KURLE
+__ZN7WebCore21ResourceLoadScheduler32notifyDidScheduleResourceRequestEPNS_14ResourceLoaderE
 __ZN7WebCore21ResourceLoadScheduler6removeEPNS_14ResourceLoaderE
 __ZN7WebCore21ResourceLoadSchedulerC2Ev
 __ZN7WebCore21ResourceLoadSchedulerD2Ev
@@ -641,6 +645,7 @@ __ZN7WebCore25ImmutableStylePropertySetD1Ev
 __ZN7WebCore25addLanguageChangeObserverEPvPFvS0_E
 __ZN7WebCore25computeViewportAttributesENS_17ViewportArgumentsEiiifNS_7IntSizeE
 __ZN7WebCore25jsStringWithCacheSlowCaseEPN3JSC9ExecStateERN3WTF7HashMapIPNS3_10StringImplENS0_4WeakINS0_8JSStringEEENS3_7PtrHashIS6_EENS3_10HashTraitsIS6_EENSC_IS9_EEEES6_
+__ZN7WebCore26NetscapePlugInStreamLoader6createEPNS_5FrameEPNS_32NetscapePlugInStreamLoaderClientERKNS_15ResourceRequestE
 __ZN7WebCore26UserTypingGestureIndicator27processingUserTypingGestureEv
 __ZN7WebCore26UserTypingGestureIndicator28focusedElementAtGestureStartEv
 __ZN7WebCore26stopObservingCookieChangesEv
@@ -1206,6 +1211,7 @@ __ZNK7WebCore14DocumentLoader17parsedArchiveDataEv
 __ZNK7WebCore14DocumentLoader17reportMemoryUsageEPN3WTF16MemoryObjectInfoE
 __ZNK7WebCore14DocumentLoader19isLoadingInAPISenseEv
 __ZNK7WebCore14DocumentLoader19originalRequestCopyEv
+__ZNK7WebCore14DocumentLoader21archiveResourceForURLERKNS_4KURLE
 __ZNK7WebCore14DocumentLoader21isLoadingMainResourceEv
 __ZNK7WebCore14DocumentLoader28urlForHistoryReflectsFailureEv
 __ZNK7WebCore14DocumentLoader3urlEv
index 20695d4..a6cedec 100644 (file)
                7EE6846C12D26E3800E79415 /* ResourceHandleCFNet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7EE6845912D26E3800E79415 /* ResourceHandleCFNet.cpp */; };
                7EE6846D12D26E3800E79415 /* ResourceRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EE6845A12D26E3800E79415 /* ResourceRequest.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7EE6846E12D26E3800E79415 /* ResourceRequestCFNet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7EE6845B12D26E3800E79415 /* ResourceRequestCFNet.cpp */; };
-               7EE6846F12D26E3800E79415 /* ResourceRequestCFNet.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EE6845C12D26E3800E79415 /* ResourceRequestCFNet.h */; };
+               7EE6846F12D26E3800E79415 /* ResourceRequestCFNet.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EE6845C12D26E3800E79415 /* ResourceRequestCFNet.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7EE6847012D26E3800E79415 /* ResourceResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EE6845D12D26E3800E79415 /* ResourceResponse.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7EE6847112D26E3800E79415 /* ResourceResponseCFNet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7EE6845E12D26E3800E79415 /* ResourceResponseCFNet.cpp */; };
                7EE6847512D26E7000E79415 /* ResourceLoaderCFNet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7EE6847412D26E7000E79415 /* ResourceLoaderCFNet.cpp */; };
index df0346f..f18d913 100644 (file)
 #include "FrameLoader.h"
 #include "InspectorInstrumentation.h"
 #include "KURL.h"
+#include "LoaderStrategy.h"
 #include "Logging.h"
 #include "NetscapePlugInStreamLoader.h"
+#include "PlatformStrategies.h"
 #include "ResourceLoader.h"
 #include "ResourceRequest.h"
 #include "SubresourceLoader.h"
 #include <wtf/MainThread.h>
+#include <wtf/TemporaryChange.h>
 #include <wtf/text/CString.h>
 
 #if PLATFORM(CHROMIUM)
@@ -74,8 +77,28 @@ ResourceLoadScheduler::HostInformation* ResourceLoadScheduler::hostForURL(const
 ResourceLoadScheduler* resourceLoadScheduler()
 {
     ASSERT(isMainThread());
-    DEFINE_STATIC_LOCAL(ResourceLoadScheduler, resourceLoadScheduler, ());
-    return &resourceLoadScheduler;
+    static ResourceLoadScheduler* globalScheduler = 0;
+    
+    if (!globalScheduler) {
+#if USE(PLATFORM_STRATEGIES)
+        static bool isCallingOutToStrategy = false;
+        
+        // If we're re-entering resourceLoadScheduler() while calling out to the LoaderStrategy,
+        // then the LoaderStrategy is trying to use the default resourceLoadScheduler.
+        // So we'll create it here and start using it.
+        if (isCallingOutToStrategy) {
+            globalScheduler = new ResourceLoadScheduler;
+            return globalScheduler;
+        }
+        
+        TemporaryChange<bool> recursionGuard(isCallingOutToStrategy, true);
+        globalScheduler = platformStrategies()->loaderStrategy()->resourceLoadScheduler();
+#else
+        globalScheduler = new ResourceLoadScheduler;
+#endif
+    }
+
+    return globalScheduler;
 }
 
 ResourceLoadScheduler::ResourceLoadScheduler()
@@ -140,11 +163,18 @@ void ResourceLoadScheduler::scheduleLoad(ResourceLoader* resourceLoader, Resourc
         return;
     }
 
-    // Handle asynchronously so early low priority requests don't get scheduled before later high priority ones.
-    InspectorInstrumentation::didScheduleResourceRequest(resourceLoader->frameLoader() ? resourceLoader->frameLoader()->frame()->document() : 0, resourceLoader->url());
+    notifyDidScheduleResourceRequest(resourceLoader);
+
+    // Handle asynchronously so early low priority requests don't
+    // get scheduled before later high priority ones.
     scheduleServePendingRequests();
 }
 
+void ResourceLoadScheduler::notifyDidScheduleResourceRequest(ResourceLoader* loader)
+{
+    InspectorInstrumentation::didScheduleResourceRequest(loader->frameLoader() ? loader->frameLoader()->frame()->document() : 0, loader->url());
+}
+
 void ResourceLoadScheduler::remove(ResourceLoader* resourceLoader)
 {
     ASSERT(resourceLoader);
@@ -307,4 +337,10 @@ bool ResourceLoadScheduler::HostInformation::limitRequests(ResourceLoadPriority
     return m_requestsLoading.size() >= (resourceLoadScheduler()->isSerialLoadingEnabled() ? 1 : m_maxRequestsInFlight);
 }
 
+void ResourceLoadScheduler::startResourceLoader(ResourceLoader* loader)
+{
+    ASSERT(loader);
+    loader->start();
+}
+
 } // namespace WebCore
index 5e5c49c..20e5aa7 100644 (file)
@@ -50,29 +50,33 @@ class ResourceLoadScheduler {
 public:
     friend ResourceLoadScheduler* resourceLoadScheduler();
 
-    PassRefPtr<SubresourceLoader> scheduleSubresourceLoad(Frame*, CachedResource*, const ResourceRequest&, ResourceLoadPriority, const ResourceLoaderOptions&);
-    PassRefPtr<NetscapePlugInStreamLoader> schedulePluginStreamLoad(Frame*, NetscapePlugInStreamLoaderClient*, const ResourceRequest&);
-    void addMainResourceLoad(ResourceLoader*);
-    void remove(ResourceLoader*);
-    void crossOriginRedirectReceived(ResourceLoader*, const KURL& redirectURL);
+    virtual PassRefPtr<SubresourceLoader> scheduleSubresourceLoad(Frame*, CachedResource*, const ResourceRequest&, ResourceLoadPriority, const ResourceLoaderOptions&);
+    virtual PassRefPtr<NetscapePlugInStreamLoader> schedulePluginStreamLoad(Frame*, NetscapePlugInStreamLoaderClient*, const ResourceRequest&);
+    virtual void addMainResourceLoad(ResourceLoader*);
+    virtual void remove(ResourceLoader*);
+    virtual void crossOriginRedirectReceived(ResourceLoader*, const KURL& redirectURL);
     
-    void servePendingRequests(ResourceLoadPriority minimumPriority = ResourceLoadPriorityVeryLow);
-    bool isSuspendingPendingRequests() const { return !!m_suspendPendingRequestsCount; }
-    void suspendPendingRequests();
-    void resumePendingRequests();
+    virtual void servePendingRequests(ResourceLoadPriority minimumPriority = ResourceLoadPriorityVeryLow);
+    virtual void suspendPendingRequests();
+    virtual void resumePendingRequests();
     
     bool isSerialLoadingEnabled() const { return m_isSerialLoadingEnabled; }
-    void setSerialLoadingEnabled(bool b) { m_isSerialLoadingEnabled = b; }
+    virtual void setSerialLoadingEnabled(bool b) { m_isSerialLoadingEnabled = b; }
 
 protected:
     ResourceLoadScheduler();
     virtual ~ResourceLoadScheduler();
 
+    void startResourceLoader(ResourceLoader*);
+    void notifyDidScheduleResourceRequest(ResourceLoader*);
+
 private:
     void scheduleLoad(ResourceLoader*, ResourceLoadPriority);
     void scheduleServePendingRequests();
     void requestTimerFired(Timer<ResourceLoadScheduler>*);
 
+    bool isSuspendingPendingRequests() const { return !!m_suspendPendingRequestsCount; }
+
     class HostInformation {
         WTF_MAKE_NONCOPYABLE(HostInformation); WTF_MAKE_FAST_ALLOCATED;
     public:
index b12b443..0dad87f 100644 (file)
@@ -558,4 +558,14 @@ void ResourceLoader::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
     info.addMember(m_options);
 }
 
+#if PLATFORM(MAC)
+void ResourceLoader::setIdentifier(unsigned long identifier)
+{
+    // FIXME (NetworkProcess): This is temporary to allow WebKit to directly set the identifier on a ResourceLoader.
+    // More permanently we'll want the identifier to be piped through ResourceLoader::init/start so
+    // it always has it, especially in willSendRequest.
+    m_identifier = identifier;
+}
+#endif
+
 }
index ea83121..4376a54 100644 (file)
@@ -66,7 +66,7 @@ public:
     
     virtual void setDefersLoading(bool);
 
-    unsigned long identifier() const { return m_identifier; }
+    uint64_t identifier() const { return m_identifier; }
 
     virtual void releaseResources();
     const ResourceResponse& response() const;
@@ -143,22 +143,29 @@ public:
 
     bool reachedTerminalState() const { return m_reachedTerminalState; }
 
+    const ResourceRequest& request() const { return m_request; }
+
     void setShouldBufferData(DataBufferingPolicy);
 
     virtual void reportMemoryUsage(MemoryObjectInfo*) const;
 
+#if PLATFORM(MAC)
+    // FIXME (NetworkProcess): This is temporary to allow WebKit to directly set the identifier on a ResourceLoader.
+    // More permanently we want the identifier to be piped through ResourceLoader::init/start so
+    // it always has it, especially in willSendRequest.
+    void setIdentifier(unsigned long);
+#endif
+
 protected:
     ResourceLoader(Frame*, ResourceLoaderOptions);
 
-    friend class ApplicationCacheHost;  // for access to request()
     friend class ResourceLoadScheduler; // for access to start()
-    // start() actually sends the load to the network (unless the load is being 
+    // start() actually sends the load to the network (unless the load is being
     // deferred) and should only be called by ResourceLoadScheduler or setDefersLoading().
     void start();
-    
+
     void didFinishLoadingOnePart(double finishTime);
 
-    const ResourceRequest& request() const { return m_request; }
     bool cancelled() const { return m_cancelled; }
     bool defersLoading() const { return m_defersLoading; }
 
@@ -175,7 +182,7 @@ private:
     ResourceRequest m_originalRequest; // Before redirects.
     RefPtr<ResourceBuffer> m_resourceData;
     
-    unsigned long m_identifier;
+    uint64_t m_identifier;
 
     bool m_reachedTerminalState;
     bool m_calledWillCancel;
index 1f89bfb..c545865 100644 (file)
@@ -1,5 +1,132 @@
 2012-10-26  Brady Eidson  <beidson@apple.com>
 
+        Have NetworkProcess manage resource load scheduling.
+        https://bugs.webkit.org/show_bug.cgi?id=100479
+
+        Reviewed by Alexey Proskuryakov.
+
+        Implement a ResourceLoadScheduler that models the same behavior as WebCore::ResourceLoadScheduler.
+        
+        The WebProcess scheduler acts as a marshall to the NetworkProcess scheduler via CoreIPC messaging.
+
+        Besides MainResourceLoads which are started directly in the WebProcess, all other loads are now
+        started only when the NetworkProcess tells them to start.
+
+        Build-system and messaging related stuff:
+        * DerivedSources.make:
+        * Platform/CoreIPC/MessageID.h:
+        * WebKit2.xcodeproj/project.pbxproj:
+
+        Add a new Network logging channel.
+        * Platform/Logging.cpp:
+        (WebKit::getChannelFromName):
+        * Platform/Logging.h:
+
+        Modeled after ResourceLoadScheduler::HostInformation but more specifically geared towards what NetworkProcess needs to track:
+        * NetworkProcess/HostRecord.cpp: Added.
+        (WebKit::HostRecord::HostRecord):
+        (WebKit::HostRecord::~HostRecord):
+        (WebKit::HostRecord::schedule):
+        (WebKit::HostRecord::addLoadInProgress):
+        (WebKit::HostRecord::remove):
+        (WebKit::HostRecord::hasRequests):
+        (WebKit::HostRecord::limitRequests):
+        * NetworkProcess/HostRecord.h:
+        (WebKit::HostRecord::name):
+        (WebKit::HostRecord::requestsPending):
+
+        Gateway messaging from the WebResourceLoadScheduler to the NetworkResourceLoadScheduler:
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+        (WebKit::NetworkConnectionToWebProcess::NetworkConnectionToWebProcess):
+        (WebKit::NetworkConnectionToWebProcess::~NetworkConnectionToWebProcess):
+        (WebKit::NetworkConnectionToWebProcess::registerObserver):
+        (WebKit::NetworkConnectionToWebProcess::unregisterObserver):
+        (WebKit::NetworkConnectionToWebProcess::didReceiveMessage):
+        (WebKit::NetworkConnectionToWebProcess::didReceiveSyncMessage):
+        (WebKit::NetworkConnectionToWebProcess::didClose):
+        (WebKit::NetworkConnectionToWebProcess::scheduleNetworkRequest):
+        (WebKit::NetworkConnectionToWebProcess::addLoadInProgress):
+        (WebKit::NetworkConnectionToWebProcess::removeLoadIdentifier):
+        (WebKit::NetworkConnectionToWebProcess::crossOriginRedirectReceived):
+        (WebKit::NetworkConnectionToWebProcess::servePendingRequests):
+        (WebKit::NetworkConnectionToWebProcess::suspendPendingRequests):
+        (WebKit::NetworkConnectionToWebProcess::resumePendingRequests):
+        (WebKit::NetworkConnectionToWebProcess::setSerialLoadingEnabled):
+        * NetworkProcess/NetworkConnectionToWebProcess.h:
+        (NetworkConnectionToWebProcessObserver): Add an observer interface so arbitrary objects can be notified if
+          a Network->WebProcess connection closes.
+        (WebKit::NetworkConnectionToWebProcessObserver::~NetworkConnectionToWebProcessObserver):
+        (WebKit::NetworkConnectionToWebProcess::isSerialLoadingEnabled):
+        * NetworkProcess/NetworkConnectionToWebProcess.messages.in:
+
+        Represents a request,  ResourceLoadIdentifier, and connection that all correspond to the same pending NetworkLoad:
+        * NetworkProcess/NetworkRequest.cpp:
+        (WebKit::NetworkRequest::NetworkRequest):
+        (WebKit::NetworkRequest::~NetworkRequest):
+        (WebKit::NetworkRequest::connectionToWebProcessDidClose): Using the NetworkConnectionToWebProcessObserver interface,
+          if the connection closes then clear out the connection pointer for this request that is now irrelevant.
+        * NetworkProcess/NetworkRequest.h:
+        (WebKit::NetworkRequest::create):
+        (WebKit::NetworkRequest::identifier):
+        (WebKit::NetworkRequest::connectionToWebProcess):
+
+        Manages connection-per-host scheduling with the same structure as WebCore::ResourceLoadScheduling but also with IPC:
+        * NetworkProcess/NetworkResourceLoadScheduler.cpp: Added.
+        (WebKit::NetworkResourceLoadScheduler::NetworkResourceLoadScheduler):
+        (WebKit::NetworkResourceLoadScheduler::scheduleServePendingRequests):
+        (WebKit::NetworkResourceLoadScheduler::requestTimerFired):
+        (WebKit::NetworkResourceLoadScheduler::scheduleNetworkRequest):
+        (WebKit::NetworkResourceLoadScheduler::addLoadInProgress):
+        (WebKit::NetworkResourceLoadScheduler::hostForURL):
+        (WebKit::NetworkResourceLoadScheduler::removeLoadIdentifier):
+        (WebKit::NetworkResourceLoadScheduler::crossOriginRedirectReceived):
+        (WebKit::NetworkResourceLoadScheduler::servePendingRequests):
+        (WebKit::NetworkResourceLoadScheduler::servePendingRequestsForHost): Serve as many requests for the host as we should,
+          skipping the NetworkRequests who have lost their connection to their WebProcess.
+        (WebKit::NetworkResourceLoadScheduler::suspendPendingRequests):
+        (WebKit::NetworkResourceLoadScheduler::resumePendingRequests):
+        * NetworkProcess/NetworkResourceLoadScheduler.h: Added.
+        * NetworkProcess/mac/NetworkResourceLoadSchedulerMac.mm: Added.
+        (WebKit::NetworkResourceLoadScheduler::platformInitializeMaximumHTTPConnectionCountPerHost):
+
+        * NetworkProcess/NetworkProcess.h:
+        (WebKit::NetworkProcess::networkResourceLoadScheduler): Add a scheduler global to the NetworkProcess.
+
+        A thin derivation of WebCore::ResourceLoadScheduler, most of what WebResourceLoadScheduler does is handle IPC to the NetworkProcess:
+        * WebProcess/Network/WebResourceLoadScheduler.cpp:
+        (WebKit::WebResourceLoadScheduler::WebResourceLoadScheduler):
+        (WebKit::WebResourceLoadScheduler::scheduleSubresourceLoad):
+        (WebKit::WebResourceLoadScheduler::schedulePluginStreamLoad):
+        (WebKit::WebResourceLoadScheduler::scheduleLoad):
+        (WebKit::WebResourceLoadScheduler::addMainResourceLoad):
+        (WebKit::WebResourceLoadScheduler::remove):
+        (WebKit::WebResourceLoadScheduler::crossOriginRedirectReceived):
+        (WebKit::WebResourceLoadScheduler::servePendingRequests):
+        (WebKit::WebResourceLoadScheduler::suspendPendingRequests):
+        (WebKit::WebResourceLoadScheduler::resumePendingRequests):
+        (WebKit::WebResourceLoadScheduler::setSerialLoadingEnabled):
+        (WebKit::WebResourceLoadScheduler::startResourceLoad):
+        * WebProcess/Network/WebResourceLoadScheduler.h:
+
+        Add the ability for the NetworkProcess to message back to the WebProcess telling it to start a resource load:
+        * WebProcess/Network/NetworkProcessConnection.cpp:
+        (WebKit::NetworkProcessConnection::didReceiveMessage):
+        (WebKit::NetworkProcessConnection::didReceiveSyncMessage):
+        (WebKit::NetworkProcessConnection::startResourceLoad):
+        * WebProcess/Network/NetworkProcessConnection.h:
+        * WebProcess/Network/NetworkProcessConnection.messages.in:
+
+        * WebProcess/WebCoreSupport/WebPlatformStrategies.cpp:
+        (WebKit::WebPlatformStrategies::resourceLoadScheduler): Only return the WebResourceLoadScheduler if NetworkProcess is enabled.
+
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::ensureNetworkProcessConnection): Actually keep the NetworkProcessConnection around in a member variable.
+        (WebKit::WebProcess::networkConnection):
+        * WebProcess/WebProcess.h:
+        (WebKit::WebProcess::usesNetworkProcess): Expose this for platform strategies sake.
+
+2012-10-26  Brady Eidson  <beidson@apple.com>
+
         Crash in WebProces at WebCore::ResourceLoadScheduler::crossOriginRedirectReceived + 78
         https://bugs.webkit.org/show_bug.cgi?id=100554
 
index 3597696..af65eca 100644 (file)
@@ -36,6 +36,7 @@ VPATH = \
     $(WebKit2)/WebProcess/IconDatabase \
     $(WebKit2)/WebProcess/KeyValueStorage \
     $(WebKit2)/WebProcess/MediaCache \
+    $(WebKit2)/WebProcess/Network \
     $(WebKit2)/WebProcess/Notifications \
     $(WebKit2)/WebProcess/Plugins \
     $(WebKit2)/WebProcess/ResourceCache \
@@ -57,6 +58,7 @@ MESSAGE_RECEIVERS = \
     DownloadProxy \
     EventDispatcher \
     NetworkProcess \
+    NetworkProcessConnection \
     NetworkProcessProxy \
     NPObjectMessageReceiver \
     PluginControllerProxy \
diff --git a/Source/WebKit2/NetworkProcess/HostRecord.cpp b/Source/WebKit2/NetworkProcess/HostRecord.cpp
new file mode 100644 (file)
index 0000000..01b4a69
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "HostRecord.h"
+
+#include "Logging.h"
+#include "NetworkConnectionToWebProcess.h"
+#include "NetworkProcess.h"
+#include "NetworkRequest.h"
+#include "NetworkResourceLoadScheduler.h"
+
+using namespace WebCore;
+
+namespace WebKit {
+
+HostRecord::HostRecord(const String& name, int maxRequestsInFlight)
+    : m_name(name)
+    , m_maxRequestsInFlight(maxRequestsInFlight)
+{
+}
+
+HostRecord::~HostRecord()
+{
+#ifndef NDEBUG
+    ASSERT(m_requestsLoading.isEmpty());
+    for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++)
+        ASSERT(m_requestsPending[p].isEmpty());
+#endif
+}
+
+void HostRecord::schedule(PassRefPtr<NetworkRequest> record,  ResourceLoadPriority priority)
+{
+    m_requestsPending[priority].append(record);
+}
+
+void HostRecord::addLoadInProgress(ResourceLoadIdentifier identifier)
+{
+    m_requestsLoading.add(identifier);
+}
+
+void HostRecord::remove(ResourceLoadIdentifier identifier)
+{
+    if (m_requestsLoading.contains(identifier)) {
+        m_requestsLoading.remove(identifier);
+        return;
+    }
+    
+    for (int priority = ResourceLoadPriorityHighest; priority >= ResourceLoadPriorityLowest; --priority) {  
+        RequestQueue::iterator end = m_requestsPending[priority].end();
+        for (RequestQueue::iterator it = m_requestsPending[priority].begin(); it != end; ++it) {
+            if (it->get()->identifier() == identifier) {
+                m_requestsPending[priority].remove(it);
+                return;
+            }
+        }
+    }
+}
+
+bool HostRecord::hasRequests() const
+{
+    if (!m_requestsLoading.isEmpty())
+        return true;
+
+    for (unsigned p = 0; p <= ResourceLoadPriorityHighest; p++) {
+        if (!m_requestsPending[p].isEmpty())
+            return true;
+    }
+
+    return false;
+}
+
+bool HostRecord::limitRequests(ResourceLoadPriority priority, bool serialLoadingEnabled) const
+{
+    if (priority == ResourceLoadPriorityVeryLow && !m_requestsLoading.isEmpty())
+        return true;
+
+    return m_requestsLoading.size() >= (serialLoadingEnabled ? 1 : m_maxRequestsInFlight);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/NetworkProcess/HostRecord.h b/Source/WebKit2/NetworkProcess/HostRecord.h
new file mode 100644 (file)
index 0000000..1a8b054
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HostRecord_h
+#define HostRecord_h
+
+#include <WebCore/ResourceRequest.h>
+#include <wtf/Deque.h>
+#include <wtf/HashSet.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+class NetworkRequest;
+typedef uint64_t ResourceLoadIdentifier;
+
+class HostRecord {
+    WTF_MAKE_NONCOPYABLE(HostRecord); WTF_MAKE_FAST_ALLOCATED;
+public:
+    HostRecord(const String& name, int maxRequestsInFlight);
+    ~HostRecord();
+    
+    const String& name() const { return m_name; }
+    void schedule(PassRefPtr<NetworkRequest>,  WebCore::ResourceLoadPriority = WebCore::ResourceLoadPriorityVeryLow);
+    void addLoadInProgress(ResourceLoadIdentifier);
+    void remove(ResourceLoadIdentifier);
+    bool hasRequests() const;
+    bool limitRequests(WebCore::ResourceLoadPriority, bool serialLoadingEnabled) const;
+
+    typedef Deque<RefPtr<NetworkRequest> > RequestQueue;
+    RequestQueue& requestsPending(WebCore::ResourceLoadPriority priority) { return m_requestsPending[priority]; }
+
+private:                    
+    RequestQueue m_requestsPending[WebCore::ResourceLoadPriorityHighest + 1];
+    typedef HashSet<ResourceLoadIdentifier> RequestIdentifierMap;
+    RequestIdentifierMap m_requestsLoading;
+
+    const String m_name;
+    int m_maxRequestsInFlight;
+};
+
+} // namespace WebKit
+
+#endif // #ifndef HostRecord_h
index 1fdce18..99d8092 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "ConnectionStack.h"
 #include "NetworkProcess.h"
+#include <WebCore/ResourceRequest.h>
 #include <WebCore/RunLoop.h>
 
 #if ENABLE(NETWORK_PROCESS)
@@ -42,6 +43,7 @@ PassRefPtr<NetworkConnectionToWebProcess> NetworkConnectionToWebProcess::create(
 }
 
 NetworkConnectionToWebProcess::NetworkConnectionToWebProcess(CoreIPC::Connection::Identifier connectionIdentifier)
+    : m_serialLoadingEnabled(false)
 {
     m_connection = CoreIPC::Connection::createServerConnection(connectionIdentifier, this, RunLoop::main());
     m_connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true);
@@ -51,22 +53,36 @@ NetworkConnectionToWebProcess::NetworkConnectionToWebProcess(CoreIPC::Connection
 NetworkConnectionToWebProcess::~NetworkConnectionToWebProcess()
 {
     ASSERT(!m_connection);
+    ASSERT(m_observers.isEmpty());
 }
 
-void NetworkConnectionToWebProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder)
+void NetworkConnectionToWebProcess::registerObserver(NetworkConnectionToWebProcessObserver* observer)
 {
-    ConnectionStack::CurrentConnectionPusher currentConnection(ConnectionStack::shared(), connection);
+    ASSERT(!m_observers.contains(observer));
+    m_observers.add(observer);
+}
 
+void NetworkConnectionToWebProcess::unregisterObserver(NetworkConnectionToWebProcessObserver* observer)
+{
+    ASSERT(m_observers.contains(observer));
+    m_observers.remove(observer);
+}
+    
+void NetworkConnectionToWebProcess::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder)
+{
     if (messageID.is<CoreIPC::MessageClassNetworkConnectionToWebProcess>()) {
         didReceiveNetworkConnectionToWebProcessMessage(connection, messageID, decoder);
         return;
     }
-
     ASSERT_NOT_REACHED();
 }
 
-void NetworkConnectionToWebProcess::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& arguments, OwnPtr<CoreIPC::MessageEncoder>& reply)
+void NetworkConnectionToWebProcess::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder, OwnPtr<CoreIPC::MessageEncoder>& reply)
 {
+    if (messageID.is<CoreIPC::MessageClassNetworkConnectionToWebProcess>()) {
+        didReceiveSyncNetworkConnectionToWebProcessMessage(connection, messageID, decoder, reply);
+        return;
+    }
     ASSERT_NOT_REACHED();
 }
 
@@ -77,6 +93,14 @@ void NetworkConnectionToWebProcess::didClose(CoreIPC::Connection*)
     
     NetworkProcess::shared().removeNetworkConnectionToWebProcess(this);
     
+    Vector<NetworkConnectionToWebProcessObserver*> observers;
+    copyToVector(m_observers, observers);
+    for (size_t i = 0; i < observers.size(); ++i)
+        observers[i]->connectionToWebProcessDidClose(this);
+    
+    // FIXME (NetworkProcess): We might consider actively clearing out all requests for this connection.
+    // But that might not be necessary as the observer mechanism used above is much more direct.
+    
     m_connection = 0;
 }
 
@@ -84,9 +108,44 @@ void NetworkConnectionToWebProcess::didReceiveInvalidMessage(CoreIPC::Connection
 {
 }
 
-void NetworkConnectionToWebProcess::didReceiveNetworkConnectionToWebProcessMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&)
+void NetworkConnectionToWebProcess::scheduleNetworkRequest(const ResourceRequest& request, uint32_t resourceLoadPriority, ResourceLoadIdentifier& resourceLoadIdentifier)
+{
+    resourceLoadIdentifier = NetworkProcess::shared().networkResourceLoadScheduler().scheduleNetworkRequest(request, static_cast<ResourceLoadPriority>(resourceLoadPriority), this);
+}
+
+void NetworkConnectionToWebProcess::addLoadInProgress(const WebCore::KURL& url, ResourceLoadIdentifier& identifier)
+{
+    identifier = NetworkProcess::shared().networkResourceLoadScheduler().addLoadInProgress(url);
+}
+
+void NetworkConnectionToWebProcess::removeLoadIdentifier(ResourceLoadIdentifier identifier)
+{
+    NetworkProcess::shared().networkResourceLoadScheduler().removeLoadIdentifier(identifier);
+}
+
+void NetworkConnectionToWebProcess::crossOriginRedirectReceived(ResourceLoadIdentifier identifier, const KURL& redirectURL)
+{
+    NetworkProcess::shared().networkResourceLoadScheduler().crossOriginRedirectReceived(identifier, redirectURL);
+}
+
+void NetworkConnectionToWebProcess::servePendingRequests(uint32_t resourceLoadPriority)
+{
+    NetworkProcess::shared().networkResourceLoadScheduler().servePendingRequests(static_cast<ResourceLoadPriority>(resourceLoadPriority));
+}
+
+void NetworkConnectionToWebProcess::suspendPendingRequests()
+{
+    NetworkProcess::shared().networkResourceLoadScheduler().suspendPendingRequests();
+}
+
+void NetworkConnectionToWebProcess::resumePendingRequests()
+{
+    NetworkProcess::shared().networkResourceLoadScheduler().resumePendingRequests();
+}
+
+void NetworkConnectionToWebProcess::setSerialLoadingEnabled(bool enabled)
 {
-    // Empty for now - There are no messages to handle.
+    m_serialLoadingEnabled = enabled;
 }
 
 } // namespace WebKit
index 6351360..7f7afd4 100644 (file)
 
 #include "Connection.h"
 #include "NetworkConnectionToWebProcessMessages.h"
+#include <WebCore/ResourceLoadPriority.h>
 #include <wtf/HashSet.h>
 #include <wtf/RefCounted.h>
 
+namespace WebCore {
+class ResourceRequest;
+}
+
 namespace WebKit {
 
+class NetworkConnectionToWebProcess;
+typedef uint64_t ResourceLoadIdentifier;
+
+class NetworkConnectionToWebProcessObserver {
+public:
+    virtual ~NetworkConnectionToWebProcessObserver() { }
+    virtual void connectionToWebProcessDidClose(NetworkConnectionToWebProcess*) = 0;
+};
+
 class NetworkConnectionToWebProcess : public RefCounted<NetworkConnectionToWebProcess>, CoreIPC::Connection::Client {
 public:
     static PassRefPtr<NetworkConnectionToWebProcess> create(CoreIPC::Connection::Identifier);
     virtual ~NetworkConnectionToWebProcess();
 
     CoreIPC::Connection* connection() const { return m_connection.get(); }
+    
+    void registerObserver(NetworkConnectionToWebProcessObserver*);
+    void unregisterObserver(NetworkConnectionToWebProcessObserver*);
+
+    bool isSerialLoadingEnabled() const { return m_serialLoadingEnabled; }
 
 private:
     NetworkConnectionToWebProcess(CoreIPC::Connection::Identifier);
@@ -53,8 +72,22 @@ private:
 
     // Message handlers.
     void didReceiveNetworkConnectionToWebProcessMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&);
-
+    void didReceiveSyncNetworkConnectionToWebProcessMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&);
+    
+    void scheduleNetworkRequest(const WebCore::ResourceRequest&, uint32_t resourceLoadPriority, ResourceLoadIdentifier&);
+    void addLoadInProgress(const WebCore::KURL&, ResourceLoadIdentifier&);
+    void removeLoadIdentifier(ResourceLoadIdentifier);
+    void crossOriginRedirectReceived(ResourceLoadIdentifier, const WebCore::KURL& redirectURL);
+    void servePendingRequests(uint32_t resourceLoadPriority);
+    void suspendPendingRequests();
+    void resumePendingRequests();
+    void setSerialLoadingEnabled(bool);
+    
     RefPtr<CoreIPC::Connection> m_connection;
+    
+    HashSet<NetworkConnectionToWebProcessObserver*> m_observers;
+    
+    bool m_serialLoadingEnabled;
 };
 
 } // namespace WebKit
index a1047c8..df785a1 100644 (file)
 
 messages -> NetworkConnectionToWebProcess {
 
+    // FIXME (NetworkProcess): At least some of these synchronous messages are synchronous due to the requirement
+    // that we synchronously get an identifier for new ResourceLoaders as they are created.
+    // There's possible ResourceLoader identifier refactoring that can remove that requirement.
+    // We might also have the NetworkProcess divvy up identifiers in blocks to each WebProcess beforehand.
+    ScheduleNetworkRequest(WebCore::ResourceRequest request, uint32_t resourceLoadPriority) -> (uint64_t resourceLoadIdentifier)
+    AddLoadInProgress(WebCore::KURL url) -> (uint64_t resourceLoadIdentifier)
+    RemoveLoadIdentifier(uint64_t resourceLoadIdentifier)
+
+    // It's possible that we will be able to do away with this message and have the NetworkProcess
+    // manage it internally.
+    crossOriginRedirectReceived(uint64_t resourceLoadIdentifier, WebCore::KURL redirectURL) -> ()
+    
+    ServePendingRequests(uint32_t resourceLoadPriority)
+
+    SuspendPendingRequests() -> ()
+    ResumePendingRequests() -> ()
+    
+    SetSerialLoadingEnabled(bool enabled) -> ()
 }
 
 #endif // ENABLE(NETWORK_PROCESS)
index 5828e1f..000efc2 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(NETWORK_PROCESS)
 
 #include "ChildProcess.h"
+#include "NetworkResourceLoadScheduler.h"
 #include <wtf/Forward.h>
 
 namespace WebCore {
@@ -49,6 +50,8 @@ public:
 
     void removeNetworkConnectionToWebProcess(NetworkConnectionToWebProcess*);
 
+    NetworkResourceLoadScheduler& networkResourceLoadScheduler() { return m_networkResourceLoadScheduler; }
+
 private:
     NetworkProcess();
     ~NetworkProcess();
@@ -75,6 +78,7 @@ private:
     // Connections to WebProcesses.
     Vector<RefPtr<NetworkConnectionToWebProcess> > m_webProcessConnections;
 
+    NetworkResourceLoadScheduler m_networkResourceLoadScheduler;
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit2/NetworkProcess/NetworkRequest.cpp b/Source/WebKit2/NetworkProcess/NetworkRequest.cpp
new file mode 100644 (file)
index 0000000..ac1eebb
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "NetworkRequest.h"
+
+#include "NetworkConnectionToWebProcess.h"
+
+namespace WebKit {
+
+NetworkRequest::NetworkRequest(const WebCore::ResourceRequest& request, ResourceLoadIdentifier identifier, NetworkConnectionToWebProcess* connection)
+    : m_request(request)
+    , m_identifier(identifier)
+    , m_connection(connection)
+{
+    connection->registerObserver(this);
+}
+
+NetworkRequest::~NetworkRequest()
+{
+    if (m_connection)
+        m_connection->unregisterObserver(this);
+}
+
+void NetworkRequest::connectionToWebProcessDidClose(NetworkConnectionToWebProcess* connection)
+{
+    ASSERT_ARG(connection, connection == m_connection.get());
+    m_connection->unregisterObserver(this);
+    m_connection = 0;
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/NetworkProcess/NetworkRequest.h b/Source/WebKit2/NetworkProcess/NetworkRequest.h
new file mode 100644 (file)
index 0000000..c0d5167
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NetworkRequest_h
+#define NetworkRequest_h
+
+#include "NetworkConnectionToWebProcess.h"
+#include <WebCore/ResourceRequest.h>
+
+namespace WebKit {
+
+typedef uint64_t ResourceLoadIdentifier;
+
+class NetworkRequest : public RefCounted<NetworkRequest>, public NetworkConnectionToWebProcessObserver {
+public:
+    static RefPtr<NetworkRequest> create(const WebCore::ResourceRequest& request, ResourceLoadIdentifier identifier, NetworkConnectionToWebProcess* connection)
+    {
+        return adoptRef(new NetworkRequest(request, identifier, connection));
+    }
+    
+    ~NetworkRequest();
+
+    void connectionToWebProcessDidClose(NetworkConnectionToWebProcess*);
+    
+    ResourceLoadIdentifier identifier() { return m_identifier; }
+    
+    NetworkConnectionToWebProcess* connectionToWebProcess() { return m_connection.get(); }
+
+private:
+    NetworkRequest(const WebCore::ResourceRequest&, ResourceLoadIdentifier, NetworkConnectionToWebProcess*);
+
+    WebCore::ResourceRequest m_request;
+    ResourceLoadIdentifier m_identifier;
+
+    RefPtr<NetworkConnectionToWebProcess> m_connection;
+};
+
+} // namespace WebKit
+
+#endif // NetworkRequest_h
diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.cpp b/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.cpp
new file mode 100644 (file)
index 0000000..ccc3d76
--- /dev/null
@@ -0,0 +1,205 @@
+#include "config.h"
+#include "NetworkResourceLoadScheduler.h"
+
+#include "HostRecord.h"
+#include "Logging.h"
+#include "NetworkConnectionToWebProcess.h"
+#include "NetworkProcessconnectionMessages.h"
+#include "NetworkRequest.h"
+#include <wtf/text/CString.h>
+
+#if ENABLE(NETWORK_PROCESS)
+
+using namespace WebCore;
+
+namespace WebKit {
+
+static const unsigned maxRequestsInFlightForNonHTTPProtocols = 20;
+static unsigned maxRequestsInFlightPerHost;
+static ResourceLoadIdentifier s_currentResourceLoadIdentifier;
+
+NetworkResourceLoadScheduler::NetworkResourceLoadScheduler()
+    : m_nonHTTPProtocolHost(new HostRecord(String(), maxRequestsInFlightForNonHTTPProtocols))
+    , m_requestTimer(this, &NetworkResourceLoadScheduler::requestTimerFired)
+
+{
+    maxRequestsInFlightPerHost = platformInitializeMaximumHTTPConnectionCountPerHost();
+}
+
+void NetworkResourceLoadScheduler::scheduleServePendingRequests()
+{
+    if (!m_requestTimer.isActive())
+        m_requestTimer.startOneShot(0);
+}
+
+void NetworkResourceLoadScheduler::requestTimerFired(WebCore::Timer<NetworkResourceLoadScheduler>*)
+{
+    servePendingRequests();
+}
+
+ResourceLoadIdentifier NetworkResourceLoadScheduler::scheduleNetworkRequest(const ResourceRequest& request, ResourceLoadPriority priority, NetworkConnectionToWebProcess* connection)
+{    
+    ResourceLoadIdentifier identifier = ++s_currentResourceLoadIdentifier;
+
+    LOG(Network, "(NetworkProcess) NetworkResourceLoadScheduler::scheduleNetworkRequest resource %llu '%s'", identifier, request.url().string().utf8().data());
+
+    HostRecord* host = hostForURL(request.url(), CreateIfNotFound);
+    bool hadRequests = host->hasRequests();
+    host->schedule(NetworkRequest::create(request, identifier, connection), priority);
+    m_identifiers.add(identifier, host);
+
+    if (priority > ResourceLoadPriorityLow || !request.url().protocolIsInHTTPFamily() || (priority == ResourceLoadPriorityLow && !hadRequests)) {
+        // Try to request important resources immediately.
+        servePendingRequestsForHost(host, priority);
+        return identifier;
+    }
+    
+    // Handle asynchronously so early low priority requests don't get scheduled before later high priority ones.
+    scheduleServePendingRequests();
+    return identifier;
+}
+
+ResourceLoadIdentifier NetworkResourceLoadScheduler::addLoadInProgress(const WebCore::KURL& url)
+{
+    ResourceLoadIdentifier identifier = ++s_currentResourceLoadIdentifier;
+
+    LOG(Network, "(NetworkProcess) NetworkResourceLoadScheduler::addLoadInProgress resource %llu with url '%s'", identifier, url.string().utf8().data());
+
+    HostRecord* host = hostForURL(url, CreateIfNotFound);
+    host->addLoadInProgress(identifier);
+    m_identifiers.add(identifier, host);
+    
+    return identifier;
+}
+
+HostRecord* NetworkResourceLoadScheduler::hostForURL(const WebCore::KURL& url, CreateHostPolicy createHostPolicy)
+{
+    if (!url.protocolIsInHTTPFamily())
+        return m_nonHTTPProtocolHost;
+
+    m_hosts.checkConsistency();
+    String hostName = url.host();
+    HostRecord* host = m_hosts.get(hostName);
+    if (!host && createHostPolicy == CreateIfNotFound) {
+        host = new HostRecord(hostName, maxRequestsInFlightPerHost);
+        m_hosts.add(hostName, host);
+    }
+    
+    return host;
+}
+
+void NetworkResourceLoadScheduler::removeLoadIdentifier(ResourceLoadIdentifier identifier)
+{
+    ASSERT(identifier);
+
+    LOG(Network, "(NetworkProcess) NetworkResourceLoadScheduler::removeLoadIdentifier removing load identifier %llu", identifier);
+
+    HostRecord* host = m_identifiers.take(identifier);
+    ASSERT(host);
+    if (host)
+        host->remove(identifier);
+
+    scheduleServePendingRequests();
+}
+
+void NetworkResourceLoadScheduler::crossOriginRedirectReceived(ResourceLoadIdentifier identifier, const WebCore::KURL& redirectURL)
+{
+    LOG(Network, "(NetworkProcess) NetworkResourceLoadScheduler::crossOriginRedirectReceived resource %llu redirected to '%s'", identifier, redirectURL.string().utf8().data());
+
+    HostRecord* oldHost = m_identifiers.get(identifier);
+    HostRecord* newHost = hostForURL(redirectURL, CreateIfNotFound);
+    ASSERT(oldHost);
+    
+    if (oldHost->name() == newHost->name())
+        return;
+    
+    newHost->addLoadInProgress(identifier);
+    m_identifiers.set(identifier, newHost);
+
+    oldHost->remove(identifier);    
+}
+
+void NetworkResourceLoadScheduler::servePendingRequests(ResourceLoadPriority minimumPriority)
+{
+    if (m_suspendPendingRequestsCount)
+        return;
+
+    LOG(Network, "(NetworkProcess) NetworkResourceLoadScheduler::servePendingRequests Serving requests for up to %i hosts", m_hosts.size());
+
+    m_requestTimer.stop();
+    
+    servePendingRequestsForHost(m_nonHTTPProtocolHost, minimumPriority);
+
+    m_hosts.checkConsistency();
+    Vector<HostRecord*> hostsToServe;
+    copyValuesToVector(m_hosts, hostsToServe);
+
+    size_t size = hostsToServe.size();
+    for (size_t i = 0; i < size; ++i) {
+        HostRecord* host = hostsToServe[i];
+        if (host->hasRequests())
+            servePendingRequestsForHost(host, minimumPriority);
+        else
+            delete m_hosts.take(host->name());
+    }
+}
+
+void NetworkResourceLoadScheduler::servePendingRequestsForHost(HostRecord* host, ResourceLoadPriority minimumPriority)
+{
+    LOG(Network, "NetworkResourceLoadScheduler::servePendingRequests Host name='%s'", host->name().utf8().data());
+
+    for (int priority = ResourceLoadPriorityHighest; priority >= minimumPriority; --priority) {
+        HostRecord::RequestQueue& requestsPending = host->requestsPending(ResourceLoadPriority(priority));
+
+        while (!requestsPending.isEmpty()) {
+            RefPtr<NetworkRequest> request = requestsPending.first();
+            
+            // This request might be from WebProcess we've lost our connection to.
+            // If so we should just skip it.
+            if (!request->connectionToWebProcess()) {
+                requestsPending.removeFirst();
+                continue;
+            }
+
+            // For named hosts - which are only http(s) hosts - we should always enforce the connection limit.
+            // For non-named hosts - everything but http(s) - we should only enforce the limit if the document
+            // isn't done parsing and we don't know all stylesheets yet.
+
+            // FIXME (NetworkProcess): The above comment about document parsing and stylesheets is a holdover
+            // from the WebCore::ResourceLoadScheduler.
+            // The behavior described was at one time important for WebCore's single threadedness.
+            // It's possible that we don't care about it with the NetworkProcess.
+            // We should either decide it's not important and change the above comment, or decide it is
+            // still important and somehow account for it.
+
+            bool shouldLimitRequests = !host->name().isNull();
+            if (shouldLimitRequests && host->limitRequests(ResourceLoadPriority(priority), request->connectionToWebProcess()->isSerialLoadingEnabled()))
+                return;
+
+            requestsPending.removeFirst();
+            host->addLoadInProgress(request->identifier());
+            
+            request->connectionToWebProcess()->connection()->send(Messages::NetworkProcessConnection::StartResourceLoad(request->identifier()), 0);
+        }
+    }
+}
+
+void NetworkResourceLoadScheduler::suspendPendingRequests()
+{
+    ++m_suspendPendingRequestsCount;
+}
+
+void NetworkResourceLoadScheduler::resumePendingRequests()
+{
+    ASSERT(m_suspendPendingRequestsCount);
+    --m_suspendPendingRequestsCount;
+    if (m_suspendPendingRequestsCount)
+        return;
+
+    if (!m_hosts.isEmpty() || m_nonHTTPProtocolHost->hasRequests())
+        scheduleServePendingRequests();
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(NETWORK_PROCESS)
diff --git a/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.h b/Source/WebKit2/NetworkProcess/NetworkResourceLoadScheduler.h
new file mode 100644 (file)
index 0000000..a16a388
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NetworkResourceLoadScheduler_h
+#define NetworkResourceLoadScheduler_h
+
+#include <WebCore/ResourceRequest.h>
+#include <WebCore/Timer.h>
+
+#if ENABLE(NETWORK_PROCESS)
+
+namespace WebKit {
+
+class HostRecord;
+class NetworkConnectionToWebProcess;
+typedef uint64_t ResourceLoadIdentifier;
+
+class NetworkResourceLoadScheduler {
+    WTF_MAKE_NONCOPYABLE(NetworkResourceLoadScheduler); WTF_MAKE_FAST_ALLOCATED;
+
+public:
+    NetworkResourceLoadScheduler();
+    
+    // Adds the request to the queue for its host and create a unique identifier for it.
+    ResourceLoadIdentifier scheduleNetworkRequest(const WebCore::ResourceRequest&, WebCore::ResourceLoadPriority, NetworkConnectionToWebProcess*);
+    
+    // Creates a unique identifier for an already-in-progress load.
+    ResourceLoadIdentifier addLoadInProgress(const WebCore::KURL&);
+
+    // Called by the WebProcess when a ResourceLoader is being cleaned up.
+    void removeLoadIdentifier(ResourceLoadIdentifier);
+
+    void crossOriginRedirectReceived(ResourceLoadIdentifier, const WebCore::KURL& redirectURL);
+    void servePendingRequests(WebCore::ResourceLoadPriority = WebCore::ResourceLoadPriorityVeryLow);
+    void suspendPendingRequests();
+    void resumePendingRequests();
+    
+private:
+    enum CreateHostPolicy {
+        CreateIfNotFound,
+        FindOnly
+    };
+    
+    HostRecord* hostForURL(const WebCore::KURL&, CreateHostPolicy = FindOnly);
+    
+    void scheduleServePendingRequests();
+    void requestTimerFired(WebCore::Timer<NetworkResourceLoadScheduler>*);
+
+    void servePendingRequestsForHost(HostRecord*, WebCore::ResourceLoadPriority);
+
+    unsigned platformInitializeMaximumHTTPConnectionCountPerHost();
+
+    typedef HashMap<String, HostRecord*, StringHash> HostMap;
+    HostMap m_hosts;
+
+    typedef HashMap<ResourceLoadIdentifier, HostRecord*> IdentifierHostMap;
+    IdentifierHostMap m_identifiers;
+
+    HostRecord* m_nonHTTPProtocolHost;
+
+    unsigned m_suspendPendingRequestsCount;
+    bool m_isSerialLoadingEnabled;
+
+    WebCore::Timer<NetworkResourceLoadScheduler> m_requestTimer;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(NETWORK_PROCESS)
+
+#endif // NetworkResourceLoadScheduler_h
diff --git a/Source/WebKit2/NetworkProcess/mac/NetworkResourceLoadSchedulerMac.mm b/Source/WebKit2/NetworkProcess/mac/NetworkResourceLoadSchedulerMac.mm
new file mode 100644 (file)
index 0000000..a73d1a2
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "NetworkResourceLoadScheduler.h"
+
+#import <WebCore/ResourceRequest.h>
+#import <WebCore/ResourceRequestCFNet.h>
+#import <WebCore/WebCoreSystemInterface.h>
+#import <WebKitSystemInterface.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+unsigned NetworkResourceLoadScheduler::platformInitializeMaximumHTTPConnectionCountPerHost()
+{
+    wkInitializeMaximumHTTPConnectionCountPerHost = WKInitializeMaximumHTTPConnectionCountPerHost;
+    wkSetHTTPPipeliningMaximumPriority = WKSetHTTPPipeliningMaximumPriority;
+    wkSetHTTPPipeliningMinimumFastLanePriority = WKSetHTTPPipeliningMinimumFastLanePriority;
+
+    static const unsigned preferredConnectionCount = 6;
+    static const unsigned unlimitedConnectionCount = 10000;
+
+    // Always set the connection count per host, even when pipelining.
+    unsigned maximumHTTPConnectionCountPerHost = wkInitializeMaximumHTTPConnectionCountPerHost(preferredConnectionCount);
+
+    Boolean keyExistsAndHasValidFormat = false;
+    Boolean prefValue = CFPreferencesGetAppBooleanValue(CFSTR("WebKitEnableHTTPPipelining"), kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat);
+    
+    if (keyExistsAndHasValidFormat)
+        ResourceRequest::setHTTPPipeliningEnabled(prefValue);
+
+    if (ResourceRequest::httpPipeliningEnabled()) {
+        wkSetHTTPPipeliningMaximumPriority(toHTTPPipeliningPriority(ResourceLoadPriorityHighest));
+        wkSetHTTPPipeliningMinimumFastLanePriority(toHTTPPipeliningPriority(ResourceLoadPriorityMedium));
+
+        // When pipelining do not rate-limit requests sent from WebCore since CFNetwork handles that.
+        return unlimitedConnectionCount;
+    }
+
+    return maximumHTTPConnectionCountPerHost;
+}
+
+} // namespace WebKit
index a89e64f..dd3fcb0 100644 (file)
@@ -115,6 +115,9 @@ enum MessageClass {
     // Messages sent by the web process to the network process.
     MessageClassNetworkConnectionToWebProcess,
 
+    // Messages sent by the network process to a web process.
+    MessageClassNetworkProcessConnection,
+    
 #if ENABLE(SHARED_WORKER_PROCESS)
     // Messages sent by the UI process to the shared worker process.
     MessageClassSharedWorkerProcess,
index df98e72..6cd04b9 100644 (file)
@@ -38,6 +38,7 @@ WTFLogChannel LogView         = { 0x00000008, "WebKit2LogLevel", WTFLogChannelOf
 WTFLogChannel LogIconDatabase = { 0x00000010, "WebKit2LogLevel", WTFLogChannelOff };
 WTFLogChannel LogKeyHandling  = { 0x00000020, "WebKit2LogLevel", WTFLogChannelOff };
 WTFLogChannel LogPlugins      = { 0x00000040, "WebKit2LogLevel", WTFLogChannelOff };
+WTFLogChannel LogNetwork      = { 0x00000080, "WebKit2LogLevel", WTFLogChannelOff };
 
 #if !PLATFORM(MAC) && !PLATFORM(GTK) && !PLATFORM(QT) && !PLATFORM(EFL)
 void initializeLogChannel(WTFLogChannel* channel)
@@ -73,6 +74,9 @@ WTFLogChannel* getChannelFromName(const String& channelName)
     if (equalIgnoringCase(channelName, String("Plugins")))
         return &LogPlugins;
 
+    if (equalIgnoringCase(channelName, String("Network")))
+        return &LogNetwork;
+
     return 0;
 }
 #endif
index 603686f..ca998c2 100644 (file)
@@ -44,6 +44,7 @@ extern WTFLogChannel LogPlugins;
 extern WTFLogChannel LogSessionState;
 extern WTFLogChannel LogTextInput;
 extern WTFLogChannel LogView;
+extern WTFLogChannel LogNetwork;
 
 void initializeLogChannel(WTFLogChannel*);
 void initializeLogChannelsIfNecessary(void);
index d69da3f..5bfdc72 100644 (file)
                512935D81288D19400A4B695 /* WebContextMenuItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 512935D61288D19400A4B695 /* WebContextMenuItem.h */; };
                512935E31288D97800A4B695 /* InjectedBundlePageContextMenuClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 512935E11288D97800A4B695 /* InjectedBundlePageContextMenuClient.cpp */; };
                512935E41288D97800A4B695 /* InjectedBundlePageContextMenuClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 512935E21288D97800A4B695 /* InjectedBundlePageContextMenuClient.h */; };
+               512C06881638F67E00ABB911 /* HostRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 512C06861638F67E00ABB911 /* HostRecord.cpp */; };
+               512C06891638F67E00ABB911 /* HostRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 512C06871638F67E00ABB911 /* HostRecord.h */; };
+               512C069016390E6900ABB911 /* NetworkResourceLoadSchedulerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 512C068F16390E6900ABB911 /* NetworkResourceLoadSchedulerMac.mm */; };
                512DF6D8138C181A00A22FC6 /* KeychainItemShimMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 512DF6D6138C181A00A22FC6 /* KeychainItemShimMethods.h */; };
                512DF6D9138C181A00A22FC6 /* KeychainItemShimMethods.mm in Sources */ = {isa = PBXBuildFile; fileRef = 512DF6D7138C181A00A22FC6 /* KeychainItemShimMethods.mm */; };
                512DF6FE138C254600A22FC6 /* SecKeychainItemRequestData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5112CA4713858D4B0030867D /* SecKeychainItemRequestData.cpp */; };
                5179556E162877B300FA43B6 /* NetworkProcessProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 510CC7EB16138E7200D03ED3 /* NetworkProcessProxy.h */; };
                51795570162877CF00FA43B6 /* NetworkProcessCreationParameters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51A8A6121627F325000D90E9 /* NetworkProcessCreationParameters.cpp */; };
                51795571162877D200FA43B6 /* NetworkProcessCreationParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A8A60F1627F2BD000D90E9 /* NetworkProcessCreationParameters.h */; };
+               517CF0DF163A444C00C2950E /* NetworkRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517CF0DD163A444C00C2950E /* NetworkRequest.cpp */; };
+               517CF0E0163A444C00C2950E /* NetworkRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 517CF0DE163A444C00C2950E /* NetworkRequest.h */; };
+               517CF0E3163A486C00C2950E /* NetworkProcessConnectionMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 517CF0E1163A486C00C2950E /* NetworkProcessConnectionMessageReceiver.cpp */; };
+               517CF0E4163A486C00C2950E /* NetworkProcessConnectionMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 517CF0E2163A486C00C2950E /* NetworkProcessConnectionMessages.h */; };
+               51829DA51637C70C000953D6 /* NetworkResourceLoadScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51829DA31637C70C000953D6 /* NetworkResourceLoadScheduler.cpp */; };
+               51829DA61637C70C000953D6 /* NetworkResourceLoadScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 51829DA41637C70C000953D6 /* NetworkResourceLoadScheduler.h */; };
                51834592134532E90092B696 /* WebIconDatabaseClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51834590134532E80092B696 /* WebIconDatabaseClient.cpp */; };
                51834593134532E90092B696 /* WebIconDatabaseClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 51834591134532E80092B696 /* WebIconDatabaseClient.h */; };
                5183B3921379F7B800E8754E /* WebProcessShim.dylib in Copy Web Process Shim */ = {isa = PBXBuildFile; fileRef = 510031F61379CACB00C8DFE4 /* WebProcessShim.dylib */; };
                51A9E1291315ED35009E7031 /* WebKeyValueStorageManagerMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A9E1251315ED35009E7031 /* WebKeyValueStorageManagerMessages.h */; };
                51A9E12A1315ED35009E7031 /* WebKeyValueStorageManagerProxyMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51A9E1261315ED35009E7031 /* WebKeyValueStorageManagerProxyMessageReceiver.cpp */; };
                51A9E12B1315ED35009E7031 /* WebKeyValueStorageManagerProxyMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A9E1271315ED35009E7031 /* WebKeyValueStorageManagerProxyMessages.h */; };
-               51ABF65A16392F2000132A7A /* WebResourceLoadScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51ABF65616392F1500132A7A /* WebResourceLoadScheduler.cpp */; };
                51ACBB82127A8BAD00D203B9 /* WebContextMenuProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 51ACBB81127A8BAD00D203B9 /* WebContextMenuProxy.h */; };
                51ACBBA0127A8F2C00D203B9 /* WebContextMenuProxyMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 51ACBB9E127A8F2C00D203B9 /* WebContextMenuProxyMac.h */; };
                51ACBBA1127A8F2C00D203B9 /* WebContextMenuProxyMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51ACBB9F127A8F2C00D203B9 /* WebContextMenuProxyMac.mm */; };
                51D130551382EAC000351EDD /* SecItemResponseData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51D130511382EAC000351EDD /* SecItemResponseData.cpp */; };
                51D130561382EAC000351EDD /* SecItemResponseData.h in Headers */ = {isa = PBXBuildFile; fileRef = 51D130521382EAC000351EDD /* SecItemResponseData.h */; };
                51D130581382F10500351EDD /* WebProcessProxyMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51D130571382F10500351EDD /* WebProcessProxyMac.mm */; };
+               51DD9F2816367DA2001578E9 /* NetworkConnectionToWebProcessMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51DD9F2616367DA2001578E9 /* NetworkConnectionToWebProcessMessageReceiver.cpp */; };
+               51DD9F2916367DA2001578E9 /* NetworkConnectionToWebProcessMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 51DD9F2716367DA2001578E9 /* NetworkConnectionToWebProcessMessages.h */; };
                51EFC1CF1524E62500C9A938 /* WKBundleDOMWindowExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 51FA2D541521118600C1BA0B /* WKBundleDOMWindowExtension.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51FA2D7415212DF100C1BA0B /* InjectedBundleDOMWindowExtension.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51FA2D5C15211A5000C1BA0B /* InjectedBundleDOMWindowExtension.cpp */; };
                51FA2D7715212E2600C1BA0B /* WKBundleDOMWindowExtension.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51FA2D7515212E1E00C1BA0B /* WKBundleDOMWindowExtension.cpp */; };
+               51FB08FF1639DE1A00EC324A /* WebResourceLoadScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51ABF65616392F1500132A7A /* WebResourceLoadScheduler.cpp */; };
                5272B28A1406985D0096A5D0 /* StatisticsData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5272B2881406985D0096A5D0 /* StatisticsData.cpp */; };
                5272B28B1406985D0096A5D0 /* StatisticsData.h in Headers */ = {isa = PBXBuildFile; fileRef = 5272B2891406985D0096A5D0 /* StatisticsData.h */; };
                5D1A239115E75B220023E981 /* webkit2 in Copy Message Generation Scripts */ = {isa = PBXBuildFile; fileRef = 5D1A238E15E75AD50023E981 /* webkit2 */; };
                512935D61288D19400A4B695 /* WebContextMenuItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebContextMenuItem.h; sourceTree = "<group>"; };
                512935E11288D97800A4B695 /* InjectedBundlePageContextMenuClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundlePageContextMenuClient.cpp; sourceTree = "<group>"; };
                512935E21288D97800A4B695 /* InjectedBundlePageContextMenuClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InjectedBundlePageContextMenuClient.h; sourceTree = "<group>"; };
+               512C06861638F67E00ABB911 /* HostRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HostRecord.cpp; path = NetworkProcess/HostRecord.cpp; sourceTree = "<group>"; };
+               512C06871638F67E00ABB911 /* HostRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostRecord.h; path = NetworkProcess/HostRecord.h; sourceTree = "<group>"; };
+               512C068F16390E6900ABB911 /* NetworkResourceLoadSchedulerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkResourceLoadSchedulerMac.mm; sourceTree = "<group>"; };
                512DF6D6138C181A00A22FC6 /* KeychainItemShimMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeychainItemShimMethods.h; sourceTree = "<group>"; };
                512DF6D7138C181A00A22FC6 /* KeychainItemShimMethods.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeychainItemShimMethods.mm; sourceTree = "<group>"; };
                512E3520130B550100ABD19A /* WebApplicationCacheManagerProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebApplicationCacheManagerProxy.cpp; sourceTree = "<group>"; };
                516A4A5B120A2CCD00C05B7F /* WebError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebError.h; sourceTree = "<group>"; };
                517A33B3130B308C00F80CB5 /* WKApplicationCacheManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKApplicationCacheManager.cpp; sourceTree = "<group>"; };
                517A33B4130B308C00F80CB5 /* WKApplicationCacheManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKApplicationCacheManager.h; sourceTree = "<group>"; };
+               517CF0DD163A444C00C2950E /* NetworkRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetworkRequest.cpp; path = NetworkProcess/NetworkRequest.cpp; sourceTree = "<group>"; };
+               517CF0DE163A444C00C2950E /* NetworkRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkRequest.h; path = NetworkProcess/NetworkRequest.h; sourceTree = "<group>"; };
+               517CF0E1163A486C00C2950E /* NetworkProcessConnectionMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkProcessConnectionMessageReceiver.cpp; sourceTree = "<group>"; };
+               517CF0E2163A486C00C2950E /* NetworkProcessConnectionMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkProcessConnectionMessages.h; sourceTree = "<group>"; };
+               51829DA31637C70C000953D6 /* NetworkResourceLoadScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetworkResourceLoadScheduler.cpp; path = NetworkProcess/NetworkResourceLoadScheduler.cpp; sourceTree = "<group>"; };
+               51829DA41637C70C000953D6 /* NetworkResourceLoadScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetworkResourceLoadScheduler.h; path = NetworkProcess/NetworkResourceLoadScheduler.h; sourceTree = "<group>"; };
                51834590134532E80092B696 /* WebIconDatabaseClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebIconDatabaseClient.cpp; sourceTree = "<group>"; };
                51834591134532E80092B696 /* WebIconDatabaseClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebIconDatabaseClient.h; sourceTree = "<group>"; };
                5183B3931379F85C00E8754E /* Shim.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shim.xcconfig; sourceTree = "<group>"; };
                51D130511382EAC000351EDD /* SecItemResponseData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecItemResponseData.cpp; sourceTree = "<group>"; };
                51D130521382EAC000351EDD /* SecItemResponseData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecItemResponseData.h; sourceTree = "<group>"; };
                51D130571382F10500351EDD /* WebProcessProxyMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebProcessProxyMac.mm; sourceTree = "<group>"; };
+               51DD9F2616367DA2001578E9 /* NetworkConnectionToWebProcessMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkConnectionToWebProcessMessageReceiver.cpp; sourceTree = "<group>"; };
+               51DD9F2716367DA2001578E9 /* NetworkConnectionToWebProcessMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkConnectionToWebProcessMessages.h; sourceTree = "<group>"; };
                51FA2D541521118600C1BA0B /* WKBundleDOMWindowExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBundleDOMWindowExtension.h; sourceTree = "<group>"; };
                51FA2D5A15211A1E00C1BA0B /* InjectedBundleDOMWindowExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InjectedBundleDOMWindowExtension.h; sourceTree = "<group>"; };
                51FA2D5C15211A5000C1BA0B /* InjectedBundleDOMWindowExtension.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundleDOMWindowExtension.cpp; sourceTree = "<group>"; };
                51FA2D7515212E1E00C1BA0B /* WKBundleDOMWindowExtension.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKBundleDOMWindowExtension.cpp; sourceTree = "<group>"; };
+               51FB0902163A3B1C00EC324A /* NetworkProcessConnection.messages.in */ = {isa = PBXFileReference; lastKnownFileType = text; name = NetworkProcessConnection.messages.in; path = Network/NetworkProcessConnection.messages.in; sourceTree = "<group>"; };
                5272B2881406985D0096A5D0 /* StatisticsData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StatisticsData.cpp; sourceTree = "<group>"; };
                5272B2891406985D0096A5D0 /* StatisticsData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StatisticsData.h; sourceTree = "<group>"; };
                5D1A238E15E75AD50023E981 /* webkit2 */ = {isa = PBXFileReference; lastKnownFileType = folder; path = webkit2; sourceTree = "<group>"; };
                        children = (
                                5105B0D4162F7A7A00E27709 /* NetworkProcessConnection.cpp */,
                                5105B0D5162F7A7A00E27709 /* NetworkProcessConnection.h */,
+                               51FB0902163A3B1C00EC324A /* NetworkProcessConnection.messages.in */,
                                51ABF65616392F1500132A7A /* WebResourceLoadScheduler.cpp */,
                                51ABF65716392F1500132A7A /* WebResourceLoadScheduler.h */,
                        );
                        isa = PBXGroup;
                        children = (
                                510CC7DC16138E2900D03ED3 /* mac */,
+                               512C06861638F67E00ABB911 /* HostRecord.cpp */,
+                               512C06871638F67E00ABB911 /* HostRecord.h */,
                                513A16491630A9BF005D7D22 /* NetworkConnectionToWebProcess.cpp */,
                                513A164A1630A9BF005D7D22 /* NetworkConnectionToWebProcess.h */,
                                513A164B1630A9BF005D7D22 /* NetworkConnectionToWebProcess.messages.in */,
                                510CC7E016138E2900D03ED3 /* NetworkProcess.h */,
                                51A8A6171627F5BB000D90E9 /* NetworkProcess.messages.in */,
                                510CC7E116138E2900D03ED3 /* NetworkProcessMain.h */,
+                               517CF0DD163A444C00C2950E /* NetworkRequest.cpp */,
+                               517CF0DE163A444C00C2950E /* NetworkRequest.h */,
+                               51829DA31637C70C000953D6 /* NetworkResourceLoadScheduler.cpp */,
+                               51829DA41637C70C000953D6 /* NetworkResourceLoadScheduler.h */,
                        );
                        name = NetworkProcess;
                        sourceTree = "<group>";
                        children = (
                                51A8A6151627F3F9000D90E9 /* NetworkProcessMac.mm */,
                                510CC7DD16138E2900D03ED3 /* NetworkProcessMainMac.mm */,
+                               512C068F16390E6900ABB911 /* NetworkResourceLoadSchedulerMac.mm */,
                        );
                        name = mac;
                        path = NetworkProcess/mac;
                                1A64230712DD09EB00CAAE2C /* DrawingAreaProxyMessages.h */,
                                1AA575FF1496B7C000A4EE06 /* EventDispatcherMessageReceiver.cpp */,
                                1AA576001496B7C000A4EE06 /* EventDispatcherMessages.h */,
+                               51DD9F2616367DA2001578E9 /* NetworkConnectionToWebProcessMessageReceiver.cpp */,
+                               51DD9F2716367DA2001578E9 /* NetworkConnectionToWebProcessMessages.h */,
+                               517CF0E1163A486C00C2950E /* NetworkProcessConnectionMessageReceiver.cpp */,
+                               517CF0E2163A486C00C2950E /* NetworkProcessConnectionMessages.h */,
                                51ACC9341628064800342550 /* NetworkProcessMessageReceiver.cpp */,
                                51ACC9351628064800342550 /* NetworkProcessMessages.h */,
                                513A163A163088F6005D7D22 /* NetworkProcessProxyMessageReceiver.cpp */,
                                513A163D163088F6005D7D22 /* NetworkProcessProxyMessages.h in Headers */,
                                513A164D1630A9BF005D7D22 /* NetworkConnectionToWebProcess.h in Headers */,
                                1A13BEB41635A9C800F19C03 /* StringReference.h in Headers */,
+                               51DD9F2916367DA2001578E9 /* NetworkConnectionToWebProcessMessages.h in Headers */,
+                               51829DA61637C70C000953D6 /* NetworkResourceLoadScheduler.h in Headers */,
+                               512C06891638F67E00ABB911 /* HostRecord.h in Headers */,
+                               517CF0E0163A444C00C2950E /* NetworkRequest.h in Headers */,
+                               517CF0E4163A486C00C2950E /* NetworkProcessConnectionMessages.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                513A164C1630A9BF005D7D22 /* NetworkConnectionToWebProcess.cpp in Sources */,
                                5183DDEC1630BDFC008BE5C7 /* NetworkProcessConnection.cpp in Sources */,
                                1A13BEB31635A9C800F19C03 /* StringReference.cpp in Sources */,
-                               51ABF65A16392F2000132A7A /* WebResourceLoadScheduler.cpp in Sources */,
+                               51DD9F2816367DA2001578E9 /* NetworkConnectionToWebProcessMessageReceiver.cpp in Sources */,
+                               51829DA51637C70C000953D6 /* NetworkResourceLoadScheduler.cpp in Sources */,
+                               512C06881638F67E00ABB911 /* HostRecord.cpp in Sources */,
+                               512C069016390E6900ABB911 /* NetworkResourceLoadSchedulerMac.mm in Sources */,
+                               51FB08FF1639DE1A00EC324A /* WebResourceLoadScheduler.cpp in Sources */,
+                               517CF0DF163A444C00C2950E /* NetworkRequest.cpp in Sources */,
+                               517CF0E3163A486C00C2950E /* NetworkProcessConnectionMessageReceiver.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index dd9d6cb..7ea4c9f 100644 (file)
@@ -42,12 +42,18 @@ NetworkProcessConnection::~NetworkProcessConnection()
 {
 }
 
-void NetworkProcessConnection::didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&)
+void NetworkProcessConnection::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::MessageDecoder& decoder)
 {
+    if (messageID.is<CoreIPC::MessageClassNetworkProcessConnection>()) {
+        didReceiveNetworkProcessConnectionMessage(connection, messageID, decoder);
+        return;
+    }
+    ASSERT_NOT_REACHED();
 }
 
 void NetworkProcessConnection::didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&, OwnPtr<CoreIPC::MessageEncoder>&)
 {
+    ASSERT_NOT_REACHED();
 }
 
 void NetworkProcessConnection::didClose(CoreIPC::Connection*)
@@ -60,6 +66,10 @@ void NetworkProcessConnection::didReceiveInvalidMessage(CoreIPC::Connection*, Co
 {
 }
 
+void NetworkProcessConnection::startResourceLoad(ResourceLoadIdentifier resourceLoadIdentifier)
+{
+    WebProcess::shared().webResourceLoadScheduler().startResourceLoad(resourceLoadIdentifier);
+}
     
 } // namespace WebKit
 
index 65e2598..09e2196 100644 (file)
@@ -34,6 +34,8 @@
 
 namespace WebKit {
 
+typedef uint64_t ResourceLoadIdentifier;
+
 class NetworkProcessConnection : public RefCounted<NetworkProcessConnection>, CoreIPC::Connection::Client {
 public:
     static PassRefPtr<NetworkProcessConnection> create(CoreIPC::Connection::Identifier connectionIdentifier)
@@ -53,6 +55,10 @@ private:
     virtual void didClose(CoreIPC::Connection*);
     virtual void didReceiveInvalidMessage(CoreIPC::Connection*, CoreIPC::MessageID);
 
+    void didReceiveNetworkProcessConnectionMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::MessageDecoder&);
+
+    void startResourceLoad(ResourceLoadIdentifier);
+
     // The connection from the web process to the network process.
     RefPtr<CoreIPC::Connection> m_connection;
 };
diff --git a/Source/WebKit2/WebProcess/Network/NetworkProcessConnection.messages.in b/Source/WebKit2/WebProcess/Network/NetworkProcessConnection.messages.in
new file mode 100644 (file)
index 0000000..69aeabb
--- /dev/null
@@ -0,0 +1,32 @@
+# Copyright (C) 2012 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#if ENABLE(NETWORK_PROCESS)
+
+messages -> NetworkProcessConnection {
+
+    // FIXME (NetworkProcess): This message is for the NetworkProcess to tell the WebProcess to start a load.
+    // Once the NetworkProcess is doing the loading itself then we should remove it.
+    StartResourceLoad(uint64_t resourceLoadIdentifier)
+}
+
+#endif // ENABLE(NETWORK_PROCESS)
index 0af6d45..00aceb2 100644 (file)
 #include "config.h"
 #include "WebResourceLoadScheduler.h"
 
+#include "Logging.h"
+#include "NetworkConnectionToWebProcessMessages.h"
+#include "NetworkProcessConnection.h"
+#include "WebCoreArgumentCoders.h"
+#include "WebProcess.h"
+#include <WebCore/DocumentLoader.h>
+#include <WebCore/Frame.h>
+#include <WebCore/FrameLoader.h>
+#include <WebCore/NetscapePlugInStreamLoader.h>
+#include <WebCore/ResourceLoader.h>
+#include <WebCore/SubresourceLoader.h>
+#include <wtf/text/CString.h>
+
 #if ENABLE(NETWORK_PROCESS)
 
 using namespace WebCore;
 
 namespace WebKit {
 
+WebResourceLoadScheduler::WebResourceLoadScheduler()
+    : m_suspendPendingRequestsCount(0)
+{
+}
+
 WebResourceLoadScheduler::~WebResourceLoadScheduler()
 {
 }
 
+PassRefPtr<SubresourceLoader> WebResourceLoadScheduler::scheduleSubresourceLoad(Frame* frame, CachedResource* resource, const ResourceRequest& request, ResourceLoadPriority priority, const ResourceLoaderOptions& options)
+{
+    RefPtr<SubresourceLoader> loader = SubresourceLoader::create(frame, resource, request, options);
+    if (loader)
+        scheduleLoad(loader.get(), priority);
+    return loader.release();
+}
+
+PassRefPtr<NetscapePlugInStreamLoader> WebResourceLoadScheduler::schedulePluginStreamLoad(Frame* frame, NetscapePlugInStreamLoaderClient* client, const ResourceRequest& request)
+{
+    RefPtr<NetscapePlugInStreamLoader> loader = NetscapePlugInStreamLoader::create(frame, client, request);
+    if (loader)
+        scheduleLoad(loader.get(), ResourceLoadPriorityLow);
+    return loader.release();
+}
+
+void WebResourceLoadScheduler::scheduleLoad(ResourceLoader* resourceLoader, ResourceLoadPriority priority)
+{
+    LOG(Network, "(WebProcess) WebResourceLoadScheduler::scheduleLoad, url '%s' priority %i", resourceLoader->url().string().utf8().data(), priority);
+
+    ASSERT(resourceLoader);
+    ASSERT(priority != ResourceLoadPriorityUnresolved);
+    priority = ResourceLoadPriorityHighest;
+
+    // If there's a web archive resource for this URL, we don't need to schedule the load since it will never touch the network.
+    if (resourceLoader->documentLoader()->archiveResourceForURL(resourceLoader->request().url())) {
+        startResourceLoader(resourceLoader);
+        return;
+    }
+    
+    ResourceLoadIdentifier identifier;
+    
+    ResourceRequest request = resourceLoader->request();
+    
+    // We want the network process involved in scheduling data URL loads but it doesn't need to know the full (often long) URL.
+    if (request.url().protocolIsData()) {
+        DEFINE_STATIC_LOCAL(KURL, dataURL, (KURL(), "data:"));
+        request.setURL(dataURL);
+    }
+
+    if (!WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::ScheduleNetworkRequest(request, priority), Messages::NetworkConnectionToWebProcess::ScheduleNetworkRequest::Reply(identifier), 0)) {
+        // FIXME (NetworkProcess): What should we do if this fails?
+        ASSERT_NOT_REACHED();
+    }
+    
+    resourceLoader->setIdentifier(identifier);
+    m_pendingResourceLoaders.set(identifier, resourceLoader);
+    
+    notifyDidScheduleResourceRequest(resourceLoader);
+}
+
+void WebResourceLoadScheduler::addMainResourceLoad(ResourceLoader* resourceLoader)
+{
+    LOG(Network, "(WebProcess) WebResourceLoadScheduler::addMainResourceLoad, url '%s'", resourceLoader->url().string().utf8().data());
+
+    ResourceLoadIdentifier identifier;
+
+    if (!WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::AddLoadInProgress(resourceLoader->url()), Messages::NetworkConnectionToWebProcess::AddLoadInProgress::Reply(identifier), 0)) {
+        // FIXME (NetworkProcess): What should we do if this fails?
+        ASSERT_NOT_REACHED();
+    }
+
+    resourceLoader->setIdentifier(identifier);
+    
+    m_activeResourceLoaders.set(identifier, resourceLoader);
+}
+
+void WebResourceLoadScheduler::remove(ResourceLoader* resourceLoader)
+{
+    ASSERT(resourceLoader);
+    LOG(Network, "(WebProcess) WebResourceLoadScheduler::remove, url '%s'", resourceLoader->url().string().utf8().data());
+
+    // FIXME (NetworkProcess): It's possible for a resourceLoader to be removed before it ever started,
+    // meaning before it even has an identifier.
+    // We should make this not be possible.
+    // The ResourceLoader code path should always for an identifier to ResourceLoaders.
+    
+    ResourceLoadIdentifier identifier = resourceLoader->identifier();
+    if (!identifier) {
+        LOG_ERROR("WebResourceLoadScheduler removing a ResourceLoader that has no identifier.");
+        return;
+    }
+    
+    WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::RemoveLoadIdentifier(identifier), 0);
+    
+    ASSERT(m_pendingResourceLoaders.contains(identifier) || m_activeResourceLoaders.contains(identifier));
+    m_pendingResourceLoaders.remove(identifier);
+    m_activeResourceLoaders.remove(identifier);
+}
+
+void WebResourceLoadScheduler::crossOriginRedirectReceived(ResourceLoader* resourceLoader, const KURL& redirectURL)
+{
+    LOG(Network, "(WebProcess) WebResourceLoadScheduler::crossOriginRedirectReceived. From '%s' to '%s'", resourceLoader->url().string().utf8().data(), redirectURL.string().utf8().data());
+
+    ASSERT(resourceLoader);
+    ASSERT(resourceLoader->identifier());
+
+    if (!WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::crossOriginRedirectReceived(resourceLoader->identifier(), redirectURL), Messages::NetworkConnectionToWebProcess::crossOriginRedirectReceived::Reply(), 0)) {
+        // FIXME (NetworkProcess): What should we do if this fails?
+        ASSERT_NOT_REACHED();
+    }
+}
+
+void WebResourceLoadScheduler::servePendingRequests(ResourceLoadPriority minimumPriority)
+{
+    LOG(Network, "(WebProcess) WebResourceLoadScheduler::servePendingRequests");
+    
+    // If this WebProcess has its own request suspension count then we don't even
+    // have to bother messaging the NetworkProcess.
+    if (m_suspendPendingRequestsCount)
+        return;
+
+    WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::ServePendingRequests(minimumPriority), 0);
+}
+
+void WebResourceLoadScheduler::suspendPendingRequests()
+{
+    WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::SuspendPendingRequests(), Messages::NetworkConnectionToWebProcess::SuspendPendingRequests::Reply(), 0);
+
+    ++m_suspendPendingRequestsCount;
+}
+
+void WebResourceLoadScheduler::resumePendingRequests()
+{
+    WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::ResumePendingRequests(), Messages::NetworkConnectionToWebProcess::ResumePendingRequests::Reply(), 0);
+
+    ASSERT(m_suspendPendingRequestsCount);
+    --m_suspendPendingRequestsCount;
+}
+
+void WebResourceLoadScheduler::setSerialLoadingEnabled(bool enabled)
+{
+    WebProcess::shared().networkConnection()->connection()->sendSync(Messages::NetworkConnectionToWebProcess::SetSerialLoadingEnabled(enabled), Messages::NetworkConnectionToWebProcess::SetSerialLoadingEnabled::Reply(), 0);
+}
+
+void WebResourceLoadScheduler::startResourceLoad(ResourceLoadIdentifier identifier)
+{
+    RefPtr<ResourceLoader> loader = m_pendingResourceLoaders.take(identifier);
+    ASSERT(loader);
+    
+    LOG(Network, "(WebProcess) WebResourceLoadScheduler::startResourceLoad starting load for '%s'", loader->url().string().utf8().data());
+
+    m_activeResourceLoaders.set(identifier, loader);
+
+    startResourceLoader(loader.get());
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(NETWORK_PROCESS)
index dfd985f..422427b 100644 (file)
 #ifndef WebResourceLoadScheduler_h
 #define WebResourceLoadScheduler_h
 
+#include <WebCore/ResourceLoadPriority.h>
 #include <WebCore/ResourceLoadScheduler.h>
+#include <WebCore/ResourceLoader.h>
 
 #if ENABLE(NETWORK_PROCESS)
 
 namespace WebKit {
 
+class NetworkProcessConnection;
+typedef uint64_t ResourceLoadIdentifier;
+
 class WebResourceLoadScheduler : public WebCore::ResourceLoadScheduler {
+    WTF_MAKE_NONCOPYABLE(WebResourceLoadScheduler); WTF_MAKE_FAST_ALLOCATED;
 public:
+    WebResourceLoadScheduler();
     virtual ~WebResourceLoadScheduler();
+    
+    virtual PassRefPtr<WebCore::SubresourceLoader> scheduleSubresourceLoad(WebCore::Frame*, WebCore::CachedResource*, const WebCore::ResourceRequest&, WebCore::ResourceLoadPriority, const WebCore::ResourceLoaderOptions&) OVERRIDE;
+    virtual PassRefPtr<WebCore::NetscapePlugInStreamLoader> schedulePluginStreamLoad(WebCore::Frame*, WebCore::NetscapePlugInStreamLoaderClient*, const WebCore::ResourceRequest&) OVERRIDE;
+    
+    virtual void addMainResourceLoad(WebCore::ResourceLoader*) OVERRIDE;
+    virtual void remove(WebCore::ResourceLoader*) OVERRIDE;
+    virtual void crossOriginRedirectReceived(WebCore::ResourceLoader*, const WebCore::KURL& redirectURL) OVERRIDE;
+    
+    virtual void servePendingRequests(WebCore::ResourceLoadPriority minimumPriority = WebCore::ResourceLoadPriorityVeryLow) OVERRIDE;
+
+    virtual void suspendPendingRequests() OVERRIDE;
+    virtual void resumePendingRequests() OVERRIDE;
+
+    virtual void setSerialLoadingEnabled(bool) OVERRIDE;
+
+private:
+    void scheduleLoad(WebCore::ResourceLoader*, WebCore::ResourceLoadPriority);
+
+    // NetworkProcessConnection gets to tell loads to actually start.
+    // FIXME (NetworkProcess): Once actual loading takes place in the NetworkProcess we won't need this.
+    friend class NetworkProcessConnection;
+    void startResourceLoad(ResourceLoadIdentifier);
+    
+    typedef HashMap<unsigned long, RefPtr<WebCore::ResourceLoader> > ResourceLoaderMap;
+    ResourceLoaderMap m_pendingResourceLoaders;
+    ResourceLoaderMap m_activeResourceLoaders;
+    
+    unsigned m_suspendPendingRequestsCount;
+
 };
 
 } // namespace WebKit
index d5e4b2a..f12b851 100644 (file)
@@ -104,12 +104,18 @@ void WebPlatformStrategies::notifyCookiesChanged()
 // LoaderStrategy
 
 #if ENABLE(NETWORK_PROCESS)
-
 ResourceLoadScheduler* WebPlatformStrategies::resourceLoadScheduler()
 {
-    return WebCore::resourceLoadScheduler();
+    static ResourceLoadScheduler* scheduler;
+    if (!scheduler) {
+        if (WebProcess::shared().usesNetworkProcess())
+            scheduler = &WebProcess::shared().webResourceLoadScheduler();
+        else
+            scheduler = WebCore::resourceLoadScheduler();
+    }
+    
+    return scheduler;
 }
-
 #endif
 
 // PluginStrategy
index 60e602c..976a136 100644 (file)
@@ -307,8 +307,7 @@ void WebProcess::ensureNetworkProcessConnection()
 #else
     ASSERT_NOT_REACHED();
 #endif
-
-    RefPtr<NetworkProcessConnection> m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
+    m_networkProcessConnection = NetworkProcessConnection::create(connectionIdentifier);
 }
 #endif // ENABLE(NETWORK_PROCESS)
 
@@ -1032,8 +1031,18 @@ void WebProcess::postInjectedBundleMessage(const CoreIPC::DataReference& message
 }
 
 #if ENABLE(NETWORK_PROCESS)
+NetworkProcessConnection* WebProcess::networkConnection()
+{
+    // FIXME (NetworkProcess): How do we handle not having the connection when the WebProcess needs it?
+    // If the NetworkProcess crashed, for example.  Do we respawn it?
+    ASSERT(m_networkProcessConnection);
+    return m_networkProcessConnection.get();
+}
+
 void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connection)
 {
+    // FIXME (NetworkProcess): How do we handle not having the connection when the WebProcess needs it?
+    // If the NetworkProcess crashed, for example.  Do we respawn it?
     ASSERT(m_networkProcessConnection);
     ASSERT(m_networkProcessConnection == connection);
 
@@ -1042,6 +1051,8 @@ void WebProcess::networkProcessConnectionClosed(NetworkProcessConnection* connec
 
 void WebProcess::networkProcessCrashed(CoreIPC::Connection*)
 {
+    // FIXME (NetworkProcess): How do we handle not having the connection when the WebProcess needs it?
+    // If the NetworkProcess crashed, for example.  Do we respawn it?
     ASSERT(m_networkProcessConnection);
     
     networkProcessConnectionClosed(m_networkProcessConnection.get());
index 7468cd6..c248a4e 100644 (file)
@@ -203,7 +203,9 @@ public:
 #endif
 
 #if ENABLE(NETWORK_PROCESS)
+    NetworkProcessConnection* networkConnection();
     void networkProcessConnectionClosed(NetworkProcessConnection*);
+    bool usesNetworkProcess() const { return m_usesNetworkProcess; }
     WebResourceLoadScheduler& webResourceLoadScheduler() { return m_webResourceLoadScheduler; }
 #endif