1/*
2 * Copyright (C) 2010-2018 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. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "LayerTreeContext.h"
29#include "NPRuntimeObjectMap.h"
30#include "Plugin.h"
31#include "PluginController.h"
32#include "WebFrame.h"
33#include <WebCore/ActivityState.h>
34#include <WebCore/FindOptions.h>
35#include <WebCore/Image.h>
36#include <WebCore/MediaCanStartListener.h>
37#include <WebCore/MediaProducer.h>
38#include <WebCore/PluginViewBase.h>
39#include <WebCore/ResourceError.h>
40#include <WebCore/ResourceResponse.h>
41#include <WebCore/Timer.h>
42#include <memory>
43#include <wtf/Deque.h>
44#include <wtf/RunLoop.h>
45
46// FIXME: Eventually this should move to WebCore.
47
48#if PLATFORM(COCOA)
49OBJC_CLASS NSDictionary;
50OBJC_CLASS PDFSelection;
51#endif
52
53namespace WTF {
54class MachSendRight;
55}
56
57namespace WebCore {
58class Frame;
59class HTMLPlugInElement;
60class MouseEvent;
61}
62
63namespace WebKit {
64
65class WebEvent;
66
67class PluginView : public WebCore::PluginViewBase, public PluginController, private WebCore::MediaCanStartListener, private WebFrame::LoadListener, private WebCore::MediaProducer {
68public:
69 static Ref<PluginView> create(WebCore::HTMLPlugInElement&, Ref<Plugin>&&, const Plugin::Parameters&);
70
71 void recreateAndInitialize(Ref<Plugin>&&);
72
73 WebCore::Frame* frame() const;
74
75 bool isBeingDestroyed() const { return !m_plugin || m_plugin->isBeingDestroyed(); }
76
77 void manualLoadDidReceiveResponse(const WebCore::ResourceResponse&);
78 void manualLoadDidReceiveData(const char* bytes, int length);
79 void manualLoadDidFinishLoading();
80 void manualLoadDidFail(const WebCore::ResourceError&);
81
82 void activityStateDidChange(OptionSet<WebCore::ActivityState::Flag> changed);
83 void setLayerHostingMode(LayerHostingMode);
84
85#if PLATFORM(COCOA)
86 void setDeviceScaleFactor(float);
87 void windowAndViewFramesChanged(const WebCore::FloatRect& windowFrameInScreenCoordinates, const WebCore::FloatRect& viewFrameInWindowCoordinates);
88 bool sendComplexTextInput(uint64_t pluginComplexTextInputIdentifier, const String& textInput);
89 RetainPtr<PDFDocument> pdfDocumentForPrinting() const { return m_plugin->pdfDocumentForPrinting(); }
90 NSObject *accessibilityObject() const;
91 id accessibilityAssociatedPluginParentForElement(WebCore::Element*) const override;
92#endif
93
94 WebCore::HTMLPlugInElement* pluginElement() const { return m_pluginElement.get(); }
95 const Plugin::Parameters& initialParameters() const { return m_parameters; }
96 Plugin* plugin() const { return m_plugin.get(); }
97
98 void setPageScaleFactor(double scaleFactor, WebCore::IntPoint origin);
99 double pageScaleFactor() const;
100 bool handlesPageScaleFactor() const;
101 bool requiresUnifiedScaleFactor() const;
102
103 void pageScaleFactorDidChange();
104 void topContentInsetDidChange();
105
106 void webPageDestroyed();
107
108 bool handleEditingCommand(const String& commandName, const String& argument);
109 bool isEditingCommandEnabled(const String& commandName);
110
111 unsigned countFindMatches(const String& target, WebCore::FindOptions, unsigned maxMatchCount);
112 bool findString(const String& target, WebCore::FindOptions, unsigned maxMatchCount);
113
114 String getSelectionString() const;
115
116 bool shouldAllowScripting();
117
118 RefPtr<WebCore::SharedBuffer> liveResourceData() const;
119 bool performDictionaryLookupAtLocation(const WebCore::FloatPoint&);
120 String getSelectionForWordAtPoint(const WebCore::FloatPoint&) const;
121 bool existingSelectionContainsPoint(const WebCore::FloatPoint&) const;
122
123private:
124 PluginView(WebCore::HTMLPlugInElement&, Ref<Plugin>&&, const Plugin::Parameters&);
125 virtual ~PluginView();
126
127 void initializePlugin();
128
129 void viewGeometryDidChange();
130 void viewVisibilityDidChange();
131 WebCore::IntRect clipRectInWindowCoordinates() const;
132 void focusPluginElement();
133
134 void pendingURLRequestsTimerFired();
135 class URLRequest;
136 void performURLRequest(URLRequest*);
137
138 // Perform a URL request where the frame target is not null.
139 void performFrameLoadURLRequest(URLRequest*);
140
141 // Perform a URL request where the URL protocol is "javascript:".
142 void performJavaScriptURLRequest(URLRequest*);
143
144 class Stream;
145 void addStream(Stream*);
146 void removeStream(Stream*);
147 void cancelAllStreams();
148
149 void redeliverManualStream();
150
151 void pluginSnapshotTimerFired();
152 void pluginDidReceiveUserInteraction();
153
154 bool shouldCreateTransientPaintingSnapshot() const;
155
156 // WebCore::PluginViewBase
157#if PLATFORM(COCOA)
158 PlatformLayer* platformLayer() const override;
159#endif
160 JSC::JSObject* scriptObject(JSC::JSGlobalObject*) override;
161 void storageBlockingStateChanged() override;
162 void privateBrowsingStateChanged(bool) override;
163 bool getFormValue(String&) override;
164 bool scroll(WebCore::ScrollDirection, WebCore::ScrollGranularity) override;
165 WebCore::Scrollbar* horizontalScrollbar() override;
166 WebCore::Scrollbar* verticalScrollbar() override;
167 bool wantsWheelEvents() override;
168 bool shouldAlwaysAutoStart() const override;
169 void beginSnapshottingRunningPlugin() override;
170 bool shouldAllowNavigationFromDrags() const override;
171 bool shouldNotAddLayer() const override;
172 void willDetachRenderer() override;
173
174 // WebCore::Widget
175 void setFrameRect(const WebCore::IntRect&) override;
176 void paint(WebCore::GraphicsContext&, const WebCore::IntRect&, WebCore::Widget::SecurityOriginPaintPolicy) override;
177 void invalidateRect(const WebCore::IntRect&) override;
178 void setFocus(bool) override;
179 void frameRectsChanged() override;
180 void setParent(WebCore::ScrollView*) override;
181 void handleEvent(WebCore::Event&) override;
182 void notifyWidget(WebCore::WidgetNotification) override;
183 void show() override;
184 void hide() override;
185 void setParentVisible(bool) override;
186 bool transformsAffectFrameRect() override;
187 void clipRectChanged() override;
188
189 // WebCore::MediaCanStartListener
190 void mediaCanStart(WebCore::Document&) override;
191
192 // WebCore::MediaProducer
193 MediaProducer::MediaStateFlags mediaState() const override { return m_pluginIsPlayingAudio ? MediaProducer::IsPlayingAudio : MediaProducer::IsNotPlaying; }
194 void pageMutedStateDidChange() override;
195
196 // PluginController
197 void invalidate(const WebCore::IntRect&) override;
198 String userAgent() override;
199 void loadURL(uint64_t requestID, const String& method, const String& urlString, const String& target, const WebCore::HTTPHeaderMap& headerFields, const Vector<uint8_t>& httpBody, bool allowPopups) override;
200 void cancelStreamLoad(uint64_t streamID) override;
201 void continueStreamLoad(uint64_t streamID) override;
202 void cancelManualStreamLoad() override;
203#if ENABLE(NETSCAPE_PLUGIN_API)
204 NPObject* windowScriptNPObject() override;
205 NPObject* pluginElementNPObject() override;
206 bool evaluate(NPObject*, const String& scriptString, NPVariant* result, bool allowPopups) override;
207 void setPluginIsPlayingAudio(bool) override;
208 bool isMuted() const override;
209#endif
210 void setStatusbarText(const String&) override;
211 bool isAcceleratedCompositingEnabled() override;
212 void pluginProcessCrashed() override;
213#if PLATFORM(COCOA)
214 void pluginFocusOrWindowFocusChanged(bool pluginHasFocusAndWindowHasFocus) override;
215 void setComplexTextInputState(PluginComplexTextInputState) override;
216 const WTF::MachSendRight& compositingRenderServerPort() override;
217#endif
218 float contentsScaleFactor() override;
219 String proxiesForURL(const String&) override;
220 String cookiesForURL(const String&) override;
221 void setCookiesForURL(const String& urlString, const String& cookieString) override;
222 bool getAuthenticationInfo(const WebCore::ProtectionSpace&, String& username, String& password) override;
223 bool isPrivateBrowsingEnabled() override;
224 bool asynchronousPluginInitializationEnabled() const override;
225 bool asynchronousPluginInitializationEnabledForAllPlugins() const override;
226 bool artificialPluginInitializationDelayEnabled() const override;
227 void protectPluginFromDestruction() override;
228 void unprotectPluginFromDestruction() override;
229#if PLATFORM(X11)
230 uint64_t createPluginContainer() override;
231 void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID) override;
232 void windowedPluginVisibilityDidChange(bool isVisible, uint64_t windowID) override;
233#endif
234
235 void didInitializePlugin() override;
236 void didFailToInitializePlugin() override;
237 void destroyPluginAndReset();
238
239 // WebFrame::LoadListener
240 void didFinishLoad(WebFrame*) override;
241 void didFailLoad(WebFrame*, bool wasCancelled) override;
242
243 std::unique_ptr<WebEvent> createWebEvent(WebCore::MouseEvent&) const;
244
245 RefPtr<WebCore::HTMLPlugInElement> m_pluginElement;
246 RefPtr<Plugin> m_plugin;
247 WebPage* m_webPage;
248 Plugin::Parameters m_parameters;
249
250 bool m_isInitialized { false };
251 bool m_isWaitingForSynchronousInitialization { false };
252 bool m_isWaitingUntilMediaCanStart { false };
253 bool m_pluginProcessHasCrashed { false };
254
255#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC)
256 bool m_didPlugInStartOffScreen { false };
257#endif
258
259 // Pending URLRequests that the plug-in has made.
260 Deque<RefPtr<URLRequest>> m_pendingURLRequests;
261 RunLoop::Timer<PluginView> m_pendingURLRequestsTimer;
262
263 // Pending frame loads that the plug-in has made.
264 typedef HashMap<RefPtr<WebFrame>, RefPtr<URLRequest>> FrameLoadMap;
265 FrameLoadMap m_pendingFrameLoads;
266
267 // Streams that the plug-in has requested to load.
268 HashMap<uint64_t, RefPtr<Stream>> m_streams;
269
270#if ENABLE(NETSCAPE_PLUGIN_API)
271 // A map of all related NPObjects for this plug-in view.
272 NPRuntimeObjectMap m_npRuntimeObjectMap { this };
273#endif
274
275 // The manual stream state. This is used so we can deliver a manual stream to a plug-in
276 // when it is initialized.
277 enum class ManualStreamState { Initial, HasReceivedResponse, Finished, Failed };
278 ManualStreamState m_manualStreamState { ManualStreamState::Initial };
279
280 WebCore::ResourceResponse m_manualStreamResponse;
281 WebCore::ResourceError m_manualStreamError;
282 RefPtr<WebCore::SharedBuffer> m_manualStreamData;
283
284 // This snapshot is used to avoid side effects should the plugin run JS during painting.
285 RefPtr<ShareableBitmap> m_transientPaintingSnapshot;
286 // This timer is used when plugin snapshotting is enabled, to capture a plugin placeholder.
287 WebCore::DeferrableOneShotTimer m_pluginSnapshotTimer;
288#if ENABLE(PRIMARY_SNAPSHOTTED_PLUGIN_HEURISTIC) || PLATFORM(COCOA)
289 unsigned m_countSnapshotRetries { 0 };
290#endif
291 bool m_didReceiveUserInteraction { false };
292
293 double m_pageScaleFactor { 1 };
294
295 bool m_pluginIsPlayingAudio { false };
296};
297
298} // namespace WebKit
299