OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 5 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/utf_offset_string_conversions.h" |
13 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
14 #include "ppapi/c/dev/ppb_console_dev.h" | 15 #include "ppapi/c/dev/ppb_console_dev.h" |
15 #include "ppapi/c/dev/ppb_find_dev.h" | 16 #include "ppapi/c/dev/ppb_find_dev.h" |
16 #include "ppapi/c/dev/ppb_memory_dev.h" | 17 #include "ppapi/c/dev/ppb_memory_dev.h" |
17 #include "ppapi/c/dev/ppb_zoom_dev.h" | 18 #include "ppapi/c/dev/ppb_zoom_dev.h" |
18 #include "ppapi/c/dev/ppp_find_dev.h" | 19 #include "ppapi/c/dev/ppp_find_dev.h" |
19 #include "ppapi/c/dev/ppp_mouse_lock_dev.h" | 20 #include "ppapi/c/dev/ppp_mouse_lock_dev.h" |
20 #include "ppapi/c/dev/ppp_policy_update_dev.h" | 21 #include "ppapi/c/dev/ppp_policy_update_dev.h" |
21 #include "ppapi/c/dev/ppp_selection_dev.h" | 22 #include "ppapi/c/dev/ppp_selection_dev.h" |
22 #include "ppapi/c/dev/ppp_zoom_dev.h" | 23 #include "ppapi/c/dev/ppp_zoom_dev.h" |
23 #include "ppapi/c/pp_input_event.h" | 24 #include "ppapi/c/pp_input_event.h" |
24 #include "ppapi/c/pp_instance.h" | 25 #include "ppapi/c/pp_instance.h" |
25 #include "ppapi/c/pp_rect.h" | 26 #include "ppapi/c/pp_rect.h" |
26 #include "ppapi/c/pp_resource.h" | 27 #include "ppapi/c/pp_resource.h" |
27 #include "ppapi/c/pp_var.h" | 28 #include "ppapi/c/pp_var.h" |
28 #include "ppapi/c/ppb_core.h" | 29 #include "ppapi/c/ppb_core.h" |
29 #include "ppapi/c/ppb_instance.h" | 30 #include "ppapi/c/ppb_instance.h" |
30 #include "ppapi/c/ppp_input_event.h" | 31 #include "ppapi/c/ppp_input_event.h" |
31 #include "ppapi/c/ppp_instance.h" | 32 #include "ppapi/c/ppp_instance.h" |
32 #include "ppapi/c/ppp_messaging.h" | 33 #include "ppapi/c/ppp_messaging.h" |
33 #include "ppapi/c/private/ppb_instance_private.h" | 34 #include "ppapi/c/private/ppb_instance_private.h" |
34 #include "ppapi/c/private/ppp_instance_private.h" | 35 #include "ppapi/c/private/ppp_instance_private.h" |
35 #include "ppapi/shared_impl/input_event_impl.h" | 36 #include "ppapi/shared_impl/input_event_impl.h" |
36 #include "ppapi/shared_impl/resource.h" | 37 #include "ppapi/shared_impl/resource.h" |
| 38 #include "ppapi/shared_impl/time_conversion.h" |
37 #include "ppapi/shared_impl/url_util_impl.h" | 39 #include "ppapi/shared_impl/url_util_impl.h" |
38 #include "ppapi/shared_impl/var.h" | 40 #include "ppapi/shared_impl/var.h" |
39 #include "ppapi/thunk/enter.h" | 41 #include "ppapi/thunk/enter.h" |
40 #include "ppapi/thunk/ppb_buffer_api.h" | 42 #include "ppapi/thunk/ppb_buffer_api.h" |
41 #include "printing/units.h" | 43 #include "printing/units.h" |
42 #include "skia/ext/platform_canvas.h" | 44 #include "skia/ext/platform_canvas.h" |
43 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" | 45 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" |
44 #include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h" | 46 #include "third_party/WebKit/Source/WebKit/chromium/public/WebConsoleMessage.h" |
45 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" | 47 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" |
46 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 48 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 typedef bool (*RenderPDFPageToDCProc)( | 129 typedef bool (*RenderPDFPageToDCProc)( |
128 const unsigned char* pdf_buffer, int buffer_size, int page_number, HDC dc, | 130 const unsigned char* pdf_buffer, int buffer_size, int page_number, HDC dc, |
129 int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y, | 131 int dpi_x, int dpi_y, int bounds_origin_x, int bounds_origin_y, |
130 int bounds_width, int bounds_height, bool fit_to_bounds, | 132 int bounds_width, int bounds_height, bool fit_to_bounds, |
131 bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds, | 133 bool stretch_to_bounds, bool keep_aspect_ratio, bool center_in_bounds, |
132 bool autorotate); | 134 bool autorotate); |
133 #endif // defined(OS_WIN) | 135 #endif // defined(OS_WIN) |
134 | 136 |
135 namespace { | 137 namespace { |
136 | 138 |
| 139 #if !defined(TOUCH_UI) |
| 140 // The default text input type is to regard the plugin always accept text input. |
| 141 // This is for allowing users to use input methods even on completely-IME- |
| 142 // unaware plugins (e.g., PPAPI Flash or PDF plugin for M16). |
| 143 // Plugins need to explicitly opt out the text input mode if they know |
| 144 // that they don't accept texts. |
| 145 const ui::TextInputType kPluginDefaultTextInputType = ui::TEXT_INPUT_TYPE_TEXT; |
| 146 #else |
| 147 // On the other hand, for touch ui, accepting text input implies to pop up |
| 148 // virtual keyboard always. It makes IME-unaware plugins almost unusable, |
| 149 // and hence is disabled by default (codereview.chromium.org/7800044). |
| 150 const ui::TextInputType kPluginDefaultTextInputType = ui::TEXT_INPUT_TYPE_NONE; |
| 151 #endif |
| 152 |
137 #define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \ | 153 #define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \ |
138 COMPILE_ASSERT(static_cast<int>(WebCursorInfo::webkit_name) \ | 154 COMPILE_ASSERT(static_cast<int>(WebCursorInfo::webkit_name) \ |
139 == static_cast<int>(np_name), \ | 155 == static_cast<int>(np_name), \ |
140 mismatching_enums) | 156 mismatching_enums) |
141 | 157 |
142 COMPILE_ASSERT_MATCHING_ENUM(TypePointer, PP_CURSORTYPE_POINTER); | 158 COMPILE_ASSERT_MATCHING_ENUM(TypePointer, PP_CURSORTYPE_POINTER); |
143 COMPILE_ASSERT_MATCHING_ENUM(TypeCross, PP_CURSORTYPE_CROSS); | 159 COMPILE_ASSERT_MATCHING_ENUM(TypeCross, PP_CURSORTYPE_CROSS); |
144 COMPILE_ASSERT_MATCHING_ENUM(TypeHand, PP_CURSORTYPE_HAND); | 160 COMPILE_ASSERT_MATCHING_ENUM(TypeHand, PP_CURSORTYPE_HAND); |
145 COMPILE_ASSERT_MATCHING_ENUM(TypeIBeam, PP_CURSORTYPE_IBEAM); | 161 COMPILE_ASSERT_MATCHING_ENUM(TypeIBeam, PP_CURSORTYPE_IBEAM); |
146 COMPILE_ASSERT_MATCHING_ENUM(TypeWait, PP_CURSORTYPE_WAIT); | 162 COMPILE_ASSERT_MATCHING_ENUM(TypeWait, PP_CURSORTYPE_WAIT); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 plugin_graphics_3d_interface_(NULL), | 275 plugin_graphics_3d_interface_(NULL), |
260 always_on_top_(false), | 276 always_on_top_(false), |
261 fullscreen_container_(NULL), | 277 fullscreen_container_(NULL), |
262 flash_fullscreen_(false), | 278 flash_fullscreen_(false), |
263 desired_fullscreen_state_(false), | 279 desired_fullscreen_state_(false), |
264 fullscreen_(false), | 280 fullscreen_(false), |
265 message_channel_(NULL), | 281 message_channel_(NULL), |
266 sad_plugin_(NULL), | 282 sad_plugin_(NULL), |
267 input_event_mask_(0), | 283 input_event_mask_(0), |
268 filtered_input_event_mask_(0), | 284 filtered_input_event_mask_(0), |
| 285 text_input_type_(kPluginDefaultTextInputType), |
| 286 text_input_caret_(0, 0, 0, 0), |
| 287 text_input_caret_bounds_(0, 0, 0, 0), |
| 288 text_input_caret_set_(false), |
269 lock_mouse_callback_(PP_BlockUntilComplete()) { | 289 lock_mouse_callback_(PP_BlockUntilComplete()) { |
270 pp_instance_ = ResourceTracker::Get()->AddInstance(this); | 290 pp_instance_ = ResourceTracker::Get()->AddInstance(this); |
271 | 291 |
272 memset(¤t_print_settings_, 0, sizeof(current_print_settings_)); | 292 memset(¤t_print_settings_, 0, sizeof(current_print_settings_)); |
273 DCHECK(delegate); | 293 DCHECK(delegate); |
274 module_->InstanceCreated(this); | 294 module_->InstanceCreated(this); |
275 delegate_->InstanceCreated(this); | 295 delegate_->InstanceCreated(this); |
276 message_channel_.reset(new MessageChannel(this)); | 296 message_channel_.reset(new MessageChannel(this)); |
277 } | 297 } |
278 | 298 |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 argc, | 488 argc, |
469 argn.get(), | 489 argn.get(), |
470 argv.get())); | 490 argv.get())); |
471 } | 491 } |
472 | 492 |
473 bool PluginInstance::HandleDocumentLoad(PPB_URLLoader_Impl* loader) { | 493 bool PluginInstance::HandleDocumentLoad(PPB_URLLoader_Impl* loader) { |
474 return PP_ToBool(instance_interface_->HandleDocumentLoad( | 494 return PP_ToBool(instance_interface_->HandleDocumentLoad( |
475 pp_instance(), loader->pp_resource())); | 495 pp_instance(), loader->pp_resource())); |
476 } | 496 } |
477 | 497 |
| 498 bool PluginInstance::SendCompositionEventToPlugin(PP_InputEvent_Type type, |
| 499 const string16& text) { |
| 500 std::vector<WebKit::WebCompositionUnderline> empty; |
| 501 return SendCompositionEventWithUnderlineInformationToPlugin( |
| 502 type, text, empty, static_cast<int>(text.size()), |
| 503 static_cast<int>(text.size())); |
| 504 } |
| 505 |
| 506 bool PluginInstance::SendCompositionEventWithUnderlineInformationToPlugin( |
| 507 PP_InputEvent_Type type, |
| 508 const string16& text, |
| 509 const std::vector<WebKit::WebCompositionUnderline>& underlines, |
| 510 int selection_start, |
| 511 int selection_end) { |
| 512 // Keep a reference on the stack. See NOTE above. |
| 513 scoped_refptr<PluginInstance> ref(this); |
| 514 |
| 515 if (!LoadInputEventInterface()) |
| 516 return false; |
| 517 |
| 518 PP_InputEvent_Class event_class = PP_INPUTEVENT_CLASS_IME; |
| 519 if (!(filtered_input_event_mask_ & event_class) && |
| 520 !(input_event_mask_ & event_class)) |
| 521 return false; |
| 522 |
| 523 ::ppapi::InputEventData event; |
| 524 event.event_type = type; |
| 525 event.event_time_stamp = ::ppapi::TimeTicksToPPTimeTicks( |
| 526 base::TimeTicks::Now()); |
| 527 |
| 528 // Convert UTF16 text to UTF8 with offset conversion. |
| 529 std::vector<size_t> utf16_offsets; |
| 530 utf16_offsets.push_back(selection_start); |
| 531 utf16_offsets.push_back(selection_end); |
| 532 for (size_t i = 0; i < underlines.size(); ++i) { |
| 533 utf16_offsets.push_back(underlines[i].startOffset); |
| 534 utf16_offsets.push_back(underlines[i].endOffset); |
| 535 } |
| 536 std::vector<size_t> utf8_offsets(utf16_offsets); |
| 537 event.character_text = UTF16ToUTF8AndAdjustOffsets(text, &utf8_offsets); |
| 538 |
| 539 // Set the converted selection range. |
| 540 event.composition_selection_start = (utf8_offsets[0] == std::string::npos ? |
| 541 event.character_text.size() : utf8_offsets[0]); |
| 542 event.composition_selection_end = (utf8_offsets[1] == std::string::npos ? |
| 543 event.character_text.size() : utf8_offsets[1]); |
| 544 |
| 545 // Set the converted segmentation points. |
| 546 // Be sure to add 0 and size(), and remove duplication or errors. |
| 547 std::set<size_t> offset_set(utf8_offsets.begin()+2, utf8_offsets.end()); |
| 548 offset_set.insert(0); |
| 549 offset_set.insert(event.character_text.size()); |
| 550 offset_set.erase(std::string::npos); |
| 551 event.composition_segment_offsets.assign(offset_set.begin(), |
| 552 offset_set.end()); |
| 553 |
| 554 // Set the composition target. |
| 555 for (size_t i = 0; i < underlines.size(); ++i) { |
| 556 if (underlines[i].thick) { |
| 557 std::vector<uint32_t>::iterator it = |
| 558 std::find(event.composition_segment_offsets.begin(), |
| 559 event.composition_segment_offsets.end(), |
| 560 utf8_offsets[2*i+2]); |
| 561 if (it != event.composition_segment_offsets.end()) { |
| 562 event.composition_target_segment = |
| 563 it - event.composition_segment_offsets.begin(); |
| 564 break; |
| 565 } |
| 566 } |
| 567 } |
| 568 |
| 569 // Send the event. |
| 570 bool handled = false; |
| 571 if (filtered_input_event_mask_ & event_class) |
| 572 event.is_filtered = true; |
| 573 else |
| 574 handled = true; // Unfiltered events are assumed to be handled. |
| 575 scoped_refptr<InputEventImpl> event_resource( |
| 576 new InputEventImpl(InputEventImpl::InitAsImpl(), |
| 577 pp_instance(), event)); |
| 578 handled |= PP_ToBool(plugin_input_event_interface_->HandleInputEvent( |
| 579 pp_instance(), event_resource->pp_resource())); |
| 580 return handled; |
| 581 } |
| 582 |
| 583 bool PluginInstance::HandleCompositionStart(const string16& text) { |
| 584 return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_COMPOSITION_START, |
| 585 text); |
| 586 } |
| 587 |
| 588 bool PluginInstance::HandleCompositionUpdate( |
| 589 const string16& text, |
| 590 const std::vector<WebKit::WebCompositionUnderline>& underlines, |
| 591 int selection_start, |
| 592 int selection_end) { |
| 593 return SendCompositionEventWithUnderlineInformationToPlugin( |
| 594 PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE, |
| 595 text, underlines, selection_start, selection_end); |
| 596 } |
| 597 |
| 598 bool PluginInstance::HandleCompositionEnd(const string16& text) { |
| 599 return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_COMPOSITION_END, |
| 600 text); |
| 601 } |
| 602 |
| 603 bool PluginInstance::HandleTextInput(const string16& text) { |
| 604 return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_TEXT, |
| 605 text); |
| 606 } |
| 607 |
| 608 void PluginInstance::UpdateCaretPosition(const gfx::Rect& caret, |
| 609 const gfx::Rect& bounding_box) { |
| 610 text_input_caret_ = caret; |
| 611 text_input_caret_bounds_ = bounding_box; |
| 612 text_input_caret_set_ = true; |
| 613 } |
| 614 |
| 615 void PluginInstance::SetTextInputType(ui::TextInputType type) { |
| 616 text_input_type_ = type; |
| 617 } |
| 618 |
| 619 bool PluginInstance::IsPluginAcceptingCompositionEvents() const { |
| 620 return (filtered_input_event_mask_ & PP_INPUTEVENT_CLASS_IME) || |
| 621 (input_event_mask_ & PP_INPUTEVENT_CLASS_IME); |
| 622 } |
| 623 |
| 624 gfx::Rect PluginInstance::GetCaretBounds() const { |
| 625 if (!text_input_caret_set_) { |
| 626 // If it is never set by the plugin, use the bottom left corner. |
| 627 return gfx::Rect(position().x(), position().y()+position().height(), 0, 0); |
| 628 } |
| 629 |
| 630 // TODO(kinaba) Take CSS transformation into accont. |
| 631 // TODO(kinaba) Take bounding_box into account. On some platforms, an |
| 632 // "exclude rectangle" where candidate window must avoid the region can be |
| 633 // passed to IME. Currently, we pass only the caret rectangle because |
| 634 // it is the only information supported uniformly in Chromium. |
| 635 gfx::Rect caret(text_input_caret_); |
| 636 caret.Offset(position().origin()); |
| 637 return caret; |
| 638 } |
| 639 |
478 bool PluginInstance::HandleInputEvent(const WebKit::WebInputEvent& event, | 640 bool PluginInstance::HandleInputEvent(const WebKit::WebInputEvent& event, |
479 WebCursorInfo* cursor_info) { | 641 WebCursorInfo* cursor_info) { |
480 TRACE_EVENT0("ppapi", "PluginInstance::HandleInputEvent"); | 642 TRACE_EVENT0("ppapi", "PluginInstance::HandleInputEvent"); |
481 | 643 |
482 if (WebInputEvent::isMouseEventType(event.type)) | 644 if (WebInputEvent::isMouseEventType(event.type)) |
483 delegate()->DidReceiveMouseEvent(this); | 645 delegate()->DidReceiveMouseEvent(this); |
484 | 646 |
485 // Don't dispatch input events to crashed plugins. | 647 // Don't dispatch input events to crashed plugins. |
486 if (module()->is_crashed()) | 648 if (module()->is_crashed()) |
487 return false; | 649 return false; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 instance_interface_->DidChangeView(pp_instance(), &pp_position, &pp_clip); | 738 instance_interface_->DidChangeView(pp_instance(), &pp_position, &pp_clip); |
577 } | 739 } |
578 | 740 |
579 void PluginInstance::SetWebKitFocus(bool has_focus) { | 741 void PluginInstance::SetWebKitFocus(bool has_focus) { |
580 if (has_webkit_focus_ == has_focus) | 742 if (has_webkit_focus_ == has_focus) |
581 return; | 743 return; |
582 | 744 |
583 bool old_plugin_focus = PluginHasFocus(); | 745 bool old_plugin_focus = PluginHasFocus(); |
584 has_webkit_focus_ = has_focus; | 746 has_webkit_focus_ = has_focus; |
585 if (PluginHasFocus() != old_plugin_focus) { | 747 if (PluginHasFocus() != old_plugin_focus) { |
586 delegate()->PluginFocusChanged(PluginHasFocus()); | 748 delegate()->PluginFocusChanged(this, PluginHasFocus()); |
587 instance_interface_->DidChangeFocus(pp_instance(), | 749 instance_interface_->DidChangeFocus(pp_instance(), |
588 PP_FromBool(PluginHasFocus())); | 750 PP_FromBool(PluginHasFocus())); |
589 } | 751 } |
590 } | 752 } |
591 | 753 |
592 void PluginInstance::SetContentAreaFocus(bool has_focus) { | 754 void PluginInstance::SetContentAreaFocus(bool has_focus) { |
593 if (has_content_area_focus_ == has_focus) | 755 if (has_content_area_focus_ == has_focus) |
594 return; | 756 return; |
595 | 757 |
596 bool old_plugin_focus = PluginHasFocus(); | 758 bool old_plugin_focus = PluginHasFocus(); |
(...skipping 1209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1806 } | 1968 } |
1807 WebKit::WebDocument main_document = | 1969 WebKit::WebDocument main_document = |
1808 containing_document.frame()->view()->mainFrame()->document(); | 1970 containing_document.frame()->view()->mainFrame()->document(); |
1809 | 1971 |
1810 return containing_document.securityOrigin().canAccess( | 1972 return containing_document.securityOrigin().canAccess( |
1811 main_document.securityOrigin()); | 1973 main_document.securityOrigin()); |
1812 } | 1974 } |
1813 | 1975 |
1814 } // namespace ppapi | 1976 } // namespace ppapi |
1815 } // namespace webkit | 1977 } // namespace webkit |
OLD | NEW |