WebCore:
authortimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 5 Mar 2008 00:57:26 +0000 (00:57 +0000)
committertimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 5 Mar 2008 00:57:26 +0000 (00:57 +0000)
        Reviewed by Darin Adler.

        <rdar://problem/5720160> Browser windows "do nothing" while modal
        dialog or menu is up due to run loop modes (or while scrolling)

        Adds a new SchedulePair object that holds a runloop and the mode to use.
        A HashSet of SchedulePairs is tracked by Page so it can be used for resource
        loading and, in the future, maybe SharedTimerMac.

        * WebCore.base.exp: Add new exports for WebKit.
        * WebCore.xcodeproj/project.pbxproj: Add new files.
        * loader/mac/DocumentLoaderMac.cpp: Added.
        (WebCore::scheduleAll): Call schedule all the ResourceLoader handles.
        (WebCore::unscheduleAll): Call unschedule all the ResourceLoader handles.
        (WebCore::DocumentLoader::schedule): Schedule all the ResourceLoaders owned by the DocumentLoader.
        (WebCore::DocumentLoader::unschedule): Unschedule all the ResourceLoaders owned by the DocumentLoader.
        * loader/DocumentLoader.h:
        * page/Page.h:
        (WebCore::Page::scheduledRunLoopPairs): Return m_scheduledRunLoopPairs.
        * page/mac/PageMac.cpp:
        (WebCore::Page::addSchedulePair): Add a SchedulePair to m_scheduledRunLoopPairs.
        (WebCore::Page::removeSchedulePair): Removes a SchedulePair from m_scheduledRunLoopPairs.
        * platform/cf/SchedulePair.cpp: Added.
        * platform/cf/SchedulePair.h: Added.
        * platform/mac/SchedulePairMac.mm: Added.
        * platform/network/ResourceHandle.h:
        * platform/network/mac/FormDataStreamMac.mm:
        (WebCore::advanceCurrentStream): Use the new SchedulePair.
        (WebCore::formCreate): Ditto.
        (WebCore::formFinalize): Ditto.
        (WebCore::formSchedule): Ditto.
        (WebCore::formUnschedule): Ditto.
        * platform/network/mac/ResourceHandleMac.mm:
        (WebCore::ResourceHandle::start): Schedule the connection with all the SchedulePairs
        that Page holds. If Page has no SchedulePairs, schedule with the current runloop, and
        pick the mode based on ResourceHandle::loadsDuringCommonRunLoopModes.
        (WebCore::ResourceHandle::schedule):
        (WebCore::ResourceHandle::unschedule):

WebKit/mac:

        Reviewed by Darin Adler.

        <rdar://problem/5720160> Browser windows "do nothing" while modal
        dialog or menu is up due to run loop modes (or while scrolling)

        Add new API that lets a WebView be scheduled with multiple runloops and modes.
        This lets loading continue when in a nested runloop or in a different mode.

        * Misc/WebKitVersionChecks.h: Add a new version define:
        WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES.
        * WebView/WebView.mm:
        (-[WebView _commonInitializationWithFrameName:groupName:]): Schedule in the main runloop and with
        the default runloop mode if we are linked on an earlier WebKit version, use common modes otherwise.
        (-[WebView scheduleInRunLoop:forMode:]): New API, that calls through to Page.
        (-[WebView unscheduleFromRunLoop:forMode:]): Ditto.
        * WebView/WebViewPrivate.h: Add the new pending API methods.

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

18 files changed:
WebCore/ChangeLog
WebCore/WebCore.base.exp
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/loader/DocumentLoader.h
WebCore/loader/mac/DocumentLoaderMac.cpp [new file with mode: 0644]
WebCore/page/Page.h
WebCore/page/mac/PageMac.cpp [new file with mode: 0644]
WebCore/platform/cf/SchedulePair.cpp [new file with mode: 0644]
WebCore/platform/cf/SchedulePair.h [new file with mode: 0644]
WebCore/platform/mac/SchedulePairMac.mm [new file with mode: 0644]
WebCore/platform/network/ResourceHandle.h
WebCore/platform/network/ResourceHandleInternal.h
WebCore/platform/network/mac/FormDataStreamMac.mm
WebCore/platform/network/mac/ResourceHandleMac.mm
WebKit/mac/ChangeLog
WebKit/mac/Misc/WebKitVersionChecks.h
WebKit/mac/WebView/WebView.mm
WebKit/mac/WebView/WebViewPrivate.h

index 0026a74..b5f5911 100644 (file)
@@ -1,3 +1,44 @@
+2008-03-04  Timothy Hatcher  <timothy@apple.com>
+
+        Reviewed by Darin Adler.
+
+        <rdar://problem/5720160> Browser windows "do nothing" while modal
+        dialog or menu is up due to run loop modes (or while scrolling)
+
+        Adds a new SchedulePair object that holds a runloop and the mode to use.
+        A HashSet of SchedulePairs is tracked by Page so it can be used for resource
+        loading and, in the future, maybe SharedTimerMac.
+
+        * WebCore.base.exp: Add new exports for WebKit.
+        * WebCore.xcodeproj/project.pbxproj: Add new files.
+        * loader/mac/DocumentLoaderMac.cpp: Added.
+        (WebCore::scheduleAll): Call schedule all the ResourceLoader handles.
+        (WebCore::unscheduleAll): Call unschedule all the ResourceLoader handles.
+        (WebCore::DocumentLoader::schedule): Schedule all the ResourceLoaders owned by the DocumentLoader.
+        (WebCore::DocumentLoader::unschedule): Unschedule all the ResourceLoaders owned by the DocumentLoader.
+        * loader/DocumentLoader.h:
+        * page/Page.h:
+        (WebCore::Page::scheduledRunLoopPairs): Return m_scheduledRunLoopPairs.
+        * page/mac/PageMac.cpp:
+        (WebCore::Page::addSchedulePair): Add a SchedulePair to m_scheduledRunLoopPairs.
+        (WebCore::Page::removeSchedulePair): Removes a SchedulePair from m_scheduledRunLoopPairs.
+        * platform/cf/SchedulePair.cpp: Added.
+        * platform/cf/SchedulePair.h: Added.
+        * platform/mac/SchedulePairMac.mm: Added.
+        * platform/network/ResourceHandle.h:
+        * platform/network/mac/FormDataStreamMac.mm:
+        (WebCore::advanceCurrentStream): Use the new SchedulePair.
+        (WebCore::formCreate): Ditto.
+        (WebCore::formFinalize): Ditto.
+        (WebCore::formSchedule): Ditto.
+        (WebCore::formUnschedule): Ditto.
+        * platform/network/mac/ResourceHandleMac.mm:
+        (WebCore::ResourceHandle::start): Schedule the connection with all the SchedulePairs
+        that Page holds. If Page has no SchedulePairs, schedule with the current runloop, and
+        pick the mode based on ResourceHandle::loadsDuringCommonRunLoopModes.
+        (WebCore::ResourceHandle::schedule):
+        (WebCore::ResourceHandle::unschedule):
+
 2008-03-04  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Darin Adler.
index c552f4a..ea4effc 100644 (file)
@@ -239,6 +239,7 @@ __ZN7WebCore12IconDatabase27checkIntegrityBeforeOpeningEv
 __ZN7WebCore12IconDatabase4openERKNS_6StringE
 __ZN7WebCore12IconDatabase5closeEv
 __ZN7WebCore12IconDatabase9setClientEPNS_18IconDatabaseClientE
+__ZN7WebCore12SchedulePairC1EP9NSRunLoopPK10__CFString
 __ZN7WebCore12SharedBuffer10wrapNSDataEP6NSData
 __ZN7WebCore12SharedBuffer12createNSDataEv
 __ZN7WebCore12TextEncodingC1ERKNS_6StringE
@@ -371,8 +372,10 @@ __ZN7WebCore4KURLC1Ev
 __ZN7WebCore4Node17stopIgnoringLeaksEv
 __ZN7WebCore4Node18startIgnoringLeaksEv
 __ZN7WebCore4Page12setGroupNameERKNS_6StringE
+__ZN7WebCore4Page15addSchedulePairEN3WTF10PassRefPtrINS_12SchedulePairEEE
 __ZN7WebCore4Page15backForwardListEv
 __ZN7WebCore4Page16setDefersLoadingEb
+__ZN7WebCore4Page18removeSchedulePairEN3WTF10PassRefPtrINS_12SchedulePairEEE
 __ZN7WebCore4Page23clearUndoRedoOperationsEv
 __ZN7WebCore4Page37setInLowQualityImageInterpolationModeEb
 __ZN7WebCore4Page6goBackEv
index 93bc80f..5f8b38f 100644 (file)
                1C11CCC80AA6093700DADB20 /* DOMHTMLElement.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 85DF2EEB0AA387CB00AD64C5 /* DOMHTMLElement.h */; };
                1C14E76B0AD8C81C00B6158B /* deleteButtonPressed.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 1C14E7690AD8C81C00B6158B /* deleteButtonPressed.tiff */; };
                1C14E76C0AD8C81C00B6158B /* deleteButton.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 1C14E76A0AD8C81C00B6158B /* deleteButton.tiff */; };
+               1C26497A0D7E248A00BD10F2 /* DocumentLoaderMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C2649790D7E248A00BD10F2 /* DocumentLoaderMac.cpp */; };
+               1C26497C0D7E24EC00BD10F2 /* PageMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C26497B0D7E24EC00BD10F2 /* PageMac.cpp */; };
                1C4C8F020AD85D87009475CE /* DeleteButtonController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C4C8F000AD85D87009475CE /* DeleteButtonController.h */; };
                1C4C8F660AD8655D009475CE /* DeleteButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C4C8F640AD8655D009475CE /* DeleteButton.h */; };
                1C6B7C9A0CEFC9D00076DE61 /* InspectorLocalizedStrings.js in Resources */ = {isa = PBXBuildFile; fileRef = 1C6B7C980CEFC9BE0076DE61 /* InspectorLocalizedStrings.js */; };
                1CB4214B0AF2B2CA0085AD91 /* DOMElementInternal.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 85E711490AC5D5340053270F /* DOMElementInternal.h */; };
                1CB4214C0AF2B2CA0085AD91 /* DOMHTMLElementInternal.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 85E711580AC5D5340053270F /* DOMHTMLElementInternal.h */; };
                1CB4214D0AF2B2CA0085AD91 /* DOMRangeInternal.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 8538F05A0AD722F1006A81D1 /* DOMRangeInternal.h */; };
+               1CE24F970D7CAF0E007E04C2 /* SchedulePairMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1CE24F960D7CAF0E007E04C2 /* SchedulePairMac.mm */; };
                1CE83AC30ADAFFD7009354F6 /* DeleteButtonController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C4C8EFF0AD85D87009475CE /* DeleteButtonController.cpp */; };
                1CE83AC40ADAFFD8009354F6 /* DeleteButton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C4C8F630AD8655D009475CE /* DeleteButton.cpp */; };
+               1CEFC9B90D78DC8C007D2579 /* SchedulePair.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CEFC9B70D78DC8C007D2579 /* SchedulePair.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               1CEFC9BA0D78DC8C007D2579 /* SchedulePair.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CEFC9B80D78DC8C007D2579 /* SchedulePair.cpp */; };
                1CFAE3230A6D6A3F0032593D /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CFAE3220A6D6A3F0032593D /* libobjc.dylib */; };
                1CFCEE960AACC40100348750 /* DOMHTMLBodyElementPrivate.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 1CFCEE8D0AACC3CD00348750 /* DOMHTMLBodyElementPrivate.h */; };
                1CFCEE970AACC40100348750 /* DOMHTMLButtonElementPrivate.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 1CFCEE8E0AACC3CD00348750 /* DOMHTMLButtonElementPrivate.h */; };
                1AFE11980CBFFCC4003017FA /* JSSQLResultSetRowList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSQLResultSetRowList.h; sourceTree = "<group>"; };
                1C14E7690AD8C81C00B6158B /* deleteButtonPressed.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = deleteButtonPressed.tiff; sourceTree = "<group>"; };
                1C14E76A0AD8C81C00B6158B /* deleteButton.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = deleteButton.tiff; sourceTree = "<group>"; };
+               1C2649790D7E248A00BD10F2 /* DocumentLoaderMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DocumentLoaderMac.cpp; sourceTree = "<group>"; };
+               1C26497B0D7E24EC00BD10F2 /* PageMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageMac.cpp; sourceTree = "<group>"; };
                1C4C8EFF0AD85D87009475CE /* DeleteButtonController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeleteButtonController.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                1C4C8F000AD85D87009475CE /* DeleteButtonController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeleteButtonController.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                1C4C8F630AD8655D009475CE /* DeleteButton.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeleteButton.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                1CDD45E40BA9C84600F90147 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; };
                1CDD45E50BA9C84600F90147 /* WebCore.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = WebCore.xcconfig; sourceTree = "<group>"; };
                1CDD45E60BA9C84600F90147 /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
+               1CE24F960D7CAF0E007E04C2 /* SchedulePairMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SchedulePairMac.mm; sourceTree = "<group>"; };
+               1CEFC9B70D78DC8C007D2579 /* SchedulePair.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SchedulePair.h; sourceTree = "<group>"; };
+               1CEFC9B80D78DC8C007D2579 /* SchedulePair.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SchedulePair.cpp; sourceTree = "<group>"; };
                1CFAE3220A6D6A3F0032593D /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = /usr/lib/libobjc.dylib; sourceTree = "<absolute>"; };
                1CFCEE7F0AACC3B300348750 /* DOMHTMLAnchorElementPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMHTMLAnchorElementPrivate.h; sourceTree = "<group>"; };
                1CFCEE880AACC3C000348750 /* DOMHTMLAreaElementPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMHTMLAreaElementPrivate.h; sourceTree = "<group>"; };
                1AE42F670AA4B8CB00C8612D /* cf */ = {
                        isa = PBXGroup;
                        children = (
+                               1CEFC9B70D78DC8C007D2579 /* SchedulePair.h */,
+                               1CEFC9B80D78DC8C007D2579 /* SchedulePair.cpp */,
                                1A98956A0AA78F80005EF5EF /* KURLCFNet.cpp */,
                                5160306B0CC4362300C8AC25 /* FileSystemCF.cpp */,
                        );
                                BC7B2AF90450824100A8000F /* PlatformScrollBarMac.mm */,
                                A82398A709B3ACF500B60641 /* PlugInInfoStoreMac.mm */,
                                0668E18E0ADD9640004128E0 /* PopupMenuMac.mm */,
+                               1CE24F960D7CAF0E007E04C2 /* SchedulePairMac.mm */,
                                BCAA90C20A7EBA60008B1229 /* ScrollBar.cpp */,
                                9353676A09AED88B00D35CD6 /* ScrollViewMac.mm */,
                                AB71709F0B31193B0017123E /* SearchPopupMenuMac.mm */,
                93A1EAA20A5634D8006960A0 /* mac */ = {
                        isa = PBXGroup;
                        children = (
+                               1C2649790D7E248A00BD10F2 /* DocumentLoaderMac.cpp */,
                                656D371A0ADBA5DE00A4554D /* LoaderNSURLExtras.h */,
                                656D371B0ADBA5DE00A4554D /* LoaderNSURLExtras.m */,
                                51AA3F6E0BD5AA9E00892971 /* ResourceLoaderMac.mm */,
                                93C09A7E0B064EEF005ABD4D /* EventHandlerMac.mm */,
                                A718788F0B2D04AC00A16ECE /* DragControllerMac.mm */,
                                65BF023C0974819000C43196 /* FrameMac.mm */,
+                               1C26497B0D7E24EC00BD10F2 /* PageMac.cpp */,
                                654EC60F097778F500DAB52C /* WebCoreFrameBridge.h */,
                                654EC610097778F500DAB52C /* WebCoreFrameBridge.mm */,
                                F587854C02DE375901EA4122 /* WebCoreFrameView.h */,
                                A779791A0D6B9D0C003851B9 /* ImageData.h in Headers */,
                                A77979270D6B9E64003851B9 /* JSCanvasPixelArray.h in Headers */,
                                A77979290D6B9E64003851B9 /* JSImageData.h in Headers */,
+                               1CEFC9B90D78DC8C007D2579 /* SchedulePair.h in Headers */,
                                1AF326480D78B5530068F0C4 /* WebCoreAXObject.h in Headers */,
                                1AF3264A0D78B5530068F0C4 /* WebCoreScriptDebugger.h in Headers */,
                                1AF326780D78B9440068F0C4 /* AXObjectCache.h in Headers */,
                                A77979260D6B9E64003851B9 /* JSCanvasPixelArray.cpp in Sources */,
                                A77979280D6B9E64003851B9 /* JSImageData.cpp in Sources */,
                                A766F3530D6BDE3500ABDDB3 /* JSCanvasPixelArrayCustom.cpp in Sources */,
+                               1CEFC9BA0D78DC8C007D2579 /* SchedulePair.cpp in Sources */,
                                1AF326460D78B5530068F0C4 /* AXObjectCacheMac.mm in Sources */,
                                1AF326470D78B5530068F0C4 /* GlobalHistoryMac.mm in Sources */,
                                1AF326490D78B5530068F0C4 /* WebCoreAXObject.mm in Sources */,
                                1AF3264B0D78B5530068F0C4 /* WebCoreScriptDebugger.mm in Sources */,
+                               1CE24F970D7CAF0E007E04C2 /* SchedulePairMac.mm in Sources */,
                                BCA83E4F0D7CE1E9003421A8 /* JSClipboard.cpp in Sources */,
                                BCA83E520D7CE205003421A8 /* JSClipboardCustom.cpp in Sources */,
                                BC6C49F30D7DBA0500FFA558 /* JSImageConstructor.cpp in Sources */,
+                               1C26497A0D7E248A00BD10F2 /* DocumentLoaderMac.cpp in Sources */,
+                               1C26497C0D7E24EC00BD10F2 /* PageMac.cpp in Sources */,
                                BC3452430D7E00EA0016574A /* JSRGBColor.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
index 15303fe..bb93fd6 100644 (file)
@@ -50,6 +50,7 @@ namespace WebCore {
     class KURL;
     class MainResourceLoader;
     class ResourceLoader;
+    class SchedulePair;
     class SharedBuffer;
     class SubstituteData;
 
@@ -114,6 +115,11 @@ namespace WebCore {
         void setTitle(const String&);
         String overrideEncoding() const;
 
+#if PLATFORM(MAC)
+        void schedule(SchedulePair*);
+        void unschedule(SchedulePair*);
+#endif
+
         void addResponse(const ResourceResponse&);
         const ResponseVector& responses() const;
 
diff --git a/WebCore/loader/mac/DocumentLoaderMac.cpp b/WebCore/loader/mac/DocumentLoaderMac.cpp
new file mode 100644 (file)
index 0000000..b6f5b25
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2008 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "DocumentLoader.h"
+#include "MainResourceLoader.h"
+#include "ResourceHandle.h"
+#include "ResourceLoader.h"
+
+namespace WebCore {
+
+static void scheduleAll(const ResourceLoaderSet& loaders, SchedulePair* pair)
+{
+    const ResourceLoaderSet copy = loaders;
+    ResourceLoaderSet::const_iterator end = copy.end();
+    for (ResourceLoaderSet::const_iterator it = copy.begin(); it != end; ++it)
+        if (ResourceHandle* handle = (*it)->handle())
+            handle->schedule(pair);
+}
+
+static void unscheduleAll(const ResourceLoaderSet& loaders, SchedulePair* pair)
+{
+    const ResourceLoaderSet copy = loaders;
+    ResourceLoaderSet::const_iterator end = copy.end();
+    for (ResourceLoaderSet::const_iterator it = copy.begin(); it != end; ++it)
+        if (ResourceHandle* handle = (*it)->handle())
+            handle->unschedule(pair);
+}
+
+void DocumentLoader::schedule(SchedulePair* pair)
+{
+    if (m_mainResourceLoader && m_mainResourceLoader->handle())
+        m_mainResourceLoader->handle()->schedule(pair);
+    scheduleAll(m_subresourceLoaders, pair);
+    scheduleAll(m_plugInStreamLoaders, pair);
+    scheduleAll(m_multipartSubresourceLoaders, pair);
+}
+
+void DocumentLoader::unschedule(SchedulePair* pair)
+{
+    if (m_mainResourceLoader && m_mainResourceLoader->handle())
+        m_mainResourceLoader->handle()->unschedule(pair);
+    unscheduleAll(m_subresourceLoaders, pair);
+    unscheduleAll(m_plugInStreamLoaders, pair);
+    unscheduleAll(m_multipartSubresourceLoaders, pair);
+}
+
+} // namespace
index c94ea78..d3363ad 100644 (file)
@@ -26,6 +26,9 @@
 #include "ContextMenuController.h"
 #include "FrameLoaderTypes.h"
 #include "PlatformString.h"
+#if PLATFORM(MAC)
+#include "SchedulePair.h"
+#endif
 #include <wtf/HashSet.h>
 #include <wtf/OwnPtr.h>
 
@@ -117,6 +120,14 @@ namespace WebCore {
         unsigned int markAllMatchesForText(const String&, TextCaseSensitivity, bool shouldHighlight, unsigned);
         void unmarkAllTextMatches();
 
+#if PLATFORM(MAC)
+        void addSchedulePair(PassRefPtr<SchedulePair>);
+        void removeSchedulePair(PassRefPtr<SchedulePair>);
+        SchedulePairHashSet* scheduledRunLoopPairs() { return m_scheduledRunLoopPairs.get(); }
+
+        OwnPtr<SchedulePairHashSet> m_scheduledRunLoopPairs;
+#endif
+
         const Selection& selection() const;
 
         void setDefersLoading(bool);
diff --git a/WebCore/page/mac/PageMac.cpp b/WebCore/page/mac/PageMac.cpp
new file mode 100644 (file)
index 0000000..fabdcf3
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2008 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "DocumentLoader.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameTree.h"
+#include "Page.h"
+
+namespace WebCore {
+
+void Page::addSchedulePair(PassRefPtr<SchedulePair> prpPair)
+{
+    RefPtr<SchedulePair> pair = prpPair;
+
+    if (!m_scheduledRunLoopPairs)
+        m_scheduledRunLoopPairs.set(new SchedulePairHashSet);
+    m_scheduledRunLoopPairs->add(pair);
+
+    for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) {
+        if (DocumentLoader* documentLoader = frame->loader()->documentLoader())
+            documentLoader->schedule(pair.get());
+        if (DocumentLoader* documentLoader = frame->loader()->provisionalDocumentLoader())
+            documentLoader->schedule(pair.get());
+    }
+
+    // FIXME: make SharedTimerMac use these SchedulePairs.
+}
+
+void Page::removeSchedulePair(PassRefPtr<SchedulePair> prpPair)
+{
+    ASSERT(m_scheduledRunLoopPairs);
+    if (!m_scheduledRunLoopPairs)
+        return;
+
+    RefPtr<SchedulePair> pair = prpPair;
+    m_scheduledRunLoopPairs->remove(pair);
+
+    for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) {
+        if (DocumentLoader* documentLoader = frame->loader()->documentLoader())
+            documentLoader->unschedule(pair.get());
+        if (DocumentLoader* documentLoader = frame->loader()->provisionalDocumentLoader())
+            documentLoader->unschedule(pair.get());
+    }
+}
+
+} // namespace
diff --git a/WebCore/platform/cf/SchedulePair.cpp b/WebCore/platform/cf/SchedulePair.cpp
new file mode 100644 (file)
index 0000000..ee5ae95
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "SchedulePair.h"
+
+namespace WebCore {
+
+SchedulePair::SchedulePair(CFRunLoopRef runLoop, CFStringRef mode)
+    : m_runLoop(runLoop)
+{
+    if (mode)
+        m_mode.adoptCF(CFStringCreateCopy(0, mode));
+}
+
+bool SchedulePair::operator==(const SchedulePair& other) const
+{
+    if (runLoop() != other.runLoop())
+        return false;
+    CFStringRef thisMode = mode();
+    CFStringRef otherMode = other.mode();
+    if (!thisMode || !otherMode)
+        return thisMode == otherMode;
+    return CFEqual(thisMode, otherMode);
+}
+
+} // namespace
diff --git a/WebCore/platform/cf/SchedulePair.h b/WebCore/platform/cf/SchedulePair.h
new file mode 100644 (file)
index 0000000..f19f371
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2008 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 SchedulePair_h
+#define SchedulePair_h
+
+#include "PlatformString.h"
+
+#include <wtf/HashSet.h>
+#include <wtf/HashTraits.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/RetainPtr.h>
+
+#if PLATFORM(MAC)
+#ifdef __OBJC__
+@class NSRunLoop;
+#else
+class NSRunLoop;
+#endif
+#endif
+
+namespace WebCore {
+
+class SchedulePair : public RefCounted<SchedulePair> {
+public:
+    static PassRefPtr<SchedulePair> create(CFRunLoopRef runLoop, CFStringRef mode) { return adoptRef(new SchedulePair(runLoop, mode)); }
+
+#if PLATFORM(MAC)
+    static PassRefPtr<SchedulePair> create(NSRunLoop* runLoop, CFStringRef mode) { return adoptRef(new SchedulePair(runLoop, mode)); }
+    NSRunLoop* nsRunLoop() const { return m_nsRunLoop.get(); }
+#endif
+
+    CFRunLoopRef runLoop() const { return m_runLoop.get(); }
+    CFStringRef mode() const { return m_mode.get(); }
+
+    bool operator==(const SchedulePair& other) const;
+
+private:
+    SchedulePair(CFRunLoopRef, CFStringRef);
+
+#if PLATFORM(MAC)
+    SchedulePair(NSRunLoop*, CFStringRef);
+    RetainPtr<NSRunLoop*> m_nsRunLoop;
+#endif
+
+    RetainPtr<CFRunLoopRef> m_runLoop;
+    RetainPtr<CFStringRef> m_mode;
+};
+
+struct SchedulePairHash {
+    static unsigned hash(const RefPtr<SchedulePair>& pair)
+    {
+        uintptr_t hashCodes[2] = { reinterpret_cast<uintptr_t>(pair->runLoop()), pair->mode() ? CFHash(pair->mode()) : 0 };
+        return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
+    }
+
+    static bool equal(const RefPtr<SchedulePair>& a, const RefPtr<SchedulePair>& b) { return a == b; }
+
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+struct SchedulePairTraits : WTF::GenericHashTraits<RefPtr<SchedulePair> > {
+    static const bool emptyValueIsZero = true;
+
+    static const RefPtr<SchedulePair>& deletedValue() 
+    {
+        static const RefPtr<SchedulePair> SchedulePairDeletedValue = SchedulePair::create(static_cast<CFRunLoopRef>(0), 0);    
+        return SchedulePairDeletedValue; 
+    }
+
+    static SchedulePair* emptyValue() { return 0; }
+};
+
+typedef HashSet<RefPtr<SchedulePair>, SchedulePairHash, SchedulePairTraits > SchedulePairHashSet;
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/mac/SchedulePairMac.mm b/WebCore/platform/mac/SchedulePairMac.mm
new file mode 100644 (file)
index 0000000..e1709b3
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "SchedulePair.h"
+
+namespace WebCore {
+
+SchedulePair::SchedulePair(NSRunLoop* runLoop, CFStringRef mode)
+    : m_nsRunLoop(runLoop)
+    , m_runLoop([runLoop getCFRunLoop])
+{
+    if (mode)
+        m_mode.adoptCF(CFStringCreateCopy(0, mode));
+}
+
+} // namespace
index e5a8065..c0cf15a 100644 (file)
@@ -78,6 +78,7 @@ class ResourceHandleClient;
 class ResourceHandleInternal;
 class ResourceRequest;
 class ResourceResponse;
+class SchedulePair;
 class SharedBuffer;
 class SubresourceLoader;
 class SubresourceLoaderClient;
@@ -103,11 +104,16 @@ public:
     void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&);
     void receivedCancellation(const AuthenticationChallenge&);
 #endif
+
 #if PLATFORM(MAC)
     void didCancelAuthenticationChallenge(const AuthenticationChallenge&);
     NSURLConnection *connection() const;
     WebCoreResourceHandleAsDelegate *delegate();
     void releaseDelegate();
+    id releaseProxy();
+
+    void schedule(SchedulePair*);
+    void unschedule(SchedulePair*);
 #elif USE(CFNETWORK)
     static CFRunLoopRef loaderRunLoop();
     CFURLConnectionRef connection() const;
@@ -116,12 +122,9 @@ public:
     static void setHostAllowsAnyHTTPSCertificate(const String&);
     static void setClientCertificate(const String& host, CFDataRef);
 #endif
+
     PassRefPtr<SharedBuffer> bufferedData();
     static bool supportsBufferedData();
-    
-#if PLATFORM(MAC)
-    id releaseProxy();
-#endif
 
 #if USE(WININET)
     void setHasReceivedResponse(bool = true);
index 16f960e..42c7e93 100644 (file)
@@ -107,6 +107,7 @@ namespace WebCore {
             , m_frame(0)
 #endif
 #if PLATFORM(MAC)
+            , m_startWhenScheduled(false)
             , m_currentMacChallenge(nil)
 #elif USE(CFNETWORK)
             , m_currentCFChallenge(0)
@@ -132,6 +133,7 @@ namespace WebCore {
         RetainPtr<NSURLConnection> m_connection;
         RetainPtr<WebCoreResourceHandleAsDelegate> m_delegate;
         RetainPtr<id> m_proxy;
+        bool m_startWhenScheduled;
 #endif
 #if USE(WININET)
         HANDLE m_fileHandle;
index c88fb81..efd09b0 100644 (file)
@@ -33,6 +33,7 @@
 
 #import "CString.h"
 #import "FormData.h"
+#import "SchedulePair.h"
 #import "WebCoreSystemInterface.h"
 #import <sys/stat.h>
 #import <sys/types.h>
@@ -50,53 +51,13 @@ static HashMap<CFReadStreamRef, RefPtr<FormData> >& getStreamFormDatas()
 static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context);
 
 struct FormStreamFields {
-    CFMutableSetRef scheduledRunLoopPairs;
+    SchedulePairHashSet scheduledRunLoopPairs;
     Vector<FormDataElement> remainingElements; // in reverse order
     CFReadStreamRef currentStream;
     char* currentData;
     CFReadStreamRef formStream;
 };
 
-struct SchedulePair {
-    CFRunLoopRef runLoop;
-    CFStringRef mode;
-};
-
-static const void* pairRetain(CFAllocatorRef alloc, const void* value)
-{
-    const SchedulePair* pair = static_cast<const SchedulePair*>(value);
-
-    SchedulePair* result = new SchedulePair;
-    CFRetain(pair->runLoop);
-    result->runLoop = pair->runLoop;
-    result->mode = CFStringCreateCopy(alloc, pair->mode);
-    return result;
-}
-
-static void pairRelease(CFAllocatorRef alloc, const void* value)
-{
-    const SchedulePair* pair = static_cast<const SchedulePair*>(value);
-
-    CFRelease(pair->runLoop);
-    CFRelease(pair->mode);
-    delete pair;
-}
-
-static Boolean pairEqual(const void* a, const void* b)
-{
-    const SchedulePair* pairA = static_cast<const SchedulePair*>(a);
-    const SchedulePair* pairB = static_cast<const SchedulePair*>(b);
-
-    return pairA->runLoop == pairB->runLoop && CFEqual(pairA->mode, pairB->mode);
-}
-
-static CFHashCode pairHash(const void* value)
-{
-    const SchedulePair* pair = static_cast<const SchedulePair*>(value);
-
-    return (CFHashCode)pair->runLoop ^ CFHash(pair->mode);
-}
-
 static void closeCurrentStream(FormStreamFields *form)
 {
     if (form->currentStream) {
@@ -111,14 +72,6 @@ static void closeCurrentStream(FormStreamFields *form)
     }
 }
 
-static void scheduleWithPair(const void* value, void* context)
-{
-    const SchedulePair* pair = static_cast<const SchedulePair*>(value);
-    CFReadStreamRef stream = (CFReadStreamRef)context;
-
-    CFReadStreamScheduleWithRunLoop(stream, pair->runLoop, pair->mode);
-}
-
 static void advanceCurrentStream(FormStreamFields *form)
 {
     closeCurrentStream(form);
@@ -148,7 +101,9 @@ static void advanceCurrentStream(FormStreamFields *form)
         formEventCallback, &context);
 
     // Schedule with the current set of run loops.
-    CFSetApplyFunction(form->scheduledRunLoopPairs, scheduleWithPair, form->currentStream);
+    SchedulePairHashSet::iterator end = form->scheduledRunLoopPairs.end();
+    for (SchedulePairHashSet::iterator it = form->scheduledRunLoopPairs.begin(); it != end; ++it)
+        CFReadStreamScheduleWithRunLoop(form->currentStream, (*it)->runLoop(), (*it)->mode());
 }
 
 static void openNextStream(FormStreamFields* form)
@@ -165,10 +120,7 @@ static void* formCreate(CFReadStreamRef stream, void* context)
 {
     FormData* formData = static_cast<FormData*>(context);
 
-    CFSetCallBacks runLoopAndModeCallBacks = { 0, pairRetain, pairRelease, NULL, pairEqual, pairHash };
-
     FormStreamFields* newInfo = new FormStreamFields;
-    newInfo->scheduledRunLoopPairs = CFSetCreateMutable(0, 0, &runLoopAndModeCallBacks);
     newInfo->currentStream = NULL;
     newInfo->currentData = 0;
     newInfo->formStream = stream; // Don't retain. That would create a reference cycle.
@@ -191,7 +143,6 @@ static void formFinalize(CFReadStreamRef stream, void* context)
     getStreamFormDatas().remove(stream);
 
     closeCurrentStream(form);
-    CFRelease(form->scheduledRunLoopPairs);
     delete form;
 }
 
@@ -256,8 +207,7 @@ static void formSchedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringR
 
     if (form->currentStream)
         CFReadStreamScheduleWithRunLoop(form->currentStream, runLoop, runLoopMode);
-    SchedulePair pair = { runLoop, runLoopMode };
-    CFSetAddValue(form->scheduledRunLoopPairs, &pair);
+    form->scheduledRunLoopPairs.add(SchedulePair::create(runLoop, runLoopMode));
 }
 
 static void formUnschedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context)
@@ -266,8 +216,7 @@ static void formUnschedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStrin
 
     if (form->currentStream)
         CFReadStreamUnscheduleFromRunLoop(form->currentStream, runLoop, runLoopMode);
-    SchedulePair pair = { runLoop, runLoopMode };
-    CFSetRemoveValue(form->scheduledRunLoopPairs, &pair);
+    form->scheduledRunLoopPairs.remove(SchedulePair::create(runLoop, runLoopMode));
 }
 
 static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context)
index 9978a18..6c84ffd 100644 (file)
 #import "DocLoader.h"
 #import "Frame.h"
 #import "FrameLoader.h"
+#import "Page.h"
 #import "ResourceError.h"
 #import "ResourceResponse.h"
+#import "SchedulePair.h"
 #import "SharedBuffer.h"
 #import "SubresourceLoader.h"
 #import "AuthenticationChallenge.h"
@@ -119,9 +121,10 @@ bool ResourceHandle::start(Frame* frame)
 
     // If we are no longer attached to a Page, this must be an attempted load from an
     // onUnload handler, so let's just block it.
-    if (!frame->page())
+    Page* page = frame->page();
+    if (!page)
         return false;
-  
+
 #ifndef NDEBUG
     isInitializingConnection = YES;
 #endif
@@ -141,15 +144,42 @@ bool ResourceHandle::start(Frame* frame)
     NSURLConnection *connection;
     
     if (d->m_shouldContentSniff) 
+#ifdef BUILDING_ON_TIGER
         connection = [[NSURLConnection alloc] initWithRequest:d->m_request.nsURLRequest() delegate:delegate];
+#else
+        connection = [[NSURLConnection alloc] initWithRequest:d->m_request.nsURLRequest() delegate:delegate startImmediately:NO];
+#endif
     else {
         NSMutableURLRequest *request = [d->m_request.nsURLRequest() mutableCopy];
         wkSetNSURLRequestShouldContentSniff(request, NO);
+#ifdef BUILDING_ON_TIGER
         connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
+#else
+        connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate startImmediately:NO];
+#endif
         [request release];
     }
-    
-    
+
+#ifndef BUILDING_ON_TIGER
+    bool scheduled = false;
+    if (SchedulePairHashSet* scheduledPairs = page->scheduledRunLoopPairs()) {
+        SchedulePairHashSet::iterator end = scheduledPairs->end();
+        for (SchedulePairHashSet::iterator it = scheduledPairs->begin(); it != end; ++it) {
+            if (NSRunLoop *runLoop = (*it)->nsRunLoop()) {
+                [connection scheduleInRunLoop:runLoop forMode:(NSString *)(*it)->mode()];
+                scheduled = true;
+            }
+        }
+    }
+
+    // Start the connection if we did schedule with at least one runloop.
+    // We can't start the connection until we have one runloop scheduled.
+    if (scheduled)
+        [connection start];
+    else
+        d->m_startWhenScheduled = true;
+#endif
+
 #ifndef NDEBUG
     isInitializingConnection = NO;
 #endif
@@ -157,7 +187,7 @@ bool ResourceHandle::start(Frame* frame)
     [connection release];
     if (d->m_defersLoading)
         wkSetNSURLConnectionDefersCallbacks(d->m_connection.get(), YES);
-    
+
     if (d->m_connection)
         return true;
 
@@ -177,6 +207,24 @@ void ResourceHandle::setDefersLoading(bool defers)
     wkSetNSURLConnectionDefersCallbacks(d->m_connection.get(), defers);
 }
 
+void ResourceHandle::schedule(SchedulePair* pair)
+{
+    NSRunLoop *runLoop = pair->nsRunLoop();
+    if (!runLoop)
+        return;
+    [d->m_connection.get() scheduleInRunLoop:runLoop forMode:(NSString *)pair->mode()];
+    if (d->m_startWhenScheduled) {
+        [d->m_connection.get() start];
+        d->m_startWhenScheduled = false;
+    }
+}
+
+void ResourceHandle::unschedule(SchedulePair* pair)
+{
+    if (NSRunLoop *runLoop = pair->nsRunLoop())
+        [d->m_connection.get() unscheduleFromRunLoop:runLoop forMode:(NSString *)pair->mode()];
+}
+
 WebCoreResourceHandleAsDelegate *ResourceHandle::delegate()
 {
     if (!d->m_delegate) {
index 9394b8a..81994f2 100644 (file)
@@ -1,3 +1,22 @@
+2008-03-04  Timothy Hatcher  <timothy@apple.com>
+
+        Reviewed by Darin Adler.
+
+        <rdar://problem/5720160> Browser windows "do nothing" while modal
+        dialog or menu is up due to run loop modes (or while scrolling)
+
+        Add new API that lets a WebView be scheduled with multiple runloops and modes.
+        This lets loading continue when in a nested runloop or in a different mode.
+
+        * Misc/WebKitVersionChecks.h: Add a new version define:
+        WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES.
+        * WebView/WebView.mm:
+        (-[WebView _commonInitializationWithFrameName:groupName:]): Schedule in the main runloop and with
+        the default runloop mode if we are linked on an earlier WebKit version, use common modes otherwise.
+        (-[WebView scheduleInRunLoop:forMode:]): New API, that calls through to Page.
+        (-[WebView unscheduleFromRunLoop:forMode:]): Ditto.
+        * WebView/WebViewPrivate.h: Add the new pending API methods.
+
 2008-03-04  Anders Carlsson  <andersca@apple.com>
 
         Reviewed by Darin.
index 5e3ed90..be38c32 100644 (file)
@@ -46,6 +46,7 @@
 #define WEBKIT_FIRST_VERSION_WITH_CACHE_MODEL_API 0x020B0500 // 523.5.0
 #define WEBKIT_FIRST_VERSION_WITHOUT_JAVASCRIPT_RETURN_QUIRK 0x020D0100 // 525.1.0
 #define WEBKIT_FIRST_VERSION_WITH_IE_COMPATIBLE_KEYBOARD_EVENT_DISPATCH 0x020D0100 // 525.1.0
+#define WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES 0x020E0000 // 526.0.0
 
 #ifdef __cplusplus
 extern "C" {
index d259294..a08ebf1 100644 (file)
@@ -1823,6 +1823,11 @@ WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementati
     _private->page = new Page(new WebChromeClient(self), new WebContextMenuClient(self), new WebEditorClient(self), new WebDragClient(self), new WebInspectorClient(self));
     [[[WebFrameBridge alloc] initMainFrameWithPage:_private->page frameName:frameName frameView:frameView] release];
 
+    if (WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES))
+        [self scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
+    else
+        [self scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
+
     [self _addToAllWebViewsSet];
     [self setGroupName:groupName];
     
@@ -1831,9 +1836,8 @@ WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementati
     // contained frame view. This works together with our becomeFirstResponder 
     // and setNextKeyView overrides.
     NSView *nextKeyView = [self nextKeyView];
-    if (nextKeyView != nil && nextKeyView != frameView) {
+    if (nextKeyView && nextKeyView != frameView)
         [frameView setNextKeyView:nextKeyView];
-    }
     [super setNextKeyView:frameView];
 
     ++WebViewCount;
@@ -2838,6 +2842,18 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
 
 @implementation WebView (WebPendingPublic)
 
+- (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
+{
+    if (runLoop && mode)
+        core(self)->addSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
+}
+
+- (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode
+{
+    if (runLoop && mode)
+        core(self)->removeSchedulePair(SchedulePair::create(runLoop, (CFStringRef)mode));
+}
+
 - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
 {
     if (_private->closed)
index 9c95ab0..d75f2ef 100644 (file)
@@ -84,6 +84,9 @@ typedef enum {
 
 @interface WebView (WebPendingPublic)
 
+- (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode;
+- (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode;
+
 /*!
 @method searchFor:direction:caseSensitive:wrap:startInSelection:
  @abstract Searches a document view for a string and highlights the string if it is found.