1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "TextInputController.h"
32
33 #include "TestCommon.h"
34 #include "public/platform/WebString.h"
35 #include "public/platform/WebVector.h"
36 #include "public/web/WebBindings.h"
37 #include "public/web/WebCompositionUnderline.h"
38 #include "public/web/WebFrame.h"
39 #include "public/web/WebInputEvent.h"
40 #include "public/web/WebRange.h"
41 #include "public/web/WebView.h"
42 #include <string>
43
44 using namespace blink;
45 using namespace std;
46
47 namespace WebTestRunner {
48
TextInputController()49 TextInputController::TextInputController()
50 {
51 bindMethod("doCommand", &TextInputController::doCommand);
52 bindMethod("firstRectForCharacterRange", &TextInputController::firstRectForCharacterRange);
53 bindMethod("hasMarkedText", &TextInputController::hasMarkedText);
54 bindMethod("insertText", &TextInputController::insertText);
55 bindMethod("markedRange", &TextInputController::markedRange);
56 bindMethod("selectedRange", &TextInputController::selectedRange);
57 bindMethod("setMarkedText", &TextInputController::setMarkedText);
58 bindMethod("unmarkText", &TextInputController::unmarkText);
59 bindMethod("setComposition", &TextInputController::setComposition);
60 }
61
insertText(const CppArgumentList & arguments,CppVariant * result)62 void TextInputController::insertText(const CppArgumentList& arguments, CppVariant* result)
63 {
64 result->setNull();
65
66 if (arguments.size() < 1 || !arguments[0].isString())
67 return;
68
69 m_webView->confirmComposition(WebString::fromUTF8(arguments[0].toString()));
70 }
71
doCommand(const CppArgumentList & arguments,CppVariant * result)72 void TextInputController::doCommand(const CppArgumentList& arguments, CppVariant* result)
73 {
74 result->setNull();
75
76 WebFrame* mainFrame = m_webView->mainFrame();
77 if (!mainFrame)
78 return;
79
80 if (arguments.size() >= 1 && arguments[0].isString())
81 mainFrame->executeCommand(WebString::fromUTF8(arguments[0].toString()));
82 }
83
setMarkedText(const CppArgumentList & arguments,CppVariant * result)84 void TextInputController::setMarkedText(const CppArgumentList& arguments, CppVariant* result)
85 {
86 result->setNull();
87
88 if (arguments.size() < 3 || !arguments[0].isString()
89 || !arguments[1].isNumber() || !arguments[2].isNumber())
90 return;
91
92 WebString text(WebString::fromUTF8(arguments[0].toString()));
93 int start = arguments[1].toInt32();
94 int length = arguments[2].toInt32();
95
96 // Split underline into up to 3 elements (before, selection, and after).
97 vector<WebCompositionUnderline> underlines;
98 WebCompositionUnderline underline;
99 if (!start) {
100 underline.endOffset = length;
101 } else {
102 underline.endOffset = start;
103 underlines.push_back(underline);
104 underline.startOffset = start;
105 underline.endOffset = start + length;
106 }
107 underline.thick = true;
108 underlines.push_back(underline);
109 if (start + length < static_cast<int>(text.length())) {
110 underline.startOffset = underline.endOffset;
111 underline.endOffset = text.length();
112 underline.thick = false;
113 underlines.push_back(underline);
114 }
115
116 m_webView->setComposition(text, underlines, start, start + length);
117 }
118
unmarkText(const CppArgumentList &,CppVariant * result)119 void TextInputController::unmarkText(const CppArgumentList&, CppVariant* result)
120 {
121 result->setNull();
122
123 m_webView->confirmComposition();
124 }
125
hasMarkedText(const CppArgumentList &,CppVariant * result)126 void TextInputController::hasMarkedText(const CppArgumentList&, CppVariant* result)
127 {
128 result->setNull();
129
130 WebFrame* mainFrame = m_webView->mainFrame();
131 if (!mainFrame)
132 return;
133
134 result->set(mainFrame->hasMarkedText());
135 }
136
markedRange(const CppArgumentList &,CppVariant * result)137 void TextInputController::markedRange(const CppArgumentList&, CppVariant* result)
138 {
139 result->setNull();
140
141 WebFrame* mainFrame = m_webView->mainFrame();
142 if (!mainFrame)
143 return;
144
145 WebRange range = mainFrame->markedRange();
146 vector<int> intArray(2);
147 intArray[0] = range.startOffset();
148 intArray[1] = range.endOffset();
149
150 NPObject* resultArray = WebBindings::makeIntArray(intArray);
151 result->set(resultArray);
152 WebBindings::releaseObject(resultArray);
153 }
154
selectedRange(const CppArgumentList &,CppVariant * result)155 void TextInputController::selectedRange(const CppArgumentList&, CppVariant* result)
156 {
157 result->setNull();
158
159 WebFrame* mainFrame = m_webView->mainFrame();
160 if (!mainFrame)
161 return;
162
163 WebRange range = mainFrame->selectionRange();
164 vector<int> intArray(2);
165 intArray[0] = range.startOffset();
166 intArray[1] = range.endOffset();
167
168 NPObject* resultArray = WebBindings::makeIntArray(intArray);
169 result->set(resultArray);
170 WebBindings::releaseObject(resultArray);
171 }
172
firstRectForCharacterRange(const CppArgumentList & arguments,CppVariant * result)173 void TextInputController::firstRectForCharacterRange(const CppArgumentList& arguments, CppVariant* result)
174 {
175 result->setNull();
176
177 WebFrame* frame = m_webView->focusedFrame();
178 if (!frame)
179 return;
180
181 if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
182 return;
183
184 WebRect rect;
185 if (!frame->firstRectForCharacterRange(arguments[0].toInt32(), arguments[1].toInt32(), rect))
186 return;
187
188 vector<int> intArray(4);
189 intArray[0] = rect.x;
190 intArray[1] = rect.y;
191 intArray[2] = rect.width;
192 intArray[3] = rect.height;
193
194 NPObject* resultArray = WebBindings::makeIntArray(intArray);
195 result->set(resultArray);
196 WebBindings::releaseObject(resultArray);
197 }
198
setComposition(const CppArgumentList & arguments,CppVariant * result)199 void TextInputController::setComposition(const CppArgumentList& arguments, CppVariant* result)
200 {
201 result->setNull();
202
203 if (arguments.size() < 1)
204 return;
205
206 // Sends a keydown event with key code = 0xE5 to emulate input method behavior.
207 WebKeyboardEvent keyDown;
208 keyDown.type = WebInputEvent::RawKeyDown;
209 keyDown.modifiers = 0;
210 keyDown.windowsKeyCode = 0xE5; // VKEY_PROCESSKEY
211 keyDown.setKeyIdentifierFromWindowsKeyCode();
212 m_webView->handleInputEvent(keyDown);
213
214 WebVector<WebCompositionUnderline> underlines;
215 WebString text(WebString::fromUTF8(arguments[0].toString()));
216 m_webView->setComposition(text, underlines, 0, text.length());
217 }
218
219 }
220