1/* 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 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. 12 * 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. 24 */ 25 26#if USE(PLUGIN_HOST_PROCESS) 27 28#import "NetscapePluginInstanceProxy.h" 29 30#import "HostedNetscapePluginStream.h" 31#import "NetscapePluginHostProxy.h" 32#import "ProxyInstance.h" 33#import "WebDataSourceInternal.h" 34#import "WebFrameInternal.h" 35#import "WebHostedNetscapePluginView.h" 36#import "WebNSDataExtras.h" 37#import "WebNSURLExtras.h" 38#import "WebKitNSStringExtras.h" 39#import "WebPluginRequest.h" 40#import "WebViewInternal.h" 41#import "WebUIDelegate.h" 42#import "WebUIDelegatePrivate.h" 43 44#import <mach/mach.h> 45#import <WebCore/CookieJar.h> 46#import <WebCore/CString.h> 47#import <WebCore/DocumentLoader.h> 48#import <WebCore/Frame.h> 49#import <WebCore/FrameLoader.h> 50#import <WebCore/FrameTree.h> 51#import <WebCore/KURL.h> 52#import <WebCore/npruntime_impl.h> 53#import <WebCore/runtime_object.h> 54#import <WebCore/ScriptController.h> 55#import <WebCore/ScriptValue.h> 56#import <WebKitSystemInterface.h> 57#import <runtime/JSLock.h> 58#import <runtime/PropertyNameArray.h> 59#import <utility> 60 61extern "C" { 62#import "WebKitPluginClientServer.h" 63#import "WebKitPluginHost.h" 64} 65 66using namespace JSC; 67using namespace JSC::Bindings; 68using namespace std; 69using namespace WebCore; 70 71namespace WebKit { 72 73class NetscapePluginInstanceProxy::PluginRequest { 74public: 75 PluginRequest(uint32_t requestID, NSURLRequest *request, NSString *frameName, bool allowPopups) 76 : m_requestID(requestID) 77 , m_request(request) 78 , m_frameName(frameName) 79 , m_allowPopups(allowPopups) 80 { 81 } 82 83 uint32_t requestID() const { return m_requestID; } 84 NSURLRequest *request() const { return m_request.get(); } 85 NSString *frameName() const { return m_frameName.get(); } 86 bool allowPopups() const { return m_allowPopups; } 87 88private: 89 uint32_t m_requestID; 90 RetainPtr<NSURLRequest *> m_request; 91 RetainPtr<NSString *> m_frameName; 92 bool m_allowPopups; 93}; 94 95static uint32_t pluginIDCounter; 96 97NetscapePluginInstanceProxy::NetscapePluginInstanceProxy(NetscapePluginHostProxy* pluginHostProxy, WebHostedNetscapePluginView *pluginView, bool fullFramePlugin) 98 : m_pluginHostProxy(pluginHostProxy) 99 , m_pluginView(pluginView) 100 , m_requestTimer(this, &NetscapePluginInstanceProxy::requestTimerFired) 101 , m_currentURLRequestID(0) 102 , m_renderContextID(0) 103 , m_useSoftwareRenderer(false) 104 , m_waitingForReply(false) 105 , m_objectIDCounter(0) 106 , m_urlCheckCounter(0) 107 , m_pluginFunctionCallDepth(0) 108 , m_shouldStopSoon(false) 109 , m_currentRequestID(0) 110 , m_inDestroy(false) 111{ 112 ASSERT(m_pluginView); 113 114 if (fullFramePlugin) { 115 // For full frame plug-ins, the first requestID will always be the one for the already 116 // open stream. 117 ++m_currentRequestID; 118 } 119 120 // Assign a plug-in ID. 121 do { 122 m_pluginID = ++pluginIDCounter; 123 } while (pluginHostProxy->pluginInstance(m_pluginID) || !m_pluginID); 124 125 pluginHostProxy->addPluginInstance(this); 126} 127 128NetscapePluginInstanceProxy::~NetscapePluginInstanceProxy() 129{ 130 ASSERT(!m_pluginHostProxy); 131 132 m_pluginID = 0; 133 deleteAllValues(m_replies); 134} 135 136void NetscapePluginInstanceProxy::resize(NSRect size, NSRect clipRect, bool sync) 137{ 138 uint32_t requestID = 0; 139 140 if (sync) 141 requestID = nextRequestID(); 142 143 _WKPHResizePluginInstance(m_pluginHostProxy->port(), m_pluginID, requestID, 144 size.origin.x, size.origin.y, size.size.width, size.size.height, 145 clipRect.origin.x, clipRect.origin.y, clipRect.size.width, clipRect.size.height); 146 147 if (sync) 148 waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID); 149} 150 151void NetscapePluginInstanceProxy::stopAllStreams() 152{ 153 Vector<RefPtr<HostedNetscapePluginStream> > streamsCopy; 154 copyValuesToVector(m_streams, streamsCopy); 155 for (size_t i = 0; i < streamsCopy.size(); i++) 156 streamsCopy[i]->stop(); 157} 158 159void NetscapePluginInstanceProxy::cleanup() 160{ 161 stopAllStreams(); 162 163 m_requestTimer.stop(); 164 165 // Clear the object map, this will cause any outstanding JS objects that the plug-in had a reference to 166 // to go away when the next garbage collection takes place. 167 m_objects.clear(); 168 169 if (Frame* frame = core([m_pluginView webFrame])) 170 frame->script()->cleanupScriptObjectsForPlugin(m_pluginView); 171 172 ProxyInstanceSet instances; 173 instances.swap(m_instances); 174 175 // Invalidate all proxy instances. 176 ProxyInstanceSet::const_iterator end = instances.end(); 177 for (ProxyInstanceSet::const_iterator it = instances.begin(); it != end; ++it) 178 (*it)->invalidate(); 179 180 m_pluginView = nil; 181} 182 183void NetscapePluginInstanceProxy::invalidate() 184{ 185 // If the plug-in host has died, the proxy will be null. 186 if (!m_pluginHostProxy) 187 return; 188 189 m_pluginHostProxy->removePluginInstance(this); 190 m_pluginHostProxy = 0; 191} 192 193void NetscapePluginInstanceProxy::destroy() 194{ 195 uint32_t requestID = nextRequestID(); 196 197 m_inDestroy = true; 198 199 _WKPHDestroyPluginInstance(m_pluginHostProxy->port(), m_pluginID, requestID); 200 201 // If the plug-in host crashes while we're waiting for a reply, the last reference to the instance proxy 202 // will go away. Prevent this by protecting it here. 203 RefPtr<NetscapePluginInstanceProxy> protect(this); 204 205 // We don't care about the reply here - we just want to block until the plug-in instance has been torn down. 206 waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID); 207 208 m_inDestroy = false; 209 210 cleanup(); 211 invalidate(); 212} 213 214void NetscapePluginInstanceProxy::setManualStream(PassRefPtr<HostedNetscapePluginStream> manualStream) 215{ 216 ASSERT(!m_manualStream); 217 218 m_manualStream = manualStream; 219} 220 221bool NetscapePluginInstanceProxy::cancelStreamLoad(uint32_t streamID, NPReason reason) 222{ 223 HostedNetscapePluginStream* stream = 0; 224 225 if (m_manualStream && streamID == 1) 226 stream = m_manualStream.get(); 227 else 228 stream = m_streams.get(streamID).get(); 229 230 if (!stream) 231 return false; 232 233 stream->cancelLoad(reason); 234 return true; 235} 236 237void NetscapePluginInstanceProxy::disconnectStream(HostedNetscapePluginStream* stream) 238{ 239 m_streams.remove(stream->streamID()); 240} 241 242void NetscapePluginInstanceProxy::pluginHostDied() 243{ 244 m_pluginHostProxy = 0; 245 246 [m_pluginView pluginHostDied]; 247 248 cleanup(); 249} 250 251void NetscapePluginInstanceProxy::focusChanged(bool hasFocus) 252{ 253 _WKPHPluginInstanceFocusChanged(m_pluginHostProxy->port(), m_pluginID, hasFocus); 254} 255 256void NetscapePluginInstanceProxy::windowFocusChanged(bool hasFocus) 257{ 258 _WKPHPluginInstanceWindowFocusChanged(m_pluginHostProxy->port(), m_pluginID, hasFocus); 259} 260 261void NetscapePluginInstanceProxy::windowFrameChanged(NSRect frame) 262{ 263 _WKPHPluginInstanceWindowFrameChanged(m_pluginHostProxy->port(), m_pluginID, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height, 264 NSMaxY([[[NSScreen screens] objectAtIndex:0] frame])); 265} 266 267void NetscapePluginInstanceProxy::startTimers(bool throttleTimers) 268{ 269 _WKPHPluginInstanceStartTimers(m_pluginHostProxy->port(), m_pluginID, throttleTimers); 270} 271 272void NetscapePluginInstanceProxy::mouseEvent(NSView *pluginView, NSEvent *event, NPCocoaEventType type) 273{ 274 NSPoint screenPoint = [[event window] convertBaseToScreen:[event locationInWindow]]; 275 NSPoint pluginPoint = [pluginView convertPoint:[event locationInWindow] fromView:nil]; 276 277 int clickCount; 278 if (type == NPCocoaEventMouseEntered || type == NPCocoaEventMouseExited) 279 clickCount = 0; 280 else 281 clickCount = [event clickCount]; 282 283 284 _WKPHPluginInstanceMouseEvent(m_pluginHostProxy->port(), m_pluginID, 285 [event timestamp], 286 type, [event modifierFlags], 287 pluginPoint.x, pluginPoint.y, 288 screenPoint.x, screenPoint.y, 289 NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]), 290 [event buttonNumber], clickCount, 291 [event deltaX], [event deltaY], [event deltaZ]); 292} 293 294void NetscapePluginInstanceProxy::keyEvent(NSView *pluginView, NSEvent *event, NPCocoaEventType type) 295{ 296 NSData *charactersData = [[event characters] dataUsingEncoding:NSUTF8StringEncoding]; 297 NSData *charactersIgnoringModifiersData = [[event charactersIgnoringModifiers] dataUsingEncoding:NSUTF8StringEncoding]; 298 299 _WKPHPluginInstanceKeyboardEvent(m_pluginHostProxy->port(), m_pluginID, 300 [event timestamp], 301 type, [event modifierFlags], 302 const_cast<char*>(reinterpret_cast<const char*>([charactersData bytes])), [charactersData length], 303 const_cast<char*>(reinterpret_cast<const char*>([charactersIgnoringModifiersData bytes])), [charactersIgnoringModifiersData length], 304 [event isARepeat], [event keyCode], WKGetNSEventKeyChar(event)); 305} 306 307void NetscapePluginInstanceProxy::syntheticKeyDownWithCommandModifier(int keyCode, char character) 308{ 309 NSData *charactersData = [NSData dataWithBytes:&character length:1]; 310 311 _WKPHPluginInstanceKeyboardEvent(m_pluginHostProxy->port(), m_pluginID, 312 [NSDate timeIntervalSinceReferenceDate], 313 NPCocoaEventKeyDown, NSCommandKeyMask, 314 const_cast<char*>(reinterpret_cast<const char*>([charactersData bytes])), [charactersData length], 315 const_cast<char*>(reinterpret_cast<const char*>([charactersData bytes])), [charactersData length], 316 false, keyCode, character); 317} 318 319void NetscapePluginInstanceProxy::flagsChanged(NSEvent *event) 320{ 321 _WKPHPluginInstanceKeyboardEvent(m_pluginHostProxy->port(), m_pluginID, 322 [event timestamp], NPCocoaEventFlagsChanged, 323 [event modifierFlags], 0, 0, 0, 0, false, [event keyCode], 0); 324} 325 326void NetscapePluginInstanceProxy::insertText(NSString *text) 327{ 328 NSData *textData = [text dataUsingEncoding:NSUTF8StringEncoding]; 329 330 _WKPHPluginInstanceInsertText(m_pluginHostProxy->port(), m_pluginID, 331 const_cast<char*>(reinterpret_cast<const char*>([textData bytes])), [textData length]); 332} 333 334bool NetscapePluginInstanceProxy::wheelEvent(NSView *pluginView, NSEvent *event) 335{ 336 NSPoint pluginPoint = [pluginView convertPoint:[event locationInWindow] fromView:nil]; 337 338 uint32_t requestID = nextRequestID(); 339 _WKPHPluginInstanceWheelEvent(m_pluginHostProxy->port(), m_pluginID, requestID, 340 [event timestamp], [event modifierFlags], 341 pluginPoint.x, pluginPoint.y, [event buttonNumber], 342 [event deltaX], [event deltaY], [event deltaZ]); 343 344 // Protect ourselves in case waiting for the reply causes us to be deleted. 345 RefPtr<NetscapePluginInstanceProxy> protect(this); 346 347 auto_ptr<NetscapePluginInstanceProxy::BooleanReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanReply>(requestID); 348 if (!reply.get() || !reply->m_result) 349 return false; 350 351 return true; 352} 353 354void NetscapePluginInstanceProxy::print(CGContextRef context, unsigned width, unsigned height) 355{ 356 uint32_t requestID = nextRequestID(); 357 _WKPHPluginInstancePrint(m_pluginHostProxy->port(), m_pluginID, requestID, width, height); 358 359 auto_ptr<NetscapePluginInstanceProxy::BooleanAndDataReply> reply = waitForReply<NetscapePluginInstanceProxy::BooleanAndDataReply>(requestID); 360 if (!reply.get() || !reply->m_returnValue) 361 return; 362 363 RetainPtr<CGDataProvider> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(reply->m_result.get())); 364 RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); 365 RetainPtr<CGImageRef> image(AdoptCF, CGImageCreate(width, height, 8, 32, width * 4, colorSpace.get(), kCGImageAlphaFirst, dataProvider.get(), 0, false, kCGRenderingIntentDefault)); 366 367 // Flip the context and draw the image. 368 CGContextSaveGState(context); 369 CGContextTranslateCTM(context, 0.0, height); 370 CGContextScaleCTM(context, 1.0, -1.0); 371 372 CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.get()); 373 374 CGContextRestoreGState(context); 375} 376 377void NetscapePluginInstanceProxy::stopTimers() 378{ 379 _WKPHPluginInstanceStopTimers(m_pluginHostProxy->port(), m_pluginID); 380} 381 382void NetscapePluginInstanceProxy::status(const char* message) 383{ 384 RetainPtr<CFStringRef> status(AdoptCF, CFStringCreateWithCString(NULL, message, kCFStringEncodingUTF8)); 385 386 if (!status) 387 return; 388 389 WebView *wv = [m_pluginView webView]; 390 [[wv _UIDelegateForwarder] webView:wv setStatusText:(NSString *)status.get()]; 391} 392 393NPError NetscapePluginInstanceProxy::loadURL(const char* url, const char* target, const char* postData, uint32_t postLen, LoadURLFlags flags, uint32_t& streamID) 394{ 395 if (!url) 396 return NPERR_INVALID_PARAM; 397 398 NSMutableURLRequest *request = [m_pluginView requestWithURLCString:url]; 399 400 if (flags & IsPost) { 401 NSData *httpBody = nil; 402 403 if (flags & PostDataIsFile) { 404 // If we're posting a file, buf is either a file URL or a path to the file. 405 RetainPtr<CFStringRef> bufString(AdoptCF, CFStringCreateWithCString(kCFAllocatorDefault, postData, kCFStringEncodingWindowsLatin1)); 406 if (!bufString) 407 return NPERR_INVALID_PARAM; 408 409 NSURL *fileURL = [NSURL _web_URLWithDataAsString:(NSString *)bufString.get()]; 410 NSString *path; 411 if ([fileURL isFileURL]) 412 path = [fileURL path]; 413 else 414 path = (NSString *)bufString.get(); 415 httpBody = [NSData dataWithContentsOfFile:[path _webkit_fixedCarbonPOSIXPath]]; 416 if (!httpBody) 417 return NPERR_FILE_NOT_FOUND; 418 } else 419 httpBody = [NSData dataWithBytes:postData length:postLen]; 420 421 if (![httpBody length]) 422 return NPERR_INVALID_PARAM; 423 424 [request setHTTPMethod:@"POST"]; 425 426 if (flags & AllowHeadersInPostData) { 427 if ([httpBody _web_startsWithBlankLine]) 428 httpBody = [httpBody subdataWithRange:NSMakeRange(1, [httpBody length] - 1)]; 429 else { 430 NSInteger location = [httpBody _web_locationAfterFirstBlankLine]; 431 if (location != NSNotFound) { 432 // If the blank line is somewhere in the middle of postData, everything before is the header. 433 NSData *headerData = [httpBody subdataWithRange:NSMakeRange(0, location)]; 434 NSMutableDictionary *header = [headerData _webkit_parseRFC822HeaderFields]; 435 unsigned dataLength = [httpBody length] - location; 436 437 // Sometimes plugins like to set Content-Length themselves when they post, 438 // but CFNetwork does not like that. So we will remove the header 439 // and instead truncate the data to the requested length. 440 NSString *contentLength = [header objectForKey:@"Content-Length"]; 441 442 if (contentLength) 443 dataLength = min(static_cast<unsigned>([contentLength intValue]), dataLength); 444 [header removeObjectForKey:@"Content-Length"]; 445 446 if ([header count] > 0) 447 [request setAllHTTPHeaderFields:header]; 448 449 // Everything after the blank line is the actual content of the POST. 450 httpBody = [httpBody subdataWithRange:NSMakeRange(location, dataLength)]; 451 } 452 } 453 } 454 455 if (![httpBody length]) 456 return NPERR_INVALID_PARAM; 457 458 // Plug-ins expect to receive uncached data when doing a POST (3347134). 459 [request setCachePolicy:NSURLRequestReloadIgnoringCacheData]; 460 [request setHTTPBody:httpBody]; 461 } 462 463 return loadRequest(request, target, flags & AllowPopups, streamID); 464} 465 466void NetscapePluginInstanceProxy::performRequest(PluginRequest* pluginRequest) 467{ 468 ASSERT(m_pluginView); 469 470 NSURLRequest *request = pluginRequest->request(); 471 NSString *frameName = pluginRequest->frameName(); 472 WebFrame *frame = nil; 473 474 NSURL *URL = [request URL]; 475 NSString *JSString = [URL _webkit_scriptIfJavaScriptURL]; 476 477 ASSERT(frameName || JSString); 478 if (frameName) { 479 // FIXME - need to get rid of this window creation which 480 // bypasses normal targeted link handling 481 frame = kit(core([m_pluginView webFrame])->loader()->findFrameForNavigation(frameName)); 482 if (!frame) { 483 WebView *currentWebView = [m_pluginView webView]; 484 NSDictionary *features = [[NSDictionary alloc] init]; 485 WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView 486 createWebViewWithRequest:nil 487 windowFeatures:features]; 488 [features release]; 489 490 if (!newWebView) { 491 _WKPHLoadURLNotify(m_pluginHostProxy->port(), m_pluginID, pluginRequest->requestID(), NPERR_GENERIC_ERROR); 492 return; 493 } 494 495 frame = [newWebView mainFrame]; 496 core(frame)->tree()->setName(frameName); 497 [[newWebView _UIDelegateForwarder] webViewShow:newWebView]; 498 } 499 } 500 501 if (JSString) { 502 ASSERT(!frame || [m_pluginView webFrame] == frame); 503 evaluateJavaScript(pluginRequest); 504 } else 505 [frame loadRequest:request]; 506} 507 508void NetscapePluginInstanceProxy::evaluateJavaScript(PluginRequest* pluginRequest) 509{ 510 NSURL *URL = [pluginRequest->request() URL]; 511 NSString *JSString = [URL _webkit_scriptIfJavaScriptURL]; 512 ASSERT(JSString); 513 514 NSString *result = [[m_pluginView webFrame] _stringByEvaluatingJavaScriptFromString:JSString forceUserGesture:pluginRequest->allowPopups()]; 515 516 // Don't continue if stringByEvaluatingJavaScriptFromString caused the plug-in to stop. 517 if (!m_pluginHostProxy) 518 return; 519 520 if (pluginRequest->frameName() != nil) 521 return; 522 523 if ([result length] > 0) { 524 // Don't call NPP_NewStream and other stream methods if there is no JS result to deliver. This is what Mozilla does. 525 NSData *JSData = [result dataUsingEncoding:NSUTF8StringEncoding]; 526 527 RefPtr<HostedNetscapePluginStream> stream = HostedNetscapePluginStream::create(this, pluginRequest->requestID(), pluginRequest->request()); 528 529 RetainPtr<NSURLResponse> response(AdoptNS, [[NSURLResponse alloc] initWithURL:URL 530 MIMEType:@"text/plain" 531 expectedContentLength:[JSData length] 532 textEncodingName:nil]); 533 stream->startStreamWithResponse(response.get()); 534 stream->didReceiveData(0, static_cast<const char*>([JSData bytes]), [JSData length]); 535 stream->didFinishLoading(0); 536 } 537} 538 539void NetscapePluginInstanceProxy::requestTimerFired(Timer<NetscapePluginInstanceProxy>*) 540{ 541 ASSERT(!m_pluginRequests.isEmpty()); 542 ASSERT(m_pluginView); 543 544 PluginRequest* request = m_pluginRequests.first(); 545 m_pluginRequests.removeFirst(); 546 547 if (!m_pluginRequests.isEmpty()) 548 m_requestTimer.startOneShot(0); 549 550 performRequest(request); 551 delete request; 552} 553 554NPError NetscapePluginInstanceProxy::loadRequest(NSURLRequest *request, const char* cTarget, bool allowPopups, uint32_t& requestID) 555{ 556 NSURL *URL = [request URL]; 557 558 if (!URL) 559 return NPERR_INVALID_URL; 560 561 // Don't allow requests to be loaded when the document loader is stopping all loaders. 562 if ([[m_pluginView dataSource] _documentLoader]->isStopping()) 563 return NPERR_GENERIC_ERROR; 564 565 NSString *target = nil; 566 if (cTarget) { 567 // Find the frame given the target string. 568 target = [NSString stringWithCString:cTarget encoding:NSISOLatin1StringEncoding]; 569 } 570 WebFrame *frame = [m_pluginView webFrame]; 571 572 // don't let a plugin start any loads if it is no longer part of a document that is being 573 // displayed unless the loads are in the same frame as the plugin. 574 if ([[m_pluginView dataSource] _documentLoader] != core([m_pluginView webFrame])->loader()->activeDocumentLoader() && 575 (!cTarget || [frame findFrameNamed:target] != frame)) { 576 return NPERR_GENERIC_ERROR; 577 } 578 579 NSString *JSString = [URL _webkit_scriptIfJavaScriptURL]; 580 if (JSString != nil) { 581 if (![[[m_pluginView webView] preferences] isJavaScriptEnabled]) { 582 // Return NPERR_GENERIC_ERROR if JS is disabled. This is what Mozilla does. 583 return NPERR_GENERIC_ERROR; 584 } 585 } else { 586 if (!FrameLoader::canLoad(URL, String(), core([m_pluginView webFrame])->document())) 587 return NPERR_GENERIC_ERROR; 588 } 589 590 // FIXME: Handle wraparound 591 requestID = ++m_currentURLRequestID; 592 593 if (cTarget || JSString) { 594 // Make when targetting a frame or evaluating a JS string, perform the request after a delay because we don't 595 // want to potentially kill the plug-in inside of its URL request. 596 597 if (JSString && target && [frame findFrameNamed:target] != frame) { 598 // For security reasons, only allow JS requests to be made on the frame that contains the plug-in. 599 return NPERR_INVALID_PARAM; 600 } 601 602 PluginRequest* pluginRequest = new PluginRequest(requestID, request, target, allowPopups); 603 m_pluginRequests.append(pluginRequest); 604 m_requestTimer.startOneShot(0); 605 } else { 606 RefPtr<HostedNetscapePluginStream> stream = HostedNetscapePluginStream::create(this, requestID, request); 607 608 m_streams.add(requestID, stream); 609 stream->start(); 610 } 611 612 return NPERR_NO_ERROR; 613} 614 615NetscapePluginInstanceProxy::Reply* NetscapePluginInstanceProxy::processRequestsAndWaitForReply(uint32_t requestID) 616{ 617 Reply* reply = 0; 618 619 while (!(reply = m_replies.take(requestID))) { 620 if (!m_pluginHostProxy->processRequests()) 621 return 0; 622 } 623 624 ASSERT(reply); 625 return reply; 626} 627 628uint32_t NetscapePluginInstanceProxy::idForObject(JSObject* object) 629{ 630 uint32_t objectID = 0; 631 632 // Assign an object ID. 633 do { 634 objectID = ++m_objectIDCounter; 635 } while (!m_objectIDCounter || m_objectIDCounter == static_cast<uint32_t>(-1) || m_objects.contains(objectID)); 636 637 m_objects.set(objectID, object); 638 639 return objectID; 640} 641 642// NPRuntime support 643bool NetscapePluginInstanceProxy::getWindowNPObject(uint32_t& objectID) 644{ 645 Frame* frame = core([m_pluginView webFrame]); 646 if (!frame) 647 return false; 648 649 if (!frame->script()->isEnabled()) 650 objectID = 0; 651 else 652 objectID = idForObject(frame->script()->windowShell()->window()); 653 654 return true; 655} 656 657bool NetscapePluginInstanceProxy::getPluginElementNPObject(uint32_t& objectID) 658{ 659 Frame* frame = core([m_pluginView webFrame]); 660 if (!frame) 661 return false; 662 663 if (JSObject* object = frame->script()->jsObjectForPluginElement([m_pluginView element])) 664 objectID = idForObject(object); 665 else 666 objectID = 0; 667 668 return true; 669} 670 671void NetscapePluginInstanceProxy::releaseObject(uint32_t objectID) 672{ 673 m_objects.remove(objectID); 674} 675 676bool NetscapePluginInstanceProxy::evaluate(uint32_t objectID, const String& script, data_t& resultData, mach_msg_type_number_t& resultLength, bool allowPopups) 677{ 678 resultData = 0; 679 resultLength = 0; 680 681 if (!m_objects.contains(objectID)) 682 return false; 683 684 Frame* frame = core([m_pluginView webFrame]); 685 if (!frame) 686 return false; 687 688 JSLock lock(SilenceAssertionsOnly); 689 690 ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(); 691 ExecState* exec = globalObject->globalExec(); 692 693 bool oldAllowPopups = frame->script()->allowPopupsFromPlugin(); 694 frame->script()->setAllowPopupsFromPlugin(allowPopups); 695 696 globalObject->globalData()->timeoutChecker.start(); 697 Completion completion = JSC::evaluate(exec, globalObject->globalScopeChain(), makeSource(script)); 698 globalObject->globalData()->timeoutChecker.stop(); 699 ComplType type = completion.complType(); 700 701 frame->script()->setAllowPopupsFromPlugin(oldAllowPopups); 702 703 JSValue result; 704 if (type == Normal) 705 result = completion.value(); 706 707 if (!result) 708 result = jsUndefined(); 709 710 marshalValue(exec, result, resultData, resultLength); 711 exec->clearException(); 712 return true; 713} 714 715bool 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) 716{ 717 resultData = 0; 718 resultLength = 0; 719 720 if (m_inDestroy) 721 return false; 722 723 JSObject* object = m_objects.get(objectID); 724 if (!object) 725 return false; 726 727 Frame* frame = core([m_pluginView webFrame]); 728 if (!frame) 729 return false; 730 731 ExecState* exec = frame->script()->globalObject()->globalExec(); 732 JSLock lock(SilenceAssertionsOnly); 733 JSValue function = object->get(exec, methodName); 734 CallData callData; 735 CallType callType = function.getCallData(callData); 736 if (callType == CallTypeNone) 737 return false; 738 739 MarkedArgumentBuffer argList; 740 demarshalValues(exec, argumentsData, argumentsLength, argList); 741 742 ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(); 743 globalObject->globalData()->timeoutChecker.start(); 744 JSValue value = call(exec, function, callType, callData, object, argList); 745 globalObject->globalData()->timeoutChecker.stop(); 746 747 marshalValue(exec, value, resultData, resultLength); 748 exec->clearException(); 749 return true; 750} 751 752bool NetscapePluginInstanceProxy::invokeDefault(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength) 753{ 754 if (m_inDestroy) 755 return false; 756 757 JSObject* object = m_objects.get(objectID); 758 if (!object) 759 return false; 760 761 Frame* frame = core([m_pluginView webFrame]); 762 if (!frame) 763 return false; 764 765 ExecState* exec = frame->script()->globalObject()->globalExec(); 766 JSLock lock(SilenceAssertionsOnly); 767 CallData callData; 768 CallType callType = object->getCallData(callData); 769 if (callType == CallTypeNone) 770 return false; 771 772 MarkedArgumentBuffer argList; 773 demarshalValues(exec, argumentsData, argumentsLength, argList); 774 775 ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(); 776 globalObject->globalData()->timeoutChecker.start(); 777 JSValue value = call(exec, object, callType, callData, object, argList); 778 globalObject->globalData()->timeoutChecker.stop(); 779 780 marshalValue(exec, value, resultData, resultLength); 781 exec->clearException(); 782 return true; 783} 784 785bool NetscapePluginInstanceProxy::construct(uint32_t objectID, data_t argumentsData, mach_msg_type_number_t argumentsLength, data_t& resultData, mach_msg_type_number_t& resultLength) 786{ 787 if (m_inDestroy) 788 return false; 789 790 JSObject* object = m_objects.get(objectID); 791 if (!object) 792 return false; 793 794 Frame* frame = core([m_pluginView webFrame]); 795 if (!frame) 796 return false; 797 798 ExecState* exec = frame->script()->globalObject()->globalExec(); 799 JSLock lock(SilenceAssertionsOnly); 800 801 ConstructData constructData; 802 ConstructType constructType = object->getConstructData(constructData); 803 if (constructType == ConstructTypeNone) 804 return false; 805 806 MarkedArgumentBuffer argList; 807 demarshalValues(exec, argumentsData, argumentsLength, argList); 808 809 ProtectedPtr<JSGlobalObject> globalObject = frame->script()->globalObject(); 810 globalObject->globalData()->timeoutChecker.start(); 811 JSValue value = JSC::construct(exec, object, constructType, constructData, argList); 812 globalObject->globalData()->timeoutChecker.stop(); 813 814 marshalValue(exec, value, resultData, resultLength); 815 exec->clearException(); 816 return true; 817} 818 819bool NetscapePluginInstanceProxy::getProperty(uint32_t objectID, const Identifier& propertyName, data_t& resultData, mach_msg_type_number_t& resultLength) 820{ 821 if (m_inDestroy) 822 return false; 823 824 JSObject* object = m_objects.get(objectID); 825 if (!object) 826 return false; 827 828 Frame* frame = core([m_pluginView webFrame]); 829 if (!frame) 830 return false; 831 832 ExecState* exec = frame->script()->globalObject()->globalExec(); 833 JSLock lock(SilenceAssertionsOnly); 834 JSValue value = object->get(exec, propertyName); 835 836 marshalValue(exec, value, resultData, resultLength); 837 exec->clearException(); 838 return true; 839} 840 841bool NetscapePluginInstanceProxy::getProperty(uint32_t objectID, unsigned propertyName, data_t& resultData, mach_msg_type_number_t& resultLength) 842{ 843 JSObject* object = m_objects.get(objectID); 844 if (!object) 845 return false; 846 847 Frame* frame = core([m_pluginView webFrame]); 848 if (!frame) 849 return false; 850 851 ExecState* exec = frame->script()->globalObject()->globalExec(); 852 JSLock lock(SilenceAssertionsOnly); 853 JSValue value = object->get(exec, propertyName); 854 855 marshalValue(exec, value, resultData, resultLength); 856 exec->clearException(); 857 return true; 858} 859 860bool NetscapePluginInstanceProxy::setProperty(uint32_t objectID, const Identifier& propertyName, data_t valueData, mach_msg_type_number_t valueLength) 861{ 862 if (m_inDestroy) 863 return false; 864 865 JSObject* object = m_objects.get(objectID); 866 if (!object) 867 return false; 868 869 Frame* frame = core([m_pluginView webFrame]); 870 if (!frame) 871 return false; 872 873 ExecState* exec = frame->script()->globalObject()->globalExec(); 874 JSLock lock(SilenceAssertionsOnly); 875 876 JSValue value = demarshalValue(exec, valueData, valueLength); 877 PutPropertySlot slot; 878 object->put(exec, propertyName, value, slot); 879 880 exec->clearException(); 881 return true; 882} 883 884bool NetscapePluginInstanceProxy::setProperty(uint32_t objectID, unsigned propertyName, data_t valueData, mach_msg_type_number_t valueLength) 885{ 886 if (m_inDestroy) 887 return false; 888 889 JSObject* object = m_objects.get(objectID); 890 if (!object) 891 return false; 892 893 Frame* frame = core([m_pluginView webFrame]); 894 if (!frame) 895 return false; 896 897 ExecState* exec = frame->script()->globalObject()->globalExec(); 898 JSLock lock(SilenceAssertionsOnly); 899 900 JSValue value = demarshalValue(exec, valueData, valueLength); 901 object->put(exec, propertyName, value); 902 903 exec->clearException(); 904 return true; 905} 906 907bool NetscapePluginInstanceProxy::removeProperty(uint32_t objectID, const Identifier& propertyName) 908{ 909 if (m_inDestroy) 910 return false; 911 912 JSObject* object = m_objects.get(objectID); 913 if (!object) 914 return false; 915 916 Frame* frame = core([m_pluginView webFrame]); 917 if (!frame) 918 return false; 919 920 ExecState* exec = frame->script()->globalObject()->globalExec(); 921 if (!object->hasProperty(exec, propertyName)) { 922 exec->clearException(); 923 return false; 924 } 925 926 JSLock lock(SilenceAssertionsOnly); 927 object->deleteProperty(exec, propertyName); 928 exec->clearException(); 929 return true; 930} 931 932bool NetscapePluginInstanceProxy::removeProperty(uint32_t objectID, unsigned propertyName) 933{ 934 if (m_inDestroy) 935 return false; 936 937 JSObject* object = m_objects.get(objectID); 938 if (!object) 939 return false; 940 941 Frame* frame = core([m_pluginView webFrame]); 942 if (!frame) 943 return false; 944 945 ExecState* exec = frame->script()->globalObject()->globalExec(); 946 if (!object->hasProperty(exec, propertyName)) { 947 exec->clearException(); 948 return false; 949 } 950 951 JSLock lock(SilenceAssertionsOnly); 952 object->deleteProperty(exec, propertyName); 953 exec->clearException(); 954 return true; 955} 956 957bool NetscapePluginInstanceProxy::hasProperty(uint32_t objectID, const Identifier& propertyName) 958{ 959 if (m_inDestroy) 960 return false; 961 962 JSObject* object = m_objects.get(objectID); 963 if (!object) 964 return false; 965 966 Frame* frame = core([m_pluginView webFrame]); 967 if (!frame) 968 return false; 969 970 ExecState* exec = frame->script()->globalObject()->globalExec(); 971 bool result = object->hasProperty(exec, propertyName); 972 exec->clearException(); 973 974 return result; 975} 976 977bool NetscapePluginInstanceProxy::hasProperty(uint32_t objectID, unsigned propertyName) 978{ 979 if (m_inDestroy) 980 return false; 981 982 JSObject* object = m_objects.get(objectID); 983 if (!object) 984 return false; 985 986 Frame* frame = core([m_pluginView webFrame]); 987 if (!frame) 988 return false; 989 990 ExecState* exec = frame->script()->globalObject()->globalExec(); 991 bool result = object->hasProperty(exec, propertyName); 992 exec->clearException(); 993 994 return result; 995} 996 997bool NetscapePluginInstanceProxy::hasMethod(uint32_t objectID, const Identifier& methodName) 998{ 999 if (m_inDestroy) 1000 return false; 1001 1002 JSObject* object = m_objects.get(objectID); 1003 if (!object) 1004 return false; 1005 1006 Frame* frame = core([m_pluginView webFrame]); 1007 if (!frame) 1008 return false; 1009 1010 ExecState* exec = frame->script()->globalObject()->globalExec(); 1011 JSLock lock(SilenceAssertionsOnly); 1012 JSValue func = object->get(exec, methodName); 1013 exec->clearException(); 1014 return !func.isUndefined(); 1015} 1016 1017bool NetscapePluginInstanceProxy::enumerate(uint32_t objectID, data_t& resultData, mach_msg_type_number_t& resultLength) 1018{ 1019 if (m_inDestroy) 1020 return false; 1021 1022 JSObject* object = m_objects.get(objectID); 1023 if (!object) 1024 return false; 1025 1026 Frame* frame = core([m_pluginView webFrame]); 1027 if (!frame) 1028 return false; 1029 1030 ExecState* exec = frame->script()->globalObject()->globalExec(); 1031 JSLock lock(SilenceAssertionsOnly); 1032 1033 PropertyNameArray propertyNames(exec); 1034 object->getPropertyNames(exec, propertyNames); 1035 1036 NSMutableArray *array = [[NSMutableArray alloc] init]; 1037 for (unsigned i = 0; i < propertyNames.size(); i++) { 1038 uint64_t methodName = reinterpret_cast<uint64_t>(_NPN_GetStringIdentifier(propertyNames[i].ustring().UTF8String().c_str())); 1039 1040 [array addObject:[NSNumber numberWithLongLong:methodName]]; 1041 } 1042 1043 NSData *data = [NSPropertyListSerialization dataFromPropertyList:array format:NSPropertyListBinaryFormat_v1_0 errorDescription:0]; 1044 ASSERT(data); 1045 1046 resultLength = [data length]; 1047 mig_allocate(reinterpret_cast<vm_address_t*>(&resultData), resultLength); 1048 1049 memcpy(resultData, [data bytes], resultLength); 1050 1051 exec->clearException(); 1052 1053 return true; 1054} 1055 1056void NetscapePluginInstanceProxy::addValueToArray(NSMutableArray *array, ExecState* exec, JSValue value) 1057{ 1058 JSLock lock(SilenceAssertionsOnly); 1059 1060 if (value.isString()) { 1061 [array addObject:[NSNumber numberWithInt:StringValueType]]; 1062 [array addObject:String(value.toString(exec))]; 1063 } else if (value.isNumber()) { 1064 [array addObject:[NSNumber numberWithInt:DoubleValueType]]; 1065 [array addObject:[NSNumber numberWithDouble:value.toNumber(exec)]]; 1066 } else if (value.isBoolean()) { 1067 [array addObject:[NSNumber numberWithInt:BoolValueType]]; 1068 [array addObject:[NSNumber numberWithBool:value.toBoolean(exec)]]; 1069 } else if (value.isNull()) 1070 [array addObject:[NSNumber numberWithInt:NullValueType]]; 1071 else if (value.isObject()) { 1072 JSObject* object = asObject(value); 1073 if (object->classInfo() == &RuntimeObjectImp::s_info) { 1074 RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(object); 1075 if (ProxyInstance* instance = static_cast<ProxyInstance*>(imp->getInternalInstance())) { 1076 [array addObject:[NSNumber numberWithInt:NPObjectValueType]]; 1077 [array addObject:[NSNumber numberWithInt:instance->objectID()]]; 1078 } 1079 } else { 1080 [array addObject:[NSNumber numberWithInt:JSObjectValueType]]; 1081 [array addObject:[NSNumber numberWithInt:idForObject(object)]]; 1082 } 1083 } else 1084 [array addObject:[NSNumber numberWithInt:VoidValueType]]; 1085} 1086 1087void NetscapePluginInstanceProxy::marshalValue(ExecState* exec, JSValue value, data_t& resultData, mach_msg_type_number_t& resultLength) 1088{ 1089 RetainPtr<NSMutableArray*> array(AdoptNS, [[NSMutableArray alloc] init]); 1090 1091 addValueToArray(array.get(), exec, value); 1092 1093 RetainPtr<NSData *> data = [NSPropertyListSerialization dataFromPropertyList:array.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:0]; 1094 ASSERT(data); 1095 1096 resultLength = [data.get() length]; 1097 mig_allocate(reinterpret_cast<vm_address_t*>(&resultData), resultLength); 1098 1099 memcpy(resultData, [data.get() bytes], resultLength); 1100} 1101 1102RetainPtr<NSData *> NetscapePluginInstanceProxy::marshalValues(ExecState* exec, const ArgList& args) 1103{ 1104 RetainPtr<NSMutableArray*> array(AdoptNS, [[NSMutableArray alloc] init]); 1105 1106 for (unsigned i = 0; i < args.size(); i++) 1107 addValueToArray(array.get(), exec, args.at(i)); 1108 1109 RetainPtr<NSData *> data = [NSPropertyListSerialization dataFromPropertyList:array.get() format:NSPropertyListBinaryFormat_v1_0 errorDescription:0]; 1110 ASSERT(data); 1111 1112 return data; 1113} 1114 1115bool NetscapePluginInstanceProxy::demarshalValueFromArray(ExecState* exec, NSArray *array, NSUInteger& index, JSValue& result) 1116{ 1117 if (index == [array count]) 1118 return false; 1119 1120 int type = [[array objectAtIndex:index++] intValue]; 1121 switch (type) { 1122 case VoidValueType: 1123 result = jsUndefined(); 1124 return true; 1125 case NullValueType: 1126 result = jsNull(); 1127 return true; 1128 case BoolValueType: 1129 result = jsBoolean([[array objectAtIndex:index++] boolValue]); 1130 return true; 1131 case DoubleValueType: 1132 result = jsNumber(exec, [[array objectAtIndex:index++] doubleValue]); 1133 return true; 1134 case StringValueType: { 1135 NSString *string = [array objectAtIndex:index++]; 1136 1137 result = jsString(exec, String(string)); 1138 return true; 1139 } 1140 case JSObjectValueType: { 1141 uint32_t objectID = [[array objectAtIndex:index++] intValue]; 1142 1143 result = m_objects.get(objectID); 1144 ASSERT(result); 1145 return true; 1146 } 1147 case NPObjectValueType: { 1148 uint32_t objectID = [[array objectAtIndex:index++] intValue]; 1149 1150 Frame* frame = core([m_pluginView webFrame]); 1151 if (!frame) 1152 return false; 1153 1154 if (!frame->script()->isEnabled()) 1155 return false; 1156 1157 RefPtr<RootObject> rootObject = frame->script()->createRootObject(m_pluginView); 1158 if (!rootObject) 1159 return false; 1160 1161 result = ProxyInstance::create(rootObject.release(), this, objectID)->createRuntimeObject(exec); 1162 return true; 1163 } 1164 default: 1165 ASSERT_NOT_REACHED(); 1166 return false; 1167 } 1168} 1169 1170JSValue NetscapePluginInstanceProxy::demarshalValue(ExecState* exec, const char* valueData, mach_msg_type_number_t valueLength) 1171{ 1172 RetainPtr<NSData*> data(AdoptNS, [[NSData alloc] initWithBytesNoCopy:(void*)valueData length:valueLength freeWhenDone:NO]); 1173 1174 RetainPtr<NSArray*> array = [NSPropertyListSerialization propertyListFromData:data.get() 1175 mutabilityOption:NSPropertyListImmutable 1176 format:0 1177 errorDescription:0]; 1178 NSUInteger position = 0; 1179 JSValue value; 1180 bool result = demarshalValueFromArray(exec, array.get(), position, value); 1181 ASSERT_UNUSED(result, result); 1182 1183 return value; 1184} 1185 1186void NetscapePluginInstanceProxy::demarshalValues(ExecState* exec, data_t valuesData, mach_msg_type_number_t valuesLength, MarkedArgumentBuffer& result) 1187{ 1188 RetainPtr<NSData*> data(AdoptNS, [[NSData alloc] initWithBytesNoCopy:valuesData length:valuesLength freeWhenDone:NO]); 1189 1190 RetainPtr<NSArray*> array = [NSPropertyListSerialization propertyListFromData:data.get() 1191 mutabilityOption:NSPropertyListImmutable 1192 format:0 1193 errorDescription:0]; 1194 NSUInteger position = 0; 1195 JSValue value; 1196 while (demarshalValueFromArray(exec, array.get(), position, value)) 1197 result.append(value); 1198} 1199 1200PassRefPtr<Instance> NetscapePluginInstanceProxy::createBindingsInstance(PassRefPtr<RootObject> rootObject) 1201{ 1202 uint32_t requestID = nextRequestID(); 1203 1204 if (_WKPHGetScriptableNPObject(m_pluginHostProxy->port(), m_pluginID, requestID) != KERN_SUCCESS) 1205 return 0; 1206 1207 auto_ptr<GetScriptableNPObjectReply> reply = waitForReply<GetScriptableNPObjectReply>(requestID); 1208 if (!reply.get()) 1209 return 0; 1210 1211 if (!reply->m_objectID) 1212 return 0; 1213 1214 return ProxyInstance::create(rootObject, this, reply->m_objectID); 1215} 1216 1217void NetscapePluginInstanceProxy::addInstance(ProxyInstance* instance) 1218{ 1219 ASSERT(!m_instances.contains(instance)); 1220 1221 m_instances.add(instance); 1222} 1223 1224void NetscapePluginInstanceProxy::removeInstance(ProxyInstance* instance) 1225{ 1226 ASSERT(m_instances.contains(instance)); 1227 1228 m_instances.remove(instance); 1229} 1230 1231void NetscapePluginInstanceProxy::willCallPluginFunction() 1232{ 1233 m_pluginFunctionCallDepth++; 1234} 1235 1236void NetscapePluginInstanceProxy::didCallPluginFunction() 1237{ 1238 ASSERT(m_pluginFunctionCallDepth > 0); 1239 m_pluginFunctionCallDepth--; 1240 1241 // If -stop was called while we were calling into a plug-in function, and we're no longer 1242 // inside a plug-in function, stop now. 1243 if (!m_pluginFunctionCallDepth && m_shouldStopSoon) { 1244 m_shouldStopSoon = false; 1245 [m_pluginView stop]; 1246 } 1247} 1248 1249bool NetscapePluginInstanceProxy::shouldStop() 1250{ 1251 if (m_pluginFunctionCallDepth) { 1252 m_shouldStopSoon = true; 1253 return false; 1254 } 1255 1256 return true; 1257} 1258 1259uint32_t NetscapePluginInstanceProxy::nextRequestID() 1260{ 1261 uint32_t requestID = ++m_currentRequestID; 1262 1263 // We don't want to return the HashMap empty/deleted "special keys" 1264 if (requestID == 0 || requestID == static_cast<uint32_t>(-1)) 1265 return nextRequestID(); 1266 1267 return requestID; 1268} 1269 1270void NetscapePluginInstanceProxy::invalidateRect(double x, double y, double width, double height) 1271{ 1272 ASSERT(m_pluginView); 1273 1274 [m_pluginView invalidatePluginContentRect:NSMakeRect(x, y, width, height)]; 1275} 1276 1277bool NetscapePluginInstanceProxy::getCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t& cookiesData, mach_msg_type_number_t& cookiesLength) 1278{ 1279 ASSERT(m_pluginView); 1280 1281 NSURL *url = [m_pluginView URLWithCString:urlData]; 1282 if (!url) 1283 return false; 1284 1285 if (Frame* frame = core([m_pluginView webFrame])) { 1286 String cookieString = cookies(frame->document(), url); 1287 WebCore::CString cookieStringUTF8 = cookieString.utf8(); 1288 if (cookieStringUTF8.isNull()) 1289 return false; 1290 1291 cookiesLength = cookieStringUTF8.length(); 1292 mig_allocate(reinterpret_cast<vm_address_t*>(&cookiesData), cookiesLength); 1293 memcpy(cookiesData, cookieStringUTF8.data(), cookiesLength); 1294 1295 return true; 1296 } 1297 1298 return false; 1299} 1300 1301bool NetscapePluginInstanceProxy::setCookies(data_t urlData, mach_msg_type_number_t urlLength, data_t cookiesData, mach_msg_type_number_t cookiesLength) 1302{ 1303 ASSERT(m_pluginView); 1304 1305 NSURL *url = [m_pluginView URLWithCString:urlData]; 1306 if (!url) 1307 return false; 1308 1309 if (Frame* frame = core([m_pluginView webFrame])) { 1310 String cookieString = String::fromUTF8(cookiesData, cookiesLength); 1311 if (!cookieString) 1312 return false; 1313 1314 WebCore::setCookies(frame->document(), url, cookieString); 1315 return true; 1316 } 1317 1318 return false; 1319} 1320 1321bool NetscapePluginInstanceProxy::getProxy(data_t urlData, mach_msg_type_number_t urlLength, data_t& proxyData, mach_msg_type_number_t& proxyLength) 1322{ 1323 ASSERT(m_pluginView); 1324 1325 NSURL *url = [m_pluginView URLWithCString:urlData]; 1326 if (!url) 1327 return false; 1328 1329 WebCore::CString proxyStringUTF8 = proxiesForURL(url); 1330 1331 proxyLength = proxyStringUTF8.length(); 1332 mig_allocate(reinterpret_cast<vm_address_t*>(&proxyData), proxyLength); 1333 memcpy(proxyData, proxyStringUTF8.data(), proxyLength); 1334 1335 return true; 1336} 1337 1338bool NetscapePluginInstanceProxy::getAuthenticationInfo(data_t protocolData, data_t hostData, uint32_t port, data_t schemeData, data_t realmData, 1339 data_t& usernameData, mach_msg_type_number_t& usernameLength, data_t& passwordData, mach_msg_type_number_t& passwordLength) 1340{ 1341 WebCore::CString username; 1342 WebCore::CString password; 1343 1344 if (!WebKit::getAuthenticationInfo(protocolData, hostData, port, schemeData, realmData, username, password)) 1345 return false; 1346 1347 usernameLength = username.length(); 1348 mig_allocate(reinterpret_cast<vm_address_t*>(&usernameData), usernameLength); 1349 memcpy(usernameData, username.data(), usernameLength); 1350 1351 passwordLength = password.length(); 1352 mig_allocate(reinterpret_cast<vm_address_t*>(&passwordData), passwordLength); 1353 memcpy(passwordData, password.data(), passwordLength); 1354 1355 return true; 1356} 1357 1358bool NetscapePluginInstanceProxy::convertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, 1359 double& destX, double& destY, NPCoordinateSpace destSpace) 1360{ 1361 ASSERT(m_pluginView); 1362 1363 return [m_pluginView convertFromX:sourceX andY:sourceY space:sourceSpace toX:&destX andY:&destY space:destSpace]; 1364} 1365 1366uint32_t NetscapePluginInstanceProxy::checkIfAllowedToLoadURL(const char* url, const char* target) 1367{ 1368 uint32_t checkID; 1369 1370 // Assign a check ID 1371 do { 1372 checkID = ++m_urlCheckCounter; 1373 } while (m_urlChecks.contains(checkID) || !m_urlCheckCounter); 1374 1375 NSString *frameName = target ? [NSString stringWithCString:target encoding:NSISOLatin1StringEncoding] : nil; 1376 1377 NSNumber *contextInfo = [[NSNumber alloc] initWithUnsignedInt:checkID]; 1378 WebPluginContainerCheck *check = [WebPluginContainerCheck checkWithRequest:[m_pluginView requestWithURLCString:url] 1379 target:frameName 1380 resultObject:m_pluginView 1381 selector:@selector(_containerCheckResult:contextInfo:) 1382 controller:m_pluginView 1383 contextInfo:contextInfo]; 1384 1385 [contextInfo release]; 1386 m_urlChecks.set(checkID, check); 1387 [check start]; 1388 1389 return checkID; 1390} 1391 1392void NetscapePluginInstanceProxy::cancelCheckIfAllowedToLoadURL(uint32_t checkID) 1393{ 1394 URLCheckMap::iterator it = m_urlChecks.find(checkID); 1395 if (it == m_urlChecks.end()) 1396 return; 1397 1398 WebPluginContainerCheck *check = it->second.get(); 1399 [check cancel]; 1400 m_urlChecks.remove(it); 1401} 1402 1403void NetscapePluginInstanceProxy::checkIfAllowedToLoadURLResult(uint32_t checkID, bool allowed) 1404{ 1405 _WKPHCheckIfAllowedToLoadURLResult(m_pluginHostProxy->port(), m_pluginID, checkID, allowed); 1406} 1407 1408void NetscapePluginInstanceProxy::resolveURL(const char* url, const char* target, data_t& resolvedURLData, mach_msg_type_number_t& resolvedURLLength) 1409{ 1410 ASSERT(m_pluginView); 1411 1412 WebCore::CString resolvedURL = [m_pluginView resolvedURLStringForURL:url target:target]; 1413 1414 resolvedURLLength = resolvedURL.length(); 1415 mig_allocate(reinterpret_cast<vm_address_t*>(&resolvedURLData), resolvedURLLength); 1416 memcpy(resolvedURLData, resolvedURL.data(), resolvedURLLength); 1417} 1418 1419} // namespace WebKit 1420 1421#endif // USE(PLUGIN_HOST_PROCESS) 1422