1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/webui/internals/sessions/session_service_internals_handler.h"
#include <string>
#include "base/i18n/time_formatting.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/app_session_service.h"
#include "chrome/browser/sessions/app_session_service_factory.h"
#include "chrome/browser/sessions/session_service_factory.h"
#include "chrome/browser/sessions/session_service_log.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/webui_url_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_ui_data_source.h"
namespace {
// This is for debugging, so it doesn't use local time conversions.
std::string EventTimeToString(const SessionServiceEvent& event) {
return base::UnlocalizedTimeFormatWithPattern(event.time, "M/d/y H:mm:ss");
}
std::string EventToString(const SessionServiceEvent& event) {
switch (event.type) {
case SessionServiceEventLogType::kStart:
return base::StrCat(
{EventTimeToString(event), " start",
(event.data.start.did_last_session_crash ? " (last session crashed)"
: std::string())});
case SessionServiceEventLogType::kRestore:
return base::StrCat(
{EventTimeToString(event), " restore windows=",
base::NumberToString(event.data.restore.window_count),
" tabs=", base::NumberToString(event.data.restore.tab_count),
(event.data.restore.encountered_error_reading ? " (error reading)"
: std::string())});
case SessionServiceEventLogType::kExit:
return base::StrCat(
{EventTimeToString(event), " exit (shutdown) windows=",
base::NumberToString(event.data.exit.window_count),
" tabs=", base::NumberToString(event.data.exit.tab_count),
" is_first_service=",
base::NumberToString(event.data.exit.is_first_session_service),
" did_schedule_command=",
base::NumberToString(event.data.exit.did_schedule_command)});
case SessionServiceEventLogType::kWriteError:
return base::StrCat(
{EventTimeToString(event), " write errors (",
base::NumberToString(event.data.write_error.error_count), ")"});
case SessionServiceEventLogType::kRestoreCanceled:
return base::StrCat({EventTimeToString(event), " restore canceled"});
case SessionServiceEventLogType::kRestoreInitiated:
return base::StrCat(
{EventTimeToString(event), " restore initiated sync=",
base::NumberToString(event.data.restore_initiated.synchronous),
" restore_browser=",
base::NumberToString(event.data.restore_initiated.restore_browser)});
}
}
std::string GetSessionServiceInternalsAsString(Profile* profile) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
std::vector<std::string> events;
events.push_back("<pre>");
for (const auto& event : GetSessionServiceEvents(profile)) {
events.push_back(EventToString(event));
}
events.push_back("</pre>");
base::Value::Dict internals_output;
#if DCHECK_IS_ON()
internals_output.Set(
"AppSessionService",
AppSessionServiceFactory::GetForProfile(profile)->ToDebugValue());
internals_output.Set(
"SessionService",
SessionServiceFactory::GetForProfile(profile)->ToDebugValue());
#else
internals_output.Set("",
"Build with DCHECKs enabled to see information here");
#endif // DCHECK_IS_ON()
return base::StrCat({"<h3>Events:</h3>\n<pre>\n",
base::JoinString(events, "\n"),
"</pre>\n<h3>Service States</h3>\n<pre>\n",
internals_output.DebugString(), "</pre>\n"});
}
} // namespace
// static
bool SessionServiceInternalsHandler::ShouldHandleWebUIRequestCallback(
const std::string& path) {
return path == chrome::kChromeUISessionServiceInternalsPath;
}
// static
void SessionServiceInternalsHandler::HandleWebUIRequestCallback(
Profile* profile,
const std::string& path,
content::WebUIDataSource::GotDataCallback callback) {
DCHECK(ShouldHandleWebUIRequestCallback(path));
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
std::move(callback).Run(base::MakeRefCounted<base::RefCountedString>(
GetSessionServiceInternalsAsString(profile)));
}
|