OLD | NEW |
| (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 "ash/devtools/ash_devtools_css_agent.h" | |
6 #include "ash/devtools/ash_devtools_dom_agent.h" | |
7 #include "ash/devtools/ui_element.h" | |
8 #include "ash/devtools/window_element.h" | |
9 #include "ash/public/cpp/shell_window_ids.h" | |
10 #include "ash/shell.h" | |
11 #include "ash/test/ash_test_base.h" | |
12 #include "ash/wm/widget_finder.h" | |
13 #include "base/memory/ptr_util.h" | |
14 #include "base/strings/stringprintf.h" | |
15 #include "ui/aura/window_tree_host.h" | |
16 #include "ui/display/display.h" | |
17 #include "ui/views/background.h" | |
18 #include "ui/views/widget/native_widget_private.h" | |
19 #include "ui/views/widget/widget.h" | |
20 | |
21 namespace ash { | |
22 namespace { | |
23 | |
24 using namespace ui::devtools::protocol; | |
25 | |
26 const int kDefaultChildNodeCount = -1; | |
27 const SkColor kBackgroundColor = SK_ColorRED; | |
28 const SkColor kBorderColor = SK_ColorBLUE; | |
29 | |
30 class TestView : public views::View { | |
31 public: | |
32 TestView(const char* name) : views::View(), name_(name) {} | |
33 | |
34 const char* GetClassName() const override { return name_; } | |
35 | |
36 private: | |
37 const char* name_; | |
38 | |
39 DISALLOW_COPY_AND_ASSIGN(TestView); | |
40 }; | |
41 | |
42 class FakeFrontendChannel : public FrontendChannel { | |
43 public: | |
44 FakeFrontendChannel() {} | |
45 ~FakeFrontendChannel() override {} | |
46 | |
47 int CountProtocolNotificationMessageStartsWith(const std::string& message) { | |
48 int count = 0; | |
49 for (const std::string& s : protocol_notification_messages_) { | |
50 if (base::StartsWith(s, message, base::CompareCase::SENSITIVE)) | |
51 count++; | |
52 } | |
53 return count; | |
54 } | |
55 | |
56 int CountProtocolNotificationMessage(const std::string& message) { | |
57 return std::count(protocol_notification_messages_.begin(), | |
58 protocol_notification_messages_.end(), message); | |
59 } | |
60 | |
61 // FrontendChannel | |
62 void sendProtocolResponse(int callId, | |
63 std::unique_ptr<Serializable> message) override {} | |
64 void flushProtocolNotifications() override {} | |
65 void sendProtocolNotification( | |
66 std::unique_ptr<Serializable> message) override { | |
67 protocol_notification_messages_.push_back(message->serialize()); | |
68 } | |
69 | |
70 private: | |
71 std::vector<std::string> protocol_notification_messages_; | |
72 | |
73 DISALLOW_COPY_AND_ASSIGN(FakeFrontendChannel); | |
74 }; | |
75 | |
76 std::string GetAttributeValue(const std::string& attribute, DOM::Node* node) { | |
77 EXPECT_TRUE(node->hasAttributes()); | |
78 Array<std::string>* attributes = node->getAttributes(nullptr); | |
79 for (size_t i = 0; i < attributes->length() - 1; i++) { | |
80 if (attributes->get(i) == attribute) | |
81 return attributes->get(i + 1); | |
82 } | |
83 return nullptr; | |
84 } | |
85 | |
86 bool Equals(aura::Window* window, DOM::Node* node) { | |
87 int children_count = static_cast<int>(window->children().size()); | |
88 if (GetInternalWidgetForWindow(window)) | |
89 children_count++; | |
90 return "Window" == node->getNodeName() && | |
91 window->GetName() == GetAttributeValue("name", node) && | |
92 children_count == node->getChildNodeCount(kDefaultChildNodeCount); | |
93 } | |
94 | |
95 void Compare(views::Widget* widget, DOM::Node* node) { | |
96 EXPECT_EQ("Widget", node->getNodeName()); | |
97 EXPECT_EQ(widget->GetName(), GetAttributeValue("name", node)); | |
98 EXPECT_EQ(widget->GetRootView() ? 1 : 0, | |
99 node->getChildNodeCount(kDefaultChildNodeCount)); | |
100 } | |
101 | |
102 void Compare(views::View* view, DOM::Node* node) { | |
103 EXPECT_EQ("View", node->getNodeName()); | |
104 EXPECT_EQ(view->GetClassName(), GetAttributeValue("name", node)); | |
105 EXPECT_EQ(view->child_count(), | |
106 node->getChildNodeCount(kDefaultChildNodeCount)); | |
107 } | |
108 | |
109 void Compare(aura::Window* window, DOM::Node* node) { | |
110 EXPECT_TRUE(Equals(window, node)); | |
111 } | |
112 | |
113 DOM::Node* FindInRoot(aura::Window* window, DOM::Node* root) { | |
114 if (Equals(window, root)) | |
115 return root; | |
116 | |
117 Array<DOM::Node>* children = root->getChildren(nullptr); | |
118 DOM::Node* window_node = nullptr; | |
119 for (size_t i = 0; i < children->length(); i++) { | |
120 window_node = FindInRoot(window, children->get(i)); | |
121 if (window_node) | |
122 return window_node; | |
123 } | |
124 return window_node; | |
125 } | |
126 | |
127 int GetPropertyByName(const std::string& name, | |
128 Array<CSS::CSSProperty>* properties) { | |
129 for (size_t i = 0; i < properties->length(); i++) { | |
130 CSS::CSSProperty* property = properties->get(i); | |
131 if (property->getName() == name) { | |
132 int value; | |
133 EXPECT_TRUE(base::StringToInt(property->getValue(), &value)); | |
134 return value; | |
135 } | |
136 } | |
137 NOTREACHED(); | |
138 return -1; | |
139 } | |
140 | |
141 aura::Window* GetHighlightingWindow(aura::Window* root_window) { | |
142 const aura::Window::Windows& overlay_windows = | |
143 root_window->GetChildById(kShellWindowId_OverlayContainer)->children(); | |
144 for (aura::Window* window : overlay_windows) { | |
145 if (window->GetName() == "HighlightingWidget") | |
146 return window; | |
147 } | |
148 NOTREACHED(); | |
149 return nullptr; | |
150 } | |
151 | |
152 std::unique_ptr<DOM::RGBA> SkColorToRGBA(const SkColor& color) { | |
153 return DOM::RGBA::create() | |
154 .setA(SkColorGetA(color) / 255) | |
155 .setB(SkColorGetB(color)) | |
156 .setG(SkColorGetG(color)) | |
157 .setR(SkColorGetR(color)) | |
158 .build(); | |
159 } | |
160 | |
161 std::unique_ptr<DOM::HighlightConfig> CreateHighlightConfig( | |
162 const SkColor& background_color, | |
163 const SkColor& border_color) { | |
164 return DOM::HighlightConfig::create() | |
165 .setContentColor(SkColorToRGBA(background_color)) | |
166 .setBorderColor(SkColorToRGBA(border_color)) | |
167 .build(); | |
168 } | |
169 | |
170 void ExpectHighlighted(const gfx::Rect& bounds, aura::Window* root_window) { | |
171 aura::Window* highlighting_window = GetHighlightingWindow(root_window); | |
172 EXPECT_TRUE(highlighting_window->IsVisible()); | |
173 EXPECT_EQ(bounds, highlighting_window->GetBoundsInScreen()); | |
174 EXPECT_EQ(kBackgroundColor, GetInternalWidgetForWindow(highlighting_window) | |
175 ->GetRootView() | |
176 ->background() | |
177 ->get_color()); | |
178 } | |
179 | |
180 } // namespace | |
181 | |
182 class AshDevToolsTest : public test::AshTestBase { | |
183 public: | |
184 AshDevToolsTest() {} | |
185 ~AshDevToolsTest() override {} | |
186 | |
187 views::internal::NativeWidgetPrivate* CreateTestNativeWidget() { | |
188 views::Widget* widget = new views::Widget; | |
189 views::Widget::InitParams params; | |
190 params.ownership = views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET; | |
191 params.parent = nullptr; | |
192 if (!dom_agent()->root_windows().empty()) { | |
193 params.parent = dom_agent()->root_windows()[0]->GetChildById( | |
194 kShellWindowId_DefaultContainer); | |
195 } | |
196 widget->Init(params); | |
197 return widget->native_widget_private(); | |
198 } | |
199 | |
200 std::unique_ptr<views::Widget> CreateTestWidget(const gfx::Rect& bounds) { | |
201 return AshTestBase::CreateTestWidget(nullptr, kShellWindowId_Invalid, | |
202 bounds); | |
203 } | |
204 | |
205 void SetUp() override { | |
206 fake_frontend_channel_ = base::MakeUnique<FakeFrontendChannel>(); | |
207 uber_dispatcher_ = | |
208 base::MakeUnique<UberDispatcher>(fake_frontend_channel_.get()); | |
209 dom_agent_ = base::MakeUnique<devtools::AshDevToolsDOMAgent>(); | |
210 dom_agent_->Init(uber_dispatcher_.get()); | |
211 css_agent_ = | |
212 base::MakeUnique<devtools::AshDevToolsCSSAgent>(dom_agent_.get()); | |
213 css_agent_->Init(uber_dispatcher_.get()); | |
214 css_agent_->enable(); | |
215 AshTestBase::SetUp(); | |
216 } | |
217 | |
218 void TearDown() override { | |
219 css_agent_.reset(); | |
220 dom_agent_.reset(); | |
221 uber_dispatcher_.reset(); | |
222 fake_frontend_channel_.reset(); | |
223 AshTestBase::TearDown(); | |
224 } | |
225 | |
226 void ExpectChildNodeInserted(int parent_id, int prev_sibling_id) { | |
227 EXPECT_EQ(1, frontend_channel()->CountProtocolNotificationMessageStartsWith( | |
228 base::StringPrintf("{\"method\":\"DOM.childNodeInserted\"," | |
229 "\"params\":{\"parentNodeId\":%d," | |
230 "\"previousNodeId\":%d", | |
231 parent_id, prev_sibling_id))); | |
232 } | |
233 | |
234 void ExpectChildNodeRemoved(int parent_id, int node_id) { | |
235 EXPECT_EQ(1, frontend_channel()->CountProtocolNotificationMessage( | |
236 base::StringPrintf( | |
237 "{\"method\":\"DOM.childNodeRemoved\",\"params\":{" | |
238 "\"parentNodeId\":%d,\"nodeId\":%d}}", | |
239 parent_id, node_id))); | |
240 } | |
241 | |
242 int GetStyleSheetChangedCount(int node_id) { | |
243 return frontend_channel()->CountProtocolNotificationMessage( | |
244 base::StringPrintf("{\"method\":\"CSS.styleSheetChanged\",\"params\":{" | |
245 "\"styleSheetId\":\"%d\"}}", | |
246 node_id)); | |
247 } | |
248 | |
249 void CompareNodeBounds(DOM::Node* node, const gfx::Rect& bounds) { | |
250 Maybe<CSS::CSSStyle> styles; | |
251 css_agent_->getMatchedStylesForNode(node->getNodeId(), &styles); | |
252 ASSERT_TRUE(styles.isJust()); | |
253 Array<CSS::CSSProperty>* properties = styles.fromJust()->getCssProperties(); | |
254 EXPECT_EQ(bounds.height(), GetPropertyByName("height", properties)); | |
255 EXPECT_EQ(bounds.width(), GetPropertyByName("width", properties)); | |
256 EXPECT_EQ(bounds.x(), GetPropertyByName("x", properties)); | |
257 EXPECT_EQ(bounds.y(), GetPropertyByName("y", properties)); | |
258 } | |
259 | |
260 void SetStyleTexts(DOM::Node* node, | |
261 const std::string& style_text, | |
262 bool success) { | |
263 auto edits = Array<CSS::StyleDeclarationEdit>::create(); | |
264 auto edit = CSS::StyleDeclarationEdit::create() | |
265 .setStyleSheetId(base::IntToString(node->getNodeId())) | |
266 .setText(style_text) | |
267 .build(); | |
268 edits->addItem(std::move(edit)); | |
269 std::unique_ptr<Array<CSS::CSSStyle>> output; | |
270 EXPECT_EQ(success, | |
271 css_agent_->setStyleTexts(std::move(edits), &output).isSuccess()); | |
272 | |
273 if (success) | |
274 ASSERT_TRUE(output); | |
275 else | |
276 ASSERT_FALSE(output); | |
277 } | |
278 | |
279 void HighlightNode(int node_id) { | |
280 dom_agent_->highlightNode( | |
281 CreateHighlightConfig(kBackgroundColor, kBorderColor), node_id); | |
282 } | |
283 | |
284 void HideHighlight(int root_window_index) { | |
285 dom_agent_->hideHighlight(); | |
286 ASSERT_FALSE( | |
287 GetHighlightingWindow(dom_agent()->root_windows()[root_window_index]) | |
288 ->IsVisible()); | |
289 } | |
290 | |
291 FakeFrontendChannel* frontend_channel() { | |
292 return fake_frontend_channel_.get(); | |
293 } | |
294 | |
295 devtools::AshDevToolsCSSAgent* css_agent() { return css_agent_.get(); } | |
296 devtools::AshDevToolsDOMAgent* dom_agent() { return dom_agent_.get(); } | |
297 | |
298 private: | |
299 std::unique_ptr<UberDispatcher> uber_dispatcher_; | |
300 std::unique_ptr<FakeFrontendChannel> fake_frontend_channel_; | |
301 std::unique_ptr<devtools::AshDevToolsDOMAgent> dom_agent_; | |
302 std::unique_ptr<devtools::AshDevToolsCSSAgent> css_agent_; | |
303 | |
304 DISALLOW_COPY_AND_ASSIGN(AshDevToolsTest); | |
305 }; | |
306 | |
307 TEST_F(AshDevToolsTest, GetDocumentWithWindowWidgetView) { | |
308 std::unique_ptr<views::Widget> widget( | |
309 CreateTestWidget(gfx::Rect(1, 1, 1, 1))); | |
310 aura::Window* parent_window = widget->GetNativeWindow(); | |
311 parent_window->SetName("parent_window"); | |
312 std::unique_ptr<aura::Window> child_window = CreateChildWindow(parent_window); | |
313 child_window->SetName("child_window"); | |
314 widget->Show(); | |
315 views::View* child_view = new TestView("child_view"); | |
316 widget->GetRootView()->AddChildView(child_view); | |
317 | |
318 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
319 dom_agent()->getDocument(&root); | |
320 | |
321 DOM::Node* parent_node = FindInRoot(parent_window, root.get()); | |
322 ASSERT_TRUE(parent_node); | |
323 Array<DOM::Node>* parent_children = parent_node->getChildren(nullptr); | |
324 ASSERT_TRUE(parent_children); | |
325 DOM::Node* widget_node = parent_children->get(0); | |
326 Compare(widget.get(), widget_node); | |
327 Compare(child_window.get(), parent_children->get(1)); | |
328 Array<DOM::Node>* widget_children = widget_node->getChildren(nullptr); | |
329 ASSERT_TRUE(widget_children); | |
330 Compare(widget->GetRootView(), widget_children->get(0)); | |
331 ASSERT_TRUE(widget_children->get(0)->getChildren(nullptr)); | |
332 Compare(child_view, widget_children->get(0)->getChildren(nullptr)->get(1)); | |
333 } | |
334 | |
335 TEST_F(AshDevToolsTest, GetDocumentNativeWidgetOwnsWidget) { | |
336 views::internal::NativeWidgetPrivate* native_widget_private = | |
337 CreateTestNativeWidget(); | |
338 views::Widget* widget = native_widget_private->GetWidget(); | |
339 aura::Window* parent_window = widget->GetNativeWindow(); | |
340 | |
341 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
342 dom_agent()->getDocument(&root); | |
343 | |
344 DOM::Node* parent_node = FindInRoot(parent_window, root.get()); | |
345 ASSERT_TRUE(parent_node); | |
346 DOM::Node* widget_node = parent_node->getChildren(nullptr)->get(0); | |
347 Compare(widget, widget_node); | |
348 // Destroy NativeWidget followed by |widget| | |
349 widget->CloseNow(); | |
350 } | |
351 | |
352 TEST_F(AshDevToolsTest, WindowAddedChildNodeInserted) { | |
353 // Initialize DOMAgent | |
354 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
355 dom_agent()->getDocument(&root); | |
356 | |
357 aura::Window* root_window = dom_agent()->root_windows()[0]; | |
358 aura::Window* parent_window = root_window->children()[0]; | |
359 DOM::Node* parent_node = FindInRoot(parent_window, root.get()); | |
360 Array<DOM::Node>* parent_node_children = parent_node->getChildren(nullptr); | |
361 DOM::Node* sibling_node = | |
362 parent_node_children->get(parent_node_children->length() - 1); | |
363 | |
364 std::unique_ptr<aura::Window> child(CreateChildWindow(parent_window)); | |
365 ExpectChildNodeInserted(parent_node->getNodeId(), sibling_node->getNodeId()); | |
366 } | |
367 | |
368 TEST_F(AshDevToolsTest, WindowDestroyedChildNodeRemoved) { | |
369 // Initialize DOMAgent | |
370 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
371 dom_agent()->getDocument(&root); | |
372 | |
373 aura::Window* root_window = dom_agent()->root_windows()[0]; | |
374 aura::Window* rotation_window = root_window->children()[0]; | |
375 aura::Window* parent_window = rotation_window->children()[0]; | |
376 aura::Window* child_window = parent_window->children()[0]; | |
377 DOM::Node* root_node = | |
378 root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0); | |
379 DOM::Node* parent_node = root_node->getChildren(nullptr)->get(0); | |
380 DOM::Node* child_node = parent_node->getChildren(nullptr)->get(0); | |
381 | |
382 Compare(parent_window, parent_node); | |
383 Compare(child_window, child_node); | |
384 delete child_window; | |
385 ExpectChildNodeRemoved(parent_node->getNodeId(), child_node->getNodeId()); | |
386 } | |
387 | |
388 TEST_F(AshDevToolsTest, WindowReorganizedChildNodeRearranged) { | |
389 // Initialize DOMAgent | |
390 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
391 dom_agent()->getDocument(&root); | |
392 | |
393 aura::Window* root_window = dom_agent()->root_windows()[0]; | |
394 aura::Window* rotation_window = root_window->children()[0]; | |
395 aura::Window* parent_window = rotation_window->children()[0]; | |
396 aura::Window* target_window = rotation_window->children()[1]; | |
397 aura::Window* child_window = parent_window->children()[0]; | |
398 | |
399 DOM::Node* root_node = | |
400 root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0); | |
401 DOM::Node* parent_node = root_node->getChildren(nullptr)->get(0); | |
402 DOM::Node* target_node = root_node->getChildren(nullptr)->get(1); | |
403 Array<DOM::Node>* target_node_children = target_node->getChildren(nullptr); | |
404 DOM::Node* sibling_node = | |
405 target_node_children->get(target_node_children->length() - 1); | |
406 DOM::Node* child_node = parent_node->getChildren(nullptr)->get(0); | |
407 | |
408 Compare(parent_window, parent_node); | |
409 Compare(target_window, target_node); | |
410 Compare(child_window, child_node); | |
411 target_window->AddChild(child_window); | |
412 ExpectChildNodeRemoved(parent_node->getNodeId(), child_node->getNodeId()); | |
413 ExpectChildNodeInserted(target_node->getNodeId(), sibling_node->getNodeId()); | |
414 } | |
415 | |
416 TEST_F(AshDevToolsTest, WindowReorganizedChildNodeRemovedAndInserted) { | |
417 aura::Window* root_window = dom_agent()->root_windows()[0]; | |
418 aura::Window* rotation_window = root_window->children()[0]; | |
419 aura::Window* parent_window = rotation_window->children()[0]; | |
420 aura::Window* target_window = rotation_window->children()[1]; | |
421 std::unique_ptr<aura::Window> child_window(CreateChildWindow(parent_window)); | |
422 | |
423 // Initialize DOMAgent | |
424 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
425 dom_agent()->getDocument(&root); | |
426 DOM::Node* root_node = | |
427 root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0); | |
428 DOM::Node* parent_node = root_node->getChildren(nullptr)->get(0); | |
429 DOM::Node* target_node = root_node->getChildren(nullptr)->get(1); | |
430 Array<DOM::Node>* target_node_children = target_node->getChildren(nullptr); | |
431 DOM::Node* sibling_node = | |
432 target_node_children->get(target_node_children->length() - 1); | |
433 Array<DOM::Node>* parent_node_children = parent_node->getChildren(nullptr); | |
434 DOM::Node* child_node = | |
435 parent_node_children->get(parent_node_children->length() - 1); | |
436 | |
437 Compare(parent_window, parent_node); | |
438 Compare(target_window, target_node); | |
439 Compare(child_window.get(), child_node); | |
440 parent_window->RemoveChild(child_window.get()); | |
441 target_window->AddChild(child_window.get()); | |
442 ExpectChildNodeRemoved(parent_node->getNodeId(), child_node->getNodeId()); | |
443 ExpectChildNodeInserted(target_node->getNodeId(), sibling_node->getNodeId()); | |
444 } | |
445 | |
446 TEST_F(AshDevToolsTest, WindowStackingChangedChildNodeRemovedAndInserted) { | |
447 // Initialize DOMAgent | |
448 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
449 dom_agent()->getDocument(&root); | |
450 | |
451 aura::Window* root_window = dom_agent()->root_windows()[0]; | |
452 aura::Window* parent_window = root_window->children()[0]; | |
453 aura::Window* child_window = parent_window->children()[0]; | |
454 aura::Window* target_window = parent_window->children()[1]; | |
455 | |
456 DOM::Node* parent_node = | |
457 root->getChildren(nullptr)->get(0)->getChildren(nullptr)->get(0); | |
458 Array<DOM::Node>* parent_node_children = parent_node->getChildren(nullptr); | |
459 DOM::Node* child_node = parent_node_children->get(0); | |
460 DOM::Node* sibling_node = parent_node_children->get(1); | |
461 int parent_id = parent_node->getNodeId(); | |
462 | |
463 Compare(parent_window, parent_node); | |
464 Compare(child_window, child_node); | |
465 parent_window->StackChildAbove(child_window, target_window); | |
466 ExpectChildNodeRemoved(parent_id, child_node->getNodeId()); | |
467 ExpectChildNodeInserted(parent_id, sibling_node->getNodeId()); | |
468 } | |
469 | |
470 TEST_F(AshDevToolsTest, ViewInserted) { | |
471 std::unique_ptr<views::Widget> widget( | |
472 CreateTestWidget(gfx::Rect(1, 1, 1, 1))); | |
473 aura::Window* window = widget->GetNativeWindow(); | |
474 widget->Show(); | |
475 | |
476 // Initialize DOMAgent | |
477 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
478 dom_agent()->getDocument(&root); | |
479 | |
480 DOM::Node* parent_node = FindInRoot(window, root.get()); | |
481 ASSERT_TRUE(parent_node); | |
482 DOM::Node* widget_node = parent_node->getChildren(nullptr)->get(0); | |
483 DOM::Node* root_view_node = widget_node->getChildren(nullptr)->get(0); | |
484 Array<DOM::Node>* root_view_children = root_view_node->getChildren(nullptr); | |
485 ASSERT_TRUE(root_view_children); | |
486 DOM::Node* sibling_view_node = | |
487 root_view_children->get(root_view_children->length() - 1); | |
488 | |
489 widget->GetRootView()->AddChildView(new views::View); | |
490 ExpectChildNodeInserted(root_view_node->getNodeId(), | |
491 sibling_view_node->getNodeId()); | |
492 } | |
493 | |
494 TEST_F(AshDevToolsTest, ViewRemoved) { | |
495 std::unique_ptr<views::Widget> widget( | |
496 CreateTestWidget(gfx::Rect(1, 1, 1, 1))); | |
497 // Need to store |view| in unique_ptr because it is removed from the widget | |
498 // and needs to be destroyed independently | |
499 std::unique_ptr<views::View> child_view = base::MakeUnique<views::View>(); | |
500 aura::Window* window = widget->GetNativeWindow(); | |
501 widget->Show(); | |
502 views::View* root_view = widget->GetRootView(); | |
503 root_view->AddChildView(child_view.get()); | |
504 | |
505 // Initialize DOMAgent | |
506 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
507 dom_agent()->getDocument(&root); | |
508 | |
509 DOM::Node* parent_node = FindInRoot(window, root.get()); | |
510 ASSERT_TRUE(parent_node); | |
511 DOM::Node* widget_node = parent_node->getChildren(nullptr)->get(0); | |
512 DOM::Node* root_view_node = widget_node->getChildren(nullptr)->get(0); | |
513 Array<DOM::Node>* root_view_children = root_view_node->getChildren(nullptr); | |
514 ASSERT_TRUE(root_view_children); | |
515 DOM::Node* child_view_node = | |
516 root_view_children->get(root_view_children->length() - 1); | |
517 | |
518 Compare(child_view.get(), child_view_node); | |
519 root_view->RemoveChildView(child_view.get()); | |
520 ExpectChildNodeRemoved(root_view_node->getNodeId(), | |
521 child_view_node->getNodeId()); | |
522 } | |
523 | |
524 TEST_F(AshDevToolsTest, ViewRearranged) { | |
525 std::unique_ptr<views::Widget> widget( | |
526 CreateTestWidget(gfx::Rect(1, 1, 1, 1))); | |
527 aura::Window* window = widget->GetNativeWindow(); | |
528 widget->Show(); | |
529 views::View* root_view = widget->GetRootView(); | |
530 views::View* parent_view = new views::View; | |
531 views::View* target_view = new views::View; | |
532 views::View* child_view = new views::View; | |
533 views::View* child_view_1 = new views::View; | |
534 | |
535 root_view->AddChildView(parent_view); | |
536 root_view->AddChildView(target_view); | |
537 parent_view->AddChildView(child_view); | |
538 parent_view->AddChildView(child_view_1); | |
539 | |
540 // Initialize DOMAgent | |
541 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
542 dom_agent()->getDocument(&root); | |
543 | |
544 DOM::Node* parent_node = FindInRoot(window, root.get()); | |
545 ASSERT_TRUE(parent_node); | |
546 DOM::Node* widget_node = parent_node->getChildren(nullptr)->get(0); | |
547 DOM::Node* root_view_node = widget_node->getChildren(nullptr)->get(0); | |
548 Array<DOM::Node>* root_view_children = root_view_node->getChildren(nullptr); | |
549 ASSERT_TRUE(root_view_children); | |
550 size_t root_children_size = root_view_children->length(); | |
551 ASSERT_TRUE(root_children_size >= 2); | |
552 DOM::Node* parent_view_node = root_view_children->get(root_children_size - 2); | |
553 DOM::Node* target_view_node = root_view_children->get(root_children_size - 1); | |
554 DOM::Node* child_view_node = parent_view_node->getChildren(nullptr)->get(0); | |
555 DOM::Node* child_view_node_1 = parent_view_node->getChildren(nullptr)->get(1); | |
556 | |
557 Compare(parent_view, parent_view_node); | |
558 Compare(target_view, target_view_node); | |
559 Compare(child_view, child_view_node); | |
560 Compare(child_view_1, child_view_node_1); | |
561 | |
562 ASSERT_NE(child_view_node->getNodeId(), child_view_node_1->getNodeId()); | |
563 | |
564 // Reorder child_view_1 from index 1 to 0 in view::Views tree. This makes DOM | |
565 // tree remove view node at position 1 and insert it at position 0. | |
566 parent_view->ReorderChildView(child_view_1, 0); | |
567 ExpectChildNodeRemoved(parent_view_node->getNodeId(), | |
568 child_view_node_1->getNodeId()); | |
569 ExpectChildNodeInserted(parent_view_node->getNodeId(), 0); | |
570 | |
571 target_view->AddChildView(child_view); | |
572 ExpectChildNodeRemoved(parent_view_node->getNodeId(), | |
573 child_view_node->getNodeId()); | |
574 ExpectChildNodeInserted(target_view_node->getNodeId(), 0); | |
575 } | |
576 | |
577 TEST_F(AshDevToolsTest, ViewRearrangedRemovedAndInserted) { | |
578 std::unique_ptr<views::Widget> widget( | |
579 CreateTestWidget(gfx::Rect(1, 1, 1, 1))); | |
580 aura::Window* window = widget->GetNativeWindow(); | |
581 widget->Show(); | |
582 views::View* root_view = widget->GetRootView(); | |
583 views::View* parent_view = new views::View; | |
584 views::View* target_view = new views::View; | |
585 views::View* child_view = new views::View; | |
586 root_view->AddChildView(parent_view); | |
587 root_view->AddChildView(target_view); | |
588 parent_view->AddChildView(child_view); | |
589 | |
590 // Initialize DOMAgent | |
591 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
592 dom_agent()->getDocument(&root); | |
593 | |
594 DOM::Node* parent_node = FindInRoot(window, root.get()); | |
595 ASSERT_TRUE(parent_node); | |
596 DOM::Node* widget_node = parent_node->getChildren(nullptr)->get(0); | |
597 DOM::Node* root_view_node = widget_node->getChildren(nullptr)->get(0); | |
598 Array<DOM::Node>* root_view_children = root_view_node->getChildren(nullptr); | |
599 ASSERT_TRUE(root_view_children); | |
600 size_t root_children_size = root_view_children->length(); | |
601 ASSERT_TRUE(root_children_size >= 2); | |
602 DOM::Node* parent_view_node = root_view_children->get(root_children_size - 2); | |
603 DOM::Node* target_view_node = root_view_children->get(root_children_size - 1); | |
604 DOM::Node* child_view_node = parent_view_node->getChildren(nullptr)->get(0); | |
605 | |
606 Compare(parent_view, parent_view_node); | |
607 Compare(target_view, target_view_node); | |
608 Compare(child_view, child_view_node); | |
609 parent_view->RemoveChildView(child_view); | |
610 target_view->AddChildView(child_view); | |
611 ExpectChildNodeRemoved(parent_view_node->getNodeId(), | |
612 child_view_node->getNodeId()); | |
613 ExpectChildNodeInserted(target_view_node->getNodeId(), 0); | |
614 } | |
615 | |
616 TEST_F(AshDevToolsTest, WindowWidgetViewHighlight) { | |
617 std::unique_ptr<views::Widget> widget( | |
618 CreateTestWidget(gfx::Rect(0, 0, 400, 400))); | |
619 aura::Window* parent_window = widget->GetNativeWindow(); | |
620 std::unique_ptr<aura::Window> window(CreateChildWindow(parent_window)); | |
621 views::View* root_view = widget->GetRootView(); | |
622 | |
623 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
624 dom_agent()->getDocument(&root); | |
625 | |
626 DOM::Node* parent_node = FindInRoot(parent_window, root.get()); | |
627 ASSERT_TRUE(parent_node); | |
628 Array<DOM::Node>* parent_children = parent_node->getChildren(nullptr); | |
629 ASSERT_TRUE(parent_children); | |
630 DOM::Node* window_node = parent_children->get(1); | |
631 DOM::Node* widget_node = parent_children->get(0); | |
632 DOM::Node* root_view_node = widget_node->getChildren(nullptr)->get(0); | |
633 | |
634 HighlightNode(window_node->getNodeId()); | |
635 ExpectHighlighted(window->GetBoundsInScreen(), | |
636 dom_agent()->root_windows()[0]); | |
637 | |
638 HideHighlight(0); | |
639 | |
640 HighlightNode(widget_node->getNodeId()); | |
641 ExpectHighlighted(widget->GetWindowBoundsInScreen(), | |
642 dom_agent()->root_windows()[0]); | |
643 | |
644 HideHighlight(0); | |
645 | |
646 HighlightNode(root_view_node->getNodeId()); | |
647 ExpectHighlighted(root_view->GetBoundsInScreen(), | |
648 dom_agent()->root_windows()[0]); | |
649 | |
650 HideHighlight(0); | |
651 | |
652 // Highlight non-existent node | |
653 HighlightNode(10000); | |
654 EXPECT_FALSE( | |
655 GetHighlightingWindow(dom_agent()->root_windows()[0])->IsVisible()); | |
656 } | |
657 | |
658 int GetNodeIdFromWindow(devtools::UIElement* ui_element, aura::Window* window) { | |
659 for (auto* child : ui_element->children()) { | |
660 if (child->type() == devtools::UIElementType::WINDOW && | |
661 static_cast<devtools::WindowElement*>(child)->window() == window) { | |
662 return child->node_id(); | |
663 } | |
664 } | |
665 for (auto* child : ui_element->children()) { | |
666 if (child->type() == devtools::UIElementType::WINDOW) { | |
667 int node_id = GetNodeIdFromWindow(child, window); | |
668 if (node_id > 0) | |
669 return node_id; | |
670 } | |
671 } | |
672 return 0; | |
673 } | |
674 | |
675 TEST_F(AshDevToolsTest, MultipleDisplayHighlight) { | |
676 UpdateDisplay("300x400,500x500"); | |
677 | |
678 aura::Window::Windows root_windows = dom_agent()->root_windows(); | |
679 std::unique_ptr<aura::Window> window( | |
680 CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40))); | |
681 | |
682 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
683 dom_agent()->getDocument(&root); | |
684 | |
685 EXPECT_EQ(root_windows[0], window->GetRootWindow()); | |
686 HighlightNode( | |
687 GetNodeIdFromWindow(dom_agent()->window_element_root(), window.get())); | |
688 ExpectHighlighted(window->GetBoundsInScreen(), | |
689 dom_agent()->root_windows()[0]); | |
690 | |
691 window->SetBoundsInScreen(gfx::Rect(500, 0, 50, 50), GetSecondaryDisplay()); | |
692 EXPECT_EQ(root_windows[1], window->GetRootWindow()); | |
693 HighlightNode( | |
694 GetNodeIdFromWindow(dom_agent()->window_element_root(), window.get())); | |
695 ExpectHighlighted(window->GetBoundsInScreen(), | |
696 dom_agent()->root_windows()[1]); | |
697 } | |
698 | |
699 TEST_F(AshDevToolsTest, WindowWidgetViewGetMatchedStylesForNode) { | |
700 std::unique_ptr<views::Widget> widget( | |
701 CreateTestWidget(gfx::Rect(1, 1, 1, 1))); | |
702 aura::Window* parent_window = widget->GetNativeWindow(); | |
703 std::unique_ptr<aura::Window> window(CreateChildWindow(parent_window)); | |
704 gfx::Rect window_bounds(2, 2, 3, 3); | |
705 gfx::Rect widget_bounds(50, 50, 100, 75); | |
706 gfx::Rect view_bounds(4, 4, 3, 3); | |
707 window->SetBounds(window_bounds); | |
708 widget->SetBounds(widget_bounds); | |
709 widget->GetRootView()->SetBoundsRect(view_bounds); | |
710 | |
711 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
712 dom_agent()->getDocument(&root); | |
713 | |
714 DOM::Node* parent_node = FindInRoot(parent_window, root.get()); | |
715 ASSERT_TRUE(parent_node); | |
716 Array<DOM::Node>* parent_children = parent_node->getChildren(nullptr); | |
717 ASSERT_TRUE(parent_children); | |
718 | |
719 CompareNodeBounds(parent_node, widget_bounds); | |
720 CompareNodeBounds(parent_children->get(1), window_bounds); | |
721 CompareNodeBounds(parent_children->get(0)->getChildren(nullptr)->get(0), | |
722 view_bounds); | |
723 } | |
724 | |
725 TEST_F(AshDevToolsTest, WindowWidgetViewStyleSheetChanged) { | |
726 std::unique_ptr<views::Widget> widget( | |
727 CreateTestWidget(gfx::Rect(1, 1, 1, 1))); | |
728 aura::Window* widget_window = widget->GetNativeWindow(); | |
729 std::unique_ptr<aura::Window> child(CreateChildWindow(widget_window)); | |
730 | |
731 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
732 dom_agent()->getDocument(&root); | |
733 | |
734 gfx::Rect child_bounds(2, 2, 3, 3); | |
735 gfx::Rect widget_bounds(10, 10, 150, 160); | |
736 gfx::Rect view_bounds(4, 4, 3, 3); | |
737 child->SetBounds(child_bounds); | |
738 widget->SetBounds(widget_bounds); | |
739 widget->GetRootView()->SetBoundsRect(view_bounds); | |
740 | |
741 DOM::Node* widget_node = FindInRoot(widget_window, root.get()); | |
742 ASSERT_TRUE(widget_node); | |
743 Array<DOM::Node>* widget_node_children = widget_node->getChildren(nullptr); | |
744 ASSERT_TRUE(widget_node_children); | |
745 | |
746 EXPECT_EQ(1, GetStyleSheetChangedCount(widget_node->getNodeId())); | |
747 EXPECT_EQ( | |
748 1, GetStyleSheetChangedCount(widget_node_children->get(1)->getNodeId())); | |
749 EXPECT_EQ(2, | |
750 GetStyleSheetChangedCount(widget_node_children->get(0) | |
751 ->getChildren(nullptr) | |
752 ->get(0) | |
753 ->getNodeId())); | |
754 } | |
755 | |
756 TEST_F(AshDevToolsTest, WindowWidgetViewSetStyleText) { | |
757 std::unique_ptr<views::Widget> widget( | |
758 CreateTestWidget(gfx::Rect(0, 0, 400, 400))); | |
759 aura::Window* parent_window = widget->GetNativeWindow(); | |
760 std::unique_ptr<aura::Window> window(CreateChildWindow(parent_window)); | |
761 views::View* root_view = widget->GetRootView(); | |
762 | |
763 std::unique_ptr<ui::devtools::protocol::DOM::Node> root; | |
764 dom_agent()->getDocument(&root); | |
765 | |
766 DOM::Node* parent_node = FindInRoot(parent_window, root.get()); | |
767 ASSERT_TRUE(parent_node); | |
768 Array<DOM::Node>* parent_children = parent_node->getChildren(nullptr); | |
769 ASSERT_TRUE(parent_children); | |
770 | |
771 // Test different combinations on window node | |
772 DOM::Node* window_node = parent_children->get(1); | |
773 | |
774 SetStyleTexts(window_node, | |
775 "x: 25; y:35; width: 5; height: 20; visibility: 1;", true); | |
776 EXPECT_EQ(gfx::Rect(25, 35, 5, 20), window->bounds()); | |
777 EXPECT_TRUE(window->IsVisible()); | |
778 | |
779 SetStyleTexts(window_node, "test_nothing_happens:1;", false); | |
780 EXPECT_EQ(gfx::Rect(25, 35, 5, 20), window->bounds()); // Not changed | |
781 | |
782 SetStyleTexts(window_node, "\nheight: 10;\nvisibility: 0;\n", true); | |
783 EXPECT_EQ(gfx::Rect(25, 35, 5, 10), window->bounds()); | |
784 EXPECT_FALSE(window->IsVisible()); | |
785 | |
786 SetStyleTexts(window_node, "\nx: 10; y: 23; width: 52;\n ", true); | |
787 EXPECT_EQ(gfx::Rect(10, 23, 52, 10), window->bounds()); | |
788 | |
789 // Test different combinations on widget node | |
790 DOM::Node* widget_node = parent_children->get(0); | |
791 | |
792 SetStyleTexts(widget_node, | |
793 "x: 25; y:35; width: 53; height: 64; visibility: 0;", true); | |
794 EXPECT_EQ(gfx::Rect(25, 35, 53, 64), widget->GetRestoredBounds()); | |
795 EXPECT_FALSE(widget->IsVisible()); | |
796 | |
797 SetStyleTexts(widget_node, "test_nothing_happens:1;", false); | |
798 EXPECT_EQ(gfx::Rect(25, 35, 53, 64), | |
799 widget->GetRestoredBounds()); // Not changed | |
800 | |
801 SetStyleTexts(widget_node, "\nheight: 123;\nvisibility: 1;\n", true); | |
802 EXPECT_EQ(gfx::Rect(25, 35, 53, 123), widget->GetRestoredBounds()); | |
803 EXPECT_TRUE(widget->IsVisible()); | |
804 | |
805 SetStyleTexts(widget_node, "\nx: 10; y: 23; width: 98;\n ", true); | |
806 EXPECT_EQ(gfx::Rect(10, 23, 98, 123), widget->GetRestoredBounds()); | |
807 | |
808 // Test different combinations on view node | |
809 DOM::Node* root_view_node = widget_node->getChildren(nullptr)->get(0); | |
810 | |
811 SetStyleTexts(root_view_node, | |
812 "x: 25; y:35; width: 45; height: 20; visibility: 0;", true); | |
813 EXPECT_EQ(gfx::Rect(25, 35, 45, 20), root_view->bounds()); | |
814 EXPECT_FALSE(root_view->visible()); | |
815 | |
816 SetStyleTexts(root_view_node, "test_nothing_happens:1;", false); | |
817 EXPECT_EQ(gfx::Rect(25, 35, 45, 20), root_view->bounds()); // Not changed | |
818 | |
819 SetStyleTexts(root_view_node, "\nheight: 73;\n ", true); | |
820 EXPECT_EQ(gfx::Rect(25, 35, 45, 73), root_view->bounds()); | |
821 | |
822 SetStyleTexts(root_view_node, "\nx: 10; y: 23; width: 52;\nvisibility: 1;\n", | |
823 true); | |
824 EXPECT_EQ(gfx::Rect(10, 23, 52, 73), root_view->bounds()); | |
825 EXPECT_TRUE(root_view->visible()); | |
826 } | |
827 | |
828 } // namespace ash | |
OLD | NEW |