📄 netscapeplugininstanceproxy.mm
字号:
/* * 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. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR * 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. */#if USE(PLUGIN_HOST_PROCESS)#import "NetscapePluginInstanceProxy.h"#import "HostedNetscapePluginStream.h"#import "NetscapePluginHostProxy.h"#import "ProxyInstance.h"#import "WebDataSourceInternal.h"#import "WebFrameInternal.h"#import "WebHostedNetscapePluginView.h"#import "WebNSDataExtras.h"#import "WebNSURLExtras.h"#import "WebKitNSStringExtras.h"#import "WebPluginRequest.h"#import "WebViewInternal.h"#import "WebUIDelegate.h"#import "WebUIDelegatePrivate.h"#import <mach/mach.h>#import <WebCore/DocumentLoader.h>#import <WebCore/Frame.h>#import <WebCore/FrameLoader.h>#import <WebCore/FrameTree.h>#import <WebCore/npruntime_impl.h>#import <WebCore/runtime_object.h>#import <WebCore/ScriptController.h>#import <WebCore/ScriptValue.h>#include <runtime/JSLock.h>#include <runtime/PropertyNameArray.h>#import <utility>extern "C" {#import "WebKitPluginClientServer.h"#import "WebKitPluginHost.h"}using namespace JSC;using namespace JSC::Bindings;using namespace std;using namespace WebCore;namespace WebKit {class NetscapePluginInstanceProxy::PluginRequest {public: PluginRequest(uint32_t requestID, NSURLRequest *request, NSString *frameName, bool didStartFromUserGesture) : m_requestID(requestID) , m_request(request) , m_frameName(frameName) , m_didStartFromUserGesture(didStartFromUserGesture) { } uint32_t requestID() const { return m_requestID; } NSURLRequest *request() const { return m_request.get(); } NSString *frameName() const { return m_frameName.get(); } bool didStartFromUserGesture() const { return m_didStartFromUserGesture; } private: uint32_t m_requestID; RetainPtr<NSURLRequest *> m_request; RetainPtr<NSString *> m_frameName; bool m_didStartFromUserGesture;};static uint32_t pluginIDCounter;NetscapePluginInstanceProxy::NetscapePluginInstanceProxy(NetscapePluginHostProxy* pluginHostProxy, WebHostedNetscapePluginView *pluginView) : m_pluginHostProxy(pluginHostProxy) , m_pluginView(pluginView) , m_requestTimer(this, &NetscapePluginInstanceProxy::requestTimerFired) , m_currentRequestID(0) , m_renderContextID(0) , m_useSoftwareRenderer(false) , m_waitingForReply(false) , m_objectIDCounter(0) , m_pluginFunctionCallDepth(0) , m_shouldStopSoon(false){ ASSERT(m_pluginView); // Assign a plug-in ID. do { m_pluginID = ++pluginIDCounter; } while (pluginHostProxy->pluginInstance(m_pluginID) || !m_pluginID); pluginHostProxy->addPluginInstance(this);}NetscapePluginInstanceProxy::~NetscapePluginInstanceProxy(){ ASSERT(!m_pluginHostProxy); m_pluginID = 0;}void NetscapePluginInstanceProxy::resize(NSRect size, NSRect clipRect){ _WKPHResizePluginInstance(m_pluginHostProxy->port(), m_pluginID, size.origin.x, size.origin.y, size.size.width, size.size.height);}void NetscapePluginInstanceProxy::stopAllStreams(){ Vector<RefPtr<HostedNetscapePluginStream> > streamsCopy; copyValuesToVector(m_streams, streamsCopy); for (size_t i = 0; i < streamsCopy.size(); i++) streamsCopy[i]->stop();}void NetscapePluginInstanceProxy::cleanup(){ stopAllStreams(); // Clear the object map, this will cause any outstanding JS objects that the plug-in had a reference to // to go away when the next garbage collection takes place. m_objects.clear(); if (Frame* frame = core([m_pluginView webFrame])) frame->script()->cleanupScriptObjectsForPlugin(m_pluginView); ProxyInstanceSet instances; instances.swap(m_instances); // Invalidate all proxy instances. ProxyInstanceSet::const_iterator end = instances.end(); for (ProxyInstanceSet::const_iterator it = instances.begin(); it != end; ++it) (*it)->invalidate();}void NetscapePluginInstanceProxy::invalidate(){ // If the plug-in host has died, the proxy will be null. if (!m_pluginHostProxy) return; m_pluginHostProxy->removePluginInstance(this); m_pluginHostProxy = 0;}void NetscapePluginInstanceProxy::destroy(){ _WKPHDestroyPluginInstance(m_pluginHostProxy->port(), m_pluginID); cleanup(); invalidate();}HostedNetscapePluginStream *NetscapePluginInstanceProxy::pluginStream(uint32_t streamID){ return m_streams.get(streamID).get();}void NetscapePluginInstanceProxy::disconnectStream(HostedNetscapePluginStream* stream){ m_streams.remove(stream->streamID());} void NetscapePluginInstanceProxy::pluginHostDied(){ m_pluginHostProxy = 0; cleanup(); [m_pluginView pluginHostDied]; m_pluginView = nil;}void NetscapePluginInstanceProxy::focusChanged(bool hasFocus){ _WKPHPluginInstanceFocusChanged(m_pluginHostProxy->port(), m_pluginID, hasFocus);}void NetscapePluginInstanceProxy::windowFocusChanged(bool hasFocus){ _WKPHPluginInstanceWindowFocusChanged(m_pluginHostProxy->port(), m_pluginID, hasFocus);}void NetscapePluginInstanceProxy::windowFrameChanged(NSRect frame){ _WKPHPluginInstanceWindowFrameChanged(m_pluginHostProxy->port(), m_pluginID, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height, // FIXME: Is it always correct to pass the rect of the first screen here? NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]));} void NetscapePluginInstanceProxy::startTimers(bool throttleTimers){ _WKPHPluginInstanceStartTimers(m_pluginHostProxy->port(), m_pluginID, throttleTimers);} void NetscapePluginInstanceProxy::mouseEvent(NSView *pluginView, NSEvent *event, NPCocoaEventType type){ NSPoint screenPoint = [[event window] convertBaseToScreen:[event locationInWindow]]; NSPoint pluginPoint = [pluginView convertPoint:[event locationInWindow] fromView:nil]; int clickCount; if (type == NPCocoaEventMouseEntered || type == NPCocoaEventMouseExited) clickCount = 0; else clickCount = [event clickCount]; _WKPHPluginInstanceMouseEvent(m_pluginHostProxy->port(), m_pluginID, [event timestamp], type, [event modifierFlags], pluginPoint.x, pluginPoint.y, screenPoint.x, screenPoint.y, // FIXME: Is it always correct to pass the rect of the first screen here? NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]), [event buttonNumber], clickCount, [event deltaX], [event deltaY], [event deltaZ]);} void NetscapePluginInstanceProxy::keyEvent(NSView *pluginView, NSEvent *event, NPCocoaEventType type){ NSData *charactersData = [[event characters] dataUsingEncoding:NSUTF8StringEncoding]; NSData *charactersIgnoringModifiersData = [[event charactersIgnoringModifiers] dataUsingEncoding:NSUTF8StringEncoding]; _WKPHPluginInstanceKeyboardEvent(m_pluginHostProxy->port(), m_pluginID, [event timestamp], type, [event modifierFlags], const_cast<char*>(reinterpret_cast<const char*>([charactersData bytes])), [charactersData length], const_cast<char*>(reinterpret_cast<const char*>([charactersIgnoringModifiersData bytes])), [charactersIgnoringModifiersData length], [event isARepeat], [event keyCode]);}void NetscapePluginInstanceProxy::insertText(NSString *text){ NSData *textData = [text dataUsingEncoding:NSUTF8StringEncoding]; _WKPHPluginInstanceInsertText(m_pluginHostProxy->port(), m_pluginID, const_cast<char*>(reinterpret_cast<const char*>([textData bytes])), [textData length]);}void NetscapePluginInstanceProxy::print(CGContextRef context, unsigned width, unsigned height){ _WKPHPluginInstancePrint(m_pluginHostProxy->port(), m_pluginID, width, height); auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(); if (!reply.get() || !reply->m_returnValue) return; RetainPtr<CGDataProvider> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(reply->m_result.get())); RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); RetainPtr<CGImageRef> image(AdoptCF, CGImageCreate(width, height, 8, 32, width * 4, colorSpace.get(), kCGImageAlphaFirst, dataProvider.get(), 0, false, kCGRenderingIntentDefault)); // Flip the context and draw the image. CGContextSaveGState(context); CGContextTranslateCTM(context, 0.0, height); CGContextScaleCTM(context, 1.0, -1.0); CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.get()); CGContextRestoreGState(context);}void NetscapePluginInstanceProxy::stopTimers(){ _WKPHPluginInstanceStopTimers(m_pluginHostProxy->port(), m_pluginID);}void NetscapePluginInstanceProxy::status(const char* message){ RetainPtr<CFStringRef> status(AdoptCF, CFStringCreateWithCString(NULL, message, kCFStringEncodingUTF8)); if (!status) return; WebView *wv = [m_pluginView webView]; [[wv _UIDelegateForwarder] webView:wv setStatusText:(NSString *)status.get()];}NPError NetscapePluginInstanceProxy::loadURL(const char* url, const char* target, const char* postData, uint32_t postLen, LoadURLFlags flags, uint32_t& streamID){ if (!url) return NPERR_INVALID_PARAM; NSMutableURLRequest *request = [m_pluginView requestWithURLCString:url]; if (flags & IsPost) { NSData *httpBody = nil; if (flags & PostDataIsFile) { // If we're posting a file, buf is either a file URL or a path to the file. RetainPtr<CFStringRef> bufString(AdoptCF, CFStringCreateWithCString(kCFAllocatorDefault, postData, kCFStringEncodingWindowsLatin1)); if (!bufString) return NPERR_INVALID_PARAM; NSURL *fileURL = [NSURL _web_URLWithDataAsString:(NSString *)bufString.get()]; NSString *path; if ([fileURL isFileURL]) path = [fileURL path]; else path = (NSString *)bufString.get(); httpBody = [NSData dataWithContentsOfFile:[path _webkit_fixedCarbonPOSIXPath]]; if (!httpBody) return NPERR_FILE_NOT_FOUND; } else httpBody = [NSData dataWithBytes:postData length:postLen]; if (![httpBody length]) return NPERR_INVALID_PARAM; [request setHTTPMethod:@"POST"]; if (flags & AllowHeadersInPostData) { if ([httpBody _web_startsWithBlankLine]) httpBody = [httpBody subdataWithRange:NSMakeRange(1, [httpBody length] - 1)]; else { NSInteger location = [httpBody _web_locationAfterFirstBlankLine]; if (location != NSNotFound) { // If the blank line is somewhere in the middle of postData, everything before is the header. NSData *headerData = [httpBody subdataWithRange:NSMakeRange(0, location)]; NSMutableDictionary *header = [headerData _webkit_parseRFC822HeaderFields]; unsigned dataLength = [httpBody length] - location; // Sometimes plugins like to set Content-Length themselves when they post, // but CFNetwork does not like that. So we will remove the header // and instead truncate the data to the requested length. NSString *contentLength = [header objectForKey:@"Content-Length"]; if (contentLength) dataLength = min(static_cast<unsigned>([contentLength intValue]), dataLength); [header removeObjectForKey:@"Content-Length"]; if ([header count] > 0) [request setAllHTTPHeaderFields:header]; // Everything after the blank line is the actual content of the POST. httpBody = [httpBody subdataWithRange:NSMakeRange(location, dataLength)]; } } } if (![httpBody length]) return NPERR_INVALID_PARAM; // Plug-ins expect to receive uncached data when doing a POST (3347134). [request setCachePolicy:NSURLRequestReloadIgnoringCacheData]; [request setHTTPBody:httpBody]; } return loadRequest(request, target, flags & CurrentEventIsUserGesture, streamID);}void NetscapePluginInstanceProxy::performRequest(PluginRequest* pluginRequest){ NSURLRequest *request = pluginRequest->request(); NSString *frameName = pluginRequest->frameName();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -