Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / shell / renderer / test_runner / text_input_controller.cc
1 // Copyright 2014 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 "content/shell/renderer/test_runner/text_input_controller.h"
6
7 #include "gin/arguments.h"
8 #include "gin/handle.h"
9 #include "gin/object_template_builder.h"
10 #include "gin/wrappable.h"
11 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
12 #include "third_party/WebKit/public/web/WebFrame.h"
13 #include "third_party/WebKit/public/web/WebInputEvent.h"
14 #include "third_party/WebKit/public/web/WebKit.h"
15 #include "third_party/WebKit/public/web/WebRange.h"
16 #include "third_party/WebKit/public/web/WebView.h"
17 #include "v8/include/v8.h"
18
19 namespace content {
20
21 class TextInputControllerBindings
22     : public gin::Wrappable<TextInputControllerBindings> {
23  public:
24   static gin::WrapperInfo kWrapperInfo;
25
26   static void Install(base::WeakPtr<TextInputController> controller,
27                       blink::WebFrame* frame);
28
29  private:
30   explicit TextInputControllerBindings(
31       base::WeakPtr<TextInputController> controller);
32   virtual ~TextInputControllerBindings();
33
34   // gin::Wrappable:
35   virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
36       v8::Isolate* isolate) OVERRIDE;
37
38   void InsertText(const std::string& text);
39   void UnmarkText();
40   void DoCommand(const std::string& text);
41   void SetMarkedText(const std::string& text, int start, int length);
42   bool HasMarkedText();
43   std::vector<int> MarkedRange();
44   std::vector<int> SelectedRange();
45   std::vector<int> FirstRectForCharacterRange(unsigned location,
46                                               unsigned length);
47   void SetComposition(const std::string& text);
48
49   base::WeakPtr<TextInputController> controller_;
50
51   DISALLOW_COPY_AND_ASSIGN(TextInputControllerBindings);
52 };
53
54 gin::WrapperInfo TextInputControllerBindings::kWrapperInfo = {
55     gin::kEmbedderNativeGin};
56
57 // static
58 void TextInputControllerBindings::Install(
59     base::WeakPtr<TextInputController> controller,
60     blink::WebFrame* frame) {
61   v8::Isolate* isolate = blink::mainThreadIsolate();
62   v8::HandleScope handle_scope(isolate);
63   v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
64   if (context.IsEmpty())
65     return;
66
67   v8::Context::Scope context_scope(context);
68
69   gin::Handle<TextInputControllerBindings> bindings =
70       gin::CreateHandle(isolate, new TextInputControllerBindings(controller));
71   if (bindings.IsEmpty())
72     return;
73   v8::Handle<v8::Object> global = context->Global();
74   global->Set(gin::StringToV8(isolate, "textInputController"), bindings.ToV8());
75 }
76
77 TextInputControllerBindings::TextInputControllerBindings(
78     base::WeakPtr<TextInputController> controller)
79     : controller_(controller) {}
80
81 TextInputControllerBindings::~TextInputControllerBindings() {}
82
83 gin::ObjectTemplateBuilder
84 TextInputControllerBindings::GetObjectTemplateBuilder(v8::Isolate* isolate) {
85   return gin::Wrappable<TextInputControllerBindings>::GetObjectTemplateBuilder(
86              isolate)
87       .SetMethod("insertText", &TextInputControllerBindings::InsertText)
88       .SetMethod("unmarkText", &TextInputControllerBindings::UnmarkText)
89       .SetMethod("doCommand", &TextInputControllerBindings::DoCommand)
90       .SetMethod("setMarkedText", &TextInputControllerBindings::SetMarkedText)
91       .SetMethod("hasMarkedText", &TextInputControllerBindings::HasMarkedText)
92       .SetMethod("markedRange", &TextInputControllerBindings::MarkedRange)
93       .SetMethod("selectedRange", &TextInputControllerBindings::SelectedRange)
94       .SetMethod("firstRectForCharacterRange",
95                  &TextInputControllerBindings::FirstRectForCharacterRange)
96       .SetMethod("setComposition",
97                  &TextInputControllerBindings::SetComposition);
98 }
99
100 void TextInputControllerBindings::InsertText(const std::string& text) {
101   if (controller_)
102     controller_->InsertText(text);
103 }
104
105 void TextInputControllerBindings::UnmarkText() {
106   if (controller_)
107     controller_->UnmarkText();
108 }
109
110 void TextInputControllerBindings::DoCommand(const std::string& text) {
111   if (controller_)
112     controller_->DoCommand(text);
113 }
114
115 void TextInputControllerBindings::SetMarkedText(const std::string& text,
116                                                 int start,
117                                                 int length) {
118   if (controller_)
119     controller_->SetMarkedText(text, start, length);
120 }
121
122 bool TextInputControllerBindings::HasMarkedText() {
123   return controller_ ? controller_->HasMarkedText() : false;
124 }
125
126 std::vector<int> TextInputControllerBindings::MarkedRange() {
127   return controller_ ? controller_->MarkedRange() : std::vector<int>();
128 }
129
130 std::vector<int> TextInputControllerBindings::SelectedRange() {
131   return controller_ ? controller_->SelectedRange() : std::vector<int>();
132 }
133
134 std::vector<int> TextInputControllerBindings::FirstRectForCharacterRange(
135     unsigned location,
136     unsigned length) {
137   return controller_ ? controller_->FirstRectForCharacterRange(location, length)
138                      : std::vector<int>();
139 }
140
141 void TextInputControllerBindings::SetComposition(const std::string& text) {
142   if (controller_)
143     controller_->SetComposition(text);
144 }
145
146 // TextInputController ---------------------------------------------------------
147
148 TextInputController::TextInputController()
149     : view_(NULL), weak_factory_(this) {}
150
151 TextInputController::~TextInputController() {}
152
153 void TextInputController::Install(blink::WebFrame* frame) {
154   TextInputControllerBindings::Install(weak_factory_.GetWeakPtr(), frame);
155 }
156
157 void TextInputController::SetWebView(blink::WebView* view) {
158   view_ = view;
159 }
160
161 void TextInputController::InsertText(const std::string& text) {
162   view_->confirmComposition(blink::WebString::fromUTF8(text));
163 }
164
165 void TextInputController::UnmarkText() {
166   view_->confirmComposition();
167 }
168
169 void TextInputController::DoCommand(const std::string& text) {
170   if (view_->mainFrame())
171     view_->mainFrame()->executeCommand(blink::WebString::fromUTF8(text));
172 }
173
174 void TextInputController::SetMarkedText(const std::string& text,
175                                         int start,
176                                         int length) {
177   blink::WebString web_text(blink::WebString::fromUTF8(text));
178
179   // Split underline into up to 3 elements (before, selection, and after).
180   std::vector<blink::WebCompositionUnderline> underlines;
181   blink::WebCompositionUnderline underline;
182   if (!start) {
183     underline.endOffset = length;
184   } else {
185     underline.endOffset = start;
186     underlines.push_back(underline);
187     underline.startOffset = start;
188     underline.endOffset = start + length;
189   }
190   underline.thick = true;
191   underlines.push_back(underline);
192   if (start + length < static_cast<int>(web_text.length())) {
193     underline.startOffset = underline.endOffset;
194     underline.endOffset = web_text.length();
195     underline.thick = false;
196     underlines.push_back(underline);
197   }
198
199   view_->setComposition(web_text, underlines, start, start + length);
200 }
201
202 bool TextInputController::HasMarkedText() {
203   return view_->mainFrame() && view_->mainFrame()->hasMarkedText();
204 }
205
206 std::vector<int> TextInputController::MarkedRange() {
207   if (!view_->mainFrame())
208     return std::vector<int>();
209
210   blink::WebRange range = view_->mainFrame()->markedRange();
211   std::vector<int> int_array(2);
212   int_array[0] = range.startOffset();
213   int_array[1] = range.endOffset();
214
215   return int_array;
216 }
217
218 std::vector<int> TextInputController::SelectedRange() {
219   if (!view_->mainFrame())
220     return std::vector<int>();
221
222   blink::WebRange range = view_->mainFrame()->selectionRange();
223   std::vector<int> int_array(2);
224   int_array[0] = range.startOffset();
225   int_array[1] = range.endOffset();
226
227   return int_array;
228 }
229
230 std::vector<int> TextInputController::FirstRectForCharacterRange(
231     unsigned location,
232     unsigned length) {
233   blink::WebRect rect;
234   if (!view_->focusedFrame() ||
235       !view_->focusedFrame()->firstRectForCharacterRange(
236           location, length, rect)) {
237     return std::vector<int>();
238   }
239
240   std::vector<int> int_array(4);
241   int_array[0] = rect.x;
242   int_array[1] = rect.y;
243   int_array[2] = rect.width;
244   int_array[3] = rect.height;
245
246   return int_array;
247 }
248
249 void TextInputController::SetComposition(const std::string& text) {
250   // Sends a keydown event with key code = 0xE5 to emulate input method
251   // behavior.
252   blink::WebKeyboardEvent key_down;
253   key_down.type = blink::WebInputEvent::RawKeyDown;
254   key_down.modifiers = 0;
255   key_down.windowsKeyCode = 0xE5;  // VKEY_PROCESSKEY
256   key_down.setKeyIdentifierFromWindowsKeyCode();
257   view_->handleInputEvent(key_down);
258
259   blink::WebVector<blink::WebCompositionUnderline> underlines;
260   blink::WebString web_text(blink::WebString::fromUTF8(text));
261   view_->setComposition(web_text, underlines, 0, web_text.length());
262 }
263
264 }  // namespace content