Changeset 15750 in webkit
- Timestamp:
- Aug 1, 2006 4:06:00 PM (18 years ago)
- Location:
- trunk/WebKit
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebKit/ChangeLog
r15747 r15750 1 2006-08-01 Tim Omernick <timo@apple.com> 2 3 Reviewed by John Sullivan. 4 5 <rdar://problem/4480737> Flash crashes after it replaces itself via a document.write() 6 7 I kind of hate to do this, but this is the best way to work around buggy plug-ins like Flash that assume that 8 NPP_Destroy() cannot be called while the browser is calling one of its other plug-in functions. The classic 9 situation is a plug-in that replaces itself via an NPN_Invoke() that executes a document.write(). 10 11 * Plugins/WebBaseNetscapePluginView.h: 12 * Plugins/WebBaseNetscapePluginView.m: 13 (-[WebBaseNetscapePluginView sendEvent:]): 14 Call -willCallPlugInFunction and -didCallPlugInFunction around calls to the NPP_* functions. 15 (-[WebBaseNetscapePluginView setWindowIfNecessary]): 16 ditto 17 (-[WebBaseNetscapePluginView start]): 18 It should not be possible to start a plug-in instance while we are calling into it (one of those chicken/egg 19 problems). Added a sanity-checking assertion. 20 (-[WebBaseNetscapePluginView stop]): 21 If we're already calling a plug-in function, do not call NPP_Destroy(). The plug-in function we are calling 22 may assume that its instance->pdata, or other memory freed by NPP_Destroy(), is valid and unchanged until said 23 plugin-function returns. 24 (-[WebBaseNetscapePluginView pluginScriptableObject]): 25 Call -willCallPlugInFunction and -didCallPlugInFunction around calls to the NPP_* functions. 26 (-[WebBaseNetscapePluginView willCallPlugInFunction]): 27 Increment plug-in function call depth. 28 (-[WebBaseNetscapePluginView didCallPlugInFunction]): 29 Decrement plug-in function call depth. Stop if we're supposed to stop. 30 (-[WebBaseNetscapePluginView evaluateJavaScriptPluginRequest:]): 31 Call -willCallPlugInFunction and -didCallPlugInFunction around calls to the NPP_* functions. 32 (-[WebBaseNetscapePluginView webFrame:didFinishLoadWithReason:]): 33 ditto 34 (-[WebBaseNetscapePluginView _printedPluginBitmap]): 35 ditto 36 37 * Plugins/WebBaseNetscapePluginStream.m: 38 (-[WebBaseNetscapePluginStream startStreamResponseURL:expectedContentLength:lastModifiedDate:MIMEType:]): 39 Call -willCallPlugInFunction and -didCallPlugInFunction around calls to the NPP_* functions. 40 (-[WebBaseNetscapePluginStream _destroyStream]): 41 ditto 42 (-[WebBaseNetscapePluginStream _deliverData]): 43 ditto 44 1 45 2006-08-01 Maciej Stachowiak <mjs@apple.com> 2 46 -
trunk/WebKit/Plugins/WebBaseNetscapePluginStream.m
r14811 r15750 222 222 // FIXME: Need a way to check if stream is seekable 223 223 224 [pluginView willCallPlugInFunction]; 224 225 NPError npErr = NPP_NewStream(instance, (char *)[MIMEType UTF8String], &stream, NO, &transferMode); 226 [pluginView didCallPlugInFunction]; 225 227 LOG(Plugins, "NPP_NewStream URL=%@ MIME=%@ error=%d", responseURL, MIMEType, npErr); 226 228 … … 273 275 char *carbonPath = CarbonPathFromPOSIXPath(path); 274 276 ASSERT(carbonPath != NULL); 277 [pluginView willCallPlugInFunction]; 275 278 NPP_StreamAsFile(instance, &stream, carbonPath); 279 [pluginView didCallPlugInFunction]; 276 280 277 281 // Delete the file after calling NPP_StreamAsFile(), instead of in -dealloc/-finalize. It should be OK … … 287 291 288 292 NPError npErr; 293 [pluginView willCallPlugInFunction]; 289 294 npErr = NPP_DestroyStream(instance, &stream, reason); 295 [pluginView didCallPlugInFunction]; 290 296 LOG(Plugins, "NPP_DestroyStream responseURL=%@ error=%d", responseURL, npErr); 291 297 … … 295 301 if (sendNotification) { 296 302 // NPP_URLNotify expects the request URL, not the response URL. 303 [pluginView willCallPlugInFunction]; 297 304 NPP_URLNotify(instance, [requestURL _web_URLCString], reason, notifyData); 305 [pluginView didCallPlugInFunction]; 298 306 LOG(Plugins, "NPP_URLNotify requestURL=%@ reason=%d", requestURL, reason); 299 307 } … … 384 392 385 393 while (totalBytesDelivered < totalBytes) { 394 [pluginView willCallPlugInFunction]; 386 395 int32 deliveryBytes = NPP_WriteReady(instance, &stream); 396 [pluginView didCallPlugInFunction]; 387 397 LOG(Plugins, "NPP_WriteReady responseURL=%@ bytes=%d", responseURL, deliveryBytes); 388 398 … … 394 404 deliveryBytes = MIN(deliveryBytes, totalBytes - totalBytesDelivered); 395 405 NSData *subdata = [deliveryData subdataWithRange:NSMakeRange(totalBytesDelivered, deliveryBytes)]; 406 [pluginView willCallPlugInFunction]; 396 407 deliveryBytes = NPP_Write(instance, &stream, offset, [subdata length], (void *)[subdata bytes]); 408 [pluginView didCallPlugInFunction]; 397 409 if (deliveryBytes < 0) { 398 410 // Netscape documentation says that a negative result from NPP_Write means cancel the load. -
trunk/WebKit/Plugins/WebBaseNetscapePluginView.h
r15407 r15750 77 77 BOOL isTransparent; 78 78 BOOL isCompletelyObscured; 79 BOOL shouldStopSoon; 80 unsigned pluginFunctionCallDepth; 79 81 80 82 DOMElement *element; … … 130 132 - (void)viewDidMoveToHostWindow; 131 133 132 / * Returns the NPObject that represents the plugin interface. */134 // Returns the NPObject that represents the plugin interface. 133 135 - (void *)pluginScriptableObject; 134 136 137 // -willCallPlugInFunction must be called before calling any of the NPP_* functions for this view's NPP instance. 138 // This is necessary to ensure that plug-ins are not destroyed while WebKit calls into them. Some plug-ins (Flash 139 // at least) are written with the assumption that nothing they do in their plug-in functions can cause NPP_Destroy() 140 // to be called. Unfortunately, this is not true, especially if the plug-in uses NPN_Invoke() to execute a 141 // document.write(), which clears the document and destroys the plug-in. 142 // See <rdar://problem/4480737>. 143 - (void)willCallPlugInFunction; 144 145 // -didCallPlugInFunction should be called after returning from a plug-in function. It should be called exactly 146 // once for every call to -willCallPlugInFunction. 147 // See <rdar://problem/4480737>. 148 - (void)didCallPlugInFunction; 149 135 150 @end -
trunk/WebKit/Plugins/WebBaseNetscapePluginView.m
r15698 r15750 611 611 [[self retain] autorelease]; 612 612 613 [self willCallPlugInFunction]; 613 614 BOOL acceptedEvent = NPP_HandleEvent(instance, event); 615 [self didCallPlugInFunction]; 614 616 615 617 currentEventIsUserGesture = NO; … … 1070 1072 ASSERT((drawingModel != NPDrawingModelCoreGraphics && drawingModel != NPDrawingModelOpenGL) || [NSView focusView] == self); 1071 1073 1074 [self willCallPlugInFunction]; 1072 1075 npErr = NPP_SetWindow(instance, &window); 1076 [self didCallPlugInFunction]; 1073 1077 inSetWindow = NO; 1074 1078 … … 1208 1212 window.type = NPWindowTypeWindow; 1209 1213 1214 // NPN_New(), which creates the plug-in instance, should never be called while calling a plug-in function for that instance. 1215 ASSERT(pluginFunctionCallDepth == 0); 1216 1210 1217 [[self class] setCurrentPluginView:self]; 1211 1218 NPError npErr = NPP_New((char *)[MIMEType cString], instance, mode, argsCount, cAttributes, cValues, NULL); … … 1254 1261 - (void)stop 1255 1262 { 1263 // If we're already calling a plug-in function, do not call NPP_Destroy(). The plug-in function we are calling 1264 // may assume that its instance->pdata, or other memory freed by NPP_Destroy(), is valid and unchanged until said 1265 // plugin-function returns. 1266 // See <rdar://problem/4480737>. 1267 if (pluginFunctionCallDepth > 0) { 1268 shouldStopSoon = YES; 1269 return; 1270 } 1271 1256 1272 [self removeTrackingRect]; 1257 1273 … … 1695 1711 if (NPP_GetValue) { 1696 1712 void *value = 0; 1713 [self willCallPlugInFunction]; 1697 1714 NPError npErr = NPP_GetValue (instance, NPPVpluginScriptableNPObject, (void *)&value); 1715 [self didCallPlugInFunction]; 1698 1716 if (npErr == NPERR_NO_ERROR) { 1699 1717 return value; … … 1703 1721 } 1704 1722 1723 - (void)willCallPlugInFunction 1724 { 1725 // Could try to prevent infinite recursion here, but it's probably not worth the effort. 1726 pluginFunctionCallDepth++; 1727 } 1728 1729 - (void)didCallPlugInFunction 1730 { 1731 ASSERT(pluginFunctionCallDepth > 0); 1732 pluginFunctionCallDepth--; 1733 1734 // If -stop was called while we were calling into a plug-in function, and we're no longer 1735 // inside a plug-in function, stop now. 1736 if (pluginFunctionCallDepth == 0 && shouldStopSoon) { 1737 shouldStopSoon = NO; 1738 [self stop]; 1739 } 1740 } 1705 1741 1706 1742 @end … … 1751 1787 // like we do in KHTMLPartBrowserExtension::openURLRequest. 1752 1788 if ([JSPluginRequest sendNotification]) { 1789 [self willCallPlugInFunction]; 1753 1790 NPP_URLNotify(instance, [URL _web_URLCString], NPRES_DONE, [JSPluginRequest notifyData]); 1791 [self didCallPlugInFunction]; 1754 1792 } 1755 1793 } else if ([result length] > 0) { … … 1778 1816 ASSERT([pluginRequest sendNotification]); 1779 1817 1818 [self willCallPlugInFunction]; 1780 1819 NPP_URLNotify(instance, [[[pluginRequest request] URL] _web_URLCString], reason, [pluginRequest notifyData]); 1820 [self didCallPlugInFunction]; 1781 1821 1782 1822 [pendingFrameLoads removeObjectForKey:webFrame]; … … 2370 2410 2371 2411 // Tell the plugin to print into the GWorld 2412 [self willCallPlugInFunction]; 2372 2413 NPP_Print(instance, &npPrint); 2414 [self didCallPlugInFunction]; 2373 2415 2374 2416 // Don't need the GWorld anymore
Note: See TracChangeset
for help on using the changeset viewer.