1/* 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#import "WebDocumentLoaderMac.h" 30 31#import "WebKitVersionChecks.h" 32#import "WebView.h" 33 34using namespace WebCore; 35 36WebDocumentLoaderMac::WebDocumentLoaderMac(const ResourceRequest& request, const SubstituteData& substituteData) 37 : DocumentLoader(request, substituteData) 38 , m_dataSource(nil) 39 , m_isDataSourceRetained(false) 40{ 41} 42 43static inline bool needsDataLoadWorkaround(WebView *webView) 44{ 45#ifdef BUILDING_ON_TIGER 46 // Tiger has to be a little less efficient. 47 id frameLoadDelegate = [webView frameLoadDelegate]; 48 if (!frameLoadDelegate) 49 return false; 50 51 NSString *bundleIdentifier = [[NSBundle bundleForClass:[frameLoadDelegate class]] bundleIdentifier]; 52 53 if ([bundleIdentifier isEqualToString:@"com.apple.AppKit"]) 54 return true; 55 if ([bundleIdentifier isEqualToString:@"com.adobe.Installers.Setup"]) 56 return true; 57 return false; 58#else 59 static bool needsWorkaround = !WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITHOUT_ADOBE_INSTALLER_QUIRK) 60 && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.adobe.Installers.Setup"]; 61 return needsWorkaround; 62#endif 63} 64 65void WebDocumentLoaderMac::setDataSource(WebDataSource *dataSource, WebView *webView) 66{ 67 ASSERT(!m_dataSource); 68 ASSERT(!m_isDataSourceRetained); 69 70 m_dataSource = dataSource; 71 retainDataSource(); 72 73 m_resourceLoadDelegate = [webView resourceLoadDelegate]; 74 m_downloadDelegate = [webView downloadDelegate]; 75 76 // Some clients run the run loop in a way that prevents the data load timer 77 // from firing. We work around that issue here. See <rdar://problem/5266289> 78 // and <rdar://problem/5049509>. 79 if (needsDataLoadWorkaround(webView)) 80 m_deferMainResourceDataLoad = false; 81} 82 83WebDataSource *WebDocumentLoaderMac::dataSource() const 84{ 85 return m_dataSource; 86} 87 88void WebDocumentLoaderMac::attachToFrame() 89{ 90 DocumentLoader::attachToFrame(); 91 92 retainDataSource(); 93} 94 95void WebDocumentLoaderMac::detachFromFrame() 96{ 97 DocumentLoader::detachFromFrame(); 98 99 if (m_loadingResources.isEmpty()) 100 releaseDataSource(); 101 102 // FIXME: What prevents the data source from getting deallocated while the 103 // frame is not attached? 104} 105 106void WebDocumentLoaderMac::increaseLoadCount(unsigned long identifier) 107{ 108 ASSERT(m_dataSource); 109 110 if (m_loadingResources.contains(identifier)) 111 return; 112 m_loadingResources.add(identifier); 113 114 retainDataSource(); 115} 116 117void WebDocumentLoaderMac::decreaseLoadCount(unsigned long identifier) 118{ 119 HashSet<unsigned long>::iterator it = m_loadingResources.find(identifier); 120 121 // It is valid for a load to be cancelled before it's started. 122 if (it == m_loadingResources.end()) 123 return; 124 125 m_loadingResources.remove(it); 126 127 if (m_loadingResources.isEmpty()) { 128 m_resourceLoadDelegate = 0; 129 m_downloadDelegate = 0; 130 if (!frame()) 131 releaseDataSource(); 132 } 133} 134 135void WebDocumentLoaderMac::retainDataSource() 136{ 137 if (m_isDataSourceRetained || !m_dataSource) 138 return; 139 m_isDataSourceRetained = true; 140 CFRetain(m_dataSource); 141} 142 143void WebDocumentLoaderMac::releaseDataSource() 144{ 145 if (!m_isDataSourceRetained) 146 return; 147 ASSERT(m_dataSource); 148 m_isDataSourceRetained = false; 149 CFRelease(m_dataSource); 150} 151 152void WebDocumentLoaderMac::detachDataSource() 153{ 154 ASSERT(!m_isDataSourceRetained); 155 m_dataSource = nil; 156} 157