blob: b21b2da6afcc899ba3df1c3699dc816b3b5e2e81 [file] [log] [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/ui_devtools/views/dom_agent_views.h"
#include <memory>
#include <utility>
#include <vector>
#include "components/ui_devtools/devtools_server.h"
#include "components/ui_devtools/root_element.h"
#include "components/ui_devtools/ui_element.h"
#include "components/ui_devtools/views/view_element.h"
#include "components/ui_devtools/views/widget_element.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
namespace ui_devtools {
namespace {
using ui_devtools::protocol::Array;
using ui_devtools::protocol::DOM::Node;
} // namespace
DOMAgentViews::DOMAgentViews() = default;
DOMAgentViews::~DOMAgentViews() = default;
std::unique_ptr<Node> DOMAgentViews::BuildTreeForUIElement(
UIElement* ui_element) {
if (ui_element->type() == UIElementType::WINDOW) {
return BuildTreeForWindow(ui_element);
} else if (ui_element->type() == UIElementType::WIDGET) {
return BuildTreeForRootWidget(ui_element);
} else if (ui_element->type() == UIElementType::VIEW) {
return BuildTreeForView(ui_element);
}
return nullptr;
}
std::unique_ptr<Node> DOMAgentViews::BuildTreeForRootWidget(
UIElement* widget_element) {
DCHECK(widget_element->type() == UIElementType::WIDGET);
views::Widget* widget =
UIElement::GetBackingElement<views::Widget, WidgetElement>(
widget_element);
auto children = std::make_unique<protocol::Array<Node>>();
ViewElement* view_element =
new ViewElement(widget->GetRootView(), this, widget_element);
children->emplace_back(BuildTreeForView(view_element));
widget_element->AddChild(view_element);
std::unique_ptr<Node> node =
BuildNode("Widget",
std::make_unique<std::vector<std::string>>(
widget_element->GetAttributes()),
std::move(children), widget_element->node_id());
return node;
}
std::unique_ptr<Node> DOMAgentViews::BuildTreeForView(UIElement* view_element) {
DCHECK(view_element->type() == UIElementType::VIEW);
views::View* view =
UIElement::GetBackingElement<views::View, ViewElement>(view_element);
auto children = std::make_unique<protocol::Array<Node>>();
for (views::View* child : view->GetChildrenInZOrder()) {
// When building the subtree, a particular view could be visited multiple
// times because for each view of the subtree, we would call
// BuildTreeForView(..) on that view which causes the subtree with that view
// as root being visited again. Here we check if we already constructed the
// ViewElement and skip true.
UIElement* view_element_child = nullptr;
auto id =
view_element->FindUIElementIdForBackendElement<views::View>(child);
if (id > 0) {
view_element_child = GetElementFromNodeId(id);
} else {
view_element_child = new ViewElement(child, this, view_element);
view_element->AddChild(view_element_child);
}
children->emplace_back(BuildTreeForView(view_element_child));
}
return BuildNode(
"View",
std::make_unique<std::vector<std::string>>(view_element->GetAttributes()),
std::move(children), view_element->node_id());
}
} // namespace ui_devtools