WebKit:
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Dec 2008 21:40:36 +0000 (21:40 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 23 Dec 2008 21:40:36 +0000 (21:40 +0000)
2008-12-23  Darin Adler  <darin@apple.com>

        Reviewed by Alexey Proskuryakov.

        - fix https://bugs.webkit.org/show_bug.cgi?id=22976
          crash due to Mail's use of WebArchive and WebResource on non-main thread

        * StringsNotToBeLocalized.txt: Updated.

        * WebKit.xcodeproj/project.pbxproj: Added new file WebNSObjectExtras.mm and
        existing file WebResourceInternal.h.

WebKit/mac:

2008-12-23  Darin Adler  <darin@apple.com>

        Reviewed by Alexey Proskuryakov (a slightly earlier version).

        - fix https://bugs.webkit.org/show_bug.cgi?id=22976
          crash due to Mail's use of WebArchive and WebResource on non-main thread

        * Misc/WebKitLogging.h: Improved comments for ASSERT_MAIN_THREAD. Got rid of
        WebKitRunningOnMainThread function, which was just a cover for pthread_main_np.
        * Misc/WebKitLogging.m: Ditto.

        * Misc/WebKitVersionChecks.h: Added a version after which we won't do the
        main thread workaround.

        * Misc/WebNSObjectExtras.h: Added a new method, _webkit_getPropertyOnMainThread:,
        which performs a selector on the main thread, waits for it to complete, and then
        returns the value on the caller thread.
        * Misc/WebNSObjectExtras.mm: Added.

        * WebView/WebArchive.mm:
        (-[WebArchive init]): Added WebCoreThreadViolationCheck.
        (-[WebArchive initWithMainResource:subresources:subframeArchives:]): Perform
        initialization on main thread if needMailThreadWorkaround is true.
        Also added WebCoreThreadViolationCheck.
        (-[WebArchive initWithData:]): Added WebCoreThreadViolationCheck.
        (-[WebArchive mainResource]): Get property on main thread if
        needMailThreadWorkaround is true. Also added WebCoreThreadViolationCheck.
        (-[WebArchive subresources]): Ditto.
        (-[WebArchive subframeArchives]): Ditto.
        (-[WebArchive data]): Ditto.
        (-[WebArchive _initWithCoreLegacyWebArchive:]): Added WebCoreThreadViolationCheck.
        (-[WebArchive _coreLegacyWebArchive]): Ditto.
        (-[WebArchive _initWithArguments:]): Added. Used to implement the cross-thread
        version of initWithMainResource above.

        * WebView/WebResource.mm:
        (-[WebResource initWithCoder:]): Added WebCoreThreadViolationCheck.
        (-[WebResource data]): Get property on main thread if
        needMailThreadWorkaround is true. Also added WebCoreThreadViolationCheck.
        (-[WebResource URL]): Ditto.
        (-[WebResource MIMEType]): Ditto.
        (-[WebResource textEncodingName]): Ditto.
        (-[WebResource frameName]): Ditto.
        (-[WebResource _ignoreWhenUnarchiving]): Ditto.
        (-[WebResource _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:]):
        Perform initialization on main thread if needMailThreadWorkaround is true.
        Also added WebCoreThreadViolationCheck.
        (-[WebResource _suggestedFilename]): Added. Helper for _fileWrapperRepresentation.
        (-[WebResource _fileWrapperRepresentation]): Rewrote to use methods instead of
        getting at coreResource directly.
        (-[WebResource _response]): Get property on main thread if
        needMailThreadWorkaround is true. Also added WebCoreThreadViolationCheck.
        (-[WebResource _stringValue]): Ditto.
        (+[WebResource _needMailThreadWorkaroundIfCalledOffMainThread]): Added.
        (-[WebResource _initWithArguments:]): Added. Used to implement the cross-thread
        version of _initWithData above.

        * WebView/WebResourceInternal.h: Changed to include WebResourcePrivate.h since internal
        clients have access to the SPI as well as the API. Added definition of MAIL_THREAD_WORKAROUND
        and the needMainThreadWorkaround helper function.

        * Misc/WebIconDatabase.mm: Removed include of now-defunct FoundationExtras.h
        file. This probably fixes clean builds.
        * WebCoreSupport/WebIconDatabaseClient.mm: Ditto.

        * WebCoreSupport/WebFrameLoaderClient.mm: Removed include of WebResourcePrivate.h,
        since it's not actually used.
        * WebView/WebDataSource.mm: Ditto.
        * WebView/WebHTMLRepresentation.mm: Ditto.

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

17 files changed:
WebKit/ChangeLog
WebKit/StringsNotToBeLocalized.txt
WebKit/WebKit.xcodeproj/project.pbxproj
WebKit/mac/ChangeLog
WebKit/mac/Misc/WebIconDatabase.mm
WebKit/mac/Misc/WebKitLogging.h
WebKit/mac/Misc/WebKitLogging.m
WebKit/mac/Misc/WebKitVersionChecks.h
WebKit/mac/Misc/WebNSObjectExtras.h
WebKit/mac/Misc/WebNSObjectExtras.mm [new file with mode: 0644]
WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm
WebKit/mac/WebCoreSupport/WebIconDatabaseClient.mm
WebKit/mac/WebView/WebArchive.mm
WebKit/mac/WebView/WebDataSource.mm
WebKit/mac/WebView/WebHTMLRepresentation.mm
WebKit/mac/WebView/WebResource.mm
WebKit/mac/WebView/WebResourceInternal.h

index d00029c..a4527a7 100644 (file)
@@ -1,3 +1,15 @@
+2008-12-23  Darin Adler  <darin@apple.com>
+
+        Reviewed by Alexey Proskuryakov.
+
+        - fix https://bugs.webkit.org/show_bug.cgi?id=22976
+          crash due to Mail's use of WebArchive and WebResource on non-main thread
+
+        * StringsNotToBeLocalized.txt: Updated.
+
+        * WebKit.xcodeproj/project.pbxproj: Added new file WebNSObjectExtras.mm and
+        existing file WebResourceInternal.h.
+
 2008-12-08  David Kilzer  <ddkilzer@apple.com>
 
         Bug 22555: Sort "children" sections in Xcode project files
index 0951b69..3a6b642 100644 (file)
 "Library/Internet Plug-Ins"
 "LresultFromObject"
 "Lucida Grande"
+"MIMEType"
 "MIME\\Database\\Content Type"
 "MemoryStream"
 "MoveDown"
 "com.lizardtech.NPDjVu"
 "com.macromedia.fireworks"
 "com.microsoft.WMP.defaultplugin"
+"copyData"
 "cpuType"
 "dir"
 "displayTitle"
 "estimatedProgress"
 "eval"
 "file:"
+"frameName"
 "ftp:"
 "htm"
 "html"
 "mainFrameIcon"
 "mainFrameTitle"
 "mainFrameURL"
+"mainResource"
 "mimeType"
 "name: %@\npath: %@\nmimeTypes:\n%@\npluginDescription:%@"
 "nullplugin"
 "sourceURL"
 "src"
 "sub"
+"subframeArchives"
+"subresources"
 "text/calendar"
 "text/directory"
 "text/html"
 "text/x-vcalendar"
 "text/x-vcard"
 "text/x-vcf"
+"textEncodingName"
 "tiff"
 "txt"
 "u"
@@ -546,6 +553,8 @@ WebKit/mac/Misc/WebCache.mm:"Images"
 WebKit/mac/Misc/WebKitLogging.h:"<not running on main thread>"
 WebKit/mac/Misc/WebKitVersionChecks.m:"WebKit"
 WebKit/mac/Misc/WebNSNotificationCenterExtras.m
+WebKit/mac/Misc/WebNSObjectExtras.mm:"selector"
+WebKit/mac/Misc/WebNSObjectExtras.mm:"value"
 WebKit/mac/Misc/WebNSPasteboardExtras.mm
 WebKit/mac/Misc/WebNSURLExtras.mm:"file"
 WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm:" OK\n"
@@ -580,6 +589,7 @@ WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm:"height"
 WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm:"width"
 WebKit/mac/WebCoreSupport/WebInspectorClient.mm:"Web Inspector 2"
 WebKit/mac/WebCoreSupport/WebInspectorClient.mm:"inspector"
+WebKit/mac/WebView/WebArchive.mm:"result"
 WebKit/mac/WebView/WebHTMLView.mm:"'%@'"
 WebKit/mac/WebView/WebHTMLView.mm:"Version:"
 WebKit/mac/WebView/WebHTMLView.mm:"applet"
@@ -606,6 +616,10 @@ WebKit/mac/WebView/WebHTMLView.mm:"underline"
 WebKit/mac/WebView/WebHTMLView.mm:"white"
 WebKit/mac/WebView/WebPreferenceKeysPrivate.h
 WebKit/mac/WebView/WebPreferences.mm
+WebKit/mac/WebView/WebResource.mm:"URL"
+WebKit/mac/WebView/WebResource.mm:"data"
+WebKit/mac/WebView/WebResource.mm:"response"
+WebKit/mac/WebView/WebResource.mm:"result"
 WebKit/mac/WebView/WebView.mm:"At least one WebView is still open."
 WebKit/mac/WebView/WebView.mm:"At least one WebView was closed with fast teardown."
 WebKit/mac/WebView/WebView.mm:"Preferences"
index 29d7a1d..bf008d0 100644 (file)
                931633EB0AEDFF930062B92D /* WebFrameLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 931633EA0AEDFF930062B92D /* WebFrameLoaderClient.h */; };
                931633EF0AEDFFAE0062B92D /* WebFrameLoaderClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = 931633EE0AEDFFAE0062B92D /* WebFrameLoaderClient.mm */; };
                934C11670D8710BB00C32ABD /* WebDynamicScrollBarsViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 934C11660D8710BB00C32ABD /* WebDynamicScrollBarsViewInternal.h */; };
+               934C4A910F01406C009372C0 /* WebNSObjectExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = 934C4A900F01406C009372C0 /* WebNSObjectExtras.mm */; };
+               934C4AA00F0141F7009372C0 /* WebResourceInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 934C4A9F0F0141F7009372C0 /* WebResourceInternal.h */; };
                939810110824BF01008DF038 /* WebBackForwardList.h in Headers */ = {isa = PBXBuildFile; fileRef = 3944607D020F50ED0ECA1767 /* WebBackForwardList.h */; settings = {ATTRIBUTES = (Public, ); }; };
                939810120824BF01008DF038 /* WebHistory.h in Headers */ = {isa = PBXBuildFile; fileRef = F520FB190221DEFD01C1A525 /* WebHistory.h */; settings = {ATTRIBUTES = (Public, ); }; };
                939810130824BF01008DF038 /* WebHistoryItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 3944607F020F50ED0ECA1767 /* WebHistoryItem.h */; settings = {ATTRIBUTES = (Public, ); }; };
                9345DDB20365FFD0008635CE /* WebNSControlExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebNSControlExtras.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                9345DDB30365FFD0008635CE /* WebNSControlExtras.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebNSControlExtras.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                934C11660D8710BB00C32ABD /* WebDynamicScrollBarsViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebDynamicScrollBarsViewInternal.h; sourceTree = "<group>"; };
+               934C4A900F01406C009372C0 /* WebNSObjectExtras.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebNSObjectExtras.mm; sourceTree = "<group>"; };
+               934C4A9F0F0141F7009372C0 /* WebResourceInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebResourceInternal.h; sourceTree = "<group>"; };
                939811320824BF01008DF038 /* Info.plist */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = mac/Info.plist; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 1; };
                939811330824BF01008DF038 /* WebKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = WebKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
                93AEB17D032C1735008635CE /* WebKitLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebKitLogging.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                                51494D220C7EC1B6004178C5 /* WebNSNotificationCenterExtras.h */,
                                51494D230C7EC1B7004178C5 /* WebNSNotificationCenterExtras.m */,
                                93D1FE13067EB10B009CE68A /* WebNSObjectExtras.h */,
+                               934C4A900F01406C009372C0 /* WebNSObjectExtras.mm */,
                                ED2B2474033A2DA800C1A526 /* WebNSPasteboardExtras.h */,
                                ED2B2475033A2DA800C1A526 /* WebNSPasteboardExtras.mm */,
                                EDD1A5C605C83987008E3150 /* WebNSPrintOperationExtras.h */,
                                F5F81C3A02B67C26018635CA /* WebRenderNode.mm */,
                                84311A1205EAAAF00088EDA4 /* WebResource.h */,
                                84311A1305EAAAF00088EDA4 /* WebResource.mm */,
+                               934C4A9F0F0141F7009372C0 /* WebResourceInternal.h */,
                                513D422E034CF55A00CA2ACD /* WebResourceLoadDelegate.h */,
                                656D333D0AF21AE900212169 /* WebResourceLoadDelegatePrivate.h */,
                                84311AF105EAB12B0088EDA4 /* WebResourcePrivate.h */,
                                9398105E0824BF01008DF038 /* WebPreferencesPrivate.h in Headers */,
                                9398105F0824BF01008DF038 /* WebRenderNode.h in Headers */,
                                939810880824BF01008DF038 /* WebResource.h in Headers */,
+                               934C4AA00F0141F7009372C0 /* WebResourceInternal.h in Headers */,
                                939810600824BF01008DF038 /* WebResourceLoadDelegate.h in Headers */,
                                656D333E0AF21AE900212169 /* WebResourceLoadDelegatePrivate.h in Headers */,
                                939810890824BF01008DF038 /* WebResourcePrivate.h in Headers */,
                                65EEDE58084FFC9E0002DB25 /* WebNSFileManagerExtras.m in Sources */,
                                939810C70824BF01008DF038 /* WebNSImageExtras.m in Sources */,
                                51494D250C7EC1B7004178C5 /* WebNSNotificationCenterExtras.m in Sources */,
+                               934C4A910F01406C009372C0 /* WebNSObjectExtras.mm in Sources */,
                                939810C80824BF01008DF038 /* WebNSPasteboardExtras.mm in Sources */,
                                939811190824BF01008DF038 /* WebNSPrintOperationExtras.m in Sources */,
                                939811120824BF01008DF038 /* WebNSURLExtras.mm in Sources */,
index e3368da..c254954 100644 (file)
@@ -1,5 +1,75 @@
 2008-12-23  Darin Adler  <darin@apple.com>
 
+        Reviewed by Alexey Proskuryakov (a slightly earlier version).
+
+        - fix https://bugs.webkit.org/show_bug.cgi?id=22976
+          crash due to Mail's use of WebArchive and WebResource on non-main thread
+
+        * Misc/WebKitLogging.h: Improved comments for ASSERT_MAIN_THREAD. Got rid of
+        WebKitRunningOnMainThread function, which was just a cover for pthread_main_np.
+        * Misc/WebKitLogging.m: Ditto.
+
+        * Misc/WebKitVersionChecks.h: Added a version after which we won't do the
+        main thread workaround.
+
+        * Misc/WebNSObjectExtras.h: Added a new method, _webkit_getPropertyOnMainThread:,
+        which performs a selector on the main thread, waits for it to complete, and then
+        returns the value on the caller thread.
+        * Misc/WebNSObjectExtras.mm: Added.
+
+        * WebView/WebArchive.mm:
+        (-[WebArchive init]): Added WebCoreThreadViolationCheck.
+        (-[WebArchive initWithMainResource:subresources:subframeArchives:]): Perform
+        initialization on main thread if needMailThreadWorkaround is true.
+        Also added WebCoreThreadViolationCheck.
+        (-[WebArchive initWithData:]): Added WebCoreThreadViolationCheck.
+        (-[WebArchive mainResource]): Get property on main thread if
+        needMailThreadWorkaround is true. Also added WebCoreThreadViolationCheck.
+        (-[WebArchive subresources]): Ditto.
+        (-[WebArchive subframeArchives]): Ditto.
+        (-[WebArchive data]): Ditto.
+        (-[WebArchive _initWithCoreLegacyWebArchive:]): Added WebCoreThreadViolationCheck.
+        (-[WebArchive _coreLegacyWebArchive]): Ditto.
+        (-[WebArchive _initWithArguments:]): Added. Used to implement the cross-thread
+        version of initWithMainResource above.
+
+        * WebView/WebResource.mm:
+        (-[WebResource initWithCoder:]): Added WebCoreThreadViolationCheck.
+        (-[WebResource data]): Get property on main thread if
+        needMailThreadWorkaround is true. Also added WebCoreThreadViolationCheck.
+        (-[WebResource URL]): Ditto.
+        (-[WebResource MIMEType]): Ditto.
+        (-[WebResource textEncodingName]): Ditto.
+        (-[WebResource frameName]): Ditto.
+        (-[WebResource _ignoreWhenUnarchiving]): Ditto.
+        (-[WebResource _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:]):
+        Perform initialization on main thread if needMailThreadWorkaround is true.
+        Also added WebCoreThreadViolationCheck.
+        (-[WebResource _suggestedFilename]): Added. Helper for _fileWrapperRepresentation.
+        (-[WebResource _fileWrapperRepresentation]): Rewrote to use methods instead of
+        getting at coreResource directly.
+        (-[WebResource _response]): Get property on main thread if
+        needMailThreadWorkaround is true. Also added WebCoreThreadViolationCheck.
+        (-[WebResource _stringValue]): Ditto.
+        (+[WebResource _needMailThreadWorkaroundIfCalledOffMainThread]): Added.
+        (-[WebResource _initWithArguments:]): Added. Used to implement the cross-thread
+        version of _initWithData above.
+
+        * WebView/WebResourceInternal.h: Changed to include WebResourcePrivate.h since internal
+        clients have access to the SPI as well as the API. Added definition of MAIL_THREAD_WORKAROUND
+        and the needMainThreadWorkaround helper function.
+
+        * Misc/WebIconDatabase.mm: Removed include of now-defunct FoundationExtras.h
+        file. This probably fixes clean builds.
+        * WebCoreSupport/WebIconDatabaseClient.mm: Ditto.
+
+        * WebCoreSupport/WebFrameLoaderClient.mm: Removed include of WebResourcePrivate.h,
+        since it's not actually used.
+        * WebView/WebDataSource.mm: Ditto.
+        * WebView/WebHTMLRepresentation.mm: Ditto.
+
+2008-12-23  Darin Adler  <darin@apple.com>
+
         Reviewed by Dan Bernstein.
 
         - fix https://bugs.webkit.org/show_bug.cgi?id=22979
index d911f0c..e3040a6 100644 (file)
@@ -37,7 +37,6 @@
 #import "WebNSURLExtras.h"
 #import "WebPreferences.h"
 #import "WebTypesInternal.h"
-#import <WebCore/FoundationExtras.h>
 #import <WebCore/IconDatabase.h>
 #import <WebCore/Image.h>
 #import <WebCore/IntSize.h>
index dc37dbf..f71f730 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2007, 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
@@ -63,13 +63,11 @@ extern WTFLogChannel WebKitLogTextInput;
 
 void WebKitInitializeLoggingChannelsIfNecessary(void);
 
-BOOL WebKitRunningOnMainThread(void);
-
-// The ASSERT_MAIN_THREAD() check should be on by default in DEBUG builds
-// To disable it, even in a debug build, define DISABLE_THREAD_CHECK in your project file (or elsewhere globally)
+// FIXME: Why is this in the "logging" header file?
+// Use WebCoreThreadViolationCheck instead for checks that throw an exception even in production builds.
 #if !defined(NDEBUG) && !defined(DISABLE_THREAD_CHECK)
 #define ASSERT_MAIN_THREAD() do \
-    if (!WebKitRunningOnMainThread()) { \
+    if (!pthread_main_np()) { \
         WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, "<not running on main thread>"); \
         CRASH(); \
     } \
index 4e4294f..72a822f 100644 (file)
@@ -99,11 +99,6 @@ void WebKitInitializeLoggingChannelsIfNecessary()
     initializeLogChannel(&WebKitLogTextInput);
 }
 
-BOOL WebKitRunningOnMainThread()
-{
-    return pthread_main_np() != 0;
-}
-
 void ReportDiscardedDelegateException(SEL delegateSelector, id exception)
 {
     if ([exception isKindOfClass:[NSException class]])
index a2d6611..8b54c11 100644 (file)
@@ -49,6 +49,7 @@
 #define WEBKIT_FIRST_VERSION_WITH_LOADING_DURING_COMMON_RUNLOOP_MODES 0x020E0000 // 526.0.0
 #define WEBKIT_FIRST_VERSION_WITH_MORE_STRICT_LOCAL_RESOURCE_SECURITY_RESTRICTION 0x02100200 // 528.2.0
 #define WEBKIT_FIRST_VERSION_WITH_RELOAD_FROM_ORIGIN 0x02100700 // 528.7.0
+#define WEBKIT_FIRST_VERSION_WITHOUT_MAIL_THREAD_WORKAROUND 0x02100700 // 528.7.0
 
 #ifdef __cplusplus
 extern "C" {
index 8029825..4b482c2 100644 (file)
@@ -52,3 +52,7 @@ static inline IMP method_setImplementation(Method m, IMP i)
 }
 
 #endif
+
+@interface NSObject (WebNSObjectExtras)
+- (id)_webkit_getPropertyOnMainThread:(SEL)selector;
+@end
diff --git a/WebKit/mac/Misc/WebNSObjectExtras.mm b/WebKit/mac/Misc/WebNSObjectExtras.mm
new file mode 100644 (file)
index 0000000..0e50b81
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#import "WebNSObjectExtras.h"
+
+@implementation NSObject (WebNSObjectExtras)
+
+- (void)_webkit_getPropertyWithArguments:(NSMutableDictionary *)arguments
+{
+    SEL selector = static_cast<SEL>([[arguments objectForKey:@"selector"] pointerValue]);
+    @try {
+        id result = [self performSelector:selector];
+        if (result)
+            [arguments setObject:result forKey:@"value"];
+    } @catch(NSException *exception) {
+        [arguments setObject:exception forKey:@"exception"];
+    }
+}
+
+- (id)_webkit_getPropertyOnMainThread:(SEL)selector
+{
+    NSMutableDictionary *arguments = [[NSMutableDictionary alloc] init];
+    [arguments setObject:[NSValue valueWithPointer:selector] forKey:@"selector"];
+    [self performSelectorOnMainThread:@selector(_webkit_getPropertyWithArguments:) withObject:arguments waitUntilDone:TRUE];
+    NSException *exception = [[[arguments objectForKey:@"exception"] retain] autorelease];
+    id value = [[[arguments objectForKey:@"value"] retain] autorelease];
+    [arguments release];
+    if (exception)
+        [exception raise];
+    return value;
+}
+
+@end
index 313f49b..5de1639 100644 (file)
@@ -67,7 +67,6 @@
 #import "WebPolicyDelegatePrivate.h"
 #import "WebPreferences.h"
 #import "WebResourceLoadDelegate.h"
-#import "WebResourcePrivate.h"
 #import "WebUIDelegate.h"
 #import "WebUIDelegatePrivate.h"
 #import "WebViewInternal.h"
index 43202b0..dc9ae6d 100644 (file)
@@ -30,7 +30,6 @@
 
 #import "WebIconDatabaseInternal.h"
 
-#import <WebCore/FoundationExtras.h>
 #import <WebCore/PlatformString.h>
 
 
index 81d8251..2267457 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 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
 #import "WebArchiveInternal.h"
 
 #import "WebKitLogging.h"
+#import "WebNSObjectExtras.h"
 #import "WebResourceInternal.h"
-#import "WebResourcePrivate.h"
 #import "WebTypesInternal.h"
-
+#import <JavaScriptCore/InitializeThreading.h>
 #import <WebCore/ArchiveResource.h>
 #import <WebCore/LegacyWebArchive.h>
+#import <WebCore/ThreadCheck.h>
 #import <WebCore/WebCoreObjCExtras.h>
-#import <runtime/InitializeThreading.h>
 
 using namespace WebCore;
 
@@ -47,8 +47,7 @@ static NSString * const WebMainResourceKey = @"WebMainResource";
 static NSString * const WebSubresourcesKey = @"WebSubresources";
 static NSString * const WebSubframeArchivesKey = @"WebSubframeArchives";
 
-@interface WebArchivePrivate : NSObject
-{
+@interface WebArchivePrivate : NSObject {
 @public
     WebResource *cachedMainResource;
     NSArray *cachedSubresources;
@@ -75,8 +74,9 @@ static NSString * const WebSubframeArchivesKey = @"WebSubframeArchives";
 - (id)init
 {
     self = [super init];
-    if (self)
-        coreArchive = LegacyWebArchive::create().releaseRef();
+    if (!self)
+        return nil;
+    coreArchive = LegacyWebArchive::create().releaseRef();
     return self;
 }
 
@@ -87,9 +87,7 @@ static NSString * const WebSubframeArchivesKey = @"WebSubframeArchives";
         [self release];
         return nil;
     }
-    
     coreArchive = _coreArchive.releaseRef();
-    
     return self;
 }
 
@@ -137,6 +135,8 @@ static NSString * const WebSubframeArchivesKey = @"WebSubframeArchives";
 
 - (id)init
 {
+    WebCoreThreadViolationCheck();
+
     self = [super init];
     if (!self)
         return nil;
@@ -158,6 +158,28 @@ static BOOL isArrayOfClass(id object, Class elementClass)
 
 - (id)initWithMainResource:(WebResource *)mainResource subresources:(NSArray *)subresources subframeArchives:(NSArray *)subframeArchives
 {
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround()) {
+        // Maybe this could be done more cleanly with NSInvocation.
+        NSMutableDictionary *arguments = [[NSMutableDictionary alloc] init];
+        if (mainResource)
+            [arguments setObject:mainResource forKey:@"mainResource"];
+        if (subresources)
+            [arguments setObject:subresources forKey:@"subresources"];
+        if (subframeArchives)
+            [arguments setObject:subframeArchives forKey:@"subframeArchives"];
+        [self performSelectorOnMainThread:@selector(_initWithArguments:) withObject:arguments waitUntilDone:TRUE];
+        NSException *exception = [[[arguments objectForKey:@"exception"] retain] autorelease];
+        id result = [[[arguments objectForKey:@"result"] retain] autorelease];
+        [arguments release];
+        if (exception)
+            [exception raise];
+        return result;
+    }
+#endif
+
+    WebCoreThreadViolationCheck();
+
     self = [super init];
     if (!self)
         return nil;
@@ -209,6 +231,8 @@ static BOOL isArrayOfClass(id object, Class elementClass)
 
 - (id)initWithData:(NSData *)data
 {
+    WebCoreThreadViolationCheck();
+
     self = [super init];
     if (!self)
         return nil;
@@ -273,6 +297,13 @@ static BOOL isArrayOfClass(id object, Class elementClass)
 
 - (WebResource *)mainResource
 {
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround())
+        return [self _webkit_getPropertyOnMainThread:_cmd];
+#endif
+
+    WebCoreThreadViolationCheck();
+
     // Currently from WebKit API perspective, WebArchives are entirely immutable once created
     // If they ever become mutable, we'll need to rethink this. 
     if (!_private->cachedMainResource) {
@@ -286,6 +317,13 @@ static BOOL isArrayOfClass(id object, Class elementClass)
 
 - (NSArray *)subresources
 {
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround())
+        return [self _webkit_getPropertyOnMainThread:_cmd];
+#endif
+
+    WebCoreThreadViolationCheck();
+
     // Currently from WebKit API perspective, WebArchives are entirely immutable once created
     // If they ever become mutable, we'll need to rethink this.     
     if (!_private->cachedSubresources) {
@@ -311,6 +349,13 @@ static BOOL isArrayOfClass(id object, Class elementClass)
 
 - (NSArray *)subframeArchives
 {
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround())
+        return [self _webkit_getPropertyOnMainThread:_cmd];
+#endif
+
+    WebCoreThreadViolationCheck();
+
     // Currently from WebKit API perspective, WebArchives are entirely immutable once created
     // If they ever become mutable, we'll need to rethink this.  
     if (!_private->cachedSubframeArchives) {
@@ -334,6 +379,8 @@ static BOOL isArrayOfClass(id object, Class elementClass)
 
 - (NSData *)data
 {
+    WebCoreThreadViolationCheck();
+
 #if !LOG_DISABLED
     CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
 #endif
@@ -355,6 +402,8 @@ static BOOL isArrayOfClass(id object, Class elementClass)
 
 - (id)_initWithCoreLegacyWebArchive:(PassRefPtr<WebCore::LegacyWebArchive>)coreLegacyWebArchive
 {
+    WebCoreThreadViolationCheck();
+
     self = [super init];
     if (!self)
         return nil;
@@ -370,7 +419,31 @@ static BOOL isArrayOfClass(id object, Class elementClass)
 
 - (WebCore::LegacyWebArchive *)_coreLegacyWebArchive
 {
+    WebCoreThreadViolationCheck();
+
     return [_private coreArchive];
 }
 
 @end
+
+#ifdef MAIL_THREAD_WORKAROUND
+
+@implementation WebArchive (WebMailThreadWorkaround)
+
+- (void)_initWithArguments:(NSMutableDictionary *)arguments
+{
+    WebResource *mainResource = [arguments objectForKey:@"mainResource"];
+    NSArray *subresources = [arguments objectForKey:@"subresources"];
+    NSArray *subframeArchives = [arguments objectForKey:@"subframeArchives"];
+    @try {
+        id result = [self initWithMainResource:mainResource subresources:subresources subframeArchives:subframeArchives];
+        if (result)
+            [arguments setObject:result forKey:@"result"];
+    } @catch(NSException *exception) {
+        [arguments setObject:exception forKey:@"exception"];
+    }
+}
+
+@end
+
+#endif
index 747f39c..12afcb3 100644 (file)
@@ -46,7 +46,6 @@
 #import "WebPDFRepresentation.h"
 #import "WebResourceInternal.h"
 #import "WebResourceLoadDelegate.h"
-#import "WebResourcePrivate.h"
 #import "WebViewInternal.h"
 #import <WebCore/ApplicationCacheStorage.h>
 #import <WebCore/FrameLoader.h>
index dd862f1..604a17a 100644 (file)
@@ -39,7 +39,6 @@
 #import "WebKitStatisticsPrivate.h"
 #import "WebNSAttributedStringExtras.h"
 #import "WebNSObjectExtras.h"
-#import "WebResourcePrivate.h"
 #import "WebView.h"
 #import <Foundation/NSURLResponse.h>
 #import <WebCore/Document.h>
index 6fb10f3..9102ca7 100644 (file)
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import "WebResourcePrivate.h"
+#import "WebResourceInternal.h"
 
 #import "WebFrameInternal.h"
+#import "WebKitLogging.h"
+#import "WebKitVersionChecks.h"
 #import "WebNSDictionaryExtras.h"
+#import "WebNSObjectExtras.h"
 #import "WebNSURLExtras.h"
-
+#import <JavaScriptCore/InitializeThreading.h>
+#import <JavaScriptCore/PassRefPtr.h>
 #import <WebCore/ArchiveResource.h>
 #import <WebCore/LegacyWebArchive.h>
 #import <WebCore/TextEncoding.h>
+#import <WebCore/ThreadCheck.h>
 #import <WebCore/WebCoreObjCExtras.h>
 #import <WebCore/WebCoreURLResponse.h>
 
-#import <runtime/InitializeThreading.h>
-#import <wtf/PassRefPtr.h>
-
 using namespace WebCore;
 
 static NSString * const WebResourceDataKey =              @"WebResourceData";
@@ -50,14 +52,10 @@ static NSString * const WebResourceURLKey =               @"WebResourceURL";
 static NSString * const WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
 static NSString * const WebResourceResponseKey =          @"WebResourceResponse";
 
-#define WebResourceVersion 1
-
-@interface WebResourcePrivate : NSObject
-{
+@interface WebResourcePrivate : NSObject {
 @public
     ArchiveResource* coreResource;
 }
-
 - (id)initWithCoreResource:(PassRefPtr<ArchiveResource>)coreResource;
 @end
 
@@ -80,11 +78,9 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
 {
     self = [super init];
     if (!self)
-        return self;
-    
+        return nil;
     // Acquire the PassRefPtr<>'s ref as our own manual ref
     coreResource = passedResource.releaseRef();
-
     return self;
 }
 
@@ -125,6 +121,8 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
 
 - (id)initWithCoder:(NSCoder *)decoder
 {
+    WebCoreThreadViolationCheck();
+
     self = [super init];
     if (!self)
         return nil;
@@ -202,29 +200,78 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
 
 - (NSData *)data
 {
-    if (_private->coreResource && _private->coreResource->data())
-        return [_private->coreResource->data()->createNSData() autorelease];
-    return 0;
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround())
+        return [self _webkit_getPropertyOnMainThread:_cmd];
+#endif
+
+    WebCoreThreadViolationCheck();
+
+    if (!_private->coreResource)
+        return nil;
+    if (!_private->coreResource->data())
+        return nil;
+    return [_private->coreResource->data()->createNSData() autorelease];
 }
 
 - (NSURL *)URL
 {
-    return _private->coreResource ? (NSURL *)_private->coreResource->url() : 0;
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround())
+        return [self _webkit_getPropertyOnMainThread:_cmd];
+#endif
+
+    WebCoreThreadViolationCheck();
+
+    if (!_private->coreResource)
+        return nil;
+    NSURL *url = _private->coreResource->url();
+    return url;
 }
 
 - (NSString *)MIMEType
 {
-    return _private->coreResource ? (NSString *)_private->coreResource->mimeType() : 0;
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround())
+        return [self _webkit_getPropertyOnMainThread:_cmd];
+#endif
+
+    WebCoreThreadViolationCheck();
+
+    if (!_private->coreResource)
+        return nil;
+    NSString *mimeType = _private->coreResource->mimeType();
+    return mimeType;
 }
 
 - (NSString *)textEncodingName
 {
-    return _private->coreResource ? (NSString *)_private->coreResource->textEncoding() : 0;
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround())
+        return [self _webkit_getPropertyOnMainThread:_cmd];
+#endif
+
+    WebCoreThreadViolationCheck();
+
+    if (!_private->coreResource)
+        return nil;
+    NSString *textEncodingName = _private->coreResource->textEncoding();
+    return textEncodingName;
 }
 
 - (NSString *)frameName
 {
-    return _private->coreResource ? (NSString *)_private->coreResource->frameName() : 0;
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround())
+        return [self _webkit_getPropertyOnMainThread:_cmd];
+#endif
+
+    WebCoreThreadViolationCheck();
+
+    if (!_private->coreResource)
+        return nil;
+    NSString *frameName = _private->coreResource->frameName();
+    return frameName;
 }
 
 - (id)description
@@ -269,8 +316,18 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
 // FIXME: This "ignoreWhenUnarchiving" concept is an ugly one - can we find a cleaner solution for those who need this SPI?
 - (void)_ignoreWhenUnarchiving
 {
-    if (_private->coreResource)
-        _private->coreResource->ignoreWhenUnarchiving();
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround()) {
+        [self performSelectorOnMainThread:@selector(_ignoreWhenUnarchiving) withObject:nil waitUntilDone:TRUE];
+        return;
+    }
+#endif
+
+    WebCoreThreadViolationCheck();
+
+    if (!_private->coreResource)
+        return;
+    _private->coreResource->ignoreWhenUnarchiving();
 }
 
 - (id)_initWithData:(NSData *)data 
@@ -281,6 +338,36 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
            response:(NSURLResponse *)response
            copyData:(BOOL)copyData
 {
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround()) {
+        // Maybe this could be done more cleanly with NSInvocation.
+        NSMutableDictionary *arguments = [[NSMutableDictionary alloc] init];
+        if (data)
+            [arguments setObject:data forKey:@"data"];
+        if (URL)
+            [arguments setObject:URL forKey:@"URL"];
+        if (MIMEType)
+            [arguments setObject:MIMEType forKey:@"MIMEType"];
+        if (textEncodingName)
+            [arguments setObject:textEncodingName forKey:@"textEncodingName"];
+        if (frameName)
+            [arguments setObject:frameName forKey:@"frameName"];
+        if (response)
+            [arguments setObject:response forKey:@"response"];
+        if (copyData)
+            [arguments setObject:[NSNumber numberWithBool:YES] forKey:@"copyData"];
+        [self performSelectorOnMainThread:@selector(_initWithArguments:) withObject:arguments waitUntilDone:TRUE];
+        NSException *exception = [[[arguments objectForKey:@"exception"] retain] autorelease];
+        id result = [[[arguments objectForKey:@"result"] retain] autorelease];
+        [arguments release];
+        if (exception)
+            [exception raise];
+        return result;
+    }
+#endif
+
+    WebCoreThreadViolationCheck();
+
     self = [super init];
     if (!self)
         return nil;
@@ -308,41 +395,96 @@ static NSString * const WebResourceResponseKey =          @"WebResourceResponse"
                       copyData:NO];    
 }
 
+- (NSString *)_suggestedFilename
+{
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround())
+        return [self _webkit_getPropertyOnMainThread:_cmd];
+#endif
+
+    WebCoreThreadViolationCheck();
+
+    if (!_private->coreResource)
+        return nil;
+    NSString *suggestedFilename = _private->coreResource->response().suggestedFilename();
+    return suggestedFilename;
+}
+
 - (NSFileWrapper *)_fileWrapperRepresentation
 {
-    SharedBuffer* coreData = _private->coreResource ? _private->coreResource->data() : 0;
-    NSData *data = coreData ? [coreData->createNSData() autorelease] : nil;
-    
-    NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:data] autorelease];
-    NSString *preferredFilename = _private->coreResource ? (NSString *)_private->coreResource->response().suggestedFilename() : nil;
-    if (!preferredFilename || ![preferredFilename length]) {
-        NSURL *url = _private->coreResource ? (NSURL *)_private->coreResource->url() : nil;
-        NSString *mimeType = _private->coreResource ? (NSString *)_private->coreResource->mimeType() : nil;
-        preferredFilename = [url _webkit_suggestedFilenameWithMIMEType:mimeType];
-    }
-    
-    [wrapper setPreferredFilename:preferredFilename];
+    NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[self data]] autorelease];
+    NSString *filename = [self _suggestedFilename];
+    if (!filename || ![filename length])
+        filename = [[self URL] _webkit_suggestedFilenameWithMIMEType:[self MIMEType]];
+    [wrapper setPreferredFilename:filename];
     return wrapper;
 }
 
 - (NSURLResponse *)_response
 {
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround())
+        return [self _webkit_getPropertyOnMainThread:_cmd];
+#endif
+
+    WebCoreThreadViolationCheck();
+
     NSURLResponse *response = nil;
     if (_private->coreResource)
         response = _private->coreResource->response().nsURLResponse();
-    
     return response ? response : [[[NSURLResponse alloc] init] autorelease];        
 }
 
 - (NSString *)_stringValue
 {
-    WebCore::TextEncoding encoding(_private->coreResource ? (NSString *)_private->coreResource->textEncoding() : nil);
+#ifdef MAIL_THREAD_WORKAROUND
+    if (needMailThreadWorkaround())
+        return [self _webkit_getPropertyOnMainThread:_cmd];
+#endif
+
+    WebCoreThreadViolationCheck();
+
+    WebCore::TextEncoding encoding;
+    if (_private->coreResource)
+        encoding = _private->coreResource->textEncoding();
     if (!encoding.isValid())
         encoding = WindowsLatin1Encoding();
     
     SharedBuffer* coreData = _private->coreResource ? _private->coreResource->data() : 0;
-    
     return encoding.decode(reinterpret_cast<const char*>(coreData ? coreData->data() : 0), coreData ? coreData->size() : 0);
 }
 
 @end
+
+#ifdef MAIL_THREAD_WORKAROUND
+
+@implementation WebResource (WebMailThreadWorkaround)
+
++ (BOOL)_needMailThreadWorkaroundIfCalledOffMainThread
+{
+    static BOOL isOldMail = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_MAIL_THREAD_WORKAROUND)
+        && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.mail"];
+    return isOldMail;
+}
+
+- (void)_initWithArguments:(NSMutableDictionary *)arguments
+{
+    NSData *data = [arguments objectForKey:@"data"];
+    NSURL *URL = [arguments objectForKey:@"URL"];
+    NSString *MIMEType = [arguments objectForKey:@"MIMEType"];
+    NSString *textEncodingName = [arguments objectForKey:@"textEncodingName"];
+    NSString *frameName = [arguments objectForKey:@"frameName"];
+    NSURLResponse *response = [arguments objectForKey:@"response"];
+    bool copyData = [arguments objectForKey:@"copyData"];
+    @try {
+        id result = [self _initWithData:data URL:URL MIMEType:MIMEType textEncodingName:textEncodingName frameName:frameName response:response copyData:copyData];
+        if (result)
+            [arguments setObject:result forKey:@"result"];
+    } @catch(NSException *exception) {
+        [arguments setObject:exception forKey:@"exception"];
+    }
+}
+
+@end
+
+#endif
index 84f6aba..d135197 100644 (file)
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import "WebResource.h"
-
+#import "WebResourcePrivate.h"
 #import <wtf/PassRefPtr.h>
 
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
+#define MAIL_THREAD_WORKAROUND 1
+#endif
+
 namespace WebCore {
     class ArchiveResource;
 }
 
 @interface WebResource (WebResourceInternal)
+- (id)_initWithCoreResource:(PassRefPtr<WebCore::ArchiveResource>)coreResource;
+- (WebCore::ArchiveResource*)_coreResource;
+@end
 
-- (id)_initWithCoreResource:(WTF::PassRefPtr<WebCore::ArchiveResource>)coreResource;
-- (WebCore::ArchiveResource *)_coreResource;
+#ifdef MAIL_THREAD_WORKAROUND
 
+@interface WebResource (WebMailThreadWorkaround)
++ (BOOL)_needMailThreadWorkaroundIfCalledOffMainThread;
 @end
+
+inline bool needMailThreadWorkaround()
+{
+    return !pthread_main_np() && [WebResource _needMailThreadWorkaroundIfCalledOffMainThread];
+}
+
+#endif