Commit 4340537d authored by Xiaohui Chen's avatar Xiaohui Chen Committed by Commit Bot

Add new system log source for UI hierarchy

Bug: 1069659
Change-Id: I9b1e88b975544136d2f1827ac222874091f9b65b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2144626
Commit-Queue: Xiaohui Chen <xiaohuic@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#759023}
parent 2c797624
...@@ -45,6 +45,7 @@ component("ash") { ...@@ -45,6 +45,7 @@ component("ash") {
"public/cpp/assistant/assistant_settings.h", "public/cpp/assistant/assistant_settings.h",
"public/cpp/autotest_desks_api.h", "public/cpp/autotest_desks_api.h",
"public/cpp/autotest_private_api_utils.h", "public/cpp/autotest_private_api_utils.h",
"public/cpp/debug_utils.h",
"public/cpp/docked_magnifier_controller.h", "public/cpp/docked_magnifier_controller.h",
"public/cpp/event_rewriter_controller.h", "public/cpp/event_rewriter_controller.h",
"public/cpp/first_run_helper.h", "public/cpp/first_run_helper.h",
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "ash/accelerators/accelerator_commands.h" #include "ash/accelerators/accelerator_commands.h"
#include "ash/hud_display/hud_display.h" #include "ash/hud_display/hud_display.h"
#include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/ash_switches.h"
#include "ash/public/cpp/debug_utils.h"
#include "ash/public/cpp/toast_data.h" #include "ash/public/cpp/toast_data.h"
#include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_properties.h"
#include "ash/root_window_controller.h" #include "ash/root_window_controller.h"
...@@ -42,84 +43,6 @@ namespace ash { ...@@ -42,84 +43,6 @@ namespace ash {
namespace debug { namespace debug {
namespace { namespace {
void HandlePrintLayerHierarchy() {
for (aura::Window* root : Shell::Get()->GetAllRootWindows()) {
ui::Layer* layer = root->layer();
if (layer)
ui::PrintLayerHierarchy(
layer,
RootWindowController::ForWindow(root)->GetLastMouseLocationInRoot());
}
}
void HandlePrintViewHierarchy() {
aura::Window* active_window = window_util::GetActiveWindow();
if (!active_window)
return;
views::Widget* widget = views::Widget::GetWidgetForNativeView(active_window);
if (!widget)
return;
views::PrintViewHierarchy(widget->GetRootView());
}
void PrintWindowHierarchy(const aura::Window* active_window,
const aura::Window* focused_window,
aura::Window* window,
int indent,
std::ostringstream* out) {
std::string indent_str(indent, ' ');
std::string name(window->GetName());
if (name.empty())
name = "\"\"";
const gfx::Vector2dF& subpixel_position_offset =
window->layer()->GetSubpixelOffset();
*out << indent_str;
*out << name << " (" << window << ")"
<< " type=" << window->type();
int window_id = window->id();
if (window_id != aura::Window::kInitialId)
*out << " id=" << window_id;
if (window->GetProperty(kWindowStateKey))
*out << " " << WindowState::Get(window)->GetStateType();
*out << ((window == active_window) ? " [active]" : "")
<< ((window == focused_window) ? " [focused]" : "")
<< (window->IsVisible() ? " visible" : "") << " "
<< (window->occlusion_state() != aura::Window::OcclusionState::UNKNOWN
? aura::Window::OcclusionStateToString(window->occlusion_state())
: "")
<< " " << window->bounds().ToString();
if (!subpixel_position_offset.IsZero())
*out << " subpixel offset=" + subpixel_position_offset.ToString();
std::string* tree_id = window->GetProperty(ui::kChildAXTreeID);
if (tree_id)
*out << " ax_tree_id=" << *tree_id;
base::string16 title(window->GetTitle());
if (!title.empty())
*out << " title=" << title;
int app_type = window->GetProperty(aura::client::kAppType);
*out << " app_type=" << app_type;
std::string* pkg_name = window->GetProperty(ash::kArcPackageNameKey);
if (pkg_name)
*out << " pkg_name=" << *pkg_name;
*out << '\n';
for (aura::Window* child : window->children())
PrintWindowHierarchy(active_window, focused_window, child, indent + 3, out);
}
void HandlePrintWindowHierarchy() {
aura::Window* active_window = window_util::GetActiveWindow();
aura::Window* focused_window = window_util::GetFocusedWindow();
aura::Window::Windows roots = Shell::Get()->GetAllRootWindows();
for (size_t i = 0; i < roots.size(); ++i) {
std::ostringstream out;
out << "RootWindow " << i << ":\n";
PrintWindowHierarchy(active_window, focused_window, roots[i], 0, &out);
// Error so logs can be collected from end-users.
LOG(ERROR) << out.str();
}
}
gfx::ImageSkia CreateWallpaperImage(SkColor fill, SkColor rect) { gfx::ImageSkia CreateWallpaperImage(SkColor fill, SkColor rect) {
// TODO(oshima): Consider adding a command line option to control wallpaper // TODO(oshima): Consider adding a command line option to control wallpaper
// images for testing. The size is randomly picked. // images for testing. The size is randomly picked.
...@@ -195,6 +118,101 @@ void HandleTriggerHUDDisplay() { ...@@ -195,6 +118,101 @@ void HandleTriggerHUDDisplay() {
} // namespace } // namespace
void PrintLayerHierarchy(std::ostringstream* out) {
for (aura::Window* root : Shell::Get()->GetAllRootWindows()) {
ui::Layer* layer = root->layer();
if (layer) {
ui::PrintLayerHierarchy(
layer,
RootWindowController::ForWindow(root)->GetLastMouseLocationInRoot(),
out);
}
}
}
void HandlePrintLayerHierarchy() {
std::ostringstream out;
PrintLayerHierarchy(&out);
LOG(ERROR) << out.str();
}
void PrintViewHierarchy(std::ostringstream* out) {
aura::Window* active_window = window_util::GetActiveWindow();
if (!active_window)
return;
views::Widget* widget = views::Widget::GetWidgetForNativeView(active_window);
if (!widget)
return;
views::PrintViewHierarchy(widget->GetRootView(), out);
}
void HandlePrintViewHierarchy() {
std::ostringstream out;
PrintViewHierarchy(&out);
LOG(ERROR) << out.str();
}
void PrintWindowHierarchy(const aura::Window* active_window,
const aura::Window* focused_window,
aura::Window* window,
int indent,
std::ostringstream* out) {
std::string indent_str(indent, ' ');
std::string name(window->GetName());
if (name.empty())
name = "\"\"";
const gfx::Vector2dF& subpixel_position_offset =
window->layer()->GetSubpixelOffset();
*out << indent_str;
*out << name << " (" << window << ")"
<< " type=" << window->type();
int window_id = window->id();
if (window_id != aura::Window::kInitialId)
*out << " id=" << window_id;
if (window->GetProperty(kWindowStateKey))
*out << " " << WindowState::Get(window)->GetStateType();
*out << ((window == active_window) ? " [active]" : "")
<< ((window == focused_window) ? " [focused]" : "")
<< (window->IsVisible() ? " visible" : "") << " "
<< (window->occlusion_state() != aura::Window::OcclusionState::UNKNOWN
? aura::Window::OcclusionStateToString(window->occlusion_state())
: "")
<< " " << window->bounds().ToString();
if (!subpixel_position_offset.IsZero())
*out << " subpixel offset=" + subpixel_position_offset.ToString();
std::string* tree_id = window->GetProperty(ui::kChildAXTreeID);
if (tree_id)
*out << " ax_tree_id=" << *tree_id;
base::string16 title(window->GetTitle());
if (!title.empty())
*out << " title=" << title;
int app_type = window->GetProperty(aura::client::kAppType);
*out << " app_type=" << app_type;
std::string* pkg_name = window->GetProperty(ash::kArcPackageNameKey);
if (pkg_name)
*out << " pkg_name=" << *pkg_name;
*out << '\n';
for (aura::Window* child : window->children())
PrintWindowHierarchy(active_window, focused_window, child, indent + 3, out);
}
void PrintWindowHierarchy(std::ostringstream* out) {
aura::Window* active_window = window_util::GetActiveWindow();
aura::Window* focused_window = window_util::GetFocusedWindow();
aura::Window::Windows roots = Shell::Get()->GetAllRootWindows();
for (size_t i = 0; i < roots.size(); ++i) {
*out << "RootWindow " << i << ":\n";
PrintWindowHierarchy(active_window, focused_window, roots[i], 0, out);
}
}
void HandlePrintWindowHierarchy() {
std::ostringstream out;
PrintWindowHierarchy(&out);
LOG(ERROR) << out.str();
}
void PrintUIHierarchies() { void PrintUIHierarchies() {
// This is a separate command so the user only has to hit one key to generate // This is a separate command so the user only has to hit one key to generate
// all the logs. Developers use the individual dumps repeatedly, so keep // all the logs. Developers use the individual dumps repeatedly, so keep
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_PUBLIC_CPP_DEBUG_UTILS_H_
#define ASH_PUBLIC_CPP_DEBUG_UTILS_H_
#include <sstream>
#include "ash/ash_export.h"
namespace ash {
namespace debug {
// Prints all windows layer hierarchy to |out|.
ASH_EXPORT void PrintLayerHierarchy(std::ostringstream* out);
// Prints current active window's view hierarchy to |out|.
ASH_EXPORT void PrintViewHierarchy(std::ostringstream* out);
// Prints all windows hierarchy to |out|.
ASH_EXPORT void PrintWindowHierarchy(std::ostringstream* out);
} // namespace debug
} // namespace ash
#endif // ASH_PUBLIC_CPP_DEBUG_UTILS_H_
...@@ -2354,6 +2354,8 @@ source_set("chromeos") { ...@@ -2354,6 +2354,8 @@ source_set("chromeos") {
"system_logs/system_logs_writer.h", "system_logs/system_logs_writer.h",
"system_logs/touch_log_source.cc", "system_logs/touch_log_source.cc",
"system_logs/touch_log_source.h", "system_logs/touch_log_source.h",
"system_logs/ui_hierarchy_log_source.cc",
"system_logs/ui_hierarchy_log_source.h",
"system_token_cert_db_initializer.cc", "system_token_cert_db_initializer.cc",
"system_token_cert_db_initializer.h", "system_token_cert_db_initializer.h",
"tether/fake_tether_service.cc", "tether/fake_tether_service.cc",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/system_logs/ui_hierarchy_log_source.h"
#include <memory>
#include <utility>
#include "ash/public/cpp/debug_utils.h"
namespace system_logs {
void UiHierarchyLogSource::Fetch(SysLogsSourceCallback callback) {
DCHECK(!callback.is_null());
auto response = std::make_unique<SystemLogsResponse>();
{
std::ostringstream out;
ash::debug::PrintWindowHierarchy(&out);
response->emplace("UI Hierarchy: Windows", out.str());
}
{
std::ostringstream out;
ash::debug::PrintViewHierarchy(&out);
response->emplace("UI Hierarchy: Views", out.str());
}
{
std::ostringstream out;
ash::debug::PrintLayerHierarchy(&out);
response->emplace("UI Hierarchy: Layers", out.str());
}
std::move(callback).Run(std::move(response));
}
} // namespace system_logs
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_UI_HIERARCHY_LOG_SOURCE_H_
#define CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_UI_HIERARCHY_LOG_SOURCE_H_
#include "base/macros.h"
#include "components/feedback/system_logs/system_logs_source.h"
namespace system_logs {
class UiHierarchyLogSource : public SystemLogsSource {
public:
UiHierarchyLogSource() : SystemLogsSource("UiHierarchy") {}
UiHierarchyLogSource(const UiHierarchyLogSource&) = delete;
UiHierarchyLogSource& operator=(const UiHierarchyLogSource&) = delete;
~UiHierarchyLogSource() override = default;
private:
// Overridden from SystemLogsSource:
void Fetch(SysLogsSourceCallback callback) override;
};
} // namespace system_logs
#endif // CHROME_BROWSER_CHROMEOS_SYSTEM_LOGS_UI_HIERARCHY_LOG_SOURCE_H_
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "chrome/browser/feedback/system_logs/about_system_logs_fetcher.h" #include "chrome/browser/feedback/system_logs/about_system_logs_fetcher.h"
#include <memory>
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h" #include "chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h"
#include "chrome/browser/feedback/system_logs/log_sources/memory_details_log_source.h" #include "chrome/browser/feedback/system_logs/log_sources/memory_details_log_source.h"
...@@ -15,6 +17,7 @@ ...@@ -15,6 +17,7 @@
#include "chrome/browser/chromeos/system_logs/debug_daemon_log_source.h" #include "chrome/browser/chromeos/system_logs/debug_daemon_log_source.h"
#include "chrome/browser/chromeos/system_logs/device_event_log_source.h" #include "chrome/browser/chromeos/system_logs/device_event_log_source.h"
#include "chrome/browser/chromeos/system_logs/touch_log_source.h" #include "chrome/browser/chromeos/system_logs/touch_log_source.h"
#include "chrome/browser/chromeos/system_logs/ui_hierarchy_log_source.h"
#endif #endif
namespace system_logs { namespace system_logs {
...@@ -32,6 +35,7 @@ SystemLogsFetcher* BuildAboutSystemLogsFetcher() { ...@@ -32,6 +35,7 @@ SystemLogsFetcher* BuildAboutSystemLogsFetcher() {
fetcher->AddSource(std::make_unique<DBusLogSource>()); fetcher->AddSource(std::make_unique<DBusLogSource>());
fetcher->AddSource(std::make_unique<DeviceEventLogSource>()); fetcher->AddSource(std::make_unique<DeviceEventLogSource>());
fetcher->AddSource(std::make_unique<TouchLogSource>()); fetcher->AddSource(std::make_unique<TouchLogSource>());
fetcher->AddSource(std::make_unique<UiHierarchyLogSource>());
// Debug Daemon data source - currently only this data source supports // Debug Daemon data source - currently only this data source supports
// the scrub_data parameter. // the scrub_data parameter.
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "chrome/browser/feedback/system_logs/chrome_system_logs_fetcher.h" #include "chrome/browser/feedback/system_logs/chrome_system_logs_fetcher.h"
#include <memory>
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h" #include "chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.h"
#include "chrome/browser/feedback/system_logs/log_sources/crash_ids_source.h" #include "chrome/browser/feedback/system_logs/log_sources/crash_ids_source.h"
...@@ -18,6 +20,7 @@ ...@@ -18,6 +20,7 @@
#include "chrome/browser/chromeos/system_logs/device_event_log_source.h" #include "chrome/browser/chromeos/system_logs/device_event_log_source.h"
#include "chrome/browser/chromeos/system_logs/iwlwifi_dump_log_source.h" #include "chrome/browser/chromeos/system_logs/iwlwifi_dump_log_source.h"
#include "chrome/browser/chromeos/system_logs/touch_log_source.h" #include "chrome/browser/chromeos/system_logs/touch_log_source.h"
#include "chrome/browser/chromeos/system_logs/ui_hierarchy_log_source.h"
#endif #endif
namespace system_logs { namespace system_logs {
...@@ -37,6 +40,7 @@ SystemLogsFetcher* BuildChromeSystemLogsFetcher() { ...@@ -37,6 +40,7 @@ SystemLogsFetcher* BuildChromeSystemLogsFetcher() {
fetcher->AddSource(std::make_unique<DeviceEventLogSource>()); fetcher->AddSource(std::make_unique<DeviceEventLogSource>());
fetcher->AddSource(std::make_unique<IwlwifiDumpChecker>()); fetcher->AddSource(std::make_unique<IwlwifiDumpChecker>());
fetcher->AddSource(std::make_unique<TouchLogSource>()); fetcher->AddSource(std::make_unique<TouchLogSource>());
fetcher->AddSource(std::make_unique<UiHierarchyLogSource>());
// Debug Daemon data source - currently only this data source supports // Debug Daemon data source - currently only this data source supports
// the scrub_data parameter, but the others still get scrubbed by // the scrub_data parameter, but the others still get scrubbed by
......
...@@ -108,10 +108,16 @@ void PrintLayerHierarchyImp(const Layer* layer, ...@@ -108,10 +108,16 @@ void PrintLayerHierarchyImp(const Layer* layer,
void PrintLayerHierarchy(const Layer* layer, const gfx::Point& mouse_location) { void PrintLayerHierarchy(const Layer* layer, const gfx::Point& mouse_location) {
std::ostringstream out; std::ostringstream out;
out << "Layer hierarchy:\n"; PrintLayerHierarchy(layer, mouse_location, &out);
PrintLayerHierarchyImp(layer, 0, mouse_location, &out);
// Error so logs can be collected from end-users. // Error so logs can be collected from end-users.
LOG(ERROR) << out.str(); LOG(ERROR) << out.str();
} }
void PrintLayerHierarchy(const Layer* layer,
const gfx::Point& mouse_location,
std::ostringstream* out) {
*out << "Layer hierarchy:\n";
PrintLayerHierarchyImp(layer, 0, mouse_location, out);
}
} // namespace ui } // namespace ui
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef UI_COMPOSITOR_DEBUG_UTILS_H_ #ifndef UI_COMPOSITOR_DEBUG_UTILS_H_
#define UI_COMPOSITOR_DEBUG_UTILS_H_ #define UI_COMPOSITOR_DEBUG_UTILS_H_
#include <sstream>
#include "ui/compositor/compositor_export.h" #include "ui/compositor/compositor_export.h"
namespace gfx { namespace gfx {
...@@ -19,6 +21,12 @@ class Layer; ...@@ -19,6 +21,12 @@ class Layer;
COMPOSITOR_EXPORT void PrintLayerHierarchy(const Layer* layer, COMPOSITOR_EXPORT void PrintLayerHierarchy(const Layer* layer,
const gfx::Point& mouse_location); const gfx::Point& mouse_location);
// Print the layer hierarchy to |out|. Mark layers which contain
// |mouse_location| with '*'.
COMPOSITOR_EXPORT void PrintLayerHierarchy(const Layer* layer,
const gfx::Point& mouse_location,
std::ostringstream* out);
} // namespace ui } // namespace ui
#endif // UI_COMPOSITOR_DEBUG_UTILS_H_ #endif // UI_COMPOSITOR_DEBUG_UTILS_H_
...@@ -144,12 +144,16 @@ std::string PrintViewGraphImpl(const View* view) { ...@@ -144,12 +144,16 @@ std::string PrintViewGraphImpl(const View* view) {
void PrintViewHierarchy(const View* view) { void PrintViewHierarchy(const View* view) {
std::ostringstream out; std::ostringstream out;
out << "View hierarchy:\n"; PrintViewHierarchy(view, &out);
PrintViewHierarchyImp(view, 0, &out);
// Error so users in the field can generate and upload logs. // Error so users in the field can generate and upload logs.
LOG(ERROR) << out.str(); LOG(ERROR) << out.str();
} }
void PrintViewHierarchy(const View* view, std::ostringstream* out) {
*out << "View hierarchy:\n";
PrintViewHierarchyImp(view, 0, out);
}
void PrintFocusHierarchy(const View* view) { void PrintFocusHierarchy(const View* view) {
std::ostringstream out; std::ostringstream out;
out << "Focus hierarchy:\n"; out << "Focus hierarchy:\n";
......
...@@ -16,6 +16,9 @@ class View; ...@@ -16,6 +16,9 @@ class View;
// Log the view hierarchy. // Log the view hierarchy.
VIEWS_EXPORT void PrintViewHierarchy(const View* view); VIEWS_EXPORT void PrintViewHierarchy(const View* view);
// Print the view hierarchy to |out|.
VIEWS_EXPORT void PrintViewHierarchy(const View* view, std::ostringstream* out);
// Log the focus traversal hierarchy. // Log the focus traversal hierarchy.
VIEWS_EXPORT void PrintFocusHierarchy(const View* view); VIEWS_EXPORT void PrintFocusHierarchy(const View* view);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment