2 * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
28 #import "NetscapePluginInstanceProxy.h"
30 #import "HostedNetscapePluginStream.h"
31 #import "NetscapePluginHostProxy.h"
32 #import "ProxyInstance.h"
33 #import "ProxyRuntimeObject.h"
34 #import "WebDataSourceInternal.h"
35 #import "WebFrameInternal.h"
36 #import "WebHostedNetscapePluginView.h"
37 #import "WebKitNSStringExtras.h"
38 #import "WebNSDataExtras.h"
39 #import "WebNSURLExtras.h"
40 #import "WebPluginRequest.h"
41 #import "WebUIDelegate.h"
42 #import "WebUIDelegatePrivate.h"
43 #import "WebViewInternal.h"
44 #import <JavaScriptCore/Completion.h>
45 #import <JavaScriptCore/Error.h>
46 #import <JavaScriptCore/JSLock.h>
47 #import <JavaScriptCore/PropertyNameArray.h>
48 #import <JavaScriptCore/SourceCode.h>
49 #import <JavaScriptCore/StrongInlines.h>
50 #import <WebCore/CookieJar.h>
51 #import <WebCore/DocumentLoader.h>
52 #import <WebCore/Frame.h>
53 #import <WebCore/FrameLoader.h>
54 #import <WebCore/FrameTree.h>
55 #import <WebCore/KURL.h>
56 #import <WebCore/ProxyServer.h>
57 #import <WebCore/SecurityOrigin.h>
58 #import <WebCore/ScriptController.h>
59 #import <WebCore/ScriptValue.h>
60 #import <WebCore/UserGestureIndicator.h>
61 #import <WebCore/npruntime_impl.h>
62 #import <WebCore/runtime_object.h>
63 #import <WebKitSystemInterface.h>
66 #import <wtf/RefCountedLeakCounter.h>
67 #import <wtf/text/CString.h>
70 #import "WebKitPluginClientServer.h"
71 #import "WebKitPluginHost.h"
75 using namespace JSC::Bindings;
76 using namespace WebCore;
80 class NetscapePluginInstanceProxy::PluginRequest : public RefCounted<NetscapePluginInstanceProxy::PluginRequest> {
82 static PassRefPtr<PluginRequest> create(uint32_t requestID, NSURLRequest* request, NSString* frameName, bool allowPopups)
84 return adoptRef(new PluginRequest(requestID, request, frameName, allowPopups));
87 uint32_t requestID() const { return m_requestID; }
88 NSURLRequest* request() const { return m_request.get(); }
89 NSString* frameName() const { return m_frameName.get(); }
90 bool allowPopups() const { return m_allowPopups; }
93 PluginRequest(uint32_t requestID, NSURLRequest* request, NSString* frameName, bool allowPopups)
94 : m_requestID(requestID)
96 , m_frameName(frameName)
97 , m_allowPopups(allowPopups)
101 uint32_t m_requestID;
102 RetainPtr<NSURLRequest*> m_request;
103 RetainPtr<NSString*> m_frameName;
107 NetscapePluginInstanceProxy::LocalObjectMap::LocalObjectMap()
108 : m_objectIDCounter(0)
112 NetscapePluginInstanceProxy::LocalObjectMap::~LocalObjectMap()
116 inline bool NetscapePluginInstanceProxy::LocalObjectMap::contains(uint32_t objectID) const
118 return m_idToJSObjectMap.contains(objectID);
121 inline JSC::JSObject* NetscapePluginInstanceProxy::LocalObjectMap::get(uint32_t objectID) const
123 if (objectID == HashTraits<uint32_t>::emptyValue() || HashTraits<uint32_t>::isDeletedValue(objectID))
126 return m_idToJSObjectMap.get(objectID).get();
129 uint32_t NetscapePluginInstanceProxy::LocalObjectMap::idForObject(VM& vm, JSObject* object)
131 // This method creates objects with refcount of 1, but doesn't increase refcount when returning
132 // found objects. This extra count accounts for the main "reference" kept by plugin process.
134 // To avoid excessive IPC, plugin process doesn't send each NPObject release/retain call to
135 // Safari. It only sends one when the last reference is removed, and it can destroy the proxy
138 // However, the browser may be sending the same object out to plug-in as a function call
139 // argument at the same time - neither side can know what the other one is doing. So,
140 // is to make PCForgetBrowserObject call return a boolean result, making it possible for
141 // the browser to make plugin host keep the proxy with zero refcount for a little longer.
143 uint32_t objectID = 0;
145 HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator iter = m_jsObjectToIDMap.find(object);
146 if (iter != m_jsObjectToIDMap.end())
147 return iter->value.first;
150 objectID = ++m_objectIDCounter;
151 } while (!m_objectIDCounter || m_objectIDCounter == static_cast<uint32_t>(-1) || m_idToJSObjectMap.contains(objectID));
153 m_idToJSObjectMap.set(objectID, Strong<JSObject>(vm, object));
154 m_jsObjectToIDMap.set(object, std::make_pair(objectID, 1));
159 void NetscapePluginInstanceProxy::LocalObjectMap::retain(JSC::JSObject* object)
161 HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator iter = m_jsObjectToIDMap.find(object);
162 ASSERT(iter != m_jsObjectToIDMap.end());
164 iter->value.second = iter->value.second + 1;
167 void NetscapePluginInstanceProxy::LocalObjectMap::release(JSC::JSObject* object)
169 HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator iter = m_jsObjectToIDMap.find(object);
170 ASSERT(iter != m_jsObjectToIDMap.end());
172 ASSERT(iter->value.second > 0);
173 iter->value.second = iter->value.second - 1;
174 if (!iter->value.second) {
175 m_idToJSObjectMap.remove(iter->value.first);
176 m_jsObjectToIDMap.remove(iter);
180 void NetscapePluginInstanceProxy::LocalObjectMap::clear()
182 m_idToJSObjectMap.clear();
183 m_jsObjectToIDMap.clear();
186 bool NetscapePluginInstanceProxy::LocalObjectMap::forget(uint32_t objectID)
188 if (objectID == HashTraits<uint32_t>::emptyValue() || HashTraits<uint32_t>::isDeletedValue(objectID)) {
189 LOG_ERROR("NetscapePluginInstanceProxy::LocalObjectMap::forget: local object id %u is not valid.", objectID);
193 HashMap<uint32_t, JSC::Strong<JSC::JSObject> >::iterator iter = m_idToJSObjectMap.find(objectID);
194 if (iter == m_idToJSObjectMap.end()) {
195 LOG_ERROR("NetscapePluginInstanceProxy::LocalObjectMap::forget: local object %u doesn't exist.", objectID);
199 HashMap<JSC::JSObject*, pair<uint32_t, uint32_t> >::iterator rIter = m_jsObjectToIDMap.find(iter->value.get());
201 // If the object is being sent to plug-in right now, then it's not the time to forget.
202 if (rIter->value.second != 1)
205 m_jsObjectToIDMap.remove(rIter);
206 m_idToJSObjectMap.remove(iter);
210 static uint32_t pluginIDCounter;
212 bool NetscapePluginInstanceProxy::m_inDestroy;
214 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, netscapePluginInstanceProxyCounter, ("NetscapePluginInstanceProxy"));
216 NetscapePluginInstanceProxy::NetscapePluginInstanceProxy(NetscapePluginHostProxy* pluginHostProxy, WebHostedNetscapePluginView *pluginView, bool fullFramePlugin)
217 : m_pluginHostProxy(pluginHostProxy)
218 , m_pluginView(pluginView)
219 , m_requestTimer(this, &NetscapePluginInstanceProxy::requestTimerFired)
220 , m_currentURLRequestID(0)
221 , m_renderContextID(0)
222 , m_rendererType(UseSoftwareRenderer)
223 , m_waitingForReply(false)
224 , m_urlCheckCounter(0)
225 , m_pluginFunctionCallDepth(0)
226 , m_shouldStopSoon(false)
227 , m_currentRequestID(0)
228 , m_pluginIsWaitingForDraw(false)
230 ASSERT(m_pluginView);
232 if (fullFramePlugin) {
233 // For full frame plug-ins, the first requestID will always be the one for the already
235 ++m_currentURLRequestID;
238 // Assign a plug-in ID.
240 m_pluginID = ++pluginIDCounter;
241 } while (pluginHostProxy->pluginInstance(m_pluginID) || !m_pluginID);
244 netscapePluginInstanceProxyCounter.increment();
248 PassRefPtr<NetscapePluginInstanceProxy> NetscapePluginInstanceProxy::create(NetscapePluginHostProxy* pluginHostProxy, WebHostedNetscapePluginView *pluginView, bool fullFramePlugin)
250 RefPtr<NetscapePluginInstanceProxy> proxy = adoptRef(new NetscapePluginInstanceProxy(pluginHostProxy, pluginView, fullFramePlugin));
251 pluginHostProxy->addPluginInstance(proxy.get());
252 return proxy.release();
255 NetscapePluginInstanceProxy::~NetscapePluginInstanceProxy()
257 ASSERT(!m_pluginHostProxy);
260 deleteAllValues(m_replies);
263 netscapePluginInstanceProxyCounter.decrement();
267 void NetscapePluginInstanceProxy::resize(NSRect size, NSRect clipRect)
269 uint32_t requestID = 0;
271 requestID = nextRequestID();
273 _WKPHResizePluginInstance(m_pluginHostProxy->port(), m_pluginID, requestID,
274 size.origin.x, size.origin.y, size.size.width, size.size.height,
275 clipRect.origin.x, clipRect.origin.y, clipRect.size.width, clipRect.size.height);
277 waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
281 void NetscapePluginInstanceProxy::setShouldHostLayersInWindowServer(bool shouldHostLayersInWindowServer)
283 _WKPHPluginShouldHostLayersInWindowServerChanged(m_pluginHostProxy->port(), m_pluginID, shouldHostLayersInWindowServer);
286 void NetscapePluginInstanceProxy::layerHostingModeChanged(bool hostsLayersInWindowServer, uint32_t renderContextID)
288 setRenderContextID(renderContextID);
290 [m_pluginView setHostsLayersInWindowServer:hostsLayersInWindowServer];
293 void NetscapePluginInstanceProxy::stopAllStreams()
295 Vector<RefPtr<HostedNetscapePluginStream> > streamsCopy;
296 copyValuesToVector(m_streams, streamsCopy);
297 for (size_t i = 0; i < streamsCopy.size(); i++)
298 streamsCopy[i]->stop();
301 void NetscapePluginInstanceProxy::cleanup()
305 m_requestTimer.stop();
307 // Clear the object map, this will cause any outstanding JS objects that the plug-in had a reference to
308 // to go away when the next garbage collection takes place.
309 m_localObjects.clear();
311 if (Frame* frame = core([m_pluginView webFrame]))
312 frame->script()->cleanupScriptObjectsForPlugin(m_pluginView);
314 ProxyInstanceSet instances;
315 instances.swap(m_instances);
317 // Invalidate all proxy instances.
318 ProxyInstanceSet::const_iterator end = instances.end();
319 for (ProxyInstanceSet::const_iterator it = instances.begin(); it != end; ++it)
326 void NetscapePluginInstanceProxy::invalidate()
328 // If the plug-in host has died, the proxy will be null.
329 if (!m_pluginHostProxy)
332 m_pluginHostProxy->removePluginInstance(this);
333 m_pluginHostProxy = 0;
336 void NetscapePluginInstanceProxy::destroy()
338 uint32_t requestID = nextRequestID();
340 ASSERT(!m_inDestroy);
343 FrameLoadMap::iterator end = m_pendingFrameLoads.end();
344 for (FrameLoadMap::iterator it = m_pendingFrameLoads.begin(); it != end; ++it)
345 [(it->key) _setInternalLoadDelegate:nil];
347 _WKPHDestroyPluginInstance(m_pluginHostProxy->port(), m_pluginID, requestID);
349 // If the plug-in host crashes while we're waiting for a reply, the last reference to the instance proxy
350 // will go away. Prevent this by protecting it here.
351 RefPtr<NetscapePluginInstanceProxy> protect(this);
353 // We don't care about the reply here - we just want to block until the plug-in instance has been torn down.
354 waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
362 void NetscapePluginInstanceProxy::setManualStream(PassRefPtr<HostedNetscapePluginStream> manualStream)
364 ASSERT(!m_manualStream);
366 m_manualStream = manualStream;
369 bool NetscapePluginInstanceProxy::cancelStreamLoad(uint32_t streamID, NPReason reason)
371 HostedNetscapePluginStream* stream = 0;
373 if (m_manualStream && streamID == 1)
374 stream = m_manualStream.get();
376 stream = m_streams.get(streamID);
381 stream->cancelLoad(reason);
385 void NetscapePluginInstanceProxy::disconnectStream(HostedNetscapePluginStream* stream)
387 if (stream == m_manualStream) {
392 ASSERT(m_streams.get(stream->streamID()) == stream);
393 m_streams.remove(stream->streamID());
396 void NetscapePluginInstanceProxy::pluginHostDied()
398 m_pluginHostProxy = 0;
400 [m_pluginView pluginHostDied];
405 void NetscapePluginInstanceProxy::focusChanged(bool hasFocus)
407 _WKPHPluginInstanceFocusChanged(m_pluginHostProxy->port(), m_pluginID, hasFocus);
410 void NetscapePluginInstanceProxy::windowFocusChanged(bool hasFocus)
412 _WKPHPluginInstanceWindowFocusChanged(m_pluginHostProxy->port(), m_pluginID, hasFocus);
415 void NetscapePluginInstanceProxy::windowFrameChanged(NSRect frame)
417 _WKPHPluginInstanceWindowFrameChanged(m_pluginHostProxy->port(), m_pluginID, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height,
418 NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]));
421 void NetscapePluginInstanceProxy::startTimers(bool throttleTimers)
423 _WKPHPluginInstanceStartTimers(m_pluginHostProxy->port(), m_pluginID, throttleTimers);
426 void NetscapePluginInstanceProxy::mouseEvent(NSView *pluginView, NSEvent *event, NPCocoaEventType type)
428 NSPoint screenPoint = [[event window] convertBaseToScreen:[event locationInWindow]];
429 NSPoint pluginPoint = [pluginView convertPoint:[event locationInWindow] fromView:nil];
432 if (type == NPCocoaEventMouseEntered || type == NPCocoaEventMouseExited)
435 clickCount = [event clickCount];
438 _WKPHPluginInstanceMouseEvent(m_pluginHostProxy->port(), m_pluginID,
440 type, [event modifierFlags],
441 pluginPoint.x, pluginPoint.y,
442 screenPoint.x, screenPoint.y,
443 NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]),
444 [event buttonNumber], clickCount,
445 [event deltaX], [event deltaY], [event deltaZ]);
448 void NetscapePluginInstanceProxy::keyEvent(NSView *pluginView, NSEvent *event, NPCocoaEventType type)
450 NSData *charactersData = [[event characters] dataUsingEncoding:NSUTF8StringEncoding];
451 NSData *charactersIgnoringModifiersData = [[event charactersIgnoringModifiers] dataUsingEncoding:NSUTF8StringEncoding];
453 _WKPHPluginInstanceKeyboardEvent(m_pluginHostProxy->port(), m_pluginID,
455 type, [event modifierFlags],
456 const_cast<char*>(reinterpret_cast<const char*>([charactersData bytes])), [charactersData length],
457 const_cast<char*>(reinterpret_cast<const char*>([charactersIgnoringModifiersData bytes])), [charactersIgnoringModifiersData length],
458 [event isARepeat], [event keyCode], WKGetNSEventKeyChar(event));
461 void NetscapePluginInstanceProxy::syntheticKeyDownWithCommandModifier(int keyCode, char character)
463 NSData *charactersData = [NSData dataWithBytes:&character length:1];
465 _WKPHPluginInstanceKeyboardEvent(m_pluginHostProxy->port(), m_pluginID,
466 [NSDate timeIntervalSinceReferenceDate],
467 NPCocoaEventKeyDown, NSCommandKeyMask,
468 const_cast<char*>(reinterpret_cast<const char*>([charactersData bytes])), [charactersData length],
469 const_cast<char*>(reinterpret_cast<const char*>([charactersData bytes])), [charactersData length],
470 false, keyCode, character);
473 void NetscapePluginInstanceProxy::flagsChanged(NSEvent *event)
475 _WKPHPluginInstanceKeyboardEvent(m_pluginHostProxy->port(), m_pluginID,
476 [event timestamp], NPCocoaEventFlagsChanged,
477 [event modifierFlags], 0, 0, 0, 0, false, [event keyCode], 0);
480 void NetscapePluginInstanceProxy::insertText(NSString *text)
482 NSData *textData = [text dataUsingEncoding:NSUTF8StringEncoding];
484 _WKPHPluginInstanceInsertText(m_pluginHostProxy->port(), m_pluginID,
485 const_cast<char*>(reinterpret_cast<const char*>([textData bytes])), [textData length]);
488 bool NetscapePluginInstanceProxy::wheelEvent(NSView *pluginView, NSEvent *event)
490 NSPoint pluginPoint = [pluginView convertPoint:[event locationInWindow] fromView:nil];
492 uint32_t requestID = nextRequestID();
493 _WKPHPluginInstanceWheelEvent(m_pluginHostProxy->port(), m_pluginID, requestID,
494 [event timestamp], [event modifierFlags],
495 pluginPoint.x, pluginPoint.y, [event buttonNumber],
496 [event deltaX], [event deltaY], [event deltaZ]);
498 std::auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID);
499 if (!reply.get() || !reply->m_result)
505 void NetscapePluginInstanceProxy::print(CGContextRef context, unsigned width, unsigned height)
507 uint32_t requestID = nextRequestID();
508 _WKPHPluginInstancePrint(m_pluginHostProxy->port(), m_pluginID, requestID, width, height);
510 std::auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID);
511 if (!reply.get() || !reply->m_returnValue)
514 RetainPtr<CGDataProvider> dataProvider = adoptCF(CGDataProviderCreateWithCFData(reply->m_result.get()));
515 RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
516 RetainPtr<CGImageRef> image = adoptCF(CGImageCreate(width, height, 8, 32, width * 4, colorSpace.get(), kCGImageAlphaFirst, dataProvider.get(), 0, false, kCGRenderingIntentDefault));
518 // Flip the context and draw the image.
519 CGContextSaveGState(context);
520 CGContextTranslateCTM(context, 0.0, height);
521 CGContextScaleCTM(context, 1.0, -1.0);
523 CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.get());
525 CGContextRestoreGState(context);
528 void NetscapePluginInstanceProxy::snapshot(CGContextRef context, unsigned width, unsigned height)
530 uint32_t requestID = nextRequestID();
531 _WKPHPluginInstanceSnapshot(m_pluginHostProxy->port(), m_pluginID, requestID, width, height);
533 std::auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID);
534 if (!reply.get() || !reply->m_returnValue)
537 RetainPtr<CGDataProvider> dataProvider = adoptCF(CGDataProviderCreateWithCFData(reply->m_result.get()));
538 RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
539 RetainPtr<CGImageRef> image = adoptCF(CGImageCreate(width, height, 8, 32, width * 4, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, dataProvider.get(), 0, false, kCGRenderingIntentDefault));
541 CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.get());
544 void NetscapePluginInstanceProxy::stopTimers()
546 _WKPHPluginInstanceStopTimers(m_pluginHostProxy->port(), m_pluginID);
549 void NetscapePluginInstanceProxy::status(const char* message)
551 RetainPtr<CFStringRef> status = adoptCF(CFStringCreateWithCString(0, message ? message : "", kCFStringEncodingUTF8));
555 WebView *wv = [m_pluginView webView];
556 [[wv _UIDelegateForwarder] webView:wv setStatusText:(NSString *)status.get()];
559 NPError NetscapePluginInstanceProxy::loadURL(const char* url, const char* target, const char* postData, uint32_t postLen, LoadURLFlags flags, uint32_t& streamID)
562 return NPERR_INVALID_PARAM;
564 NSMutableURLRequest *request = [m_pluginView requestWithURLCString:url];
566 if (flags & IsPost) {
567 NSData *httpBody = nil;
569 if (flags & PostDataIsFile) {
570 // If we're posting a file, buf is either a file URL or a path to the file.
572 return NPERR_INVALID_PARAM;
573 RetainPtr<CFStringRef> bufString = adoptCF(CFStringCreateWithCString(kCFAllocatorDefault, postData, kCFStringEncodingWindowsLatin1));
575 return NPERR_INVALID_PARAM;
577 NSURL *fileURL = [NSURL _web_URLWithDataAsString:(NSString *)bufString.get()];
579 if ([fileURL isFileURL])
580 path = [fileURL path];
582 path = (NSString *)bufString.get();
583 httpBody = [NSData dataWithContentsOfFile:[path _webkit_fixedCarbonPOSIXPath]];
585 return NPERR_FILE_NOT_FOUND;
587 httpBody = [NSData dataWithBytes:postData length:postLen];
589 if (![httpBody length])
590 return NPERR_INVALID_PARAM;
592 [request setHTTPMethod:@"POST"];
594 if (flags & AllowHeadersInPostData) {
595 if ([httpBody _web_startsWithBlankLine])
596 httpBody = [httpBody subdataWithRange:NSMakeRange(1, [httpBody length] - 1)];
598 NSInteger location = [httpBody _web_locationAfterFirstBlankLine];
599 if (location != NSNotFound) {
600 // If the blank line is somewhere in the middle of postData, everything before is the header.
601 NSData *headerData = [httpBody subdataWithRange:NSMakeRange(0, location)];
602 NSMutableDictionary *header = [headerData _webkit_parseRFC822HeaderFields];
603 unsigned dataLength = [httpBody length] - location;
605 // Sometimes plugins like to set Content-Length themselves when they post,
606 // but CFNetwork does not like that. So we will remove the header
607 // and instead truncate the data to the requested length.
608 NSString *contentLength = [header objectForKey:@"Content-Length"];
611 dataLength = std::min(static_cast<unsigned>([contentLength intValue]), dataLength);
612 [header removeObjectForKey:@"Content-Length"];
614 if ([header count] > 0)
615 [request setAllHTTPHeaderFields:header];
617 // Everything after the blank line is the actual content of the POST.
618 httpBody = [httpBody subdataWithRange:NSMakeRange(location, dataLength)];
623 if (![httpBody length])
624 return NPERR_INVALID_PARAM;
626 // Plug-ins expect to receive uncached data when doing a POST (3347134).
627 [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
628 [request setHTTPBody:httpBody];
631 return loadRequest(request, target, flags & AllowPopups, streamID);
634 void NetscapePluginInstanceProxy::performRequest(PluginRequest* pluginRequest)
636 // Loading the request can cause the instance proxy to go away, so protect it.
637 RefPtr<NetscapePluginInstanceProxy> protect(this);
639 ASSERT(m_pluginView);
641 NSURLRequest *request = pluginRequest->request();
642 NSString *frameName = pluginRequest->frameName();
643 WebFrame *frame = nil;
645 NSURL *URL = [request URL];
646 NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
648 ASSERT(frameName || JSString);
650 // FIXME - need to get rid of this window creation which
651 // bypasses normal targeted link handling
652 frame = kit(core([m_pluginView webFrame])->loader().findFrameForNavigation(frameName));
654 WebView *currentWebView = [m_pluginView webView];
655 NSDictionary *features = [[NSDictionary alloc] init];
656 WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView
657 createWebViewWithRequest:nil
658 windowFeatures:features];
662 _WKPHLoadURLNotify(m_pluginHostProxy->port(), m_pluginID, pluginRequest->requestID(), NPERR_GENERIC_ERROR);
666 frame = [newWebView mainFrame];
667 core(frame)->tree()->setName(frameName);
668 [[newWebView _UIDelegateForwarder] webViewShow:newWebView];
673 ASSERT(!frame || [m_pluginView webFrame] == frame);
674 evaluateJavaScript(pluginRequest);
676 [frame loadRequest:request];
678 // Check if another plug-in view or even this view is waiting for the frame to load.
679 // If it is, tell it that the load was cancelled because it will be anyway.
680 WebHostedNetscapePluginView *view = [frame _internalLoadDelegate];
682 ASSERT([view isKindOfClass:[WebHostedNetscapePluginView class]]);
683 [view webFrame:frame didFinishLoadWithReason:NPRES_USER_BREAK];
685 m_pendingFrameLoads.set(frame, pluginRequest);
686 [frame _setInternalLoadDelegate:m_pluginView];
691 void NetscapePluginInstanceProxy::webFrameDidFinishLoadWithReason(WebFrame* webFrame, NPReason reason)
693 FrameLoadMap::iterator it = m_pendingFrameLoads.find(webFrame);
694 ASSERT(it != m_pendingFrameLoads.end());
696 PluginRequest* pluginRequest = it->value.get();
697 _WKPHLoadURLNotify(m_pluginHostProxy->port(), m_pluginID, pluginRequest->requestID(), reason);
699 m_pendingFrameLoads.remove(it);
701 [webFrame _setInternalLoadDelegate:nil];
704 void NetscapePluginInstanceProxy::evaluateJavaScript(PluginRequest* pluginRequest)
706 NSURL *URL = [pluginRequest->request() URL];
707 NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
710 RefPtr<NetscapePluginInstanceProxy> protect(this); // Executing arbitrary JavaScript can destroy the proxy.
712 NSString *result = [[m_pluginView webFrame] _stringByEvaluatingJavaScriptFromString:JSString forceUserGesture:pluginRequest->allowPopups()];
714 // Don't continue if stringByEvaluatingJavaScriptFromString caused the plug-in to stop.
715 if (!m_pluginHostProxy)
718 if (pluginRequest->frameName() != nil)
721 if ([result length] > 0) {
722 // Don't call NPP_NewStream and other stream methods if there is no JS result to deliver. This is what Mozilla does.
723 NSData *JSData = [result dataUsingEncoding:NSUTF8StringEncoding];
725 RefPtr<HostedNetscapePluginStream> stream = HostedNetscapePluginStream::create(this, pluginRequest->requestID(), pluginRequest->request());
726 m_streams.add(stream->streamID(), stream);
728 RetainPtr<NSURLResponse> response = adoptNS([[NSURLResponse alloc] initWithURL:URL
729 MIMEType:@"text/plain"
730 expectedContentLength:[JSData length]
731 textEncodingName:nil]);
732 stream->startStreamWithResponse(response.get());
733 stream->didReceiveData(0, static_cast<const char*>([JSData bytes]), [JSData length]);
734 stream->didFinishLoading(0);
738 void NetscapePluginInstanceProxy::requestTimerFired(Timer<NetscapePluginInstanceProxy>*)
740 ASSERT(!m_pluginRequests.isEmpty());
741 ASSERT(m_pluginView);
743 RefPtr<PluginRequest> request = m_pluginRequests.first();
744 m_pluginRequests.removeFirst();
746 if (!m_pluginRequests.isEmpty())
747 m_requestTimer.startOneShot(0);
749 performRequest(request.get());
752 NPError NetscapePluginInstanceProxy::loadRequest(NSURLRequest *request, const char* cTarget, bool allowPopups, uint32_t& requestID)
754 NSURL *URL = [request URL];
757 return NPERR_INVALID_URL;
759 // Don't allow requests to be loaded when the document loader is stopping all loaders.
760 DocumentLoader* documentLoader = [[m_pluginView dataSource] _documentLoader];
761 if (!documentLoader || documentLoader->isStopping())
762 return NPERR_GENERIC_ERROR;
764 NSString *target = nil;
766 // Find the frame given the target string.
767 target = [NSString stringWithCString:cTarget encoding:NSISOLatin1StringEncoding];
769 WebFrame *frame = [m_pluginView webFrame];
771 // don't let a plugin start any loads if it is no longer part of a document that is being
772 // displayed unless the loads are in the same frame as the plugin.
773 if (documentLoader != core([m_pluginView webFrame])->loader().activeDocumentLoader() &&
774 (!cTarget || [frame findFrameNamed:target] != frame)) {
775 return NPERR_GENERIC_ERROR;
778 NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
779 if (JSString != nil) {
780 if (![[[m_pluginView webView] preferences] isJavaScriptEnabled]) {
781 // Return NPERR_GENERIC_ERROR if JS is disabled. This is what Mozilla does.
782 return NPERR_GENERIC_ERROR;
785 if (!core([m_pluginView webFrame])->document()->securityOrigin()->canDisplay(URL))
786 return NPERR_GENERIC_ERROR;
789 // FIXME: Handle wraparound
790 requestID = ++m_currentURLRequestID;
792 if (cTarget || JSString) {
793 // Make when targetting a frame or evaluating a JS string, perform the request after a delay because we don't
794 // want to potentially kill the plug-in inside of its URL request.
796 if (JSString && target && [frame findFrameNamed:target] != frame) {
797 // For security reasons, only allow JS requests to be made on the frame that contains the plug-in.
798 return NPERR_INVALID_PARAM;
801 RefPtr<PluginRequest> pluginRequest = PluginRequest::create(requestID, request, target, allowPopups);
802 m_pluginRequests.append(pluginRequest.release());
803 m_requestTimer.startOneShot(0);
805 RefPtr<HostedNetscapePluginStream> stream = HostedNetscapePluginStream::create(this, requestID, request);
807 ASSERT(!m_streams.contains(requestID));
808 m_streams.add(requestID, stream);
812 return NPERR_NO_ERROR;
815 NetscapePluginInstanceProxy::Reply* NetscapePluginInstanceProxy::processRequestsAndWaitForReply(uint32_t requestID)
819 ASSERT(m_pluginHostProxy);
820 while (!(reply = m_replies.take(requestID))) {
821 if (!m_pluginHostProxy->processRequests())
824 // The host proxy can be destroyed while executing a nested processRequests() call, in which case it's normal
825 // to get a success result, but be unable to keep looping.
826 if (!m_pluginHostProxy)
835 bool NetscapePluginInstanceProxy::getWindowNPObject(uint32_t& objectID)
837 Frame* frame = core([m_pluginView webFrame]);
841 if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript))
844 objectID = m_localObjects.idForObject(*pluginWorld()->vm(), frame->script()->windowShell(pluginWorld())->window());
849 bool NetscapePluginInstanceProxy::getPluginElementNPObject(uint32_t& objectID)
851 Frame* frame = core([m_pluginView webFrame]);
855 if (JSObject* object = frame->script()->jsObjectForPluginElement([m_pluginView element]))
856 objectID = m_localObjects.idForObject(*pluginWorld()->vm(), object);
863 bool NetscapePluginInstanceProxy::forgetBrowserObjectID(uint32_t objectID)
865 return m_localObjects.forget(objectID);
868 bool NetscapePluginInstanceProxy::evaluate(uint32_t objectID, const String& script, data_t& resultData, mach_msg_type_number_t& resultLength, bool allowPopups)
876 if (!m_localObjects.contains(objectID)) {
877 LOG_ERROR("NetscapePluginInstanceProxy::evaluate: local object %u doesn't exist.", objectID);
881 Frame* frame = core([m_pluginView webFrame]);
885 JSLockHolder lock(pluginWorld()->vm());
886 Strong<JSGlobalObject> globalObject(*pluginWorld()->vm(), frame->script()->globalObject(pluginWorld()));
887 ExecState* exec = globalObject->globalExec();
889 UserGestureIndicator gestureIndicator(allowPopups ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture);
891 JSValue result = JSC::evaluate(exec, makeSource(script));
893 marshalValue(exec, result, resultData, resultLength);
894 exec->clearException();
898 bool NetscapePluginInstanceProxy::invoke(uint32_t objectID, const Identifier& methodName, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength)
906 JSObject* object = m_localObjects.get(objectID);
908 LOG_ERROR("NetscapePluginInstanceProxy::invoke: local object %u doesn't exist.", objectID);
912 Frame* frame = core([m_pluginView webFrame]);
916 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
917 JSLockHolder lock(exec);
918 JSValue function = object->get(exec, methodName);
920 CallType callType = getCallData(function, callData);
921 if (callType == CallTypeNone)
924 MarkedArgumentBuffer argList;
925 demarshalValues(exec, argumentsData, argumentsLength, argList);
927 JSValue value = call(exec, function, callType, callData, object, argList);
929 marshalValue(exec, value, resultData, resultLength);
930 exec->clearException();
934 bool NetscapePluginInstanceProxy::invokeDefault(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength)
939 JSObject* object = m_localObjects.get(objectID);
941 LOG_ERROR("NetscapePluginInstanceProxy::invokeDefault: local object %u doesn't exist.", objectID);
945 Frame* frame = core([m_pluginView webFrame]);
949 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
950 JSLockHolder lock(exec);
952 CallType callType = object->methodTable()->getCallData(object, callData);
953 if (callType == CallTypeNone)
956 MarkedArgumentBuffer argList;
957 demarshalValues(exec, argumentsData, argumentsLength, argList);
959 JSValue value = call(exec, object, callType, callData, object, argList);
961 marshalValue(exec, value, resultData, resultLength);
962 exec->clearException();
966 bool NetscapePluginInstanceProxy::construct(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength)
971 JSObject* object = m_localObjects.get(objectID);
973 LOG_ERROR("NetscapePluginInstanceProxy::construct: local object %u doesn't exist.", objectID);
977 Frame* frame = core([m_pluginView webFrame]);
981 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
982 JSLockHolder lock(exec);
984 ConstructData constructData;
985 ConstructType constructType = object->methodTable()->getConstructData(object, constructData);
986 if (constructType == ConstructTypeNone)
989 MarkedArgumentBuffer argList;
990 demarshalValues(exec, argumentsData, argumentsLength, argList);
992 JSValue value = JSC::construct(exec, object, constructType, constructData, argList);
994 marshalValue(exec, value, resultData, resultLength);
995 exec->clearException();
999 bool NetscapePluginInstanceProxy::getProperty(uint32_t objectID, const Identifier& propertyName, data_t& resultData, mach_msg_type_number_t& resultLength)
1004 JSObject* object = m_localObjects.get(objectID);
1006 LOG_ERROR("NetscapePluginInstanceProxy::getProperty: local object %u doesn't exist.", objectID);
1010 Frame* frame = core([m_pluginView webFrame]);
1014 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
1015 JSLockHolder lock(exec);
1016 JSValue value = object->get(exec, propertyName);
1018 marshalValue(exec, value, resultData, resultLength);
1019 exec->clearException();
1023 bool NetscapePluginInstanceProxy::getProperty(uint32_t objectID, unsigned propertyName, data_t& resultData, mach_msg_type_number_t& resultLength)
1025 JSObject* object = m_localObjects.get(objectID);
1027 LOG_ERROR("NetscapePluginInstanceProxy::getProperty: local object %u doesn't exist.", objectID);
1031 Frame* frame = core([m_pluginView webFrame]);
1035 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
1036 JSLockHolder lock(exec);
1037 JSValue value = object->get(exec, propertyName);
1039 marshalValue(exec, value, resultData, resultLength);
1040 exec->clearException();
1044 bool NetscapePluginInstanceProxy::setProperty(uint32_t objectID, const Identifier& propertyName, data_t valueData, mach_msg_type_number_t valueLength)
1049 JSObject* object = m_localObjects.get(objectID);
1051 LOG_ERROR("NetscapePluginInstanceProxy::setProperty: local object %u doesn't exist.", objectID);
1055 Frame* frame = core([m_pluginView webFrame]);
1059 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
1060 JSLockHolder lock(exec);
1062 JSValue value = demarshalValue(exec, valueData, valueLength);
1063 PutPropertySlot slot;
1064 object->methodTable()->put(object, exec, propertyName, value, slot);
1066 exec->clearException();
1070 bool NetscapePluginInstanceProxy::setProperty(uint32_t objectID, unsigned propertyName, data_t valueData, mach_msg_type_number_t valueLength)
1075 JSObject* object = m_localObjects.get(objectID);
1077 LOG_ERROR("NetscapePluginInstanceProxy::setProperty: local object %u doesn't exist.", objectID);
1081 Frame* frame = core([m_pluginView webFrame]);
1085 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
1086 JSLockHolder lock(exec);
1088 JSValue value = demarshalValue(exec, valueData, valueLength);
1089 object->methodTable()->putByIndex(object, exec, propertyName, value, false);
1091 exec->clearException();
1095 bool NetscapePluginInstanceProxy::removeProperty(uint32_t objectID, const Identifier& propertyName)
1100 JSObject* object = m_localObjects.get(objectID);
1102 LOG_ERROR("NetscapePluginInstanceProxy::removeProperty: local object %u doesn't exist.", objectID);
1106 Frame* frame = core([m_pluginView webFrame]);
1110 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
1111 JSLockHolder lock(exec);
1112 if (!object->hasProperty(exec, propertyName)) {
1113 exec->clearException();
1117 object->methodTable()->deleteProperty(object, exec, propertyName);
1118 exec->clearException();
1122 bool NetscapePluginInstanceProxy::removeProperty(uint32_t objectID, unsigned propertyName)
1127 JSObject* object = m_localObjects.get(objectID);
1129 LOG_ERROR("NetscapePluginInstanceProxy::removeProperty: local object %u doesn't exist.", objectID);
1133 Frame* frame = core([m_pluginView webFrame]);
1137 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
1138 JSLockHolder lock(exec);
1139 if (!object->hasProperty(exec, propertyName)) {
1140 exec->clearException();
1144 object->methodTable()->deletePropertyByIndex(object, exec, propertyName);
1145 exec->clearException();
1149 bool NetscapePluginInstanceProxy::hasProperty(uint32_t objectID, const Identifier& propertyName)
1154 JSObject* object = m_localObjects.get(objectID);
1156 LOG_ERROR("NetscapePluginInstanceProxy::hasProperty: local object %u doesn't exist.", objectID);
1160 Frame* frame = core([m_pluginView webFrame]);
1164 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
1165 bool result = object->hasProperty(exec, propertyName);
1166 exec->clearException();
1171 bool NetscapePluginInstanceProxy::hasProperty(uint32_t objectID, unsigned propertyName)
1176 JSObject* object = m_localObjects.get(objectID);
1178 LOG_ERROR("NetscapePluginInstanceProxy::hasProperty: local object %u doesn't exist.", objectID);
1182 Frame* frame = core([m_pluginView webFrame]);
1186 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
1187 bool result = object->hasProperty(exec, propertyName);
1188 exec->clearException();
1193 bool NetscapePluginInstanceProxy::hasMethod(uint32_t objectID, const Identifier& methodName)
1198 JSObject* object = m_localObjects.get(objectID);
1200 LOG_ERROR("NetscapePluginInstanceProxy::hasMethod: local object %u doesn't exist.", objectID);
1204 Frame* frame = core([m_pluginView webFrame]);
1208 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
1209 JSLockHolder lock(exec);
1210 JSValue func = object->get(exec, methodName);
1211 exec->clearException();
1212 return !func.isUndefined();
1215 bool NetscapePluginInstanceProxy::enumerate(uint32_t objectID, data_t& resultData, mach_msg_type_number_t& resultLength)
1220 JSObject* object = m_localObjects.get(objectID);
1222 LOG_ERROR("NetscapePluginInstanceProxy::enumerate: local object %u doesn't exist.", objectID);
1226 Frame* frame = core([m_pluginView webFrame]);
1230 ExecState* exec = frame->script()->globalObject(pluginWorld())->globalExec();
1231 JSLockHolder lock(exec);
1233 PropertyNameArray propertyNames(exec);
1234 object->methodTable()->getPropertyNames(object, exec, propertyNames, ExcludeDontEnumProperties);
1236 RetainPtr<NSMutableArray*> array = adoptNS([[NSMutableArray alloc] init]);
1237 for (unsigned i = 0; i < propertyNames.size(); i++) {
1238 uint64_t methodName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(propertyNames[i].string().utf8().data()));
1240 [array.get() addObject:[NSNumber numberWithLongLong:methodName]];
1243 NSData *data = [NSPropertyListSerialization dataFromPropertyList:array.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
1246 resultLength = [data length];
1247 mig_allocate(reinterpret_cast<vm_address_t*>(&resultData), resultLength);
1249 memcpy(resultData, [data bytes], resultLength);
1251 exec->clearException();
1256 static bool getObjectID(NetscapePluginInstanceProxy* pluginInstanceProxy, JSObject* object, uint64_t& objectID)
1258 if (object->classInfo() != ProxyRuntimeObject::info())
1261 ProxyRuntimeObject* runtimeObject = static_cast<ProxyRuntimeObject*>(object);
1262 ProxyInstance* instance = runtimeObject->getInternalProxyInstance();
1266 if (instance->instanceProxy() != pluginInstanceProxy)
1269 objectID = instance->objectID();
1273 void NetscapePluginInstanceProxy::addValueToArray(NSMutableArray *array, ExecState* exec, JSValue value)
1275 JSLockHolder lock(exec);
1277 if (value.isString()) {
1278 [array addObject:[NSNumber numberWithInt:StringValueType]];
1279 [array addObject:value.toWTFString(exec)];
1280 } else if (value.isNumber()) {
1281 [array addObject:[NSNumber numberWithInt:DoubleValueType]];
1282 [array addObject:[NSNumber numberWithDouble:value.toNumber(exec)]];
1283 } else if (value.isBoolean()) {
1284 [array addObject:[NSNumber numberWithInt:BoolValueType]];
1285 [array addObject:[NSNumber numberWithBool:value.toBoolean(exec)]];
1286 } else if (value.isNull())
1287 [array addObject:[NSNumber numberWithInt:NullValueType]];
1288 else if (value.isObject()) {
1289 JSObject* object = asObject(value);
1291 if (getObjectID(this, object, objectID)) {
1292 [array addObject:[NSNumber numberWithInt:NPObjectValueType]];
1293 [array addObject:[NSNumber numberWithInt:objectID]];
1295 [array addObject:[NSNumber numberWithInt:JSObjectValueType]];
1296 [array addObject:[NSNumber numberWithInt:m_localObjects.idForObject(exec->vm(), object)]];
1299 [array addObject:[NSNumber numberWithInt:VoidValueType]];
1302 void NetscapePluginInstanceProxy::marshalValue(ExecState* exec, JSValue value, data_t& resultData, mach_msg_type_number_t& resultLength)
1304 RetainPtr<NSMutableArray*> array = adoptNS([[NSMutableArray alloc] init]);
1306 addValueToArray(array.get(), exec, value);
1308 RetainPtr<NSData *> data = [NSPropertyListSerialization dataFromPropertyList:array.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
1311 resultLength = [data.get() length];
1312 mig_allocate(reinterpret_cast<vm_address_t*>(&resultData), resultLength);
1314 memcpy(resultData, [data.get() bytes], resultLength);
1317 RetainPtr<NSData *> NetscapePluginInstanceProxy::marshalValues(ExecState* exec, const ArgList& args)
1319 RetainPtr<NSMutableArray*> array = adoptNS([[NSMutableArray alloc] init]);
1321 for (unsigned i = 0; i < args.size(); i++)
1322 addValueToArray(array.get(), exec, args.at(i));
1324 RetainPtr<NSData *> data = [NSPropertyListSerialization dataFromPropertyList:array.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:0];
1330 bool NetscapePluginInstanceProxy::demarshalValueFromArray(ExecState* exec, NSArray *array, NSUInteger& index, JSValue& result)
1332 if (index == [array count])
1335 int type = [[array objectAtIndex:index++] intValue];
1338 result = jsUndefined();
1344 result = jsBoolean([[array objectAtIndex:index++] boolValue]);
1346 case DoubleValueType:
1347 result = jsNumber([[array objectAtIndex:index++] doubleValue]);
1349 case StringValueType: {
1350 NSString *string = [array objectAtIndex:index++];
1352 result = jsString(exec, String(string));
1355 case JSObjectValueType: {
1356 uint32_t objectID = [[array objectAtIndex:index++] intValue];
1358 result = m_localObjects.get(objectID);
1362 case NPObjectValueType: {
1363 uint32_t objectID = [[array objectAtIndex:index++] intValue];
1365 Frame* frame = core([m_pluginView webFrame]);
1369 if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript))
1372 RefPtr<RootObject> rootObject = frame->script()->createRootObject(m_pluginView);
1376 result = ProxyInstance::create(rootObject.release(), this, objectID)->createRuntimeObject(exec);
1380 ASSERT_NOT_REACHED();
1385 JSValue NetscapePluginInstanceProxy::demarshalValue(ExecState* exec, const char* valueData, mach_msg_type_number_t valueLength)
1387 RetainPtr<NSData*> data = adoptNS([[NSData alloc] initWithBytesNoCopy:(void*)valueData length:valueLength freeWhenDone:NO]);
1389 RetainPtr<NSArray*> array = [NSPropertyListSerialization propertyListFromData:data.get()
1390 mutabilityOption:NSPropertyListImmutable
1392 errorDescription:0];
1393 NSUInteger position = 0;
1395 bool result = demarshalValueFromArray(exec, array.get(), position, value);
1396 ASSERT_UNUSED(result, result);
1401 void NetscapePluginInstanceProxy::demarshalValues(ExecState* exec, data_t valuesData, mach_msg_type_number_t valuesLength, MarkedArgumentBuffer& result)
1403 RetainPtr<NSData*> data = adoptNS([[NSData alloc] initWithBytesNoCopy:valuesData length:valuesLength freeWhenDone:NO]);
1405 RetainPtr<NSArray*> array = [NSPropertyListSerialization propertyListFromData:data.get()
1406 mutabilityOption:NSPropertyListImmutable
1408 errorDescription:0];
1409 NSUInteger position = 0;
1411 while (demarshalValueFromArray(exec, array.get(), position, value))
1412 result.append(value);
1415 void NetscapePluginInstanceProxy::retainLocalObject(JSC::JSValue value)
1417 if (!value.isObject() || value.inherits(ProxyRuntimeObject::info()))
1420 m_localObjects.retain(asObject(value));
1423 void NetscapePluginInstanceProxy::releaseLocalObject(JSC::JSValue value)
1425 if (!value.isObject() || value.inherits(ProxyRuntimeObject::info()))
1428 m_localObjects.release(asObject(value));
1431 PassRefPtr<Instance> NetscapePluginInstanceProxy::createBindingsInstance(PassRefPtr<RootObject> rootObject)
1433 uint32_t requestID = nextRequestID();
1435 if (_WKPHGetScriptableNPObject(m_pluginHostProxy->port(), m_pluginID, requestID) != KERN_SUCCESS)
1438 std::auto_ptr<GetScriptableNPObjectReply> reply = waitForReply<GetScriptableNPObjectReply>(requestID);
1442 if (!reply->m_objectID)
1445 // Since the reply was non-null, "this" is still a valid pointer.
1446 return ProxyInstance::create(rootObject, this, reply->m_objectID);
1449 void NetscapePluginInstanceProxy::addInstance(ProxyInstance* instance)
1451 ASSERT(!m_instances.contains(instance));
1453 m_instances.add(instance);
1456 void NetscapePluginInstanceProxy::removeInstance(ProxyInstance* instance)
1458 ASSERT(m_instances.contains(instance));
1460 m_instances.remove(instance);
1463 void NetscapePluginInstanceProxy::willCallPluginFunction()
1465 m_pluginFunctionCallDepth++;
1468 void NetscapePluginInstanceProxy::didCallPluginFunction(bool& stopped)
1470 ASSERT(m_pluginFunctionCallDepth > 0);
1471 m_pluginFunctionCallDepth--;
1473 // If -stop was called while we were calling into a plug-in function, and we're no longer
1474 // inside a plug-in function, stop now.
1475 if (!m_pluginFunctionCallDepth && m_shouldStopSoon) {
1476 m_shouldStopSoon = false;
1477 [m_pluginView stop];
1482 bool NetscapePluginInstanceProxy::shouldStop()
1484 if (m_pluginFunctionCallDepth) {
1485 m_shouldStopSoon = true;
1492 uint32_t NetscapePluginInstanceProxy::nextRequestID()
1494 uint32_t requestID = ++m_currentRequestID;
1496 // We don't want to return the HashMap empty/deleted "special keys"
1497 if (requestID == 0 || requestID == static_cast<uint32_t>(-1))
1498 return nextRequestID();
1503 void NetscapePluginInstanceProxy::invalidateRect(double x, double y, double width, double height)
1505 ASSERT(m_pluginView);
1507 m_pluginIsWaitingForDraw = true;
1508 [m_pluginView invalidatePluginContentRect:NSMakeRect(x, y, width, height)];
1511 void NetscapePluginInstanceProxy::didDraw()
1513 if (!m_pluginIsWaitingForDraw)
1516 m_pluginIsWaitingForDraw = false;
1517 _WKPHPluginInstanceDidDraw(m_pluginHostProxy->port(), m_pluginID);
1520 bool NetscapePluginInstanceProxy::getCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t& cookiesData, mach_msg_type_number_t& cookiesLength)
1522 ASSERT(m_pluginView);
1524 NSURL *url = [m_pluginView URLWithCString:urlData];
1528 if (Frame* frame = core([m_pluginView webFrame])) {
1529 String cookieString = cookies(frame->document(), url);
1530 WTF::CString cookieStringUTF8 = cookieString.utf8();
1531 if (cookieStringUTF8.isNull())
1534 cookiesLength = cookieStringUTF8.length();
1535 mig_allocate(reinterpret_cast<vm_address_t*>(&cookiesData), cookiesLength);
1536 memcpy(cookiesData, cookieStringUTF8.data(), cookiesLength);
1544 bool NetscapePluginInstanceProxy::setCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t cookiesData, mach_msg_type_number_t cookiesLength)
1546 ASSERT(m_pluginView);
1548 NSURL *url = [m_pluginView URLWithCString:urlData];
1552 if (Frame* frame = core([m_pluginView webFrame])) {
1553 String cookieString = String::fromUTF8(cookiesData, cookiesLength);
1557 WebCore::setCookies(frame->document(), url, cookieString);
1564 bool NetscapePluginInstanceProxy::getProxy(data_t urlData, mach_msg_type_number_t urlLength, data_t& proxyData, mach_msg_type_number_t& proxyLength)
1566 ASSERT(m_pluginView);
1568 NSURL *url = [m_pluginView URLWithCString:urlData];
1572 Vector<ProxyServer> proxyServers = proxyServersForURL(url, 0);
1573 WTF::CString proxyStringUTF8 = toString(proxyServers).utf8();
1575 proxyLength = proxyStringUTF8.length();
1576 mig_allocate(reinterpret_cast<vm_address_t*>(&proxyData), proxyLength);
1577 memcpy(proxyData, proxyStringUTF8.data(), proxyLength);
1582 bool NetscapePluginInstanceProxy::getAuthenticationInfo(data_t protocolData, data_t hostData, uint32_t port, data_t schemeData, data_t realmData,
1583 data_t& usernameData, mach_msg_type_number_t& usernameLength, data_t& passwordData, mach_msg_type_number_t& passwordLength)
1585 WTF::CString username;
1586 WTF::CString password;
1588 if (!WebKit::getAuthenticationInfo(protocolData, hostData, port, schemeData, realmData, username, password))
1591 usernameLength = username.length();
1592 mig_allocate(reinterpret_cast<vm_address_t*>(&usernameData), usernameLength);
1593 memcpy(usernameData, username.data(), usernameLength);
1595 passwordLength = password.length();
1596 mig_allocate(reinterpret_cast<vm_address_t*>(&passwordData), passwordLength);
1597 memcpy(passwordData, password.data(), passwordLength);
1602 bool NetscapePluginInstanceProxy::convertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
1603 double& destX, double& destY, NPCoordinateSpace destSpace)
1605 ASSERT(m_pluginView);
1607 return [m_pluginView convertFromX:sourceX andY:sourceY space:sourceSpace toX:&destX andY:&destY space:destSpace];
1610 uint32_t NetscapePluginInstanceProxy::checkIfAllowedToLoadURL(const char* url, const char* target)
1614 // Assign a check ID
1616 checkID = ++m_urlCheckCounter;
1617 } while (m_urlChecks.contains(checkID) || !m_urlCheckCounter);
1619 NSString *frameName = target ? [NSString stringWithCString:target encoding:NSISOLatin1StringEncoding] : nil;
1621 NSNumber *contextInfo = [[NSNumber alloc] initWithUnsignedInt:checkID];
1622 WebPluginContainerCheck *check = [WebPluginContainerCheck checkWithRequest:[m_pluginView requestWithURLCString:url]
1624 resultObject:m_pluginView
1625 selector:@selector(_containerCheckResult:contextInfo:)
1626 controller:m_pluginView
1627 contextInfo:contextInfo];
1629 [contextInfo release];
1630 m_urlChecks.set(checkID, check);
1636 void NetscapePluginInstanceProxy::cancelCheckIfAllowedToLoadURL(uint32_t checkID)
1638 URLCheckMap::iterator it = m_urlChecks.find(checkID);
1639 if (it == m_urlChecks.end())
1642 WebPluginContainerCheck *check = it->value.get();
1644 m_urlChecks.remove(it);
1647 void NetscapePluginInstanceProxy::checkIfAllowedToLoadURLResult(uint32_t checkID, bool allowed)
1649 _WKPHCheckIfAllowedToLoadURLResult(m_pluginHostProxy->port(), m_pluginID, checkID, allowed);
1652 void NetscapePluginInstanceProxy::resolveURL(const char* url, const char* target, data_t& resolvedURLData, mach_msg_type_number_t& resolvedURLLength)
1654 ASSERT(m_pluginView);
1656 WTF::CString resolvedURL = [m_pluginView resolvedURLStringForURL:url target:target];
1658 resolvedURLLength = resolvedURL.length();
1659 mig_allocate(reinterpret_cast<vm_address_t*>(&resolvedURLData), resolvedURLLength);
1660 memcpy(resolvedURLData, resolvedURL.data(), resolvedURLLength);
1663 void NetscapePluginInstanceProxy::privateBrowsingModeDidChange(bool isPrivateBrowsingEnabled)
1665 _WKPHPluginInstancePrivateBrowsingModeDidChange(m_pluginHostProxy->port(), m_pluginID, isPrivateBrowsingEnabled);
1668 static String& globalExceptionString()
1670 DEFINE_STATIC_LOCAL(String, exceptionString, ());
1671 return exceptionString;
1674 void NetscapePluginInstanceProxy::setGlobalException(const String& exception)
1676 globalExceptionString() = exception;
1679 void NetscapePluginInstanceProxy::moveGlobalExceptionToExecState(ExecState* exec)
1681 if (globalExceptionString().isNull())
1685 JSLockHolder lock(exec);
1686 throwError(exec, createError(exec, globalExceptionString()));
1689 globalExceptionString() = String();
1692 } // namespace WebKit
1694 #endif // USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)