Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(137)

Side by Side Diff: chrome/browser/renderer_host/site_per_process_text_input_browsertest.cc

Issue 1948343002: [reland] Browser Side Text Input State Tracking for OOPIF (Aura Only) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Changed Public Test API Methods to non-const Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 <vector>
6
7 #include "base/command_line.h"
8 #include "chrome/browser/ui/browser.h"
9 #include "chrome/browser/ui/tabs/tab_strip_model.h"
10 #include "chrome/test/base/in_process_browser_test.h"
11 #include "chrome/test/base/ui_test_utils.h"
12 #include "content/public/browser/render_frame_host.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/test/browser_test_utils.h"
16 #include "content/public/test/content_browser_test_utils.h"
17 #include "content/public/test/test_utils.h"
18 #include "content/public/test/text_input_test_utils.h"
19 #include "net/dns/mock_host_resolver.h"
20 #include "net/test/embedded_test_server/embedded_test_server.h"
21 #include "ui/base/ime/text_input_client.h"
22 #include "ui/base/ime/text_input_mode.h"
23 #include "ui/base/ime/text_input_type.h"
24
25 #include "url/gurl.h"
26
27 #ifdef USE_AURA
Charlie Reis 2016/05/26 06:22:04 Having the whole file ifdef'd out on other platfor
EhsanK 2016/05/30 15:06:07 Yes. I think I had that TODO in the original file
28 ///////////////////////////////////////////////////////////////////////////////
29 // TextInputManager and IME Tests
30 //
31 // The following tests verify the correctness of TextInputState tracking on the
32 // browser side. They also make sure the IME logic works correctly. The baseline
33 // for comparison is the default functionality in the non-OOPIF case (i.e., the
34 // legacy implementation in RWHV's other than RWHVCF.).
35
36 namespace {
37 // TextInputManager Observers
Charlie Reis 2016/05/26 06:22:04 nit: Blank line before and after.
EhsanK 2016/05/30 15:06:07 Done.
38 // Observing the |TextInputState.value|.
Charlie Reis 2016/05/26 06:22:04 Please put a more thorough comment here. This is
EhsanK 2016/05/30 15:06:07 Done. This comment was wrong to begin with.
39 class TextInputManagerObserverBase {
40 public:
41 explicit TextInputManagerObserverBase(content::WebContents* web_contents)
42 : success_(false) {
43 test_observer_ =
44 content::TestTextInputManagerObserver::Create(web_contents);
45 }
46
47 virtual ~TextInputManagerObserverBase() {}
48
49 void Wait() {
Charlie Reis 2016/05/26 06:22:04 // Wait for the derived class's definition of succ
EhsanK 2016/05/30 15:06:08 I am a bit unclear on the second statement in this
50 if (success_)
51 return;
52 message_loop_runner_ = new content::MessageLoopRunner();
53 message_loop_runner_->Run();
54 }
55
56 bool success() const { return success_; }
57
58 protected:
59 base::Closure on_success() {
Charlie Reis 2016/05/26 06:22:04 Why does this return a closure, rather than just m
EhsanK 2016/05/30 15:06:07 No reasons and calling OnSuccess() is better. Ini
60 return base::Bind(&TextInputManagerObserverBase::OnSuccess,
61 base::Unretained(this));
62 }
63
64 content::TestTextInputManagerObserver* observer() {
65 return test_observer_.get();
66 }
67
68 private:
69 void OnSuccess() {
70 success_ = true;
71 if (message_loop_runner_)
72 message_loop_runner_->Quit();
73 }
74
75 std::unique_ptr<content::TestTextInputManagerObserver> test_observer_;
76 bool success_;
77 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
78
79 DISALLOW_COPY_AND_ASSIGN(TextInputManagerObserverBase);
80 };
81
82 // This class observes TextInputManager for updated |TextInputState.value|.
83 class TextInputManagerValueObserver : public TextInputManagerObserverBase {
84 public:
85 explicit TextInputManagerValueObserver(content::WebContents* web_contents,
Charlie Reis 2016/05/26 06:22:03 No explicit.
EhsanK 2016/05/30 15:06:08 Done.
86 const std::string& expected_value)
87 : TextInputManagerObserverBase(web_contents),
88 expected_value_(expected_value) {
89 observer()->SetUpdateTextInputStateCalledCallback(base::Bind(
90 &TextInputManagerValueObserver::VerifyValue, base::Unretained(this)));
91 }
92
93 private:
94 void VerifyValue(content::TestTextInputManagerObserver* observer) {
95 std::string value;
96 if (observer->GetTextInputValue(&value) && expected_value_ == value)
97 on_success().Run();
98 }
99
100 std::string expected_value_;
101 };
102
103 // This class observes the TextInputManager for updated |TextInputState.type|.
104 class TextInputManagerTypeObserver : public TextInputManagerObserverBase {
105 public:
106 explicit TextInputManagerTypeObserver(content::WebContents* web_contents,
107 ui::TextInputType expected_type)
108 : TextInputManagerObserverBase(web_contents),
109 expected_type_(expected_type) {
110 observer()->SetUpdateTextInputStateCalledCallback(base::Bind(
111 &TextInputManagerTypeObserver::VerifyType, base::Unretained(this)));
112 }
113
114 private:
115 void VerifyType(content::TestTextInputManagerObserver* observer) {
116 if (expected_type_ == observer->GetTextInputType())
117 on_success().Run();
118 }
119
120 ui::TextInputType expected_type_;
121 };
122
123 // An observer class which observes the TextInputManager until the first time
124 // the TextInputManager detects a change in TextInputState.
125 class TextInputManagerChangeObserver : public TextInputManagerObserverBase {
126 public:
127 explicit TextInputManagerChangeObserver(content::WebContents* web_contents)
128 : TextInputManagerObserverBase(web_contents) {
129 observer()->SetUpdateTextInputStateCalledCallback(base::Bind(
130 &TextInputManagerChangeObserver::VerifyChange, base::Unretained(this)));
131 }
132
133 private:
134 void VerifyChange(content::TestTextInputManagerObserver* observer) {
135 if (observer->IsTextInputStateChanged())
136 on_success().Run();
137 }
138 };
139
140 // The following class observers |TextInputState.type| for a specific RWHV.
Charlie Reis 2016/05/26 06:22:04 nit: observes
EhsanK 2016/05/30 15:06:08 Done.
141 class ViewTextInputTypeObserver : public TextInputManagerObserverBase {
142 public:
143 explicit ViewTextInputTypeObserver(content::WebContents* web_contents,
144 content::RenderWidgetHostView* rwhv,
145 ui::TextInputType expected_type)
146 : TextInputManagerObserverBase(web_contents),
147 web_contents_(web_contents),
148 view_(rwhv),
149 expected_type_(expected_type) {
150 observer()->SetUpdateTextInputStateCalledCallback(base::Bind(
151 &ViewTextInputTypeObserver::VerifyType, base::Unretained(this)));
152 }
153
154 private:
155 void VerifyType(content::TestTextInputManagerObserver* observer) {
156 std::unordered_map<content::RenderWidgetHostView*, ui::TextInputType>
157 type_map = content::GetTextInputTypeMapFromWebContents(web_contents_);
Charlie Reis 2016/05/26 06:22:03 Can we replace this API with a GetTextInputTypeFor
EhsanK 2016/05/30 15:06:07 Done. Replacing the API with a simple function see
158 if (expected_type_ == type_map[view_])
159 on_success().Run();
160 }
161
162 content::WebContents* web_contents_;
163 content::RenderWidgetHostView* view_;
164 ui::TextInputType expected_type_;
165 };
166
167 } // namespace
168
169 // Main class for all TextInputState and IME related tests.
170 class SitePerProcessTextInputManagerTest : public InProcessBrowserTest {
171 public:
172 SitePerProcessTextInputManagerTest() {}
173 ~SitePerProcessTextInputManagerTest() override {}
174
175 void SetUpCommandLine(base::CommandLine* command_line) override {
176 content::IsolateAllSitesForTesting(command_line);
177 }
178
179 void SetUpOnMainThread() override {
180 host_resolver()->AddRule("*", "127.0.0.1");
181
182 // Add content/test/data 'cross_site_iframe_factory.html'.
183 embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
184
185 ASSERT_TRUE(embedded_test_server()->Start());
186 }
187
188 protected:
189 content::WebContents* active_contents() {
190 return browser()->tab_strip_model()->GetActiveWebContents();
191 }
192
193 // static
194 // Adds an <input> field to a given frame by executing javascript code.
195 // The input can be added as the first element or the last element of
196 // |document.body|.
197 static void AddInputFieldToFrame(content::RenderFrameHost* rfh,
198 const std::string& type,
199 const std::string& value,
200 bool append_as_first_child) {
201 std::string script = base::StringPrintf(
202 "var input = document.createElement('input');"
203 "input.setAttribute('type', '%s');"
204 "input.setAttribute('value', '%s');"
205 "if (%s && !!document.body.firstChild) {"
Charlie Reis 2016/05/26 06:22:04 Maybe "document.body.%s", with the third param bei
EhsanK 2016/05/30 15:06:07 Agreed. Looks confusing the way it was.
206 " document.body.insertBefore(input, document.body.firstChild);"
207 "} else {"
208 " document.body.appendChild(input);"
209 "}",
210 type.c_str(), value.c_str(), append_as_first_child ? "true" : "false");
211 EXPECT_TRUE(ExecuteScript(rfh, script));
212 }
213
214 // Uses 'cross_site_iframe_factory.html'. The main frame's domain is
215 // 'a.com'.
216 void CreateIframePage(const std::string& structure) {
217 std::string path = base::StringPrintf("/cross_site_iframe_factory.html?%s",
218 structure.c_str());
219 GURL main_url(embedded_test_server()->GetURL("a.com", path));
220 ui_test_utils::NavigateToURL(browser(), main_url);
221 }
222
223 // Recrusively uses ChildFrameAt(frame, i) to get the i-th child frame
Charlie Reis 2016/05/26 06:22:04 nit: Recursively Actually, Iteratively, since this
EhsanK 2016/05/30 15:06:08 Done.
224 // inside frame. For example, for 'a(b(c, d(e)))', [0] returns b, and
225 // [0, 1, 0] returns e;
226 content::RenderFrameHost* GetFrame(const std::vector<size_t>& indices) {
227 content::RenderFrameHost* current = active_contents()->GetMainFrame();
228 for (size_t index : indices)
229 current = ChildFrameAt(current, index);
230 return current;
231 }
232
233 private:
234 DISALLOW_COPY_AND_ASSIGN(SitePerProcessTextInputManagerTest);
235 };
236
237 // The following test loads a page with multiple nested <iframe> elements which
238 // are in or out of process with the main frame. Then an <input> field with
239 // unique value is added to every single frame on the frame tree. The test then
240 // creates a sequence of tab presses and verifies that after each key press, the
241 // TextInputState.value reflects that of the focused input, i.e., the
242 // TextInputManager is correctly tracking TextInputState across frames.
243 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
244 TrackStateWhenSwitchingFocusedFrames) {
245 CreateIframePage("a(a,b,c(a,b,d(e, f)),g)");
246 std::vector<std::string> values{
247 "main", "node_a", "node_b", "node_c", "node_c_a",
248 "node_c_b", "node_c_d", "node_c_d_e", "node_c_d_f", "node_g"};
249
250 // TODO(ekaramad): This should not be needed and uniform initialization should
251 // work. However, in some bots, this is failing.
252 using vector = std::vector<size_t>;
Charlie Reis 2016/05/26 06:22:04 nit: Blank line after, since it looks like the TOD
EhsanK 2016/05/30 15:06:07 Done.
253 std::vector<content::RenderFrameHost*> frames{
254 GetFrame(vector{}), GetFrame(vector{0}),
255 GetFrame(vector{1}), GetFrame(vector{2}),
256 GetFrame(vector{2, 0}), GetFrame(vector{2, 1}),
257 GetFrame(vector{2, 2}), GetFrame(vector{2, 2, 0}),
258 GetFrame(vector{2, 2, 1}), GetFrame(vector{3})};
259
260 for (size_t i = 0; i < frames.size(); ++i)
261 AddInputFieldToFrame(frames[i], "text", values[i], true);
262
263 for (size_t i = 0; i < frames.size(); ++i) {
264 TextInputManagerValueObserver observer(active_contents(), values[i]);
265 SimulateKeyPress(active_contents(), ui::VKEY_TAB, false, false, false,
266 false);
267 observer.Wait();
268 }
269 }
270
271 // The following test loads a page with two OOPIFs. An <input> is added to
272 // both frames and tab key is faked until the one in the second OOPIF is
Charlie Reis 2016/05/26 06:22:04 s/faked/pressed/? (I think it's implicit that we'
EhsanK 2016/05/30 15:06:07 Done. Don't we do manual testing of chrome though?
273 // focused. Then, the renderer process for both frames are crashed. The test
Charlie Reis 2016/05/26 06:22:04 nit: processes
EhsanK 2016/05/30 15:06:07 Done.
274 // verifies that the TextInputManager stop tracking the RWHVs as well as
Charlie Reis 2016/05/26 06:22:03 nit: stops
EhsanK 2016/05/30 15:06:07 Done.
275 // properly resetting the TextInputState after the second (active) RWHV goes
Charlie Reis 2016/05/26 06:22:04 nit: resets
EhsanK 2016/05/30 15:06:08 Done.
276 // away.
277 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
278 StopTrackingCrashedChildFrame) {
279 CreateIframePage("a(b, c)");
280 std::vector<std::string> values{"node_b", "node_c"};
281 using vector = std::vector<size_t>;
282 std::vector<content::RenderFrameHost*> frames{GetFrame(vector{0}),
283 GetFrame(vector{1})};
284
285 for (size_t i = 0; i < frames.size(); ++i)
286 AddInputFieldToFrame(frames[i], "text", values[i], true);
287
288 // Tab into both inputs. And make sure we correctly receive their
289 // TextInputState. For the second tab two IPC's arrive one from the first
Charlie Reis 2016/05/26 06:22:04 nit: arrive:
EhsanK 2016/05/30 15:06:07 Done.
290 // frame to set the state to none, and another one from the second frame to
291 // set it to TEXT. To avoid the race between them, we shall also observe the
292 // first frame setting its state to NONE after the second tab.
293 ViewTextInputTypeObserver view_type_observer(
294 active_contents(), frames[0]->GetView(), ui::TEXT_INPUT_TYPE_NONE);
295
296 for (size_t i = 0; i < frames.size(); ++i) {
297 TextInputManagerValueObserver observer(active_contents(), values[i]);
298 SimulateKeyPress(active_contents(), ui::VKEY_TAB, false, false, false,
299 false);
300 observer.Wait();
301 }
302
303 // Make sure that the first view has set its TextInputState.type to NONE.
304 view_type_observer.Wait();
305
306 // Verify that we are tracking the TextInputState from the first frame.
307 content::RenderWidgetHostView* first_view = frames[0]->GetView();
308 std::unordered_map<content::RenderWidgetHostView*, ui::TextInputType>
309 type_map = content::GetTextInputTypeMapFromWebContents(active_contents());
310 EXPECT_EQ(1UL, type_map.count(first_view));
311 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, type_map[first_view]);
312
313 // Now that the second frame's <input> is focused, we crash the first frame
314 // and observe that text input state is updated for the view.
315 std::unique_ptr<content::RenderWidgetHostViewDestructionObserver>
316 destruction_observer =
317 content::RenderWidgetHostViewDestructionObserver::Create(first_view);
318 frames[0]->GetProcess()->Shutdown(0, false);
319 destruction_observer->Wait();
320
321 // Verifying that the TextInputManager has smaller cleaned the memory
Charlie Reis 2016/05/26 06:22:03 Typo?
EhsanK 2016/05/30 15:06:08 Sorry...typo seems to be an understatement in this
322 // allocated to the view.
323 type_map = content::GetTextInputTypeMapFromWebContents(active_contents());
324 EXPECT_EQ(0UL, type_map.count(first_view));
325
326 // Now crash the second <iframe> which has an active view.
327 content::RenderWidgetHostView* second_view = frames[1]->GetView();
328 TextInputManagerChangeObserver change_observer(active_contents());
329 frames[1]->GetProcess()->Shutdown(0, false);
330 change_observer.Wait();
331 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE,
332 content::GetTextInputTypeFromWebContents(active_contents()));
333 EXPECT_FALSE(!!content::GetActiveViewFromWebContents(active_contents()));
334 type_map = content::GetTextInputTypeMapFromWebContents(active_contents());
335 EXPECT_EQ(0UL, type_map.count(second_view));
336 }
337
338 // The following test loads a page with two child frames; one in process and one
Charlie Reis 2016/05/26 06:22:04 nit: Colon, not semicolon. (The second phrase wou
EhsanK 2016/05/30 15:06:07 Acknowledged.
339 // out of process with main frame. The test inserts an <input> inside each frame
340 // and focuses the first frame and observes the TextInputManager setting the
341 // state to ui::TEXT_INPUT_TYPE_TEXT. Then, the frame is detached and the test
342 // observes that the state type is reset to ui::TEXT_INPUT_TYPE_NONE. The same
343 // sequence of actions is then performed on the out of process frame.
344 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
345 ResetStateAfterFrameDetached) {
346 CreateIframePage("a(a, b)");
347 using vector = std::vector<size_t>;
348 std::vector<content::RenderFrameHost*> frames{GetFrame(vector{0}),
349 GetFrame(vector{1})};
350
351 for (size_t i = 0; i < frames.size(); ++i)
352 AddInputFieldToFrame(frames[i], "text", "", true);
353
354 // Press tab key to focus the <input> in the first frame.
355 TextInputManagerTypeObserver type_observer_text_a(active_contents(),
356 ui::TEXT_INPUT_TYPE_TEXT);
357 SimulateKeyPress(active_contents(), ui::VKEY_TAB, false, false, false, false);
358 type_observer_text_a.Wait();
359
360 // Detach first frame and observe |TextInputState.type| resetting to
361 // ui::TEXT_INPUT_TYPE_NONE.
362 TextInputManagerTypeObserver type_observer_none_a(active_contents(),
363 ui::TEXT_INPUT_TYPE_NONE);
364 EXPECT_TRUE(ExecuteScript(
365 frames[0], "document.body.removeChild(document.body.firstChild);"));
366 type_observer_none_a.Wait();
367
368 // Press tab to focus the <input> in the second frame.
369 TextInputManagerTypeObserver type_observer_text_b(active_contents(),
370 ui::TEXT_INPUT_TYPE_TEXT);
371 SimulateKeyPress(active_contents(), ui::VKEY_TAB, false, false, false, false);
372 type_observer_text_b.Wait();
373
374 // Detach first frame and observe |TextInputState.type| resetting to
375 // ui::TEXT_INPUT_TYPE_NONE.
376 TextInputManagerTypeObserver type_observer_none_b(active_contents(),
377 ui::TEXT_INPUT_TYPE_NONE);
378 EXPECT_TRUE(ExecuteScript(
379 frames[1], "document.body.removeChild(document.body.firstChild);"));
380 type_observer_none_b.Wait();
381 }
382
383 // This test creates a page with one OOPIF and adds an <input> to it. Then, the
384 // <input> is focused and the test verfies that the |TextInputState.type| is set
385 // to ui::TEXT_INPUT_TYPE_TEXT. Next, the child frame is navigated away and the
386 // test verifies that |TextInputState.type| resets to ui::TEXT_INPUT_TYPE_NONE.
387 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
388 ResetStateAfterChildNavigation) {
389 CreateIframePage("a(b)");
390 using vector = std::vector<size_t>;
391 content::RenderFrameHost* main_frame = GetFrame(vector{});
392 content::RenderFrameHost* child_frame = GetFrame(vector{0});
393
394 AddInputFieldToFrame(child_frame, "text", "child", false);
395
396 // Focus <input> in child frame and verify the |TextInputState.value|.
397 TextInputManagerValueObserver child_set_state_observer(active_contents(),
398 "child");
399 SimulateKeyPress(active_contents(), ui::VKEY_TAB, false, false, false, false);
400 child_set_state_observer.Wait();
401
402 // Navigate the child frame to about:blank and verify that TextInputManager
403 // correctly sets its |TextInputState.type| to ui::TEXT_INPUT_TYPE_NONE.
404 TextInputManagerTypeObserver child_reset_state_observer(
405 active_contents(), ui::TEXT_INPUT_TYPE_NONE);
406 EXPECT_TRUE(ExecuteScript(
407 main_frame, "document.querySelector('iframe').src = 'about:blank'"));
408 child_reset_state_observer.Wait();
409 }
410
411 // This test creates a blank page and adds an <input> to it. Then, the <input>
412 // is focused and the test verfies that the |TextInputState.type| is set to
413 // ui::TEXT_INPUT_TYPE_TEXT. Next, the browser is navigated away and the test
414 // verifies that |TextInputState.type| resets to ui::TEXT_INPUT_TYPE_NONE.
415 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
416 ResetStateAfterBrowserNavigation) {
417 CreateIframePage("a()");
418 content::RenderFrameHost* main_frame = GetFrame(std::vector<size_t>{});
419 AddInputFieldToFrame(main_frame, "text", "", false);
420
421 TextInputManagerTypeObserver set_state_observer(active_contents(),
422 ui::TEXT_INPUT_TYPE_TEXT);
423 SimulateKeyPress(active_contents(), ui::VKEY_TAB, false, false, false, false);
424 set_state_observer.Wait();
425
426 TextInputManagerTypeObserver reset_state_observer(active_contents(),
427 ui::TEXT_INPUT_TYPE_NONE);
428 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
429 reset_state_observer.Wait();
430 }
431 #endif // USE_AURA
432
433 // TODO(ekaramad): The following tests are specifically written for Aura and are
434 // based on InputMethodObserver. Write similar tests for Mac/Android/Mus
435 // (crbug.com/602723).
436 #ifdef USE_AURA
437 // Observes current input method for state changes.
438 class InputMethodObserverBase {
439 public:
440 explicit InputMethodObserverBase(content::WebContents* web_contents)
441 : success_(false),
442 test_observer_(content::TestInputMethodObserver::Create(web_contents)) {
443 }
444
445 void Wait() {
446 if (success_)
447 return;
448 message_loop_runner_ = new content::MessageLoopRunner();
449 message_loop_runner_->Run();
450 }
451
452 bool success() const { return success_; }
453
454 protected:
455 content::TestInputMethodObserver* test_observer() {
456 return test_observer_.get();
457 }
458
459 const base::Closure success_closure() {
460 return base::Bind(&InputMethodObserverBase::OnSuccess,
461 base::Unretained(this));
462 }
463
464 private:
465 void OnSuccess() {
466 success_ = true;
467 if (message_loop_runner_)
468 message_loop_runner_->Quit();
469 }
470
471 bool success_;
472 std::unique_ptr<content::TestInputMethodObserver> test_observer_;
473 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
474
475 DISALLOW_COPY_AND_ASSIGN(InputMethodObserverBase);
476 };
477
478 class InputMethodObserverForShowIme : public InputMethodObserverBase {
479 public:
480 explicit InputMethodObserverForShowIme(content::WebContents* web_contents)
481 : InputMethodObserverBase(web_contents) {
482 test_observer()->SetOnShowImeIfNeededCallback(success_closure());
483 }
484 };
485
486 // This test verifies that the IME for Aura is shown if and only if the current
487 // client's |TextInputState.type| is not ui::TEXT_INPUT_TYPE_NONE and the flag
488 // |TextInputState.show_ime_if_needed| is true. This should happen even.
Charlie Reis 2016/05/26 06:22:04 Even if what?
EhsanK 2016/05/30 15:06:07 Done.
489 // TODO(ekaramad): This test is actually a unit test and should be moved to some
490 // place more appropriate.
491 IN_PROC_BROWSER_TEST_F(SitePerProcessTextInputManagerTest,
492 CorrectlyShowImeIfNeeded) {
493 // We only need the <iframe> page to create RWHV.
494 CreateIframePage("a()");
495 content::RenderFrameHost* main_frame = GetFrame(std::vector<size_t>{});
496 content::RenderWidgetHostView* view = main_frame->GetView();
497 content::WebContents* web_contents = active_contents();
498
499 content::TextInputStateSender sender(view);
500
501 auto send_and_check_show_ime = [&sender, &web_contents]() {
502 InputMethodObserverForShowIme observer(web_contents);
503 sender.Send();
504 return observer.success();
505 };
506
507 // Sending an empty state should not trigger ime.
508 EXPECT_FALSE(send_and_check_show_ime());
509
510 // Set |TextInputState.type| to text. Expect no IME.
511 sender.SetType(ui::TEXT_INPUT_TYPE_TEXT);
512 EXPECT_FALSE(send_and_check_show_ime());
513
514 // Set |TextInputState.show_ime_if_needed| to true. Expect IME.
515 sender.SetShowImeIfNeeded(true);
516 EXPECT_TRUE(send_and_check_show_ime());
517
518 // Send the same message. Expect IME (no change).
519 EXPECT_TRUE(send_and_check_show_ime());
520
521 // Reset |TextInputState.show_ime_if_needed|. Expect no IME.
522 sender.SetShowImeIfNeeded(false);
523 EXPECT_FALSE(send_and_check_show_ime());
524
525 // Setting an irrelevant field. Expect no IME.
526 sender.SetMode(ui::TEXT_INPUT_MODE_LATIN);
527 EXPECT_FALSE(send_and_check_show_ime());
528
529 // Set |TextInputState.show_ime_if_needed|. Expect IME.
530 sender.SetShowImeIfNeeded(true);
531 EXPECT_TRUE(send_and_check_show_ime());
532
533 // Set |TextInputState.type| to ui::TEXT_INPUT_TYPE_NONE. Expect no IME.
534 sender.SetType(ui::TEXT_INPUT_TYPE_NONE);
535 EXPECT_FALSE(send_and_check_show_ime());
536 }
537 #endif // USE_AURA
OLDNEW
« no previous file with comments | « no previous file | chrome/chrome_tests.gypi » ('j') | content/browser/renderer_host/render_widget_host_view_aura.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698