OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "webkit/plugins/npapi/plugin_instance.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/file_util.h" | |
9 #include "base/message_loop/message_loop.h" | |
10 #include "base/strings/string_number_conversions.h" | |
11 #include "base/strings/utf_string_conversions.h" | |
12 #include "build/build_config.h" | |
13 #include "net/base/escape.h" | |
14 #include "webkit/plugins/npapi/plugin_host.h" | |
15 #include "webkit/plugins/npapi/plugin_lib.h" | |
16 #include "webkit/plugins/npapi/plugin_stream_url.h" | |
17 #include "webkit/plugins/npapi/plugin_string_stream.h" | |
18 #include "webkit/plugins/npapi/webplugin.h" | |
19 #include "webkit/plugins/npapi/webplugin_delegate.h" | |
20 #include "webkit/plugins/plugin_constants.h" | |
21 | |
22 #if defined(OS_MACOSX) | |
23 #include <ApplicationServices/ApplicationServices.h> | |
24 #endif | |
25 | |
26 namespace webkit { | |
27 namespace npapi { | |
28 | |
29 PluginInstance::PluginInstance(PluginLib* plugin, const std::string& mime_type) | |
30 : plugin_(plugin), | |
31 npp_(0), | |
32 host_(PluginHost::Singleton()), | |
33 npp_functions_(plugin->functions()), | |
34 window_handle_(0), | |
35 windowless_(false), | |
36 transparent_(true), | |
37 webplugin_(0), | |
38 mime_type_(mime_type), | |
39 get_notify_data_(0), | |
40 use_mozilla_user_agent_(false), | |
41 #if defined (OS_MACOSX) | |
42 #ifdef NP_NO_QUICKDRAW | |
43 drawing_model_(NPDrawingModelCoreGraphics), | |
44 #else | |
45 drawing_model_(NPDrawingModelQuickDraw), | |
46 #endif | |
47 #ifdef NP_NO_CARBON | |
48 event_model_(NPEventModelCocoa), | |
49 #else | |
50 event_model_(NPEventModelCarbon), | |
51 #endif | |
52 currently_handled_event_(NULL), | |
53 #endif | |
54 message_loop_(base::MessageLoop::current()), | |
55 load_manually_(false), | |
56 in_close_streams_(false), | |
57 next_timer_id_(1), | |
58 next_notify_id_(0), | |
59 next_range_request_id_(0), | |
60 handles_url_redirects_(false) { | |
61 npp_ = new NPP_t(); | |
62 npp_->ndata = 0; | |
63 npp_->pdata = 0; | |
64 | |
65 if (mime_type_ == kFlashPluginSwfMimeType) | |
66 transparent_ = false; | |
67 | |
68 memset(&zero_padding_, 0, sizeof(zero_padding_)); | |
69 DCHECK(message_loop_); | |
70 } | |
71 | |
72 PluginInstance::~PluginInstance() { | |
73 CloseStreams(); | |
74 | |
75 if (npp_ != 0) { | |
76 delete npp_; | |
77 npp_ = 0; | |
78 } | |
79 | |
80 if (plugin_.get()) | |
81 plugin_->CloseInstance(); | |
82 } | |
83 | |
84 PluginStreamUrl* PluginInstance::CreateStream(unsigned long resource_id, | |
85 const GURL& url, | |
86 const std::string& mime_type, | |
87 int notify_id) { | |
88 | |
89 bool notify; | |
90 void* notify_data; | |
91 GetNotifyData(notify_id, ¬ify, ¬ify_data); | |
92 PluginStreamUrl* stream = new PluginStreamUrl( | |
93 resource_id, url, this, notify, notify_data); | |
94 | |
95 AddStream(stream); | |
96 return stream; | |
97 } | |
98 | |
99 void PluginInstance::AddStream(PluginStream* stream) { | |
100 open_streams_.push_back(make_scoped_refptr(stream)); | |
101 } | |
102 | |
103 void PluginInstance::RemoveStream(PluginStream* stream) { | |
104 if (in_close_streams_) | |
105 return; | |
106 | |
107 std::vector<scoped_refptr<PluginStream> >::iterator stream_index; | |
108 for (stream_index = open_streams_.begin(); | |
109 stream_index != open_streams_.end(); ++stream_index) { | |
110 if (stream_index->get() == stream) { | |
111 open_streams_.erase(stream_index); | |
112 break; | |
113 } | |
114 } | |
115 } | |
116 | |
117 bool PluginInstance::IsValidStream(const NPStream* stream) { | |
118 std::vector<scoped_refptr<PluginStream> >::iterator stream_index; | |
119 for (stream_index = open_streams_.begin(); | |
120 stream_index != open_streams_.end(); ++stream_index) { | |
121 if ((*stream_index)->stream() == stream) | |
122 return true; | |
123 } | |
124 | |
125 return false; | |
126 } | |
127 | |
128 void PluginInstance::CloseStreams() { | |
129 in_close_streams_ = true; | |
130 for (unsigned int index = 0; index < open_streams_.size(); ++index) { | |
131 // Close all streams on the way down. | |
132 open_streams_[index]->Close(NPRES_USER_BREAK); | |
133 } | |
134 open_streams_.clear(); | |
135 in_close_streams_ = false; | |
136 } | |
137 | |
138 WebPluginResourceClient* PluginInstance::GetRangeRequest( | |
139 int id) { | |
140 PendingRangeRequestMap::iterator iter = pending_range_requests_.find(id); | |
141 if (iter == pending_range_requests_.end()) { | |
142 NOTREACHED(); | |
143 return NULL; | |
144 } | |
145 | |
146 WebPluginResourceClient* rv = iter->second->AsResourceClient(); | |
147 pending_range_requests_.erase(iter); | |
148 return rv; | |
149 } | |
150 | |
151 bool PluginInstance::Start(const GURL& url, | |
152 char** const param_names, | |
153 char** const param_values, | |
154 int param_count, | |
155 bool load_manually) { | |
156 load_manually_ = load_manually; | |
157 unsigned short mode = load_manually_ ? NP_FULL : NP_EMBED; | |
158 npp_->ndata = this; | |
159 | |
160 NPError err = NPP_New(mode, param_count, | |
161 const_cast<char **>(param_names), const_cast<char **>(param_values)); | |
162 | |
163 if (err == NPERR_NO_ERROR) { | |
164 handles_url_redirects_ = | |
165 ((npp_functions_->version >= NPVERS_HAS_URL_REDIRECT_HANDLING) && | |
166 (npp_functions_->urlredirectnotify)); | |
167 } | |
168 return err == NPERR_NO_ERROR; | |
169 } | |
170 | |
171 NPObject *PluginInstance::GetPluginScriptableObject() { | |
172 NPObject *value = NULL; | |
173 NPError error = NPP_GetValue(NPPVpluginScriptableNPObject, &value); | |
174 if (error != NPERR_NO_ERROR || value == NULL) | |
175 return NULL; | |
176 return value; | |
177 } | |
178 | |
179 bool PluginInstance::GetFormValue(base::string16* value) { | |
180 // Plugins will allocate memory for the return value by using NPN_MemAlloc(). | |
181 char *plugin_value = NULL; | |
182 NPError error = NPP_GetValue(NPPVformValue, &plugin_value); | |
183 if (error != NPERR_NO_ERROR || !plugin_value) { | |
184 return false; | |
185 } | |
186 // Assumes the result is UTF8 text, as Firefox does. | |
187 *value = UTF8ToUTF16(plugin_value); | |
188 host_->host_functions()->memfree(plugin_value); | |
189 return true; | |
190 } | |
191 | |
192 // WebPluginLoadDelegate methods | |
193 void PluginInstance::DidFinishLoadWithReason( | |
194 const GURL& url, NPReason reason, int notify_id) { | |
195 bool notify; | |
196 void* notify_data; | |
197 GetNotifyData(notify_id, ¬ify, ¬ify_data); | |
198 if (!notify) { | |
199 NOTREACHED(); | |
200 return; | |
201 } | |
202 | |
203 NPP_URLNotify(url.spec().c_str(), reason, notify_data); | |
204 } | |
205 | |
206 unsigned PluginInstance::GetBackingTextureId() { | |
207 // By default the plugin instance is not backed by an OpenGL texture. | |
208 return 0; | |
209 } | |
210 | |
211 // NPAPI methods | |
212 NPError PluginInstance::NPP_New(unsigned short mode, | |
213 short argc, | |
214 char *argn[], | |
215 char *argv[]) { | |
216 DCHECK(npp_functions_ != 0); | |
217 DCHECK(npp_functions_->newp != 0); | |
218 DCHECK(argc >= 0); | |
219 | |
220 if (npp_functions_->newp != 0) { | |
221 return npp_functions_->newp( | |
222 (NPMIMEType)mime_type_.c_str(), npp_, mode, argc, argn, argv, NULL); | |
223 } | |
224 return NPERR_INVALID_FUNCTABLE_ERROR; | |
225 } | |
226 | |
227 void PluginInstance::NPP_Destroy() { | |
228 DCHECK(npp_functions_ != 0); | |
229 DCHECK(npp_functions_->destroy != 0); | |
230 | |
231 if (npp_functions_->destroy != 0) { | |
232 NPSavedData *savedData = 0; | |
233 npp_functions_->destroy(npp_, &savedData); | |
234 | |
235 // TODO: Support savedData. Technically, these need to be | |
236 // saved on a per-URL basis, and then only passed | |
237 // to new instances of the plugin at the same URL. | |
238 // Sounds like a huge security risk. When we do support | |
239 // these, we should pass them back to the PluginLib | |
240 // to be stored there. | |
241 DCHECK(savedData == 0); | |
242 } | |
243 | |
244 for (unsigned int file_index = 0; file_index < files_created_.size(); | |
245 file_index++) { | |
246 base::DeleteFile(files_created_[file_index], false); | |
247 } | |
248 | |
249 // Ensure that no timer callbacks are invoked after NPP_Destroy. | |
250 timers_.clear(); | |
251 } | |
252 | |
253 NPError PluginInstance::NPP_SetWindow(NPWindow *window) { | |
254 DCHECK(npp_functions_ != 0); | |
255 DCHECK(npp_functions_->setwindow != 0); | |
256 | |
257 if (npp_functions_->setwindow != 0) { | |
258 return npp_functions_->setwindow(npp_, window); | |
259 } | |
260 return NPERR_INVALID_FUNCTABLE_ERROR; | |
261 } | |
262 | |
263 NPError PluginInstance::NPP_NewStream(NPMIMEType type, | |
264 NPStream *stream, | |
265 NPBool seekable, | |
266 unsigned short *stype) { | |
267 DCHECK(npp_functions_ != 0); | |
268 DCHECK(npp_functions_->newstream != 0); | |
269 if (npp_functions_->newstream != 0) { | |
270 return npp_functions_->newstream(npp_, type, stream, seekable, stype); | |
271 } | |
272 return NPERR_INVALID_FUNCTABLE_ERROR; | |
273 } | |
274 | |
275 NPError PluginInstance::NPP_DestroyStream(NPStream *stream, NPReason reason) { | |
276 DCHECK(npp_functions_ != 0); | |
277 DCHECK(npp_functions_->destroystream != 0); | |
278 | |
279 if (stream == NULL || !IsValidStream(stream) || (stream->ndata == NULL)) | |
280 return NPERR_INVALID_INSTANCE_ERROR; | |
281 | |
282 if (npp_functions_->destroystream != 0) { | |
283 NPError result = npp_functions_->destroystream(npp_, stream, reason); | |
284 stream->ndata = NULL; | |
285 return result; | |
286 } | |
287 return NPERR_INVALID_FUNCTABLE_ERROR; | |
288 } | |
289 | |
290 int PluginInstance::NPP_WriteReady(NPStream *stream) { | |
291 DCHECK(npp_functions_ != 0); | |
292 DCHECK(npp_functions_->writeready != 0); | |
293 if (npp_functions_->writeready != 0) { | |
294 return npp_functions_->writeready(npp_, stream); | |
295 } | |
296 return 0; | |
297 } | |
298 | |
299 int PluginInstance::NPP_Write(NPStream *stream, | |
300 int offset, | |
301 int len, | |
302 void *buffer) { | |
303 DCHECK(npp_functions_ != 0); | |
304 DCHECK(npp_functions_->write != 0); | |
305 if (npp_functions_->write != 0) { | |
306 return npp_functions_->write(npp_, stream, offset, len, buffer); | |
307 } | |
308 return 0; | |
309 } | |
310 | |
311 void PluginInstance::NPP_StreamAsFile(NPStream *stream, const char *fname) { | |
312 DCHECK(npp_functions_ != 0); | |
313 DCHECK(npp_functions_->asfile != 0); | |
314 if (npp_functions_->asfile != 0) { | |
315 npp_functions_->asfile(npp_, stream, fname); | |
316 } | |
317 | |
318 // Creating a temporary FilePath instance on the stack as the explicit | |
319 // FilePath constructor with StringType as an argument causes a compiler | |
320 // error when invoked via vector push back. | |
321 base::FilePath file_name = base::FilePath::FromWStringHack(UTF8ToWide(fname)); | |
322 files_created_.push_back(file_name); | |
323 } | |
324 | |
325 void PluginInstance::NPP_URLNotify(const char *url, | |
326 NPReason reason, | |
327 void *notifyData) { | |
328 DCHECK(npp_functions_ != 0); | |
329 DCHECK(npp_functions_->urlnotify != 0); | |
330 if (npp_functions_->urlnotify != 0) { | |
331 npp_functions_->urlnotify(npp_, url, reason, notifyData); | |
332 } | |
333 } | |
334 | |
335 NPError PluginInstance::NPP_GetValue(NPPVariable variable, void *value) { | |
336 DCHECK(npp_functions_ != 0); | |
337 // getvalue is NULL for Shockwave | |
338 if (npp_functions_->getvalue != 0) { | |
339 return npp_functions_->getvalue(npp_, variable, value); | |
340 } | |
341 return NPERR_INVALID_FUNCTABLE_ERROR; | |
342 } | |
343 | |
344 NPError PluginInstance::NPP_SetValue(NPNVariable variable, void *value) { | |
345 DCHECK(npp_functions_ != 0); | |
346 if (npp_functions_->setvalue != 0) { | |
347 return npp_functions_->setvalue(npp_, variable, value); | |
348 } | |
349 return NPERR_INVALID_FUNCTABLE_ERROR; | |
350 } | |
351 | |
352 short PluginInstance::NPP_HandleEvent(void* event) { | |
353 DCHECK(npp_functions_ != 0); | |
354 DCHECK(npp_functions_->event != 0); | |
355 if (npp_functions_->event != 0) { | |
356 return npp_functions_->event(npp_, (void*)event); | |
357 } | |
358 return false; | |
359 } | |
360 | |
361 bool PluginInstance::NPP_Print(NPPrint* platform_print) { | |
362 DCHECK(npp_functions_ != 0); | |
363 if (npp_functions_->print != 0) { | |
364 npp_functions_->print(npp_, platform_print); | |
365 return true; | |
366 } | |
367 return false; | |
368 } | |
369 | |
370 void PluginInstance::NPP_URLRedirectNotify(const char* url, int32_t status, | |
371 void* notify_data) { | |
372 DCHECK(npp_functions_ != 0); | |
373 if (npp_functions_->urlredirectnotify != 0) { | |
374 npp_functions_->urlredirectnotify(npp_, url, status, notify_data); | |
375 } | |
376 } | |
377 | |
378 void PluginInstance::SendJavaScriptStream(const GURL& url, | |
379 const std::string& result, | |
380 bool success, | |
381 int notify_id) { | |
382 bool notify; | |
383 void* notify_data; | |
384 GetNotifyData(notify_id, ¬ify, ¬ify_data); | |
385 | |
386 if (success) { | |
387 PluginStringStream *stream = | |
388 new PluginStringStream(this, url, notify, notify_data); | |
389 AddStream(stream); | |
390 stream->SendToPlugin(result, "text/html"); | |
391 } else { | |
392 // NOTE: Sending an empty stream here will crash MacroMedia | |
393 // Flash 9. Just send the URL Notify. | |
394 if (notify) | |
395 NPP_URLNotify(url.spec().c_str(), NPRES_DONE, notify_data); | |
396 } | |
397 } | |
398 | |
399 void PluginInstance::DidReceiveManualResponse(const GURL& url, | |
400 const std::string& mime_type, | |
401 const std::string& headers, | |
402 uint32 expected_length, | |
403 uint32 last_modified) { | |
404 DCHECK(load_manually_); | |
405 | |
406 plugin_data_stream_ = CreateStream(-1, url, mime_type, 0); | |
407 plugin_data_stream_->DidReceiveResponse(mime_type, headers, expected_length, | |
408 last_modified, true); | |
409 } | |
410 | |
411 void PluginInstance::DidReceiveManualData(const char* buffer, int length) { | |
412 DCHECK(load_manually_); | |
413 if (plugin_data_stream_.get() != NULL) { | |
414 plugin_data_stream_->DidReceiveData(buffer, length, 0); | |
415 } | |
416 } | |
417 | |
418 void PluginInstance::DidFinishManualLoading() { | |
419 DCHECK(load_manually_); | |
420 if (plugin_data_stream_.get() != NULL) { | |
421 plugin_data_stream_->DidFinishLoading(plugin_data_stream_->ResourceId()); | |
422 plugin_data_stream_->Close(NPRES_DONE); | |
423 plugin_data_stream_ = NULL; | |
424 } | |
425 } | |
426 | |
427 void PluginInstance::DidManualLoadFail() { | |
428 DCHECK(load_manually_); | |
429 if (plugin_data_stream_.get() != NULL) { | |
430 plugin_data_stream_->DidFail(plugin_data_stream_->ResourceId()); | |
431 plugin_data_stream_ = NULL; | |
432 } | |
433 } | |
434 | |
435 void PluginInstance::PluginThreadAsyncCall(void (*func)(void *), | |
436 void *user_data) { | |
437 message_loop_->PostTask( | |
438 FROM_HERE, base::Bind(&PluginInstance::OnPluginThreadAsyncCall, this, | |
439 func, user_data)); | |
440 } | |
441 | |
442 void PluginInstance::OnPluginThreadAsyncCall(void (*func)(void *), | |
443 void *user_data) { | |
444 // Do not invoke the callback if NPP_Destroy has already been invoked. | |
445 if (webplugin_) | |
446 func(user_data); | |
447 } | |
448 | |
449 uint32 PluginInstance::ScheduleTimer(uint32 interval, | |
450 NPBool repeat, | |
451 void (*func)(NPP id, uint32 timer_id)) { | |
452 // Use next timer id. | |
453 uint32 timer_id; | |
454 timer_id = next_timer_id_; | |
455 ++next_timer_id_; | |
456 DCHECK(next_timer_id_ != 0); | |
457 | |
458 // Record timer interval and repeat. | |
459 TimerInfo info; | |
460 info.interval = interval; | |
461 info.repeat = repeat ? true : false; | |
462 timers_[timer_id] = info; | |
463 | |
464 // Schedule the callback. | |
465 base::MessageLoop::current()->PostDelayedTask( | |
466 FROM_HERE, | |
467 base::Bind(&PluginInstance::OnTimerCall, this, func, npp_, timer_id), | |
468 base::TimeDelta::FromMilliseconds(interval)); | |
469 return timer_id; | |
470 } | |
471 | |
472 void PluginInstance::UnscheduleTimer(uint32 timer_id) { | |
473 // Remove info about the timer. | |
474 TimerMap::iterator it = timers_.find(timer_id); | |
475 if (it != timers_.end()) | |
476 timers_.erase(it); | |
477 } | |
478 | |
479 #if !defined(OS_MACOSX) | |
480 NPError PluginInstance::PopUpContextMenu(NPMenu* menu) { | |
481 NOTIMPLEMENTED(); | |
482 return NPERR_GENERIC_ERROR; | |
483 } | |
484 #endif | |
485 | |
486 void PluginInstance::OnTimerCall(void (*func)(NPP id, uint32 timer_id), | |
487 NPP id, | |
488 uint32 timer_id) { | |
489 // Do not invoke callback if the timer has been unscheduled. | |
490 TimerMap::iterator it = timers_.find(timer_id); | |
491 if (it == timers_.end()) | |
492 return; | |
493 | |
494 // Get all information about the timer before invoking the callback. The | |
495 // callback might unschedule the timer. | |
496 TimerInfo info = it->second; | |
497 | |
498 func(id, timer_id); | |
499 | |
500 // If the timer was unscheduled by the callback, just free up the timer id. | |
501 if (timers_.find(timer_id) == timers_.end()) | |
502 return; | |
503 | |
504 // Reschedule repeating timers after invoking the callback so callback is not | |
505 // re-entered if it pumps the message loop. | |
506 if (info.repeat) { | |
507 base::MessageLoop::current()->PostDelayedTask( | |
508 FROM_HERE, | |
509 base::Bind(&PluginInstance::OnTimerCall, this, func, npp_, timer_id), | |
510 base::TimeDelta::FromMilliseconds(info.interval)); | |
511 } else { | |
512 timers_.erase(it); | |
513 } | |
514 } | |
515 | |
516 void PluginInstance::PushPopupsEnabledState(bool enabled) { | |
517 popups_enabled_stack_.push(enabled); | |
518 } | |
519 | |
520 void PluginInstance::PopPopupsEnabledState() { | |
521 popups_enabled_stack_.pop(); | |
522 } | |
523 | |
524 void PluginInstance::RequestRead(NPStream* stream, NPByteRange* range_list) { | |
525 std::string range_info = "bytes="; | |
526 | |
527 while (range_list) { | |
528 range_info += base::IntToString(range_list->offset); | |
529 range_info.push_back('-'); | |
530 range_info += | |
531 base::IntToString(range_list->offset + range_list->length - 1); | |
532 range_list = range_list->next; | |
533 if (range_list) | |
534 range_info.push_back(','); | |
535 } | |
536 | |
537 if (plugin_data_stream_.get()) { | |
538 if (plugin_data_stream_->stream() == stream) { | |
539 webplugin_->CancelDocumentLoad(); | |
540 plugin_data_stream_ = NULL; | |
541 } | |
542 } | |
543 | |
544 // The lifetime of a NPStream instance depends on the PluginStream instance | |
545 // which owns it. When a plugin invokes NPN_RequestRead on a seekable stream, | |
546 // we don't want to create a new stream when the corresponding response is | |
547 // received. We send over a cookie which represents the PluginStream | |
548 // instance which is sent back from the renderer when the response is | |
549 // received. | |
550 std::vector<scoped_refptr<PluginStream> >::iterator stream_index; | |
551 for (stream_index = open_streams_.begin(); | |
552 stream_index != open_streams_.end(); ++stream_index) { | |
553 PluginStream* plugin_stream = stream_index->get(); | |
554 if (plugin_stream->stream() == stream) { | |
555 // A stream becomes seekable the first time NPN_RequestRead | |
556 // is called on it. | |
557 plugin_stream->set_seekable(true); | |
558 | |
559 pending_range_requests_[++next_range_request_id_] = plugin_stream; | |
560 webplugin_->InitiateHTTPRangeRequest( | |
561 stream->url, range_info.c_str(), next_range_request_id_); | |
562 return; | |
563 } | |
564 } | |
565 NOTREACHED(); | |
566 } | |
567 | |
568 void PluginInstance::RequestURL(const char* url, | |
569 const char* method, | |
570 const char* target, | |
571 const char* buf, | |
572 unsigned int len, | |
573 bool notify, | |
574 void* notify_data) { | |
575 int notify_id = 0; | |
576 if (notify) { | |
577 notify_id = ++next_notify_id_; | |
578 pending_requests_[notify_id] = notify_data; | |
579 } | |
580 | |
581 webplugin_->HandleURLRequest( | |
582 url, method, target, buf, len, notify_id, popups_allowed(), | |
583 notify ? handles_url_redirects_ : false); | |
584 } | |
585 | |
586 bool PluginInstance::ConvertPoint(double source_x, double source_y, | |
587 NPCoordinateSpace source_space, | |
588 double* dest_x, double* dest_y, | |
589 NPCoordinateSpace dest_space) { | |
590 #if defined(OS_MACOSX) | |
591 CGRect main_display_bounds = CGDisplayBounds(CGMainDisplayID()); | |
592 | |
593 double flipped_screen_x = source_x; | |
594 double flipped_screen_y = source_y; | |
595 switch(source_space) { | |
596 case NPCoordinateSpacePlugin: | |
597 flipped_screen_x += plugin_origin_.x(); | |
598 flipped_screen_y += plugin_origin_.y(); | |
599 break; | |
600 case NPCoordinateSpaceWindow: | |
601 flipped_screen_x += containing_window_frame_.x(); | |
602 flipped_screen_y = containing_window_frame_.height() - source_y + | |
603 containing_window_frame_.y(); | |
604 break; | |
605 case NPCoordinateSpaceFlippedWindow: | |
606 flipped_screen_x += containing_window_frame_.x(); | |
607 flipped_screen_y += containing_window_frame_.y(); | |
608 break; | |
609 case NPCoordinateSpaceScreen: | |
610 flipped_screen_y = main_display_bounds.size.height - flipped_screen_y; | |
611 break; | |
612 case NPCoordinateSpaceFlippedScreen: | |
613 break; | |
614 default: | |
615 NOTREACHED(); | |
616 return false; | |
617 } | |
618 | |
619 double target_x = flipped_screen_x; | |
620 double target_y = flipped_screen_y; | |
621 switch(dest_space) { | |
622 case NPCoordinateSpacePlugin: | |
623 target_x -= plugin_origin_.x(); | |
624 target_y -= plugin_origin_.y(); | |
625 break; | |
626 case NPCoordinateSpaceWindow: | |
627 target_x -= containing_window_frame_.x(); | |
628 target_y -= containing_window_frame_.y(); | |
629 target_y = containing_window_frame_.height() - target_y; | |
630 break; | |
631 case NPCoordinateSpaceFlippedWindow: | |
632 target_x -= containing_window_frame_.x(); | |
633 target_y -= containing_window_frame_.y(); | |
634 break; | |
635 case NPCoordinateSpaceScreen: | |
636 target_y = main_display_bounds.size.height - flipped_screen_y; | |
637 break; | |
638 case NPCoordinateSpaceFlippedScreen: | |
639 break; | |
640 default: | |
641 NOTREACHED(); | |
642 return false; | |
643 } | |
644 | |
645 if (dest_x) | |
646 *dest_x = target_x; | |
647 if (dest_y) | |
648 *dest_y = target_y; | |
649 return true; | |
650 #else | |
651 NOTIMPLEMENTED(); | |
652 return false; | |
653 #endif | |
654 } | |
655 | |
656 void PluginInstance::GetNotifyData( | |
657 int notify_id, bool* notify, void** notify_data) { | |
658 PendingRequestMap::iterator iter = pending_requests_.find(notify_id); | |
659 if (iter != pending_requests_.end()) { | |
660 *notify = true; | |
661 *notify_data = iter->second; | |
662 pending_requests_.erase(iter); | |
663 } else { | |
664 *notify = false; | |
665 *notify_data = NULL; | |
666 } | |
667 } | |
668 | |
669 void PluginInstance::URLRedirectResponse(bool allow, void* notify_data) { | |
670 // The notify_data passed in allows us to identify the matching stream. | |
671 std::vector<scoped_refptr<PluginStream> >::iterator stream_index; | |
672 for (stream_index = open_streams_.begin(); | |
673 stream_index != open_streams_.end(); ++stream_index) { | |
674 PluginStream* plugin_stream = stream_index->get(); | |
675 if (plugin_stream->notify_data() == notify_data) { | |
676 WebPluginResourceClient* resource_client = | |
677 plugin_stream->AsResourceClient(); | |
678 webplugin_->URLRedirectResponse(allow, resource_client->ResourceId()); | |
679 if (allow) { | |
680 plugin_stream->UpdateUrl( | |
681 plugin_stream->pending_redirect_url().c_str()); | |
682 } | |
683 break; | |
684 } | |
685 } | |
686 } | |
687 | |
688 } // namespace npapi | |
689 } // namespace webkit | |
OLD | NEW |