[WTF] Import std::optional reference implementation as WTF::Optional
[WebKit-https.git] / Source / WebKit / mac / Plugins / WebNetscapePluginView.mm
index 89e8cd0..d9e58e3 100644 (file)
@@ -10,7 +10,7 @@
  * 2.  Redistributions in binary form must reproduce the above copyright
  *     notice, this list of conditions and the following disclaimer in the
  *     documentation and/or other materials provided with the distribution. 
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
  *     its contributors may be used to endorse or promote products derived
  *     from this software without specific prior written permission. 
  *
 #import "WebNSURLExtras.h"
 #import "WebNSURLRequestExtras.h"
 #import "WebNSViewExtras.h"
-#import "WebNetscapeContainerCheckContextInfo.h"
-#import "WebNetscapeContainerCheckPrivate.h"
 #import "WebNetscapePluginEventHandler.h"
 #import "WebNetscapePluginPackage.h"
 #import "WebNetscapePluginStream.h"
-#import "WebPluginContainerCheck.h"
 #import "WebPluginRequest.h"
 #import "WebPreferences.h"
 #import "WebUIDelegatePrivate.h"
 #import <WebCore/FrameTree.h>
 #import <WebCore/FrameView.h>
 #import <WebCore/HTMLPlugInElement.h>
-#import <WebCore/Page.h> 
-#import <WebCore/PluginMainThreadScheduler.h>
+#import <WebCore/NP_jsobject.h>
+#import <WebCore/Page.h>
 #import <WebCore/ProxyServer.h>
-#import <WebCore/RunLoop.h>
 #import <WebCore/ScriptController.h>
 #import <WebCore/SecurityOrigin.h>
 #import <WebCore/SoftLinking.h> 
 #import <WebCore/WebCoreObjCExtras.h>
 #import <WebCore/WebCoreURLResponse.h>
 #import <WebCore/npruntime_impl.h>
-#import <WebKit/DOMPrivate.h>
-#import <WebKit/WebUIDelegate.h>
+#import <WebCore/runtime_root.h>
+#import <WebKitLegacy/DOMPrivate.h>
+#import <WebKitLegacy/WebUIDelegate.h>
 #import <objc/runtime.h>
 #import <runtime/InitializeThreading.h>
 #import <runtime/JSLock.h>
 #import <wtf/Assertions.h>
 #import <wtf/MainThread.h>
+#import <wtf/RunLoop.h>
 #import <wtf/text/CString.h>
 
 #define LoginWindowDidSwitchFromUserNotification    @"WebLoginWindowDidSwitchFromUserNotification"
@@ -194,8 +192,7 @@ typedef struct {
 {
     JSC::initializeThreading();
     WTF::initializeMainThreadToProcessMainThread();
-    WebCore::RunLoop::initializeMainRunLoop();
-    WebCoreObjCFinalizeOnMainThread(self);
+    RunLoop::initializeMainRunLoop();
     WKSendUserChangeNotifications();
 }
 
@@ -669,7 +666,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     ASSERT(_eventHandler);
     {
         JSC::JSLock::DropAllLocks dropAllLocks(JSDOMWindowBase::commonVM());
-        UserGestureIndicator gestureIndicator(_eventHandler->currentEventIsUserGesture() ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture);
+        UserGestureIndicator gestureIndicator(_eventHandler->currentEventIsUserGesture() ? std::optional<ProcessingUserGestureState>(ProcessingUserGesture) : std::nullopt);
         acceptedEvent = [_pluginPackage.get() pluginFuncs]->event(plugin, event);
     }
     [self didCallPlugInFunction];
@@ -707,11 +704,8 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     if (!timers)
         return;
 
-    HashMap<uint32_t, PluginTimer*>::const_iterator end = timers->end();
-    for (HashMap<uint32_t, PluginTimer*>::const_iterator it = timers->begin(); it != end; ++it) {
-        PluginTimer* timer = it->value;
-        timer->stop();
-    }    
+    for (auto& it: timers->values())
+        it->stop();
 }
 
 - (void)startTimers
@@ -725,11 +719,9 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     if (!timers)
         return;
     
-    HashMap<uint32_t, PluginTimer*>::const_iterator end = timers->end();
-    for (HashMap<uint32_t, PluginTimer*>::const_iterator it = timers->begin(); it != end; ++it) {
-        PluginTimer* timer = it->value;
-        ASSERT(!timer->isActive());
-        timer->start(_isCompletelyObscured);
+    for (auto& it: timers->values()) {
+        ASSERT(!it->isActive());
+        it->start(_isCompletelyObscured);
     }    
 }
 
@@ -1093,9 +1085,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
             _pluginLayer = adoptNS((CALayer *)value);
 
             BOOL accleratedCompositingEnabled = false;
-#if USE(ACCELERATED_COMPOSITING)
             accleratedCompositingEnabled = [[[self webView] preferences] acceleratedCompositingEnabled];
-#endif
             if (accleratedCompositingEnabled) {
                 // FIXME: This code can be shared between WebHostedNetscapePluginView and WebNetscapePluginView.
                 // Since this layer isn't going to be inserted into a view, we need to create another layer and flip its geometry
@@ -1109,10 +1099,10 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
                 realPluginLayer.get().autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
                 [_pluginLayer.get() addSublayer:realPluginLayer.get()];
 
-                // Eagerly enter compositing mode, since we know we'll need it. This avoids firing setNeedsStyleRecalc()
+                // Eagerly enter compositing mode, since we know we'll need it. This avoids firing invalidateStyle()
                 // for iframes that contain composited plugins at bad times. https://bugs.webkit.org/show_bug.cgi?id=39033
                 core([self webFrame])->view()->enterCompositingMode();
-                [self element]->setNeedsStyleRecalc(SyntheticStyleChange);
+                [self element]->invalidateStyleAndLayerComposition();
             } else
                 [self setWantsLayer:YES];
 
@@ -1159,7 +1149,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     // Check for this and don't start a load in this case.
     if (_sourceURL && ![_sourceURL.get() _web_isEmpty]) {
         NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:_sourceURL.get()];
-        [request _web_setHTTPReferrer:core([self webFrame])->loader()->outgoingReferrer()];
+        [request _web_setHTTPReferrer:core([self webFrame])->loader().outgoingReferrer()];
         [self loadRequest:request inTarget:nil withNotifyData:nil sendNotification:NO];
     } 
 }
@@ -1183,10 +1173,10 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     // To stop active streams it's necessary to invoke stop() on a copy 
     // of streams. This is because calling WebNetscapePluginStream::stop() also has the side effect
     // of removing a stream from this hash set.
-    Vector<RefPtr<WebNetscapePluginStream> > streamsCopy;
+    Vector<RefPtr<WebNetscapePluginStream>> streamsCopy;
     copyToVector(streams, streamsCopy);
-    for (size_t i = 0; i < streamsCopy.size(); i++)
-        streamsCopy[i]->stop();
+    for (auto& stream: streamsCopy)
+        stream->stop();
 
     for (WebFrame *frame in [_pendingFrameLoads keyEnumerator])
         [frame _setInternalLoadDelegate:nil];
@@ -1195,12 +1185,12 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     // Setting the window type to 0 ensures that NPP_SetWindow will be called if the plug-in is restarted.
     lastSetWindow.type = (NPWindowType)0;
     
-    _pluginLayer = 0;
+    _pluginLayer = nil;
     
     [self _destroyPlugin];
     [_pluginPackage.get() close];
     
-    _eventHandler.clear();
+    _eventHandler = nullptr;
 }
 
 - (NPEventModel)eventModel
@@ -1256,70 +1246,6 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     }
 }
 
-- (uint32_t)checkIfAllowedToLoadURL:(const char*)urlCString frame:(const char*)frameNameCString 
-                       callbackFunc:(void (*)(NPP npp, uint32_t checkID, NPBool allowed, void* context))callbackFunc 
-                            context:(void*)context
-{
-    if (!_containerChecksInProgress) 
-        _containerChecksInProgress = [[NSMutableDictionary alloc] init];
-    
-    NSString *frameName = frameNameCString ? [NSString stringWithCString:frameNameCString encoding:NSISOLatin1StringEncoding] : nil;
-    
-    ++_currentContainerCheckRequestID;
-    WebNetscapeContainerCheckContextInfo *contextInfo = [[WebNetscapeContainerCheckContextInfo alloc] initWithCheckRequestID:_currentContainerCheckRequestID 
-                                                                                                                callbackFunc:callbackFunc
-                                                                                                                      context:context];
-    
-    WebPluginContainerCheck *check = [WebPluginContainerCheck checkWithRequest:[self requestWithURLCString:urlCString]
-                                                                        target:frameName
-                                                                  resultObject:self
-                                                                      selector:@selector(_containerCheckResult:contextInfo:)
-                                                                    controller:self 
-                                                                   contextInfo:contextInfo];
-    
-    [contextInfo release];
-    [_containerChecksInProgress setObject:check forKey:[NSNumber numberWithInt:_currentContainerCheckRequestID]];
-    [check start];
-    
-    return _currentContainerCheckRequestID;
-}
-
-- (void)_containerCheckResult:(PolicyAction)policy contextInfo:(id)contextInfo
-{
-    ASSERT([contextInfo isKindOfClass:[WebNetscapeContainerCheckContextInfo class]]);
-    void (*pluginCallback)(NPP npp, uint32_t, NPBool, void*) = [contextInfo callback];
-    
-    if (!pluginCallback) {
-        ASSERT_NOT_REACHED();
-        return;
-    }
-    
-    pluginCallback([self plugin], [contextInfo checkRequestID], (policy == PolicyUse), [contextInfo context]);
-}
-
-- (void)cancelCheckIfAllowedToLoadURL:(uint32_t)checkID
-{
-    WebPluginContainerCheck *check = (WebPluginContainerCheck *)[_containerChecksInProgress objectForKey:[NSNumber numberWithInt:checkID]];
-    
-    if (!check)
-        return;
-    
-    [check cancel];
-    [_containerChecksInProgress removeObjectForKey:[NSNumber numberWithInt:checkID]];
-}
-
-// WebPluginContainerCheck automatically calls this method after invoking our _containerCheckResult: selector.
-// It works this way because calling -[WebPluginContainerCheck cancel] allows it to do it's teardown process.
-- (void)_webPluginContainerCancelCheckIfAllowedToLoadRequest:(id)webPluginContainerCheck
-{
-    ASSERT([webPluginContainerCheck isKindOfClass:[WebPluginContainerCheck class]]);
-    WebPluginContainerCheck *check = (WebPluginContainerCheck *)webPluginContainerCheck;
-    ASSERT([[check contextInfo] isKindOfClass:[WebNetscapeContainerCheckContextInfo class]]);
-    
-    [self cancelCheckIfAllowedToLoadURL:[[check contextInfo] checkRequestID]];
-}
-
-
 // MARK: NSVIEW
 
 - (id)initWithFrame:(NSRect)frame
@@ -1368,13 +1294,6 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     free(cValues);
     
     ASSERT(!_eventHandler);
-    
-    if (timers) {
-        deleteAllValues(*timers);
-        delete timers;
-    }  
-    
-    [_containerChecksInProgress release];
 }
 
 - (void)disconnectStream:(WebNetscapePluginStream*)stream
@@ -1392,16 +1311,6 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     [super dealloc];
 }
 
-- (void)finalize
-{
-    ASSERT_MAIN_THREAD();
-    ASSERT(!_isStarted);
-
-    [self fini];
-
-    [super finalize];
-}
-
 - (void)drawRect:(NSRect)rect
 {
     if (_cachedSnapshot) {
@@ -1499,7 +1408,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     ASSERT(_loadManually);
     ASSERT(!_manualStream);
 
-    _manualStream = WebNetscapePluginStream::create(core([self webFrame])->loader());
+    _manualStream = WebNetscapePluginStream::create(&core([self webFrame])->loader());
 }
 
 - (void)pluginView:(NSView *)pluginView receivedData:(NSData *)data
@@ -1657,7 +1566,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     if (frameName) {
         // FIXME - need to get rid of this window creation which
         // bypasses normal targeted link handling
-        frame = kit(core([self webFrame])->loader()->findFrameForNavigation(frameName));
+        frame = kit(core([self webFrame])->loader().findFrameForNavigation(frameName));
         if (frame == nil) {
             WebView *currentWebView = [self webView];
             NSDictionary *features = [[NSDictionary alloc] init];
@@ -1679,7 +1588,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
             }
             
             frame = [newWebView mainFrame];
-            core(frame)->tree()->setName(frameName);
+            core(frame)->tree().setName(frameName);
             [[newWebView _UIDelegateForwarder] webViewShow:newWebView];
         }
     }
@@ -1723,7 +1632,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
 
     // don't let a plugin start any loads if it is no longer part of a document that is being 
     // displayed unless the loads are in the same frame as the plugin.
-    if ([[self dataSource] _documentLoader] != core([self webFrame])->loader()->activeDocumentLoader() &&
+    if ([[self dataSource] _documentLoader] != core([self webFrame])->loader().activeDocumentLoader() &&
         (!cTarget || [frame findFrameNamed:target] != frame)) {
         return NPERR_GENERIC_ERROR; 
     }
@@ -1744,7 +1653,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     }
         
     if (cTarget || JSString) {
-        // Make when targetting a frame or evaluating a JS string, perform the request after a delay because we don't
+        // Make when targeting a frame or evaluating a JS string, perform the request after a delay because we don't
         // want to potentially kill the plug-in inside of its URL request.
         
         if (JSString && target && [frame findFrameNamed:target] != frame) {
@@ -1817,7 +1726,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
         } else {
             path = bufString;
         }
-        postData = [NSData dataWithContentsOfFile:[path _webkit_fixedCarbonPOSIXPath]];
+        postData = [NSData dataWithContentsOfFile:path];
         CFRelease(bufString);
         if (!postData) {
             return NPERR_FILE_NOT_FOUND;
@@ -2001,7 +1910,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
         case NPNVWindowNPObject:
         {
             Frame* frame = core([self webFrame]);
-            NPObject* windowScriptObject = frame ? frame->script()->windowScriptNPObject() : 0;
+            NPObject* windowScriptObject = frame ? frame->script().windowScriptNPObject() : 0;
 
             // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
             if (windowScriptObject)
@@ -2015,17 +1924,26 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
 
         case NPNVPluginElementNPObject:
         {
-            if (!_element)
-                return NPERR_GENERIC_ERROR;
-            
-            NPObject *plugInScriptObject = _element->getNPObject();
+            if (!_elementNPObject) {
+                if (!_element)
+                    return NPERR_GENERIC_ERROR;
+
+                Frame* frame = core(self.webFrame);
+                if (!frame)
+                    return NPERR_GENERIC_ERROR;
+
+                JSC::JSObject* object = frame->script().jsObjectForPluginElement(_element.get());
+                if (!object)
+                    _elementNPObject = _NPN_CreateNoScriptObject();
+                else
+                    _elementNPObject = _NPN_CreateScriptObject(0, object, frame->script().bindingRootObject());
+            }
 
             // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
-            if (plugInScriptObject)
-                _NPN_RetainObject(plugInScriptObject);
+            if (_elementNPObject)
+                _NPN_RetainObject(_elementNPObject);
 
-            void **v = (void **)value;
-            *v = plugInScriptObject;
+            *(void **)value = _elementNPObject;
 
             return NPERR_NO_ERROR;
         }
@@ -2082,18 +2000,12 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
             return NPERR_NO_ERROR;
         }
 
-        case WKNVBrowserContainerCheckFuncs:
-        {
-            *(WKNBrowserContainerCheckFuncs **)value = browserContainerCheckFuncs();
-            return NPERR_NO_ERROR;
-        }
-#if USE(ACCELERATED_COMPOSITING)
         case WKNVSupportsCompositingCoreAnimationPluginsBool:
         {
             *(NPBool *)value = [[[self webView] preferences] acceleratedCompositingEnabled];
             return NPERR_NO_ERROR;
         }
-#endif
+
         default:
             break;
     }
@@ -2165,20 +2077,21 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
         return 0;
     
     if (!timers)
-        timers = new HashMap<uint32_t, PluginTimer*>;
-    
+        timers = std::make_unique<HashMap<uint32_t, std::unique_ptr<PluginTimer>>>();
+
+    std::unique_ptr<PluginTimer>* slot;
     uint32_t timerID;
-    
-    do {
+    do
         timerID = ++currentTimerID;
-    } while (timers->contains(timerID) || timerID == 0);
-    
-    PluginTimer* timer = new PluginTimer(plugin, timerID, interval, repeat, timerFunc);
-    timers->set(timerID, timer);
+    while (!timers->isValidKey(timerID) || *(slot = &timers->add(timerID, nullptr).iterator->value));
+
+    auto timer = std::make_unique<PluginTimer>(plugin, timerID, interval, repeat, timerFunc);
 
     if (_shouldFireTimers)
         timer->start(_isCompletelyObscured);
     
+    *slot = WTFMove(timer);
+
     return timerID;
 }
 
@@ -2187,8 +2100,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     if (!timers)
         return;
     
-    if (PluginTimer* timer = timers->take(timerID))
-        delete timer;
+    timers->remove(timerID);
 }
 
 - (NPError)popUpContextMenu:(NPMenu *)menu
@@ -2215,7 +2127,11 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
                 break;
             
             if (Frame* frame = core([self webFrame])) {
-                String cookieString = cookies(frame->document(), URL); 
+                auto* document = frame->document();
+                if (!document)
+                    break;
+
+                String cookieString = cookies(*document, URL);
                 CString cookieStringUTF8 = cookieString.utf8();
                 if (cookieStringUTF8.isNull())
                     return NPERR_GENERIC_ERROR;
@@ -2265,7 +2181,8 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
                 break;
             
             if (Frame* frame = core([self webFrame])) {
-                setCookies(frame->document(), URL, cookieString);
+                if (auto* document = frame->document())
+                    setCookies(*document, URL, cookieString);
                 return NPERR_NO_ERROR;
             }
             
@@ -2301,17 +2218,6 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     return NPERR_NO_ERROR;
 }
 
-- (char*)resolveURL:(const char*)url forTarget:(const char*)target
-{
-    CString location = [self resolvedURLStringForURL:url target:target];
-
-    if (location.isNull())
-        return 0;
-    
-    // We use strdup here because the caller needs to free it with NPN_MemFree (which calls free).
-    return strdup(location.data());
-}
-
 @end
 
 @implementation WebNetscapePluginView (Internal)
@@ -2370,8 +2276,6 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
     // NPN_New(), which creates the plug-in instance, should never be called while calling a plug-in function for that instance.
     ASSERT(pluginFunctionCallDepth == 0);
 
-    PluginMainThreadScheduler::scheduler().registerPlugin(plugin);
-
     _isFlash = [_pluginPackage.get() bundleIdentifier] == "com.macromedia.Flash Player.plugin";
     _isSilverlight = [_pluginPackage.get() bundleIdentifier] == "com.microsoft.SilverlightPlugin";
 
@@ -2386,17 +2290,18 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
 
 - (void)_destroyPlugin
 {
-    PluginMainThreadScheduler::scheduler().unregisterPlugin(plugin);
-    
     if (_isSilverlight)
         [self _workaroundSilverlightFullscreenBug:NO];
     
     NPError npErr;
     npErr = ![_pluginPackage.get() pluginFuncs]->destroy(plugin, NULL);
     LOG(Plugins, "NPP_Destroy: %d", npErr);
-    
+
+    if (_elementNPObject)
+        _NPN_ReleaseObject(_elementNPObject);
+
     if (Frame* frame = core([self webFrame]))
-        frame->script()->cleanupScriptObjectsForPlugin(self);
+        frame->script().cleanupScriptObjectsForPlugin(self);
         
     free(plugin);
     plugin = NULL;