OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "build/build_config.h" | 5 #include "build/build_config.h" |
6 | 6 |
7 #include "webkit/glue/plugins/plugin_instance.h" | 7 #include "webkit/glue/plugins/plugin_instance.h" |
8 | 8 |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 transparent_(true), | 31 transparent_(true), |
32 webplugin_(0), | 32 webplugin_(0), |
33 mime_type_(mime_type), | 33 mime_type_(mime_type), |
34 use_mozilla_user_agent_(false), | 34 use_mozilla_user_agent_(false), |
35 #if defined (OS_MACOSX) | 35 #if defined (OS_MACOSX) |
36 drawing_model_(0), | 36 drawing_model_(0), |
37 event_model_(0), | 37 event_model_(0), |
38 #endif | 38 #endif |
39 message_loop_(MessageLoop::current()), | 39 message_loop_(MessageLoop::current()), |
40 load_manually_(false), | 40 load_manually_(false), |
41 in_close_streams_(false) { | 41 in_close_streams_(false), |
| 42 next_timer_id_(1) { |
42 npp_ = new NPP_t(); | 43 npp_ = new NPP_t(); |
43 npp_->ndata = 0; | 44 npp_->ndata = 0; |
44 npp_->pdata = 0; | 45 npp_->pdata = 0; |
45 | 46 |
46 memset(&zero_padding_, 0, sizeof(zero_padding_)); | 47 memset(&zero_padding_, 0, sizeof(zero_padding_)); |
47 DCHECK(message_loop_); | 48 DCHECK(message_loop_); |
48 } | 49 } |
49 | 50 |
50 PluginInstance::~PluginInstance() { | 51 PluginInstance::~PluginInstance() { |
51 CloseStreams(); | 52 CloseStreams(); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 | 150 |
150 if (npp_functions_->newp != 0) { | 151 if (npp_functions_->newp != 0) { |
151 return npp_functions_->newp( | 152 return npp_functions_->newp( |
152 (NPMIMEType)mime_type_.c_str(), npp_, mode, argc, argn, argv, NULL); | 153 (NPMIMEType)mime_type_.c_str(), npp_, mode, argc, argn, argv, NULL); |
153 } | 154 } |
154 return NPERR_INVALID_FUNCTABLE_ERROR; | 155 return NPERR_INVALID_FUNCTABLE_ERROR; |
155 } | 156 } |
156 | 157 |
157 void PluginInstance::NPP_Destroy() { | 158 void PluginInstance::NPP_Destroy() { |
158 DCHECK(npp_functions_ != 0); | 159 DCHECK(npp_functions_ != 0); |
159 DCHECK(npp_functions_->newp != 0); | 160 DCHECK(npp_functions_->destroy != 0); |
160 | 161 |
161 if (npp_functions_->destroy != 0) { | 162 if (npp_functions_->destroy != 0) { |
162 NPSavedData *savedData = 0; | 163 NPSavedData *savedData = 0; |
163 npp_functions_->destroy(npp_, &savedData); | 164 npp_functions_->destroy(npp_, &savedData); |
164 | 165 |
165 // TODO: Support savedData. Technically, these need to be | 166 // TODO: Support savedData. Technically, these need to be |
166 // saved on a per-URL basis, and then only passed | 167 // saved on a per-URL basis, and then only passed |
167 // to new instances of the plugin at the same URL. | 168 // to new instances of the plugin at the same URL. |
168 // Sounds like a huge security risk. When we do support | 169 // Sounds like a huge security risk. When we do support |
169 // these, we should pass them back to the PluginLib | 170 // these, we should pass them back to the PluginLib |
170 // to be stored there. | 171 // to be stored there. |
171 DCHECK(savedData == 0); | 172 DCHECK(savedData == 0); |
172 } | 173 } |
173 | 174 |
174 for (unsigned int file_index = 0; file_index < files_created_.size(); | 175 for (unsigned int file_index = 0; file_index < files_created_.size(); |
175 file_index++) { | 176 file_index++) { |
176 file_util::Delete(files_created_[file_index], false); | 177 file_util::Delete(files_created_[file_index], false); |
177 } | 178 } |
| 179 |
| 180 // Ensure that no timer callbacks are invoked after NPP_Destroy. |
| 181 timers_.clear(); |
178 } | 182 } |
179 | 183 |
180 NPError PluginInstance::NPP_SetWindow(NPWindow *window) { | 184 NPError PluginInstance::NPP_SetWindow(NPWindow *window) { |
181 DCHECK(npp_functions_ != 0); | 185 DCHECK(npp_functions_ != 0); |
182 DCHECK(npp_functions_->setwindow != 0); | 186 DCHECK(npp_functions_->setwindow != 0); |
183 | 187 |
184 if (npp_functions_->setwindow != 0) { | 188 if (npp_functions_->setwindow != 0) { |
185 return npp_functions_->setwindow(npp_, window); | 189 return npp_functions_->setwindow(npp_, window); |
186 } | 190 } |
187 return NPERR_INVALID_FUNCTABLE_ERROR; | 191 return NPERR_INVALID_FUNCTABLE_ERROR; |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 } | 358 } |
355 | 359 |
356 void PluginInstance::PluginThreadAsyncCall(void (*func)(void *), | 360 void PluginInstance::PluginThreadAsyncCall(void (*func)(void *), |
357 void *user_data) { | 361 void *user_data) { |
358 message_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 362 message_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
359 this, &PluginInstance::OnPluginThreadAsyncCall, func, user_data)); | 363 this, &PluginInstance::OnPluginThreadAsyncCall, func, user_data)); |
360 } | 364 } |
361 | 365 |
362 void PluginInstance::OnPluginThreadAsyncCall(void (*func)(void *), | 366 void PluginInstance::OnPluginThreadAsyncCall(void (*func)(void *), |
363 void *user_data) { | 367 void *user_data) { |
364 #if defined(OS_WIN) | 368 func(user_data); |
365 // We are invoking an arbitrary callback provided by a third | 369 } |
366 // party plugin. It's better to wrap this into an exception | 370 |
367 // block to protect us from crashes. | 371 uint32 PluginInstance::ScheduleTimer(uint32 interval, |
368 __try { | 372 NPBool repeat, |
369 func(user_data); | 373 void (*func)(NPP id, uint32 timer_id)) { |
370 } __except(EXCEPTION_EXECUTE_HANDLER) { | 374 // Use next timer id. |
371 // Maybe we can disable a crashing plugin. | 375 uint32 timer_id; |
372 // But for now, just continue. | 376 timer_id = next_timer_id_; |
| 377 ++next_timer_id_; |
| 378 DCHECK(next_timer_id_ != 0); |
| 379 |
| 380 // Record timer interval and repeat. |
| 381 TimerInfo info; |
| 382 info.interval = interval; |
| 383 info.repeat = repeat; |
| 384 timers_[timer_id] = info; |
| 385 |
| 386 // Schedule the callback. |
| 387 message_loop_->PostDelayedTask(FROM_HERE, |
| 388 NewRunnableMethod(this, |
| 389 &PluginInstance::OnTimerCall, |
| 390 func, |
| 391 npp_, |
| 392 timer_id), |
| 393 interval); |
| 394 return timer_id; |
| 395 } |
| 396 |
| 397 void PluginInstance::UnscheduleTimer(uint32 timer_id) { |
| 398 // Remove info about the timer. |
| 399 TimerMap::iterator it = timers_.find(timer_id); |
| 400 if (it != timers_.end()) |
| 401 timers_.erase(it); |
| 402 } |
| 403 |
| 404 void PluginInstance::OnTimerCall(void (*func)(NPP id, uint32 timer_id), |
| 405 NPP id, |
| 406 uint32 timer_id) { |
| 407 // Do not invoke callback if the timer has been unscheduled. |
| 408 TimerMap::iterator it = timers_.find(timer_id); |
| 409 if (it == timers_.end()) |
| 410 return; |
| 411 |
| 412 // Get all information about the timer before invoking the callback. The |
| 413 // callback might unschedule the timer. |
| 414 TimerInfo info = it->second; |
| 415 |
| 416 func(id, timer_id); |
| 417 |
| 418 // If the timer was unscheduled by the callback, just free up the timer id. |
| 419 if (timers_.find(timer_id) == timers_.end()) |
| 420 return; |
| 421 |
| 422 // Reschedule repeating timers after invoking the callback so callback is not |
| 423 // re-entered if it pumps the messager loop. |
| 424 if (info.repeat) { |
| 425 message_loop_->PostDelayedTask(FROM_HERE, |
| 426 NewRunnableMethod( |
| 427 this, |
| 428 &PluginInstance::OnTimerCall, |
| 429 func, |
| 430 npp_, |
| 431 timer_id), |
| 432 info.interval); |
| 433 } else { |
| 434 timers_.erase(it); |
373 } | 435 } |
374 #else | |
375 func(user_data); | |
376 #endif | |
377 } | 436 } |
378 | 437 |
379 void PluginInstance::PushPopupsEnabledState(bool enabled) { | 438 void PluginInstance::PushPopupsEnabledState(bool enabled) { |
380 popups_enabled_stack_.push(enabled); | 439 popups_enabled_stack_.push(enabled); |
381 } | 440 } |
382 | 441 |
383 void PluginInstance::PopPopupsEnabledState() { | 442 void PluginInstance::PopPopupsEnabledState() { |
384 popups_enabled_stack_.pop(); | 443 popups_enabled_stack_.pop(); |
385 } | 444 } |
386 | 445 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 stream->url, range_info.c_str(), | 482 stream->url, range_info.c_str(), |
424 reinterpret_cast<intptr_t>(plugin_stream), | 483 reinterpret_cast<intptr_t>(plugin_stream), |
425 plugin_stream->notify_needed(), | 484 plugin_stream->notify_needed(), |
426 reinterpret_cast<intptr_t>(plugin_stream->notify_data())); | 485 reinterpret_cast<intptr_t>(plugin_stream->notify_data())); |
427 break; | 486 break; |
428 } | 487 } |
429 } | 488 } |
430 } | 489 } |
431 | 490 |
432 } // namespace NPAPI | 491 } // namespace NPAPI |
OLD | NEW |