| Index: webkit/plugins/ppapi/ppapi_plugin_instance.cc
 | 
| diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.cc b/webkit/plugins/ppapi/ppapi_plugin_instance.cc
 | 
| index 13934ef761f10b440e46256cb73e6b88faeef2fa..703176e370abc7651897d96bc95c5e78c296e639 100644
 | 
| --- a/webkit/plugins/ppapi/ppapi_plugin_instance.cc
 | 
| +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.cc
 | 
| @@ -8,6 +8,7 @@
 | 
|  #include "base/memory/scoped_ptr.h"
 | 
|  #include "base/message_loop.h"
 | 
|  #include "base/metrics/histogram.h"
 | 
| +#include "base/utf_offset_string_conversions.h"
 | 
|  #include "base/utf_string_conversions.h"
 | 
|  #include "ppapi/c/dev/ppb_console_dev.h"
 | 
|  #include "ppapi/c/dev/ppb_find_dev.h"
 | 
| @@ -32,6 +33,7 @@
 | 
|  #include "ppapi/c/private/ppp_instance_private.h"
 | 
|  #include "ppapi/shared_impl/input_event_impl.h"
 | 
|  #include "ppapi/shared_impl/resource.h"
 | 
| +#include "ppapi/shared_impl/time_conversion.h"
 | 
|  #include "ppapi/shared_impl/var.h"
 | 
|  #include "ppapi/thunk/enter.h"
 | 
|  #include "ppapi/thunk/ppb_buffer_api.h"
 | 
| @@ -244,7 +246,11 @@ PluginInstance::PluginInstance(
 | 
|        sad_plugin_(NULL),
 | 
|        input_event_mask_(0),
 | 
|        filtered_input_event_mask_(0),
 | 
| +      text_input_type_(WebKit::WebTextInputTypeText),
 | 
| +      text_input_caret_set_(false),
 | 
|        lock_mouse_callback_(PP_BlockUntilComplete()) {
 | 
| +  memset(&text_input_caret_, 0, sizeof(text_input_caret_));
 | 
| +  memset(&text_input_caret_bounds_, 0, sizeof(text_input_caret_bounds_));
 | 
|    pp_instance_ = ResourceTracker::Get()->AddInstance(this);
 | 
|  
 | 
|    memset(¤t_print_settings_, 0, sizeof(current_print_settings_));
 | 
| @@ -447,6 +453,148 @@ bool PluginInstance::HandleDocumentLoad(PPB_URLLoader_Impl* loader) {
 | 
|        pp_instance(), loader->pp_resource()));
 | 
|  }
 | 
|  
 | 
| +bool PluginInstance::SendCompositionEventToPlugin(PP_InputEvent_Type type,
 | 
| +                                                  const string16& text) {
 | 
| +  std::vector<WebKit::WebCompositionUnderline> empty;
 | 
| +  return SendCompositionEventWithUnderlineInformationToPlugin(
 | 
| +      type, text, empty, static_cast<int>(text.size()),
 | 
| +      static_cast<int>(text.size()));
 | 
| +}
 | 
| +
 | 
| +bool PluginInstance::SendCompositionEventWithUnderlineInformationToPlugin(
 | 
| +    PP_InputEvent_Type type,
 | 
| +    const string16& text,
 | 
| +    const std::vector<WebKit::WebCompositionUnderline>& underlines,
 | 
| +    int selection_start,
 | 
| +    int selection_end) {
 | 
| +  // Keep a reference on the stack. See NOTE above.
 | 
| +  scoped_refptr<PluginInstance> ref(this);
 | 
| +
 | 
| +  if (!LoadInputEventInterface())
 | 
| +    return false;
 | 
| +
 | 
| +  PP_InputEvent_Class event_class = PP_INPUTEVENT_CLASS_IME;
 | 
| +  if (!(filtered_input_event_mask_ & event_class) &&
 | 
| +      !(input_event_mask_ & event_class))
 | 
| +    return false;
 | 
| +
 | 
| +  ::ppapi::InputEventData event;
 | 
| +  event.event_type = type;
 | 
| +  event.event_time_stamp = ::ppapi::TimeTicksToPPTimeTicks(
 | 
| +      base::TimeTicks::Now());
 | 
| +
 | 
| +  // Convert UTF16 text to UTF8 with offset conversion.
 | 
| +  std::vector<size_t> utf16_offsets;
 | 
| +  utf16_offsets.push_back(selection_start);
 | 
| +  utf16_offsets.push_back(selection_end);
 | 
| +  for (size_t i=0; i<underlines.size(); ++i) {
 | 
| +    utf16_offsets.push_back(underlines[i].startOffset);
 | 
| +    utf16_offsets.push_back(underlines[i].endOffset);
 | 
| +  }
 | 
| +  std::vector<size_t> utf8_offsets(utf16_offsets);
 | 
| +  event.character_text = UTF16ToUTF8AndAdjustOffsets(text, &utf8_offsets);
 | 
| +
 | 
| +  // Set the converted selection range.
 | 
| +  event.composition_selection_start = (utf8_offsets[0]==std::string::npos ?
 | 
| +      event.character_text.size() : utf8_offsets[0]);
 | 
| +  event.composition_selection_end = (utf8_offsets[1]==std::string::npos ?
 | 
| +      event.character_text.size() : utf8_offsets[1]);
 | 
| +
 | 
| +  // Set the converted segmentation points.
 | 
| +  // Be sure to add 0 and size(), and remove duplication or errors.
 | 
| +  std::set<size_t> offset_set(utf8_offsets.begin()+2, utf8_offsets.end());
 | 
| +  offset_set.insert(0);
 | 
| +  offset_set.insert(event.character_text.size());
 | 
| +  offset_set.erase(std::string::npos);
 | 
| +  event.composition_segments.assign(offset_set.begin(), offset_set.end());
 | 
| +
 | 
| +  // Set the composition target.
 | 
| +  for (size_t i=0; i<underlines.size(); ++i) {
 | 
| +    if (underlines[i].thick) {
 | 
| +      std::vector<uint32_t>::iterator it =
 | 
| +          std::find(event.composition_segments.begin(),
 | 
| +                    event.composition_segments.end(),
 | 
| +                    utf8_offsets[2*i+2]);
 | 
| +      if (it != event.composition_segments.end()) {
 | 
| +        event.composition_target_segment =
 | 
| +            it - event.composition_segments.begin();
 | 
| +        break;
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  // Send the event.
 | 
| +  if (filtered_input_event_mask_ & event_class)
 | 
| +    event.is_filtered = true;
 | 
| +  scoped_refptr<InputEventImpl> event_resource(
 | 
| +      new InputEventImpl(InputEventImpl::InitAsImpl(),
 | 
| +                         pp_instance(), event));
 | 
| +  return PP_ToBool(plugin_input_event_interface_->HandleInputEvent(
 | 
| +      pp_instance(), event_resource->pp_resource()));
 | 
| +}
 | 
| +
 | 
| +bool PluginInstance::HandleCompositionStart(const string16& text) {
 | 
| +  return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_COMPOSITION_START,
 | 
| +                                      text);
 | 
| +}
 | 
| +
 | 
| +bool PluginInstance::HandleCompositionUpdate(
 | 
| +    const string16& text,
 | 
| +    const std::vector<WebKit::WebCompositionUnderline>& underlines,
 | 
| +    int selection_start,
 | 
| +    int selection_end) {
 | 
| +  return SendCompositionEventWithUnderlineInformationToPlugin(
 | 
| +      PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE,
 | 
| +      text, underlines, selection_start, selection_end);
 | 
| +}
 | 
| +
 | 
| +bool PluginInstance::HandleCompositionEnd(const string16& text) {
 | 
| +  return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_COMPOSITION_END,
 | 
| +                                      text);
 | 
| +}
 | 
| +
 | 
| +bool PluginInstance::HandleTextInput(const string16& text) {
 | 
| +  return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_TEXT,
 | 
| +                                      text);
 | 
| +}
 | 
| +
 | 
| +void PluginInstance::UpdateCaretPosition(const PP_Rect& caret,
 | 
| +                                         const PP_Rect& boundingBox) {
 | 
| +  text_input_caret_ = caret;
 | 
| +  text_input_caret_bounds_ = boundingBox;
 | 
| +  text_input_caret_set_ = true;
 | 
| +}
 | 
| +
 | 
| +void PluginInstance::SetTextInputType(WebKit::WebTextInputType type) {
 | 
| +  text_input_type_ = type;
 | 
| +}
 | 
| +
 | 
| +bool PluginInstance::CanComposeInline() const {
 | 
| +  return (filtered_input_event_mask_ & PP_INPUTEVENT_CLASS_IME) ||
 | 
| +      (input_event_mask_ & PP_INPUTEVENT_CLASS_IME);
 | 
| +}
 | 
| +
 | 
| +WebKit::WebRect PluginInstance::GetCaretBounds() const {
 | 
| +  if (!text_input_caret_set_) {
 | 
| +    // If it is never set by the plugin, use the bottom left corner.
 | 
| +    WebKit::WebRect caret(position().x(),
 | 
| +                          position().y(),
 | 
| +                          0,
 | 
| +                          position().height());
 | 
| +    return caret;
 | 
| +  }
 | 
| +
 | 
| +  // TODO(kinaba) take bounds into account
 | 
| +  // TODO(kinaba) take CSS transformation into accont
 | 
| +  WebKit::WebRect caret(text_input_caret_.point.x,
 | 
| +                        text_input_caret_.point.y,
 | 
| +                        text_input_caret_.size.width,
 | 
| +                        text_input_caret_.size.height);
 | 
| +  caret.x += position().x();
 | 
| +  caret.y += position().y();
 | 
| +  return caret;
 | 
| +}
 | 
| +
 | 
|  bool PluginInstance::HandleInputEvent(const WebKit::WebInputEvent& event,
 | 
|                                        WebCursorInfo* cursor_info) {
 | 
|    // Don't dispatch input events to crashed plugins.
 | 
| @@ -548,7 +696,7 @@ void PluginInstance::SetWebKitFocus(bool has_focus) {
 | 
|    bool old_plugin_focus = PluginHasFocus();
 | 
|    has_webkit_focus_ = has_focus;
 | 
|    if (PluginHasFocus() != old_plugin_focus) {
 | 
| -    delegate()->PluginFocusChanged(PluginHasFocus());
 | 
| +    delegate()->PluginFocusChanged(this, PluginHasFocus());
 | 
|      instance_interface_->DidChangeFocus(pp_instance(),
 | 
|                                          PP_FromBool(PluginHasFocus()));
 | 
|    }
 | 
| 
 |