📄 webbasenetscapepluginstream.mm
字号:
[theHeaders appendData:[v dataUsingEncoding:NSUTF8StringEncoding]]; [theHeaders appendBytes:"\n" length:1]; } // If the content is encoded (most likely compressed), then don't send its length to the plugin, // which is only interested in the decoded length, not yet known at the moment. // <rdar://problem/4470599> tracks a request for -[NSURLResponse expectedContentLength] to incorporate this logic. NSString *contentEncoding = (NSString *)[[(NSHTTPURLResponse *)r allHeaderFields] objectForKey:@"Content-Encoding"]; if (contentEncoding && ![contentEncoding isEqualToString:@"identity"]) expectedContentLength = -1; // startStreamResponseURL:... will null-terminate. } startStream([r URL], expectedContentLength, WKGetNSURLResponseLastModifiedDate(r), [r MIMEType], theHeaders); }void WebNetscapePluginStream::startStreamWithResponse(NSURLResponse *response){ didReceiveResponse(0, response);}bool WebNetscapePluginStream::wantsAllStreams() const{ if (!m_pluginFuncs->getvalue) return false; void *value = 0; NPError error; [m_pluginView.get() willCallPlugInFunction]; { JSC::JSLock::DropAllLocks dropAllLocks(false); error = m_pluginFuncs->getvalue(m_plugin, NPPVpluginWantsAllNetworkStreams, &value); } [m_pluginView.get() didCallPlugInFunction]; if (error != NPERR_NO_ERROR) return false; return value;}void WebNetscapePluginStream::destroyStream(){ if (m_isTerminated) return; RefPtr<WebNetscapePluginStream> protect(this); ASSERT(m_reason != WEB_REASON_NONE); ASSERT([m_deliveryData.get() length] == 0); m_deliverDataTimer.stop(); if (m_stream.ndata) { if (m_reason == NPRES_DONE && (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY)) { ASSERT(m_fileDescriptor == -1); ASSERT(m_path); NSString *carbonPath = CarbonPathFromPOSIXPath(m_path.get()); ASSERT(carbonPath != NULL); [m_pluginView.get() willCallPlugInFunction]; m_pluginFuncs->asfile(m_plugin, &m_stream, [carbonPath fileSystemRepresentation]); [m_pluginView.get() didCallPlugInFunction]; LOG(Plugins, "NPP_StreamAsFile responseURL=%@ path=%s", m_responseURL.get(), carbonPath); } if (m_path) { // Delete the file after calling NPP_StreamAsFile(), instead of in -dealloc/-finalize. It should be OK // to delete the file here -- NPP_StreamAsFile() is always called immediately before NPP_DestroyStream() // (the stream destruction function), so there can be no expectation that a plugin will read the stream // file asynchronously after NPP_StreamAsFile() is called. unlink([m_path.get() fileSystemRepresentation]); m_path = 0; if (m_isTerminated) return; } if (m_fileDescriptor != -1) { // The file may still be open if we are destroying the stream before it completed loading. close(m_fileDescriptor); m_fileDescriptor = -1; } if (m_newStreamSuccessful) { [m_pluginView.get() willCallPlugInFunction];#if !LOG_DISABLED NPError npErr = #endif m_pluginFuncs->destroystream(m_plugin, &m_stream, m_reason); [m_pluginView.get() didCallPlugInFunction]; LOG(Plugins, "NPP_DestroyStream responseURL=%@ error=%d", m_responseURL.get(), npErr); } free(m_headers); m_headers = NULL; m_stream.headers = NULL; m_stream.ndata = 0; if (m_isTerminated) return; } if (m_sendNotification) { // NPP_URLNotify expects the request URL, not the response URL. [m_pluginView.get() willCallPlugInFunction]; m_pluginFuncs->urlnotify(m_plugin, [m_requestURL.get() _web_URLCString], m_reason, m_notifyData); [m_pluginView.get() didCallPlugInFunction]; LOG(Plugins, "NPP_URLNotify requestURL=%@ reason=%d", m_requestURL.get(), m_reason); } m_isTerminated = true; setPlugin(0);}void WebNetscapePluginStream::destroyStreamWithReason(NPReason reason){ m_reason = reason; if (m_reason != NPRES_DONE) { // Stop any pending data from being streamed. [m_deliveryData.get() setLength:0]; } else if ([m_deliveryData.get() length] > 0) { // There is more data to be streamed, don't destroy the stream now. return; } RefPtr<WebNetscapePluginStream> protect(this); destroyStream(); ASSERT(!m_stream.ndata);}void WebNetscapePluginStream::cancelLoadWithError(NSError *error){ if (m_frameLoader) { ASSERT(!m_loader); DocumentLoader* documentLoader = m_frameLoader->activeDocumentLoader(); ASSERT(documentLoader); if (documentLoader->isLoadingMainResource()) documentLoader->cancelMainResourceLoad(error); return; } if (!m_loader->isDone()) m_loader->cancel(error);}void WebNetscapePluginStream::destroyStreamWithError(NSError *error){ destroyStreamWithReason(reasonForError(error));}void WebNetscapePluginStream::didFail(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceError& error){ destroyStreamWithError(error);}void WebNetscapePluginStream::cancelLoadAndDestroyStreamWithError(NSError *error){ RefPtr<WebNetscapePluginStream> protect(this); cancelLoadWithError(error); destroyStreamWithError(error); setPlugin(0);} void WebNetscapePluginStream::deliverData(){ if (!m_stream.ndata || [m_deliveryData.get() length] == 0) return; RefPtr<WebNetscapePluginStream> protect(this); int32 totalBytes = [m_deliveryData.get() length]; int32 totalBytesDelivered = 0; while (totalBytesDelivered < totalBytes) { [m_pluginView.get() willCallPlugInFunction]; int32 deliveryBytes = m_pluginFuncs->writeready(m_plugin, &m_stream); [m_pluginView.get() didCallPlugInFunction]; LOG(Plugins, "NPP_WriteReady responseURL=%@ bytes=%d", m_responseURL.get(), deliveryBytes); if (m_isTerminated) return; if (deliveryBytes <= 0) { // Plug-in can't receive anymore data right now. Send it later. if (!m_deliverDataTimer.isActive()) m_deliverDataTimer.startOneShot(0); break; } else { deliveryBytes = MIN(deliveryBytes, totalBytes - totalBytesDelivered); NSData *subdata = [m_deliveryData.get() subdataWithRange:NSMakeRange(totalBytesDelivered, deliveryBytes)]; [m_pluginView.get() willCallPlugInFunction]; deliveryBytes = m_pluginFuncs->write(m_plugin, &m_stream, m_offset, [subdata length], (void *)[subdata bytes]); [m_pluginView.get() didCallPlugInFunction]; if (deliveryBytes < 0) { // Netscape documentation says that a negative result from NPP_Write means cancel the load. cancelLoadAndDestroyStreamWithError(pluginCancelledConnectionError()); return; } deliveryBytes = MIN((unsigned)deliveryBytes, [subdata length]); m_offset += deliveryBytes; totalBytesDelivered += deliveryBytes; LOG(Plugins, "NPP_Write responseURL=%@ bytes=%d total-delivered=%d/%d", m_responseURL.get(), deliveryBytes, m_offset, m_stream.end); } } if (totalBytesDelivered > 0) { if (totalBytesDelivered < totalBytes) { NSMutableData *newDeliveryData = [[NSMutableData alloc] initWithCapacity:totalBytes - totalBytesDelivered]; [newDeliveryData appendBytes:(char *)[m_deliveryData.get() bytes] + totalBytesDelivered length:totalBytes - totalBytesDelivered]; [m_deliveryData.get() release]; m_deliveryData = newDeliveryData; [newDeliveryData release]; } else { [m_deliveryData.get() setLength:0]; if (m_reason != WEB_REASON_NONE) destroyStream(); } }}void WebNetscapePluginStream::deliverDataTimerFired(WebCore::Timer<WebNetscapePluginStream>* timer){ deliverData();}void WebNetscapePluginStream::deliverDataToFile(NSData *data){ if (m_fileDescriptor == -1 && !m_path) { NSString *temporaryFileMask = [NSTemporaryDirectory() stringByAppendingPathComponent:@"WebKitPlugInStreamXXXXXX"]; char *temporaryFileName = strdup([temporaryFileMask fileSystemRepresentation]); m_fileDescriptor = mkstemp(temporaryFileName); if (m_fileDescriptor == -1) { LOG_ERROR("Can't create a temporary file."); // This is not a network error, but the only error codes are "network error" and "user break". destroyStreamWithReason(NPRES_NETWORK_ERR); free(temporaryFileName); return; } m_path.adoptNS([[NSString stringWithUTF8String:temporaryFileName] retain]); free(temporaryFileName); } int dataLength = [data length]; if (!dataLength) return; int byteCount = write(m_fileDescriptor, [data bytes], dataLength); if (byteCount != dataLength) { // This happens only rarely, when we are out of disk space or have a disk I/O error. LOG_ERROR("error writing to temporary file, errno %d", errno); close(m_fileDescriptor); m_fileDescriptor = -1; // This is not a network error, but the only error codes are "network error" and "user break". destroyStreamWithReason(NPRES_NETWORK_ERR); m_path = 0; }}void WebNetscapePluginStream::didFinishLoading(NetscapePlugInStreamLoader*){ if (!m_stream.ndata) return; if (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY) { // Fake the delivery of an empty data to ensure that the file has been created deliverDataToFile([NSData data]); if (m_fileDescriptor != -1) close(m_fileDescriptor); m_fileDescriptor = -1; } destroyStreamWithReason(NPRES_DONE);}void WebNetscapePluginStream::didReceiveData(NetscapePlugInStreamLoader*, const char* bytes, int length){ NSData *data = [[NSData alloc] initWithBytesNoCopy:(void*)bytes length:length freeWhenDone:NO]; ASSERT([data length] > 0); if (m_transferMode != NP_ASFILEONLY) { if (!m_deliveryData) m_deliveryData.adoptNS([[NSMutableData alloc] initWithCapacity:[data length]]); [m_deliveryData.get() appendData:data]; deliverData(); } if (m_transferMode == NP_ASFILE || m_transferMode == NP_ASFILEONLY) deliverDataToFile(data); [data release];}static NSString *CarbonPathFromPOSIXPath(NSString *posixPath){ // Doesn't add a trailing colon for directories; this is a problem for paths to a volume, // so this function would need to be revised if we ever wanted to call it with that. CFURLRef url = (CFURLRef)[NSURL fileURLWithPath:posixPath]; if (!url) return nil; return WebCFAutorelease(CFURLCopyFileSystemPath(url, kCFURLHFSPathStyle));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -