1 // Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include "include/base/cef_callback.h"
6 #include "include/wrapper/cef_closure_task.h"
7 #include "tests/ceftests/test_handler.h"
8 #include "tests/gtest/include/gtest/gtest.h"
9
10 namespace {
11
12 const char kTestHTMLWithRegions[] =
13 "<html>"
14 " <body>"
15 " <div style=\"position: absolute; top: 50px; left: 50px; width: 200px; "
16 "height: 200px; background-color: red; -webkit-app-region: drag;\">"
17 " <div style=\"position: absolute; top: 50%; left: 50%; "
18 "transform: translate(-50%, -50%); width: 50px; height: 50px; "
19 "background-color: blue; -webkit-app-region: no-drag;\">"
20 " </div>"
21 " </div>"
22 " </body>"
23 "</html>";
24
25 const char kTestHTMLWithoutRegions[] = "<html><body>Hello World!</body></html>";
26
27 const char kTestHTMLWithChangingRegions[] =
28 "<html>"
29 " <body>"
30 " <div id=\"layer\" style=\"position: absolute; top: 50px; left: 50px; "
31 "width: 200px; height: 200px; background-color: red; "
32 "-webkit-app-region: drag;\">"
33 " <div style=\"position: absolute; top: 50%; left: 50%; "
34 "transform: translate(-50%, -50%); width: 50px; height: 50px; "
35 "background-color: blue; -webkit-app-region: no-drag;\">"
36 " </div>"
37 " </div>"
38 " <script>"
39 " window.setTimeout(function() {"
40 " var layer = document.getElementById('layer');"
41 " layer.style.top = '0px';"
42 " layer.style.left = '0px';"
43 " }, 500);"
44 " </script>"
45 " </body>"
46 "</html>";
47
48 class DraggableRegionsTestHandler : public TestHandler,
49 public CefDragHandler,
50 public CefFrameHandler {
51 public:
52 // Test steps executed in order.
53 enum Step {
54 // Nav 1: Two regions (get notification).
55 kStepWithRegions = 1,
56 // Nav 2: Starts with the same region as Nav 1 (no notification),
57 // then a changed region (get notification).
58 kStepWithChangingRegions,
59 // Nav 3: No regions (get notification).
60 kStepWithoutRegions,
61 // GoBack: Two regions (get notification), then a changed region (get
62 // notification). Note the first notification is not sent if
63 // BackForwardCache is enabled.
64 kStepWithChangingRegions2,
65 kStepWithChangingRegions3,
66 // GoForward: No regions (get notification).
67 kStepWithoutRegions2,
68
69 kStepMax = kStepWithoutRegions2,
70 };
71
DraggableRegionsTestHandler(bool same_origin)72 explicit DraggableRegionsTestHandler(bool same_origin)
73 : same_origin_(same_origin) {}
74
RunTest()75 void RunTest() override {
76 // Add HTML documents with and without draggable regions.
77 AddResource(GetURL(kStepWithRegions), kTestHTMLWithRegions, "text/html");
78 AddResource(GetURL(kStepWithChangingRegions), kTestHTMLWithChangingRegions,
79 "text/html");
80 AddResource(GetURL(kStepWithoutRegions), kTestHTMLWithoutRegions,
81 "text/html");
82
83 // Create the browser
84 CreateBrowser(GetURL(kStepWithRegions));
85
86 // Time out the test after a reasonable period of time.
87 SetTestTimeout();
88 }
89
GetDragHandler()90 CefRefPtr<CefDragHandler> GetDragHandler() override { return this; }
GetFrameHandler()91 CefRefPtr<CefFrameHandler> GetFrameHandler() override { return this; }
92
OnDraggableRegionsChanged(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const std::vector<CefDraggableRegion> & regions)93 void OnDraggableRegionsChanged(
94 CefRefPtr<CefBrowser> browser,
95 CefRefPtr<CefFrame> frame,
96 const std::vector<CefDraggableRegion>& regions) override {
97 EXPECT_UI_THREAD();
98 EXPECT_TRUE(browser->IsSame(GetBrowser()));
99 EXPECT_TRUE(frame->IsMain());
100
101 draggable_regions_changed_ct_++;
102
103 switch (step_) {
104 case kStepWithRegions:
105 case kStepWithChangingRegions2:
106 EXPECT_EQ(2U, regions.size());
107 EXPECT_NEAR(50, regions[0].bounds.x, 1);
108 EXPECT_NEAR(50, regions[0].bounds.y, 1);
109 EXPECT_NEAR(200, regions[0].bounds.width, 1);
110 EXPECT_NEAR(200, regions[0].bounds.height, 1);
111 EXPECT_EQ(1, regions[0].draggable);
112 EXPECT_NEAR(125, regions[1].bounds.x, 1);
113 EXPECT_NEAR(125, regions[1].bounds.y, 1);
114 EXPECT_NEAR(50, regions[1].bounds.width, 1);
115 EXPECT_NEAR(50, regions[1].bounds.height, 1);
116 EXPECT_EQ(0, regions[1].draggable);
117 break;
118 case kStepWithChangingRegions:
119 case kStepWithChangingRegions3:
120 EXPECT_EQ(2U, regions.size());
121 EXPECT_EQ(0, regions[0].bounds.x);
122 EXPECT_EQ(0, regions[0].bounds.y);
123 EXPECT_NEAR(200, regions[0].bounds.width, 1);
124 EXPECT_NEAR(200, regions[0].bounds.height, 1);
125 EXPECT_EQ(1, regions[0].draggable);
126 EXPECT_NEAR(75, regions[1].bounds.x, 1);
127 EXPECT_NEAR(75, regions[1].bounds.y, 1);
128 EXPECT_NEAR(50, regions[1].bounds.width, 2);
129 EXPECT_NEAR(50, regions[1].bounds.height, 2);
130 EXPECT_EQ(0, regions[1].draggable);
131 break;
132 case kStepWithoutRegions:
133 case kStepWithoutRegions2:
134 EXPECT_TRUE(regions.empty());
135 break;
136 }
137
138 NextTest(browser);
139 }
140
OnFrameAttached(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,bool reattached)141 void OnFrameAttached(CefRefPtr<CefBrowser> browser,
142 CefRefPtr<CefFrame> frame,
143 bool reattached) override {
144 EXPECT_UI_THREAD();
145 EXPECT_TRUE(browser->IsSame(GetBrowser()));
146 EXPECT_TRUE(frame->IsMain());
147
148 if (reattached) {
149 // When BackForwardCache is enabled and we go back to
150 // kTestHTMLWithChangingRegions, draggable regions will already be in the
151 // final position because the page content is not reloaded.
152 if (step_ == kStepWithChangingRegions2) {
153 step_ = kStepWithChangingRegions3;
154 expected_draggable_regions_changed_ct_--;
155 }
156 }
157 }
158
DestroyTest()159 void DestroyTest() override {
160 EXPECT_EQ(expected_draggable_regions_changed_ct_,
161 draggable_regions_changed_ct_);
162
163 TestHandler::DestroyTest();
164 }
165
166 private:
NextTest(CefRefPtr<CefBrowser> browser)167 void NextTest(CefRefPtr<CefBrowser> browser) {
168 CefRefPtr<CefFrame> frame(browser->GetMainFrame());
169
170 switch (step_) {
171 case kStepWithRegions:
172 step_ = kStepWithChangingRegions;
173 frame->LoadURL(GetURL(kStepWithChangingRegions));
174 break;
175 case kStepWithChangingRegions:
176 step_ = kStepWithoutRegions;
177 frame->LoadURL(GetURL(kStepWithoutRegions));
178 break;
179 case kStepWithoutRegions: {
180 step_ = kStepWithChangingRegions2;
181 browser->GoBack();
182 break;
183 }
184 case kStepWithChangingRegions2: {
185 step_ = kStepWithChangingRegions3;
186 break;
187 }
188 case kStepWithChangingRegions3: {
189 step_ = kStepWithoutRegions2;
190 browser->GoForward();
191 break;
192 }
193 case kStepWithoutRegions2: {
194 DestroyTest();
195 break;
196 }
197 }
198 }
199
GetURL(Step step) const200 std::string GetURL(Step step) const {
201 // When |same_origin_| is true every other URL gets a different origin.
202 switch (step) {
203 case kStepWithRegions:
204 return same_origin_ ? "http://test.com/regions"
205 : "http://test2.com/regions";
206 case kStepWithChangingRegions:
207 case kStepWithChangingRegions2:
208 case kStepWithChangingRegions3:
209 return "http://test.com/changing-regions";
210 case kStepWithoutRegions:
211 case kStepWithoutRegions2:
212 return same_origin_ ? "http://test.com/no-regions"
213 : "http://test2.com/no-regions";
214 }
215
216 NOTREACHED();
217 return "";
218 }
219
220 const bool same_origin_;
221
222 Step step_ = kStepWithRegions;
223 int draggable_regions_changed_ct_ = 0;
224 int expected_draggable_regions_changed_ct_ = kStepMax;
225
226 IMPLEMENT_REFCOUNTING(DraggableRegionsTestHandler);
227 };
228
229 } // namespace
230
231 // Verify that draggable regions work in the same origin.
TEST(DraggableRegionsTest,DraggableRegionsSameOrigin)232 TEST(DraggableRegionsTest, DraggableRegionsSameOrigin) {
233 CefRefPtr<DraggableRegionsTestHandler> handler =
234 new DraggableRegionsTestHandler(/*same_origin=*/true);
235 handler->ExecuteTest();
236 ReleaseAndWaitForDestructor(handler);
237 }
238
239 // Verify that draggable regions work cross-origin.
TEST(DraggableRegionsTest,DraggableRegionsCrossOrigin)240 TEST(DraggableRegionsTest, DraggableRegionsCrossOrigin) {
241 CefRefPtr<DraggableRegionsTestHandler> handler =
242 new DraggableRegionsTestHandler(/*same_origin=*/false);
243 handler->ExecuteTest();
244 ReleaseAndWaitForDestructor(handler);
245 }
246