|
1 /* |
|
2 * Copyright (C) 2010 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 #include "NetscapePlugin.h" |
|
27 |
|
28 #include "NetscapePluginStream.h" |
|
29 #include "PluginController.h" |
|
30 #include <WebCore/GraphicsContext.h> |
|
31 #include <WebCore/HTTPHeaderMap.h> |
|
32 #include <WebCore/IntRect.h> |
|
33 #include <WebCore/KURL.h> |
|
34 #include <utility> |
|
35 #include <wtf/text/CString.h> |
|
36 |
|
37 using namespace WebCore; |
|
38 using namespace std; |
|
39 |
|
40 namespace WebKit { |
|
41 |
|
42 NetscapePlugin::NetscapePlugin(PassRefPtr<NetscapePluginModule> pluginModule) |
|
43 : m_pluginController(0) |
|
44 , m_nextRequestID(0) |
|
45 , m_pluginModule(pluginModule) |
|
46 , m_npWindow() |
|
47 , m_isStarted(false) |
|
48 , m_inNPPNew(false) |
|
49 #if PLATFORM(MAC) |
|
50 , m_drawingModel(static_cast<NPDrawingModel>(-1)) |
|
51 , m_eventModel(static_cast<NPEventModel>(-1)) |
|
52 #endif |
|
53 { |
|
54 m_npp.ndata = this; |
|
55 m_npp.pdata = 0; |
|
56 |
|
57 m_pluginModule->pluginCreated(); |
|
58 } |
|
59 |
|
60 NetscapePlugin::~NetscapePlugin() |
|
61 { |
|
62 ASSERT(!m_isStarted); |
|
63 |
|
64 m_pluginModule->pluginDestroyed(); |
|
65 } |
|
66 |
|
67 PassRefPtr<NetscapePlugin> NetscapePlugin::fromNPP(NPP npp) |
|
68 { |
|
69 if (npp) { |
|
70 NetscapePlugin* plugin = static_cast<NetscapePlugin*>(npp->ndata); |
|
71 ASSERT(npp == &plugin->m_npp); |
|
72 |
|
73 return plugin; |
|
74 } |
|
75 |
|
76 // FIXME: Return the current NetscapePlugin here. |
|
77 ASSERT_NOT_REACHED(); |
|
78 return 0; |
|
79 } |
|
80 |
|
81 void NetscapePlugin::invalidate(const NPRect* invalidRect) |
|
82 { |
|
83 IntRect rect; |
|
84 |
|
85 if (!invalidRect) |
|
86 rect = IntRect(0, 0, m_frameRect.width(), m_frameRect.height()); |
|
87 else |
|
88 rect = IntRect(invalidRect->left, invalidRect->top, |
|
89 invalidRect->right - invalidRect->left, invalidRect->bottom - invalidRect->top); |
|
90 |
|
91 m_pluginController->invalidate(rect); |
|
92 } |
|
93 |
|
94 const char* NetscapePlugin::userAgent() |
|
95 { |
|
96 if (m_userAgent.isNull()) { |
|
97 // FIXME: Pass the src URL. |
|
98 m_userAgent = m_pluginController->userAgent(KURL()).utf8(); |
|
99 ASSERT(!m_userAgent.isNull()); |
|
100 } |
|
101 |
|
102 return m_userAgent.data(); |
|
103 } |
|
104 |
|
105 void NetscapePlugin::loadURL(const String& method, const String& urlString, const String& target, const HTTPHeaderMap& headerFields, const Vector<char>& httpBody, |
|
106 bool sendNotification, void* notificationData) |
|
107 { |
|
108 uint64_t requestID = ++m_nextRequestID; |
|
109 |
|
110 m_pluginController->loadURL(requestID, method, urlString, target, headerFields, httpBody, allowPopups()); |
|
111 |
|
112 if (target.isNull()) { |
|
113 // The browser is going to send the data in a stream, create a plug-in stream. |
|
114 RefPtr<NetscapePluginStream> pluginStream = NetscapePluginStream::create(this, requestID, sendNotification, notificationData); |
|
115 ASSERT(!m_streams.contains(requestID)); |
|
116 |
|
117 m_streams.set(requestID, pluginStream.release()); |
|
118 return; |
|
119 } |
|
120 |
|
121 if (sendNotification) { |
|
122 // Eventually we are going to get a frameDidFinishLoading or frameDidFail call for this request. |
|
123 // Keep track of the notification data so we can call NPP_URLNotify. |
|
124 ASSERT(!m_pendingURLNotifications.contains(requestID)); |
|
125 m_pendingURLNotifications.set(requestID, make_pair(urlString, notificationData)); |
|
126 } |
|
127 } |
|
128 |
|
129 NPError NetscapePlugin::destroyStream(NPStream* stream, NPReason reason) |
|
130 { |
|
131 NetscapePluginStream* pluginStream = 0; |
|
132 |
|
133 for (StreamsMap::const_iterator it = m_streams.begin(), end = m_streams.end(); it != end; ++it) { |
|
134 if (it->second->npStream() == stream) { |
|
135 pluginStream = it->second.get(); |
|
136 break; |
|
137 } |
|
138 } |
|
139 |
|
140 if (!pluginStream) |
|
141 return NPERR_INVALID_INSTANCE_ERROR; |
|
142 |
|
143 return pluginStream->destroy(reason); |
|
144 } |
|
145 |
|
146 NPObject* NetscapePlugin::windowScriptNPObject() |
|
147 { |
|
148 return m_pluginController->windowScriptNPObject(); |
|
149 } |
|
150 |
|
151 NPObject* NetscapePlugin::pluginElementNPObject() |
|
152 { |
|
153 return m_pluginController->pluginElementNPObject(); |
|
154 } |
|
155 |
|
156 void NetscapePlugin::cancelStreamLoad(NetscapePluginStream* pluginStream) |
|
157 { |
|
158 // Ask the plug-in controller to cancel this stream load. |
|
159 m_pluginController->cancelStreamLoad(pluginStream->streamID()); |
|
160 } |
|
161 |
|
162 void NetscapePlugin::removePluginStream(NetscapePluginStream* pluginStream) |
|
163 { |
|
164 ASSERT(m_streams.get(pluginStream->streamID()) == pluginStream); |
|
165 m_streams.remove(pluginStream->streamID()); |
|
166 } |
|
167 |
|
168 NPError NetscapePlugin::NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* savedData) |
|
169 { |
|
170 return m_pluginModule->pluginFuncs().newp(pluginType, &m_npp, mode, argc, argn, argv, savedData); |
|
171 } |
|
172 |
|
173 NPError NetscapePlugin::NPP_Destroy(NPSavedData** savedData) |
|
174 { |
|
175 return m_pluginModule->pluginFuncs().destroy(&m_npp, savedData); |
|
176 } |
|
177 |
|
178 NPError NetscapePlugin::NPP_SetWindow(NPWindow* npWindow) |
|
179 { |
|
180 return m_pluginModule->pluginFuncs().setwindow(&m_npp, npWindow); |
|
181 } |
|
182 |
|
183 NPError NetscapePlugin::NPP_NewStream(NPMIMEType mimeType, NPStream* stream, NPBool seekable, uint16_t* streamType) |
|
184 { |
|
185 return m_pluginModule->pluginFuncs().newstream(&m_npp, mimeType, stream, seekable, streamType); |
|
186 } |
|
187 |
|
188 NPError NetscapePlugin::NPP_DestroyStream(NPStream* stream, NPReason reason) |
|
189 { |
|
190 return m_pluginModule->pluginFuncs().destroystream(&m_npp, stream, reason); |
|
191 } |
|
192 |
|
193 void NetscapePlugin::NPP_StreamAsFile(NPStream* stream, const char* filename) |
|
194 { |
|
195 return m_pluginModule->pluginFuncs().asfile(&m_npp, stream, filename); |
|
196 } |
|
197 |
|
198 int32_t NetscapePlugin::NPP_WriteReady(NPStream* stream) |
|
199 { |
|
200 return m_pluginModule->pluginFuncs().writeready(&m_npp, stream); |
|
201 } |
|
202 |
|
203 int32_t NetscapePlugin::NPP_Write(NPStream* stream, int32_t offset, int32_t len, void* buffer) |
|
204 { |
|
205 return m_pluginModule->pluginFuncs().write(&m_npp, stream, offset, len, buffer); |
|
206 } |
|
207 |
|
208 void NetscapePlugin::NPP_URLNotify(const char* url, NPReason reason, void* notifyData) |
|
209 { |
|
210 m_pluginModule->pluginFuncs().urlnotify(&m_npp, url, reason, notifyData); |
|
211 } |
|
212 |
|
213 NPError NetscapePlugin::NPP_GetValue(NPPVariable variable, void *value) |
|
214 { |
|
215 return m_pluginModule->pluginFuncs().getvalue(&m_npp, variable, value); |
|
216 } |
|
217 |
|
218 void NetscapePlugin::callSetWindow() |
|
219 { |
|
220 m_npWindow.x = m_frameRect.x(); |
|
221 m_npWindow.y = m_frameRect.y(); |
|
222 m_npWindow.width = m_frameRect.width(); |
|
223 m_npWindow.height = m_frameRect.height(); |
|
224 m_npWindow.clipRect.top = m_clipRect.y(); |
|
225 m_npWindow.clipRect.left = m_clipRect.x(); |
|
226 m_npWindow.clipRect.bottom = m_clipRect.bottom(); |
|
227 m_npWindow.clipRect.right = m_clipRect.right(); |
|
228 |
|
229 NPP_SetWindow(&m_npWindow); |
|
230 } |
|
231 |
|
232 bool NetscapePlugin::shouldLoadSrcURL() |
|
233 { |
|
234 // Check if we should cancel the load |
|
235 NPBool cancelSrcStream = false; |
|
236 |
|
237 if (NPP_GetValue(NPPVpluginCancelSrcStream, &cancelSrcStream) != NPERR_NO_ERROR) |
|
238 return true; |
|
239 |
|
240 return !cancelSrcStream; |
|
241 } |
|
242 |
|
243 NetscapePluginStream* NetscapePlugin::streamFromID(uint64_t streamID) |
|
244 { |
|
245 return m_streams.get(streamID).get(); |
|
246 } |
|
247 |
|
248 void NetscapePlugin::stopAllStreams() |
|
249 { |
|
250 Vector<RefPtr<NetscapePluginStream> > streams; |
|
251 copyValuesToVector(m_streams, streams); |
|
252 |
|
253 for (size_t i = 0; i < streams.size(); ++i) |
|
254 streams[i]->stop(NPRES_USER_BREAK); |
|
255 } |
|
256 |
|
257 bool NetscapePlugin::allowPopups() const |
|
258 { |
|
259 // FIXME: Handle popups. |
|
260 return false; |
|
261 } |
|
262 |
|
263 bool NetscapePlugin::initialize(PluginController* pluginController, const Parameters& parameters) |
|
264 { |
|
265 ASSERT(!m_pluginController); |
|
266 ASSERT(pluginController); |
|
267 |
|
268 m_pluginController = pluginController; |
|
269 |
|
270 uint16_t mode = parameters.loadManually ? NP_FULL : NP_EMBED; |
|
271 |
|
272 m_inNPPNew = true; |
|
273 |
|
274 CString mimeTypeCString = parameters.mimeType.utf8(); |
|
275 |
|
276 ASSERT(parameters.names.size() == parameters.values.size()); |
|
277 |
|
278 Vector<CString> paramNames; |
|
279 Vector<CString> paramValues; |
|
280 for (size_t i = 0; i < parameters.names.size(); ++i) { |
|
281 paramNames.append(parameters.names[i].utf8()); |
|
282 paramValues.append(parameters.values[i].utf8()); |
|
283 } |
|
284 |
|
285 // The strings that these pointers point to are kept alive by paramNames and paramValues. |
|
286 Vector<const char*> names; |
|
287 Vector<const char*> values; |
|
288 for (size_t i = 0; i < paramNames.size(); ++i) { |
|
289 names.append(paramNames[i].data()); |
|
290 values.append(paramValues[i].data()); |
|
291 } |
|
292 |
|
293 NPError error = NPP_New(const_cast<char*>(mimeTypeCString.data()), mode, names.size(), |
|
294 const_cast<char**>(names.data()), const_cast<char**>(values.data()), 0); |
|
295 m_inNPPNew = false; |
|
296 |
|
297 if (error != NPERR_NO_ERROR) |
|
298 return false; |
|
299 |
|
300 m_isStarted = true; |
|
301 |
|
302 // FIXME: This is not correct in all cases. |
|
303 m_npWindow.type = NPWindowTypeDrawable; |
|
304 |
|
305 if (!platformPostInitialize()) { |
|
306 destroy(); |
|
307 return false; |
|
308 } |
|
309 |
|
310 // Load the src URL if needed. |
|
311 if (!parameters.url.isEmpty() && shouldLoadSrcURL()) |
|
312 loadURL("GET", parameters.url.string(), String(), HTTPHeaderMap(), Vector<char>(), false, 0); |
|
313 |
|
314 return true; |
|
315 } |
|
316 |
|
317 void NetscapePlugin::destroy() |
|
318 { |
|
319 ASSERT(m_isStarted); |
|
320 |
|
321 // Stop all streams. |
|
322 stopAllStreams(); |
|
323 |
|
324 NPP_Destroy(0); |
|
325 |
|
326 m_isStarted = false; |
|
327 m_pluginController = 0; |
|
328 } |
|
329 |
|
330 void NetscapePlugin::paint(GraphicsContext* context, const IntRect& dirtyRect) |
|
331 { |
|
332 ASSERT(m_isStarted); |
|
333 |
|
334 platformPaint(context, dirtyRect); |
|
335 } |
|
336 |
|
337 void NetscapePlugin::geometryDidChange(const IntRect& frameRect, const IntRect& clipRect) |
|
338 { |
|
339 ASSERT(m_isStarted); |
|
340 |
|
341 if (m_frameRect == frameRect && m_clipRect == clipRect) { |
|
342 // Nothing to do. |
|
343 return; |
|
344 } |
|
345 |
|
346 m_frameRect = frameRect; |
|
347 m_clipRect = clipRect; |
|
348 |
|
349 callSetWindow(); |
|
350 } |
|
351 |
|
352 void NetscapePlugin::frameDidFinishLoading(uint64_t requestID) |
|
353 { |
|
354 PendingURLNotifyMap::iterator it = m_pendingURLNotifications.find(requestID); |
|
355 if (it == m_pendingURLNotifications.end()) |
|
356 return; |
|
357 |
|
358 String url = it->second.first; |
|
359 void* notificationData = it->second.second; |
|
360 |
|
361 m_pendingURLNotifications.remove(it); |
|
362 |
|
363 NPP_URLNotify(url.utf8().data(), NPRES_DONE, notificationData); |
|
364 } |
|
365 |
|
366 void NetscapePlugin::frameDidFail(uint64_t requestID, bool wasCancelled) |
|
367 { |
|
368 PendingURLNotifyMap::iterator it = m_pendingURLNotifications.find(requestID); |
|
369 if (it == m_pendingURLNotifications.end()) |
|
370 return; |
|
371 |
|
372 String url = it->second.first; |
|
373 void* notificationData = it->second.second; |
|
374 |
|
375 m_pendingURLNotifications.remove(it); |
|
376 |
|
377 NPP_URLNotify(url.utf8().data(), wasCancelled ? NPRES_USER_BREAK : NPRES_NETWORK_ERR, notificationData); |
|
378 } |
|
379 |
|
380 void NetscapePlugin::didEvaluateJavaScript(uint64_t requestID, const String& requestURLString, const String& result) |
|
381 { |
|
382 if (NetscapePluginStream* pluginStream = streamFromID(requestID)) |
|
383 pluginStream->sendJavaScriptStream(requestURLString, result); |
|
384 } |
|
385 |
|
386 void NetscapePlugin::streamDidReceiveResponse(uint64_t streamID, const KURL& responseURL, uint32_t streamLength, |
|
387 uint32_t lastModifiedTime, const String& mimeType, const String& headers) |
|
388 { |
|
389 if (NetscapePluginStream* pluginStream = streamFromID(streamID)) |
|
390 pluginStream->didReceiveResponse(responseURL, streamLength, lastModifiedTime, mimeType, headers); |
|
391 } |
|
392 |
|
393 void NetscapePlugin::streamDidReceiveData(uint64_t streamID, const char* bytes, int length) |
|
394 { |
|
395 if (NetscapePluginStream* pluginStream = streamFromID(streamID)) |
|
396 pluginStream->didReceiveData(bytes, length); |
|
397 } |
|
398 |
|
399 void NetscapePlugin::streamDidFinishLoading(uint64_t streamID) |
|
400 { |
|
401 if (NetscapePluginStream* pluginStream = streamFromID(streamID)) |
|
402 pluginStream->didFinishLoading(); |
|
403 } |
|
404 |
|
405 void NetscapePlugin::streamDidFail(uint64_t streamID, bool wasCancelled) |
|
406 { |
|
407 if (NetscapePluginStream* pluginStream = streamFromID(streamID)) |
|
408 pluginStream->didFail(wasCancelled); |
|
409 } |
|
410 |
|
411 PluginController* NetscapePlugin::controller() |
|
412 { |
|
413 return m_pluginController; |
|
414 } |
|
415 |
|
416 } // namespace WebKit |