Changeset 77055 in webkit
- Timestamp:
- Jan 29, 2011 12:34:46 AM (13 years ago)
- Location:
- trunk/Source
- Files:
-
- 2 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r77053 r77055 1 2011-01-28 Jon Honeycutt <jhoneycutt@apple.com> 2 3 Downloads in WK2 on Windows should write resume data to bundle 4 https://bugs.webkit.org/show_bug.cgi?id=53282 5 <rdar://problem/8753077> 6 7 Reviewed by Alice Liu. 8 9 * WebCore.vcproj/WebCore.vcproj: 10 Added new files to project. 11 12 * platform/network/cf/DownloadBundle.h: Added. 13 * platform/network/win/DownloadBundleWin.cpp: Added. 14 (WebCore::DownloadBundle::magicNumber): 15 Moved from WebKit's WebDownload so that WebKit and WebKit2 can share 16 it. 17 (WebCore::DownloadBundle::fileExtension): 18 Ditto. 19 (WebCore::DownloadBundle::appendResumeData): 20 Ditto - but modified to return bool rather than HRESULT and to clean up 21 whitespace. 22 (WebCore::DownloadBundle::extractResumeData): 23 Ditto - modified to clean up whitespace. 24 1 25 2011-01-29 Sheriff Bot <webkit.review.bot@gmail.com> 2 26 -
trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj
r76980 r77055 29337 29337 </File> 29338 29338 <File 29339 RelativePath="..\platform\network\cf\DownloadBundle.h" 29340 > 29341 </File> 29342 <File 29339 29343 RelativePath="..\platform\network\cf\FormDataStreamCFNet.cpp" 29340 29344 > … … 29628 29632 Name="win" 29629 29633 > 29634 <File 29635 RelativePath="..\platform\network\win\DownloadBundleWin.cpp" 29636 > 29637 </File> 29630 29638 <File 29631 29639 RelativePath="..\platform\network\win\NetworkStateNotifierWin.cpp" -
trunk/Source/WebKit/win/ChangeLog
r76983 r77055 1 2011-01-28 Jon Honeycutt <jhoneycutt@apple.com> 2 3 Downloads in WK2 on Windows should write resume data to bundle 4 https://bugs.webkit.org/show_bug.cgi?id=53282 5 <rdar://problem/8753077> 6 7 Reviewed by Alice Liu. 8 9 * WebDownload.cpp: 10 (WebDownload::bundlePathForTargetPath): 11 Use the new WebCore::DownloadBundle function. 12 (WebDownload::request): 13 14 * WebDownload.h: 15 Removed declarations for functions that were moved to a new location. 16 17 * WebDownloadCFNet.cpp: 18 (WebDownload::initToResumeWithBundle): 19 Use the new WebCore::DownloadBundle function. 20 (WebDownload::cancelForResume): 21 Fix a leak of the resume data CFDataRef by using adoptCF(). Use the new 22 WebCore::DownloadBundle function. 23 1 24 2011-01-28 Dan Bernstein <mitz@apple.com> 2 25 -
trunk/Source/WebKit/win/WebDownload.cpp
r56825 r77055 39 39 #include <wtf/text/CString.h> 40 40 41 #include <io.h>42 #include <sys/stat.h>43 #include <sys/types.h>44 45 41 #pragma warning(push, 0) 46 42 #include <WebCore/BString.h> 43 #include <WebCore/DownloadBundle.h> 47 44 #include <WebCore/NotImplemented.h> 48 45 #include <WebCore/ResourceError.h> … … 55 52 56 53 using namespace WebCore; 57 58 // Download Bundle file utilities ----------------------------------------------------------------59 const String& WebDownload::bundleExtension()60 {61 DEFINE_STATIC_LOCAL(const String, bundleExtension, (".download"));62 return bundleExtension;63 }64 65 UInt32 WebDownload::bundleMagicNumber()66 {67 return 0xDECAF4EA;68 }69 54 70 55 // WebDownload ---------------------------------------------------------------- … … 166 151 bundle.truncate(1); 167 152 168 bundle += bundleExtension();153 bundle += DownloadBundle::fileExtension(); 169 154 *bundlePath = SysAllocStringLen(bundle.characters(), bundle.length()); 170 155 if (!*bundlePath) … … 183 168 return S_OK; 184 169 } 185 186 // Download Bundle file utilities ----------------------------------------------------------------187 188 CFDataRef WebDownload::extractResumeDataFromBundle(const String& bundlePath)189 {190 if (bundlePath.isEmpty()) {191 LOG_ERROR("Cannot create resume data from empty download bundle path");192 return 0;193 }194 195 // Open a handle to the bundle file196 String nullifiedPath = bundlePath;197 FILE* bundle = 0;198 if (_wfopen_s(&bundle, nullifiedPath.charactersWithNullTermination(), TEXT("r+b")) || !bundle) {199 LOG_ERROR("Failed to open file %s to get resume data", bundlePath.ascii().data());200 return 0;201 }202 203 CFDataRef result = 0;204 Vector<UInt8> footerBuffer;205 206 // Stat the file to get its size207 struct _stat64 fileStat;208 if (_fstat64(_fileno(bundle), &fileStat))209 goto exit;210 211 // Check for the bundle magic number at the end of the file212 fpos_t footerMagicNumberPosition = fileStat.st_size - 4;213 ASSERT(footerMagicNumberPosition >= 0);214 if (footerMagicNumberPosition < 0)215 goto exit;216 if (fsetpos(bundle, &footerMagicNumberPosition))217 goto exit;218 219 UInt32 footerMagicNumber = 0;220 if (fread(&footerMagicNumber, 4, 1, bundle) != 1) {221 LOG_ERROR("Failed to read footer magic number from the bundle - errno(%i)", errno);222 goto exit;223 }224 225 if (footerMagicNumber != bundleMagicNumber()) {226 LOG_ERROR("Footer's magic number does not match 0x%X - errno(%i)", bundleMagicNumber(), errno);227 goto exit;228 }229 230 // Now we're *reasonably* sure this is a .download bundle we actually wrote.231 // Get the length of the resume data232 fpos_t footerLengthPosition = fileStat.st_size - 8;233 ASSERT(footerLengthPosition >= 0);234 if (footerLengthPosition < 0)235 goto exit;236 237 if (fsetpos(bundle, &footerLengthPosition))238 goto exit;239 240 UInt32 footerLength = 0;241 if (fread(&footerLength, 4, 1, bundle) != 1) {242 LOG_ERROR("Failed to read ResumeData length from the bundle - errno(%i)", errno);243 goto exit;244 }245 246 // Make sure theres enough bytes to read in for the resume data, and perform the read247 fpos_t footerStartPosition = fileStat.st_size - 8 - footerLength;248 ASSERT(footerStartPosition >= 0);249 if (footerStartPosition < 0)250 goto exit;251 if (fsetpos(bundle, &footerStartPosition))252 goto exit;253 254 footerBuffer.resize(footerLength);255 if (fread(footerBuffer.data(), 1, footerLength, bundle) != footerLength) {256 LOG_ERROR("Failed to read ResumeData from the bundle - errno(%i)", errno);257 goto exit;258 }259 260 // CFURLDownload will seek to the appropriate place in the file (before our footer) and start overwriting from there261 // However, say we were within a few hundred bytes of the end of a download when it was paused -262 // The additional footer extended the length of the file beyond its final length, and there will be junk data leftover263 // at the end. Therefore, now that we've retrieved the footer data, we need to truncate it.264 if (errno_t resizeError = _chsize_s(_fileno(bundle), footerStartPosition)) {265 LOG_ERROR("Failed to truncate the resume footer off the end of the file - errno(%i)", resizeError);266 goto exit;267 }268 269 // Finally, make the resume data. Now, it is possible by some twist of fate the bundle magic number270 // was naturally at the end of the file and its not actually a valid bundle. That, or someone engineered271 // it that way to try to attack us. In that cause, this CFData will successfully create but when we272 // actually try to start the CFURLDownload using this bogus data, it will fail and we will handle that gracefully273 result = CFDataCreate(0, footerBuffer.data(), footerLength);274 exit:275 fclose(bundle);276 return result;277 }278 279 HRESULT WebDownload::appendResumeDataToBundle(CFDataRef resumeData, const String& bundlePath)280 {281 if (!resumeData) {282 LOG_ERROR("Invalid resume data to write to bundle path");283 return E_FAIL;284 }285 if (bundlePath.isEmpty()) {286 LOG_ERROR("Cannot write resume data to empty download bundle path");287 return E_FAIL;288 }289 290 String nullifiedPath = bundlePath;291 FILE* bundle = 0;292 if (_wfopen_s(&bundle, nullifiedPath.charactersWithNullTermination(), TEXT("ab")) || !bundle) {293 LOG_ERROR("Failed to open file %s to append resume data", bundlePath.ascii().data());294 return E_FAIL;295 }296 297 HRESULT hr = E_FAIL;298 299 const UInt8* resumeBytes = CFDataGetBytePtr(resumeData);300 ASSERT(resumeBytes);301 if (!resumeBytes)302 goto exit;303 304 UInt32 resumeLength = CFDataGetLength(resumeData);305 ASSERT(resumeLength > 0);306 if (resumeLength < 1)307 goto exit;308 309 if (fwrite(resumeBytes, 1, resumeLength, bundle) != resumeLength) {310 LOG_ERROR("Failed to write resume data to the bundle - errno(%i)", errno);311 goto exit;312 }313 314 if (fwrite(&resumeLength, 4, 1, bundle) != 1) {315 LOG_ERROR("Failed to write footer length to the bundle - errno(%i)", errno);316 goto exit;317 }318 319 const UInt32& magic = bundleMagicNumber();320 if (fwrite(&magic, 4, 1, bundle) != 1) {321 LOG_ERROR("Failed to write footer magic number to the bundle - errno(%i)", errno);322 goto exit;323 }324 325 hr = S_OK;326 exit:327 fclose(bundle);328 return hr;329 } -
trunk/Source/WebKit/win/WebDownload.h
r65021 r77055 123 123 124 124 protected: 125 static CFDataRef extractResumeDataFromBundle(const WTF::String&);126 static HRESULT appendResumeDataToBundle(CFDataRef, const WTF::String&);127 static const WTF::String& bundleExtension();128 static UInt32 bundleMagicNumber();129 130 125 ULONG m_refCount; 131 126 -
trunk/Source/WebKit/win/WebDownloadCFNet.cpp
r56825 r77055 49 49 #include <WebCore/BString.h> 50 50 #include <WebCore/CredentialStorage.h> 51 #include <WebCore/DownloadBundle.h> 51 52 #include <WebCore/LoaderRunLoopCF.h> 52 53 #include <WebCore/ResourceError.h> … … 168 169 LOG(Download, "Attempting resume of download bundle %s", String(bundlePath, SysStringLen(bundlePath)).ascii().data()); 169 170 170 RetainPtr<CFDataRef> resumeData(AdoptCF, extractResumeDataFromBundle(String(bundlePath, SysStringLen(bundlePath))));171 171 RetainPtr<CFDataRef> resumeData(AdoptCF, DownloadBundle::extractResumeData(String(bundlePath, SysStringLen(bundlePath)))); 172 172 173 if (!resumeData) 173 174 return E_FAIL; … … 195 196 // Attempt to remove the ".download" extension from the bundle for the final file destination 196 197 // Failing that, we clear m_destination and will ask the delegate later once the download starts 197 if (m_bundlePath.endsWith( bundleExtension(), false)) {198 if (m_bundlePath.endsWith(DownloadBundle::fileExtension(), false)) { 198 199 m_destination = m_bundlePath.threadsafeCopy(); 199 m_destination.truncate(m_destination.length() - bundleExtension().length());200 m_destination.truncate(m_destination.length() - DownloadBundle::fileExtension().length()); 200 201 } else 201 202 m_destination = String(); … … 250 251 CFURLDownloadCancel(m_download.get()); 251 252 252 resumeData = CFURLDownloadCopyResumeData(m_download.get());253 resumeData.adoptCF(CFURLDownloadCopyResumeData(m_download.get())); 253 254 if (!resumeData) { 254 255 LOG(Download, "WebDownload - Unable to create resume data for download (%p)", this); … … 256 257 } 257 258 258 appendResumeDataToBundle(resumeData.get(), m_bundlePath);259 259 DownloadBundle::appendResumeData(resumeData.get(), m_bundlePath); 260 260 261 exit: 261 262 m_download = 0; … … 289 290 290 291 m_destination = String(path, SysStringLen(path)); 291 m_bundlePath = m_destination + bundleExtension();292 m_bundlePath = m_destination + DownloadBundle::fileExtension(); 292 293 293 294 CFURLRef pathURL = MarshallingHelpers::PathStringToFileCFURLRef(m_bundlePath); -
trunk/Source/WebKit2/ChangeLog
r77054 r77055 1 2011-01-28 Jon Honeycutt <jhoneycutt@apple.com> 2 3 Downloads in WK2 on Windows should write resume data to bundle 4 https://bugs.webkit.org/show_bug.cgi?id=53282 5 <rdar://problem/8753077> 6 7 Reviewed by Alice Liu. 8 9 * WebProcess/Downloads/Download.cpp: 10 (WebKit::Download::decideDestinationWithSuggestedFilename): 11 Call didDecideDestination(), now that the destination is decided. 12 13 * WebProcess/Downloads/Download.h: 14 Declare didDecideDestination(). Added member variables to hold the 15 destination file path and the download bundle path. 16 (WebKit::Download::destination): 17 Return the path to the final destination for this download. 18 19 * WebProcess/Downloads/cf/DownloadCFNet.cpp: 20 (WebKit::Download::start): 21 Remove the name of an unused param. 22 (WebKit::Download::startWithHandle): 23 Ditto. 24 (WebKit::Download::cancel): 25 Tell CFNetwork not to delete the file upon failure, and tell it to 26 cancel the download. Copy the resume data for the download, and append 27 it to the download bundle. Call didCancel() with an empty 28 DataReference, since we have written our own resume data. 29 (WebKit::decideDestinationWithSuggestedObjectNameCallback): 30 Remove some unused param names. Removed the call to 31 CFURLDownloadSetDestination() - this is now handled in 32 Download::didDecideDestination(). 33 (WebKit::didCreateDestinationCallback): 34 Report that the final destination was created, rather than the download 35 bundle, matching old WebKit. 36 (WebKit::Download::didDecideDestination): 37 Store the final destination and the download bundle paths, and call 38 CFURLDownloadSetDestination(), passing the path to the download bundle. 39 40 * WebProcess/Downloads/curl/DownloadCurl.cpp: 41 (WebKit::Download::didDecideDestination): 42 Stubbed. 43 44 * WebProcess/Downloads/mac/DownloadMac.mm: 45 (WebKit::Download::didDecideDestination): 46 Stubbed - unneeded on the Mac. 47 48 * WebProcess/Downloads/qt/DownloadQt.cpp: 49 (WebKit::Download::didDecideDestination): 50 Stubbed. 51 1 52 2011-01-29 Jeff Miller <jeffm@apple.com> 2 53 -
trunk/Source/WebKit2/WebProcess/Downloads/Download.cpp
r76916 r77055 96 96 m_sandboxExtension->consume(); 97 97 98 didDecideDestination(destination, allowOverwrite); 99 98 100 return destination; 99 101 } -
trunk/Source/WebKit2/WebProcess/Downloads/Download.h
r77029 r77055 83 83 void didFail(const WebCore::ResourceError&, const CoreIPC::DataReference& resumeData); 84 84 void didCancel(const CoreIPC::DataReference& resumeData); 85 void didDecideDestination(const String&, bool allowOverwrite); 86 87 #if USE(CFNETWORK) 88 const String& destination() const { return m_destination; } 89 #endif 85 90 86 91 private: … … 99 104 #endif 100 105 #if USE(CFNETWORK) 106 String m_destination; 107 String m_bundlePath; 101 108 RetainPtr<CFURLDownloadRef> m_download; 102 109 #endif -
trunk/Source/WebKit2/WebProcess/Downloads/cf/DownloadCFNet.cpp
r76916 r77055 31 31 32 32 #pragma warning(push, 0) 33 #include <WebCore/DownloadBundle.h> 33 34 #include <WebCore/LoaderRunLoopCF.h> 34 35 #include <WebCore/ResourceError.h> … … 54 55 static void didFailCallback(CFURLDownloadRef download, CFErrorRef error, const void* clientInfo); 55 56 56 void Download::start(WebPage* initiatingWebPage)57 void Download::start(WebPage*) 57 58 { 58 59 ASSERT(!m_download); … … 72 73 } 73 74 74 void Download::startWithHandle(WebPage* initiatingPage, ResourceHandle* handle, const ResourceRequest& initialRequest, const ResourceResponse& response)75 void Download::startWithHandle(WebPage*, ResourceHandle* handle, const ResourceRequest& initialRequest, const ResourceResponse& response) 75 76 { 76 77 ASSERT(!m_download); … … 100 101 void Download::cancel() 101 102 { 102 notImplemented(); 103 ASSERT(m_download); 104 if (!m_download) 105 return; 106 107 CFURLDownloadSetDeletesUponFailure(m_download.get(), false); 108 CFURLDownloadCancel(m_download.get()); 109 110 RetainPtr<CFDataRef> resumeData(AdoptCF, CFURLDownloadCopyResumeData(m_download.get())); 111 if (resumeData) 112 DownloadBundle::appendResumeData(resumeData.get(), m_bundlePath); 113 114 didCancel(CoreIPC::DataReference()); 103 115 } 104 116 … … 153 165 } 154 166 155 void decideDestinationWithSuggestedObjectNameCallback(CFURLDownloadRef cfURLDownloadRef, CFStringRef objectName, const void* clientInfo)167 void decideDestinationWithSuggestedObjectNameCallback(CFURLDownloadRef, CFStringRef objectName, const void* clientInfo) 156 168 { 157 169 Download* download = downloadFromClientInfo(clientInfo); 158 170 bool allowOverwrite; 159 String destination = download->decideDestinationWithSuggestedFilename(objectName, allowOverwrite); 160 if (destination.isNull()) 171 download->decideDestinationWithSuggestedFilename(objectName, allowOverwrite); 172 } 173 174 void didCreateDestinationCallback(CFURLDownloadRef, CFURLRef, const void* clientInfo) 175 { 176 // The concept of the ".download bundle" is internal to the Download, so we try to hide its 177 // existence by reporting the final destination was created, when in reality the bundle was created. 178 179 Download* download = downloadFromClientInfo(clientInfo); 180 download->didCreateDestination(download->destination()); 181 } 182 183 void Download::didDecideDestination(const String& destination, bool allowOverwrite) 184 { 185 ASSERT(!destination.isEmpty()); 186 if (destination.isEmpty()) 161 187 return; 162 188 163 RetainPtr<CFStringRef> cfPath(AdoptCF, CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar*>(destination.characters()), destination.length(), kCFAllocatorNull)); 164 RetainPtr<CFURLRef> pathURL(AdoptCF, CFURLCreateWithFileSystemPath(0, cfPath.get(), kCFURLWindowsPathStyle, false)); 165 CFURLDownloadSetDestination(cfURLDownloadRef, pathURL.get(), allowOverwrite); 166 } 167 168 void didCreateDestinationCallback(CFURLDownloadRef, CFURLRef url, const void* clientInfo) 169 { 170 RetainPtr<CFStringRef> path(AdoptCF, CFURLCopyFileSystemPath(url, kCFURLWindowsPathStyle)); 171 String result(path.get()); 172 downloadFromClientInfo(clientInfo)->didCreateDestination(result); 189 m_destination = destination; 190 m_bundlePath = destination + DownloadBundle::fileExtension(); 191 192 RetainPtr<CFStringRef> bundlePath(AdoptCF, CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar*>(m_bundlePath.characters()), m_bundlePath.length(), kCFAllocatorNull)); 193 RetainPtr<CFURLRef> bundlePathURL(AdoptCF, CFURLCreateWithFileSystemPath(0, bundlePath.get(), kCFURLWindowsPathStyle, false)); 194 CFURLDownloadSetDestination(m_download.get(), bundlePathURL.get(), allowOverwrite); 173 195 } 174 196 -
trunk/Source/WebKit2/WebProcess/Downloads/curl/DownloadCurl.cpp
r76916 r77055 54 54 } 55 55 56 void Download::didDecideDestination(const String& destination, bool allowOverwrite) 57 { 58 notImplemented(); 59 } 60 56 61 } // namespace WebKit -
trunk/Source/WebKit2/WebProcess/Downloads/mac/DownloadMac.mm
r76991 r77055 170 170 } 171 171 172 void Download::didDecideDestination(const String& destination, bool allowOverwrite) 173 { 174 } 175 172 176 } // namespace WebKit 173 177 -
trunk/Source/WebKit2/WebProcess/Downloads/qt/DownloadQt.cpp
r76916 r77055 53 53 } 54 54 55 void Download::didDecideDestination(const String& destination, bool allowOverwrite) 56 { 57 notImplemented(); 58 } 59 55 60 } // namespace WebKit
Note: See TracChangeset
for help on using the changeset viewer.