Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ppapi / tests / test_view.cc
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
3 // found in the LICENSE file.
4
5 #include "ppapi/tests/test_view.h"
6
7 #include <sstream>
8
9 #include "ppapi/c/pp_time.h"
10 #include "ppapi/c/private/ppb_testing_private.h"
11 #include "ppapi/cpp/completion_callback.h"
12 #include "ppapi/tests/testing_instance.h"
13
14 REGISTER_TEST_CASE(View);
15
16 // When waiting for view changed events, wait no longer than this.
17 #if !defined(THREAD_SANITIZER)
18 static int kViewChangeTimeoutSec = 5;
19 #else
20 // ThreadSanitizer may slow the interaction down significantly.
21 static int kViewChangeTimeoutSec = 30;
22 #endif
23
24 TestView::TestView(TestingInstance* instance)
25     : TestCase(instance),
26       post_quit_on_view_changed_(false) {
27 }
28
29 void TestView::DidChangeView(const pp::View& view) {
30   last_view_ = view;
31   page_visibility_log_.push_back(view.IsPageVisible());
32
33   if (post_quit_on_view_changed_) {
34     post_quit_on_view_changed_ = false;
35     testing_interface_->QuitMessageLoop(instance_->pp_instance());
36   }
37 }
38
39 bool TestView::Init() {
40   return CheckTestingInterface();
41 }
42
43 void TestView::RunTests(const std::string& filter) {
44   RUN_TEST(CreatedVisible, filter);
45   RUN_TEST(CreatedInvisible, filter);
46   RUN_TEST(PageHideShow, filter);
47   RUN_TEST(SizeChange, filter);
48   RUN_TEST(ClipChange, filter);
49 }
50
51 bool TestView::WaitUntilViewChanged() {
52   // Schedule a callback so this step times out if we don't get a ViewChanged
53   // in a reasonable amount of time.
54   pp::CompletionCallbackFactory<TestView> factory(this);
55   pp::CompletionCallback timeout =
56       factory.NewCallback(&TestView::QuitMessageLoop);
57   pp::Module::Get()->core()->CallOnMainThread(
58       kViewChangeTimeoutSec * 1000, timeout);
59
60   size_t old_page_visibility_change_count = page_visibility_log_.size();
61
62   // Run a nested message loop. It will exit either on ViewChanged or if the
63   // timeout happens.
64   post_quit_on_view_changed_ = true;
65   testing_interface_->RunMessageLoop(instance_->pp_instance());
66   post_quit_on_view_changed_ = false;
67
68   // We know we got a view changed event if something was appended to the log.
69   return page_visibility_log_.size() > old_page_visibility_change_count;
70 }
71
72 void TestView::QuitMessageLoop(int32_t result) {
73   testing_interface_->QuitMessageLoop(instance_->pp_instance());
74 }
75
76 std::string TestView::TestCreatedVisible() {
77   ASSERT_FALSE(page_visibility_log_.empty());
78   ASSERT_TRUE(page_visibility_log_[0]);
79   PASS();
80 }
81
82 std::string TestView::TestCreatedInvisible() {
83   ASSERT_FALSE(page_visibility_log_.empty());
84
85   if (page_visibility_log_[0]) {
86     // Add more error message since this test has some extra requirements.
87     instance_->AppendError("Initial page is set to visible. NOTE: "
88         "This test must be run in a background tab. "
89         "Either run in the UI test which does this, or you can middle-click "
90         "on the test link to run manually.");
91   }
92   ASSERT_FALSE(page_visibility_log_[0]);
93   PASS();
94 }
95
96 std::string TestView::TestPageHideShow() {
97   // Initial state should be visible.
98   ASSERT_FALSE(page_visibility_log_.empty());
99   ASSERT_TRUE(page_visibility_log_[0]);
100
101   // Now that we're alive, tell the test knows it can change our visibility.
102   instance_->ReportProgress("TestPageHideShow:Created");
103
104   // Wait until we get a hide event, being careful to handle spurious
105   // notifications of ViewChanged.
106   PP_Time begin_time = pp::Module::Get()->core()->GetTime();
107   while (WaitUntilViewChanged() &&
108          page_visibility_log_[page_visibility_log_.size() - 1] &&
109          pp::Module::Get()->core()->GetTime() - begin_time <
110              kViewChangeTimeoutSec) {
111   }
112   if (page_visibility_log_[page_visibility_log_.size() - 1]) {
113     // Didn't get a view changed event that changed visibility (though there
114     // may have been some that didn't change visibility).
115     // Add more error message since this test has some extra requirements.
116     return "Didn't receive a hide event in timeout. NOTE: "
117         "This test requires tab visibility to change and won't pass if you "
118         "just run it in a browser. Normally the UI test should handle "
119         "this. You can also run manually by waiting 2 secs, creating a new "
120         "tab, waiting 2 more secs, and closing the new tab.";
121   }
122
123   // Tell the test so it can show us again.
124   instance_->ReportProgress("TestPageHideShow:Hidden");
125
126   // Wait until we get a show event.
127   begin_time = pp::Module::Get()->core()->GetTime();
128   while (WaitUntilViewChanged() &&
129          !page_visibility_log_[page_visibility_log_.size() - 1] &&
130          pp::Module::Get()->core()->GetTime() - begin_time <
131              kViewChangeTimeoutSec) {
132   }
133   ASSERT_TRUE(page_visibility_log_[page_visibility_log_.size() - 1]);
134
135   PASS();
136 }
137
138 std::string TestView::TestSizeChange() {
139   pp::Rect original_rect = last_view_.GetRect();
140
141   pp::Rect desired_rect = original_rect;
142   desired_rect.set_width(original_rect.width() + 10);
143   desired_rect.set_height(original_rect.height() + 12);
144
145   std::ostringstream script_stream;
146   script_stream << "var plugin = document.getElementById('plugin');";
147   script_stream << "plugin.setAttribute('width', "
148                 << desired_rect.width() << ");";
149   script_stream << "plugin.setAttribute('height', "
150                 << desired_rect.height() << ");";
151
152   instance_->EvalScript(script_stream.str());
153
154   PP_Time begin_time = pp::Module::Get()->core()->GetTime();
155   while (WaitUntilViewChanged() && last_view_.GetRect() != desired_rect &&
156          pp::Module::Get()->core()->GetTime() - begin_time <
157              kViewChangeTimeoutSec) {
158   }
159   ASSERT_TRUE(last_view_.GetRect() == desired_rect);
160
161   PASS();
162 }
163
164 std::string TestView::TestClipChange() {
165   pp::Rect original_rect = last_view_.GetRect();
166
167   // Original clip should be the full frame.
168   pp::Rect original_clip = last_view_.GetClipRect();
169   ASSERT_TRUE(original_clip.x() == 0);
170   ASSERT_TRUE(original_clip.y() == 0);
171   ASSERT_TRUE(original_clip.width() == original_rect.width());
172   ASSERT_TRUE(original_clip.height() == original_rect.height());
173
174   int clip_amount = original_rect.height() / 2;
175
176   // It might be nice to set the position to be absolute and set the location,
177   // but this will cause WebKit to actually tear down the plugin and recreate
178   // it. So instead we add a big div to cause the document to be scrollable,
179   // and scroll it down.
180   std::ostringstream script_stream;
181   script_stream
182       << "var big = document.createElement('div');"
183       << "big.setAttribute('style', 'position:absolute; left:100px; "
184                                     "top:0px; width:1px; height:5000px;');"
185       << "document.body.appendChild(big);"
186       << "window.scrollBy(0, " << original_rect.y() + clip_amount << ");";
187
188   instance_->EvalScript(script_stream.str());
189
190   pp::Rect desired_clip = original_clip;
191   desired_clip.set_y(clip_amount);
192   desired_clip.set_height(desired_clip.height() - desired_clip.y());
193
194   PP_Time begin_time = pp::Module::Get()->core()->GetTime();
195   while (WaitUntilViewChanged() && last_view_.GetClipRect() != desired_clip &&
196          pp::Module::Get()->core()->GetTime() - begin_time <
197              kViewChangeTimeoutSec) {
198   }
199   ASSERT_TRUE(last_view_.GetClipRect() == desired_clip);
200   PASS();
201 }