summaryrefslogtreecommitdiff
path: root/chromium/fuchsia/base
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/fuchsia/base
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/fuchsia/base')
-rw-r--r--chromium/fuchsia/base/BUILD.gn23
-rw-r--r--chromium/fuchsia/base/DEPS1
-rw-r--r--chromium/fuchsia/base/agent_impl.cc1
-rw-r--r--chromium/fuchsia/base/agent_impl.h1
-rw-r--r--chromium/fuchsia/base/agent_manager.h1
-rw-r--r--chromium/fuchsia/base/config_reader.cc16
-rw-r--r--chromium/fuchsia/base/context_provider_test_connector.cc12
-rw-r--r--chromium/fuchsia/base/context_provider_test_connector.h1
-rw-r--r--chromium/fuchsia/base/feedback_registration.cc30
-rw-r--r--chromium/fuchsia/base/feedback_registration.h22
-rw-r--r--chromium/fuchsia/base/frame_test_util.cc15
-rw-r--r--chromium/fuchsia/base/frame_test_util.h6
-rw-r--r--chromium/fuchsia/base/inspect.cc28
-rw-r--r--chromium/fuchsia/base/inspect.h20
-rw-r--r--chromium/fuchsia/base/inspect_unittest.cc95
-rw-r--r--chromium/fuchsia/base/legacymetrics_client.cc85
-rw-r--r--chromium/fuchsia/base/legacymetrics_client.h17
-rw-r--r--chromium/fuchsia/base/legacymetrics_client_unittest.cc111
-rw-r--r--chromium/fuchsia/base/legacymetrics_histogram_flattener.cc1
19 files changed, 425 insertions, 61 deletions
diff --git a/chromium/fuchsia/base/BUILD.gn b/chromium/fuchsia/base/BUILD.gn
index 2dba9680aad..4e0d73dd164 100644
--- a/chromium/fuchsia/base/BUILD.gn
+++ b/chromium/fuchsia/base/BUILD.gn
@@ -4,30 +4,37 @@
assert(is_fuchsia)
-import("//build/buildflag_header.gni")
import("//build/config/fuchsia/generate_runner_scripts.gni")
-import("//fuchsia/release_channel.gni")
import("//testing/test.gni")
# Integration helpers for commonly used fuchsia.* APIs.
source_set("base") {
sources = [
"config_reader.cc",
+ "feedback_registration.cc",
"fuchsia_dir_scheme.cc",
"init_logging.cc",
+ "inspect.cc",
"mem_buffer_util.cc",
"string_util.cc",
]
public = [
"config_reader.h",
+ "feedback_registration.h",
"fuchsia_dir_scheme.h",
"init_logging.h",
+ "inspect.h",
"mem_buffer_util.h",
"string_util.h",
]
deps = [
"//base",
+ "//components/version_info",
+ "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.feedback",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mem",
+ "//third_party/fuchsia-sdk/sdk/pkg/fdio",
+ "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
+ "//third_party/fuchsia-sdk/sdk/pkg/sys_inspect_cpp",
"//url",
]
}
@@ -78,13 +85,6 @@ source_set("legacymetrics") {
friend = [ ":*" ]
}
-# Used to propagate release-qualified package names to integration test code.
-buildflag_header("release_channel_buildflags") {
- header = "release_channel.h"
- flags = [ "FUCHSIA_RELEASE_CHANNEL_SUFFIX=\"$release_channel_suffix\"" ]
- visibility = [ "//fuchsia/*" ]
-}
-
source_set("test_support") {
testonly = true
sources = [
@@ -106,7 +106,6 @@ source_set("test_support") {
public_deps = [
":base",
":modular",
- ":release_channel_buildflags",
"//base",
"//net",
"//net:test_support",
@@ -120,6 +119,7 @@ source_set("test_support") {
test("cr_fuchsia_base_unittests") {
sources = [
"agent_impl_unittests.cc",
+ "inspect_unittest.cc",
"legacymetrics_client_unittest.cc",
"legacymetrics_histogram_flattener_unittest.cc",
"legacymetrics_user_event_recorder_unittest.cc",
@@ -132,6 +132,9 @@ test("cr_fuchsia_base_unittests") {
"//base:testfidl",
"//base/test:run_all_unittests",
"//base/test:test_support",
+ "//components/version_info",
"//testing/gtest",
+ "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
+ "//third_party/fuchsia-sdk/sdk/pkg/sys_inspect_cpp",
]
}
diff --git a/chromium/fuchsia/base/DEPS b/chromium/fuchsia/base/DEPS
index 9455f2ca503..5ded5f1b3d8 100644
--- a/chromium/fuchsia/base/DEPS
+++ b/chromium/fuchsia/base/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/version_info",
"+mojo/public",
"+third_party/blink/public/common/messaging",
"+third_party/blink/public/mojom/messaging",
diff --git a/chromium/fuchsia/base/agent_impl.cc b/chromium/fuchsia/base/agent_impl.cc
index b692599f2a2..4ecd277425e 100644
--- a/chromium/fuchsia/base/agent_impl.cc
+++ b/chromium/fuchsia/base/agent_impl.cc
@@ -7,7 +7,6 @@
#include <lib/sys/cpp/component_context.h>
#include "base/bind.h"
-#include "base/fuchsia/default_context.h"
namespace cr_fuchsia {
diff --git a/chromium/fuchsia/base/agent_impl.h b/chromium/fuchsia/base/agent_impl.h
index b630dc8bb6c..389efb30b28 100644
--- a/chromium/fuchsia/base/agent_impl.h
+++ b/chromium/fuchsia/base/agent_impl.h
@@ -15,7 +15,6 @@
#include "base/bind.h"
#include "base/containers/flat_map.h"
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/scoped_service_binding.h"
#include "base/fuchsia/service_provider_impl.h"
#include "base/macros.h"
diff --git a/chromium/fuchsia/base/agent_manager.h b/chromium/fuchsia/base/agent_manager.h
index 7f60750e471..17fd60c254c 100644
--- a/chromium/fuchsia/base/agent_manager.h
+++ b/chromium/fuchsia/base/agent_manager.h
@@ -10,7 +10,6 @@
#include <lib/sys/cpp/component_context.h>
#include "base/containers/flat_map.h"
-#include "base/fuchsia/default_context.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
diff --git a/chromium/fuchsia/base/config_reader.cc b/chromium/fuchsia/base/config_reader.cc
index 87eaab8e48c..0c73357e93a 100644
--- a/chromium/fuchsia/base/config_reader.cc
+++ b/chromium/fuchsia/base/config_reader.cc
@@ -29,14 +29,14 @@ base::Optional<base::Value> ReadPackageConfig() {
return base::nullopt;
}
- base::JSONReader reader;
- base::Optional<base::Value> parsed = reader.Read(file_content);
- CHECK(parsed) << "Failed to parse " << path.value() << ": "
- << reader.GetErrorMessage();
- CHECK(parsed->is_dict()) << "Config is not a JSON dictinary: "
- << path.value();
-
- return std::move(parsed.value());
+ base::JSONReader::ValueWithError parsed =
+ base::JSONReader::ReadAndReturnValueWithError(file_content);
+ CHECK(parsed.value) << "Failed to parse " << path.value() << ": "
+ << parsed.error_message;
+ CHECK(parsed.value->is_dict())
+ << "Config is not a JSON dictionary: " << path.value();
+
+ return std::move(parsed.value);
}
} // namespace
diff --git a/chromium/fuchsia/base/context_provider_test_connector.cc b/chromium/fuchsia/base/context_provider_test_connector.cc
index ba5f1234432..307f0bd9d0f 100644
--- a/chromium/fuchsia/base/context_provider_test_connector.cc
+++ b/chromium/fuchsia/base/context_provider_test_connector.cc
@@ -12,10 +12,8 @@
#include <zircon/processargs.h>
#include <utility>
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/fuchsia_logging.h"
-#include "base/strings/strcat.h"
-#include "fuchsia/base/release_channel.h"
+#include "base/fuchsia/process_context.h"
namespace cr_fuchsia {
@@ -24,9 +22,8 @@ fidl::InterfaceHandle<fuchsia::io::Directory> StartWebEngineForTests(
component_controller_request,
const base::CommandLine& command_line) {
fuchsia::sys::LaunchInfo launch_info;
- launch_info.url = base::StrCat({"fuchsia-pkg://fuchsia.com/web_engine",
- BUILDFLAG(FUCHSIA_RELEASE_CHANNEL_SUFFIX),
- "#meta/context_provider.cmx"});
+ launch_info.url =
+ "fuchsia-pkg://fuchsia.com/web_engine#meta/context_provider.cmx";
launch_info.arguments = command_line.argv();
// Clone stderr from the current process to WebEngine and ask it to
@@ -43,8 +40,7 @@ fidl::InterfaceHandle<fuchsia::io::Directory> StartWebEngineForTests(
web_engine_services_dir.NewRequest().TakeChannel();
fuchsia::sys::LauncherPtr launcher;
- base::fuchsia::ComponentContextForCurrentProcess()->svc()->Connect(
- launcher.NewRequest());
+ base::ComponentContextForProcess()->svc()->Connect(launcher.NewRequest());
launcher->CreateComponent(std::move(launch_info),
std::move(component_controller_request));
diff --git a/chromium/fuchsia/base/context_provider_test_connector.h b/chromium/fuchsia/base/context_provider_test_connector.h
index 0d5ca1fd707..5c4604b25bc 100644
--- a/chromium/fuchsia/base/context_provider_test_connector.h
+++ b/chromium/fuchsia/base/context_provider_test_connector.h
@@ -20,7 +20,6 @@ fidl::InterfaceHandle<fuchsia::io::Directory> StartWebEngineForTests(
const base::CommandLine& command_line =
base::CommandLine(base::CommandLine::NO_PROGRAM));
-// TODO(crbug.com/1046615): Use test manifests for package specification.
fuchsia::web::ContextProviderPtr ConnectContextProvider(
fidl::InterfaceRequest<fuchsia::sys::ComponentController>
component_controller_request,
diff --git a/chromium/fuchsia/base/feedback_registration.cc b/chromium/fuchsia/base/feedback_registration.cc
new file mode 100644
index 00000000000..d8bee5ff647
--- /dev/null
+++ b/chromium/fuchsia/base/feedback_registration.cc
@@ -0,0 +1,30 @@
+// 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 "fuchsia/base/feedback_registration.h"
+
+#include <fuchsia/feedback/cpp/fidl.h>
+#include <lib/sys/cpp/component_context.h>
+
+#include "base/fuchsia/process_context.h"
+#include "base/strings/string_piece.h"
+#include "components/version_info/version_info.h"
+
+namespace cr_fuchsia {
+
+void RegisterCrashReportingFields(base::StringPiece component_url,
+ base::StringPiece crash_product_name) {
+ fuchsia::feedback::CrashReportingProduct product_data;
+ product_data.set_name(crash_product_name.as_string());
+ product_data.set_version(version_info::GetVersionNumber());
+ // TODO(https://crbug.com/1077428): Use the actual channel when appropriate.
+ // For now, always set it to the empty string to avoid reporting "missing".
+ product_data.set_channel("");
+ base::ComponentContextForProcess()
+ ->svc()
+ ->Connect<fuchsia::feedback::CrashReportingProductRegister>()
+ ->Upsert(component_url.as_string(), std::move(product_data));
+}
+
+} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/feedback_registration.h b/chromium/fuchsia/base/feedback_registration.h
new file mode 100644
index 00000000000..7e983bf6a70
--- /dev/null
+++ b/chromium/fuchsia/base/feedback_registration.h
@@ -0,0 +1,22 @@
+// 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 FUCHSIA_BASE_FEEDBACK_REGISTRATION_H_
+#define FUCHSIA_BASE_FEEDBACK_REGISTRATION_H_
+
+#include "base/strings/string_piece_forward.h"
+
+namespace cr_fuchsia {
+
+// Overrides the default Fuchsia product info in crash reports.
+// Crashes for the component |component_url| will contain |crash_product_name|,
+// the version from version_info, and an appropriate value for the release
+// channel. |component_url| must match the current component. The calling
+// process must have access to "fuchsia.feedback.CrashReportingProductRegister".
+void RegisterCrashReportingFields(base::StringPiece component_url,
+ base::StringPiece crash_product_name);
+
+} // namespace cr_fuchsia
+
+#endif // FUCHSIA_BASE_FEEDBACK_REGISTRATION_H_ \ No newline at end of file
diff --git a/chromium/fuchsia/base/frame_test_util.cc b/chromium/fuchsia/base/frame_test_util.cc
index c234b3a97fd..2150cd86360 100644
--- a/chromium/fuchsia/base/frame_test_util.cc
+++ b/chromium/fuchsia/base/frame_test_util.cc
@@ -54,4 +54,19 @@ fuchsia::web::LoadUrlParams CreateLoadUrlParamsWithUserActivation() {
return load_url_params;
}
+fuchsia::web::WebMessage CreateWebMessageWithMessagePortRequest(
+ fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request,
+ fuchsia::mem::Buffer buffer) {
+ fuchsia::web::OutgoingTransferable outgoing;
+ outgoing.set_message_port(std::move(message_port_request));
+
+ std::vector<fuchsia::web::OutgoingTransferable> outgoing_vector;
+ outgoing_vector.push_back(std::move(outgoing));
+
+ fuchsia::web::WebMessage web_message;
+ web_message.set_outgoing_transfer(std::move(outgoing_vector));
+ web_message.set_data(std::move(buffer));
+ return web_message;
+}
+
} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/frame_test_util.h b/chromium/fuchsia/base/frame_test_util.h
index 2c2ee036456..20534eaf5e9 100644
--- a/chromium/fuchsia/base/frame_test_util.h
+++ b/chromium/fuchsia/base/frame_test_util.h
@@ -31,6 +31,12 @@ base::Optional<base::Value> ExecuteJavaScript(fuchsia::web::Frame* frame,
// autoplay to be used, which is used by many media tests.
fuchsia::web::LoadUrlParams CreateLoadUrlParamsWithUserActivation();
+// Creates a WebMessage with one outgoing transferable set to
+// |message_port_request| and data set to |buffer|.
+fuchsia::web::WebMessage CreateWebMessageWithMessagePortRequest(
+ fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request,
+ fuchsia::mem::Buffer buffer);
+
} // namespace cr_fuchsia
#endif // FUCHSIA_BASE_FRAME_TEST_UTIL_H_
diff --git a/chromium/fuchsia/base/inspect.cc b/chromium/fuchsia/base/inspect.cc
new file mode 100644
index 00000000000..775ae986618
--- /dev/null
+++ b/chromium/fuchsia/base/inspect.cc
@@ -0,0 +1,28 @@
+// 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 "fuchsia/base/inspect.h"
+
+#include <lib/sys/inspect/cpp/component.h>
+
+#include "components/version_info/version_info.h"
+
+namespace cr_fuchsia {
+
+namespace {
+const char kVersion[] = "version";
+const char kLastChange[] = "last_change_revision";
+} // namespace
+
+void PublishVersionInfoToInspect(sys::ComponentInspector* inspector) {
+ // These values are managed by the inspector, since they won't be updated over
+ // the lifetime of the component.
+ // TODO(https://crbug.com/1077428): Add release channel.
+ inspector->root().CreateString(kVersion, version_info::GetVersionNumber(),
+ inspector);
+ inspector->root().CreateString(kLastChange, version_info::GetLastChange(),
+ inspector);
+}
+
+} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/inspect.h b/chromium/fuchsia/base/inspect.h
new file mode 100644
index 00000000000..4d8d35335ee
--- /dev/null
+++ b/chromium/fuchsia/base/inspect.h
@@ -0,0 +1,20 @@
+// 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 FUCHSIA_BASE_INSPECT_H_
+#define FUCHSIA_BASE_INSPECT_H_
+
+namespace sys {
+class ComponentInspector;
+} // namespace sys
+
+namespace cr_fuchsia {
+
+// Publish the Chromium version via the Inspect API. The lifetime of
+// |inspector| has to be the same as the component it belongs to.
+void PublishVersionInfoToInspect(sys::ComponentInspector* inspector);
+
+} // namespace cr_fuchsia
+
+#endif // FUCHSIA_BASE_INSPECT_H_ \ No newline at end of file
diff --git a/chromium/fuchsia/base/inspect_unittest.cc b/chromium/fuchsia/base/inspect_unittest.cc
new file mode 100644
index 00000000000..7a2bff50c81
--- /dev/null
+++ b/chromium/fuchsia/base/inspect_unittest.cc
@@ -0,0 +1,95 @@
+// 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 "fuchsia/base/inspect.h"
+
+#include <lib/fdio/directory.h>
+#include <lib/inspect/cpp/hierarchy.h>
+#include <lib/inspect/cpp/reader.h>
+#include <lib/inspect/service/cpp/reader.h>
+#include <lib/sys/cpp/component_context.h>
+#include <lib/sys/inspect/cpp/component.h>
+#include <cstdint>
+#include <memory>
+
+#include "base/task/single_thread_task_executor.h"
+#include "base/test/task_environment.h"
+#include "components/version_info/version_info.h"
+#include "fuchsia/base/mem_buffer_util.h"
+#include "fuchsia/base/string_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cr_fuchsia {
+
+namespace {
+
+const char kVersion[] = "version";
+const char kLastChange[] = "last_change_revision";
+
+class InspectTest : public ::testing::Test {
+ public:
+ InspectTest() {
+ fidl::InterfaceHandle<fuchsia::io::Directory> incoming_directory;
+ auto incoming_services =
+ std::make_shared<sys::ServiceDirectory>(std::move(incoming_directory));
+ context_ = std::make_unique<sys::ComponentContext>(
+ std::move(incoming_services),
+ published_root_directory_.NewRequest().TakeChannel());
+ inspector_ = std::make_unique<sys::ComponentInspector>(context_.get());
+ base::RunLoop().RunUntilIdle();
+ }
+
+ InspectTest(const InspectTest&) = delete;
+ InspectTest& operator=(const InspectTest&) = delete;
+
+ protected:
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
+ std::unique_ptr<sys::ComponentContext> context_;
+ fidl::InterfaceHandle<fuchsia::io::Directory> published_root_directory_;
+ std::unique_ptr<sys::ComponentInspector> inspector_;
+};
+
+} // namespace
+
+TEST_F(InspectTest, PublishVersionInfoToInspect) {
+ cr_fuchsia::PublishVersionInfoToInspect(inspector_.get());
+ fidl::InterfaceHandle<fuchsia::io::Directory> directory;
+ zx_status_t status = fdio_service_connect_at(
+ published_root_directory_.channel().get(), "diagnostics",
+ directory.NewRequest().TakeChannel().release());
+ ASSERT_EQ(ZX_OK, status);
+ std::unique_ptr<sys::ServiceDirectory> diagnostics =
+ std::make_unique<sys::ServiceDirectory>(std::move(directory));
+
+ // Access the inspect::Tree where the data is served. |tree| is in the
+ // directory created for the test, not the diagnostics directory for the test
+ // component.
+ fuchsia::inspect::TreePtr tree;
+ diagnostics->Connect(tree.NewRequest());
+ fuchsia::inspect::TreeContent content;
+ base::RunLoop run_loop;
+ tree->GetContent([&content, &run_loop](fuchsia::inspect::TreeContent c) {
+ content = std::move(c);
+ run_loop.Quit();
+ });
+ run_loop.Run();
+
+ // Parse the data as an inspect::Hierarchy.
+ ASSERT_TRUE(content.has_buffer());
+ std::string buffer_data;
+ cr_fuchsia::StringFromMemBuffer(content.buffer(), &buffer_data);
+ inspect::Hierarchy hierarchy =
+ inspect::ReadFromBuffer(cr_fuchsia::StringToBytes(buffer_data))
+ .take_value();
+
+ auto* property =
+ hierarchy.node().get_property<inspect::StringPropertyValue>(kVersion);
+ EXPECT_EQ(property->value(), version_info::GetVersionNumber());
+ property =
+ hierarchy.node().get_property<inspect::StringPropertyValue>(kLastChange);
+ EXPECT_EQ(property->value(), version_info::GetLastChange());
+}
+
+} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/legacymetrics_client.cc b/chromium/fuchsia/base/legacymetrics_client.cc
index a2d45a83ac8..58f384124c1 100644
--- a/chromium/fuchsia/base/legacymetrics_client.cc
+++ b/chromium/fuchsia/base/legacymetrics_client.cc
@@ -11,8 +11,8 @@
#include <utility>
#include <vector>
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/fuchsia_logging.h"
+#include "base/fuchsia/process_context.h"
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -34,11 +34,13 @@ void LegacyMetricsClient::Start(base::TimeDelta report_interval) {
DCHECK(!metrics_recorder_) << "Start() called more than once.";
report_interval_ = report_interval;
- metrics_recorder_ = base::fuchsia::ComponentContextForCurrentProcess()
+ metrics_recorder_ = base::ComponentContextForProcess()
->svc()
->Connect<fuchsia::legacymetrics::MetricsRecorder>();
metrics_recorder_.set_error_handler(fit::bind_member(
this, &LegacyMetricsClient::OnMetricsRecorderDisconnected));
+ metrics_recorder_.events().OnCloseSoon =
+ fit::bind_member(this, &LegacyMetricsClient::OnCloseSoon);
user_events_recorder_ = std::make_unique<LegacyMetricsUserActionRecorder>();
ScheduleNextReport();
}
@@ -54,7 +56,18 @@ void LegacyMetricsClient::SetReportAdditionalMetricsCallback(
report_additional_callback_ = std::move(callback);
}
+void LegacyMetricsClient::SetNotifyFlushCallback(NotifyFlushCallback callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(callback);
+ DCHECK(!metrics_recorder_)
+ << "SetNotifyFlushCallback() must be called before Start().";
+
+ notify_flush_callback_ = std::move(callback);
+}
+
void LegacyMetricsClient::ScheduleNextReport() {
+ DCHECK(!is_flushing_);
+
DVLOG(1) << "Scheduling next report in " << report_interval_.InSeconds()
<< "seconds.";
timer_.Start(FROM_HERE, report_interval_, this,
@@ -91,44 +104,70 @@ void LegacyMetricsClient::Report(
}
}
- if (events.empty()) {
- ScheduleNextReport();
- return;
- }
+ std::move(events.begin(), events.end(), std::back_inserter(to_send_));
- DrainBuffer(std::move(events));
+ DrainBuffer();
}
-void LegacyMetricsClient::DrainBuffer(
- std::vector<fuchsia::legacymetrics::Event> buffer) {
- if (buffer.empty()) {
+void LegacyMetricsClient::DrainBuffer() {
+ DVLOG(1) << __func__ << " called.";
+
+ if (record_ack_pending_) {
+ // There is a Record() call already inflight. When it is acknowledged,
+ // buffer draining will continue.
+ return;
+ }
+
+ if (to_send_.empty()) {
DVLOG(1) << "Buffer drained.";
- ScheduleNextReport();
+
+ if (is_flushing_) {
+ metrics_recorder_.Unbind();
+ } else {
+ ScheduleNextReport();
+ }
+
return;
}
- // Since ordering doesn't matter, we can efficiently drain |buffer| by
+ // Since ordering doesn't matter, we can efficiently drain |to_send_| by
// repeatedly sending and truncating its tail.
- const size_t batch_size = std::min(buffer.size(), kMaxBatchSize);
- const size_t batch_start_idx = buffer.size() - batch_size;
+ const size_t batch_size = std::min(to_send_.size(), kMaxBatchSize);
+ const size_t batch_start_idx = to_send_.size() - batch_size;
std::vector<fuchsia::legacymetrics::Event> batch;
batch.resize(batch_size);
- std::move(buffer.begin() + batch_start_idx, buffer.end(), batch.begin());
- buffer.resize(buffer.size() - batch_size);
-
- metrics_recorder_->Record(std::move(batch),
- [this, buffer = std::move(buffer)]() mutable {
- DrainBuffer(std::move(buffer));
- });
+ std::move(to_send_.begin() + batch_start_idx, to_send_.end(), batch.begin());
+ to_send_.resize(to_send_.size() - batch_size);
+
+ record_ack_pending_ = true;
+ metrics_recorder_->Record(std::move(batch), [this]() {
+ record_ack_pending_ = false;
+ DrainBuffer();
+ });
}
void LegacyMetricsClient::OnMetricsRecorderDisconnected(zx_status_t status) {
- ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status)
- << "MetricsRecorder connection lost.";
+ ZX_LOG(ERROR, status) << "MetricsRecorder connection lost.";
// Stop recording & reporting user events.
user_events_recorder_.reset();
timer_.AbandonAndStop();
}
+void LegacyMetricsClient::OnCloseSoon() {
+ DVLOG(1) << __func__ << " called.";
+
+ timer_.AbandonAndStop();
+
+ is_flushing_ = true;
+ if (notify_flush_callback_) {
+ // Defer reporting until the flush operation has finished.
+ std::move(notify_flush_callback_)
+ .Run(base::BindOnce(&LegacyMetricsClient::StartReport,
+ weak_factory_.GetWeakPtr()));
+ } else {
+ StartReport();
+ }
+}
+
} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/legacymetrics_client.h b/chromium/fuchsia/base/legacymetrics_client.h
index 98576a1f410..b9ec76a2a1f 100644
--- a/chromium/fuchsia/base/legacymetrics_client.h
+++ b/chromium/fuchsia/base/legacymetrics_client.h
@@ -31,6 +31,8 @@ class LegacyMetricsClient {
using ReportAdditionalMetricsCallback = base::RepeatingCallback<void(
base::OnceCallback<void(std::vector<fuchsia::legacymetrics::Event>)>)>;
+ using NotifyFlushCallback =
+ base::OnceCallback<void(base::OnceClosure completion_cb)>;
LegacyMetricsClient();
~LegacyMetricsClient();
@@ -50,18 +52,27 @@ class LegacyMetricsClient {
void SetReportAdditionalMetricsCallback(
ReportAdditionalMetricsCallback callback);
+ // Sets a |callback| which is invoked to warn that the connection to the
+ // remote MetricsRecorder will be terminated. The completion closure passed to
+ // |callback| should be invoked to signal flush completion.
+ void SetNotifyFlushCallback(NotifyFlushCallback callback);
+
private:
void ScheduleNextReport();
void StartReport();
void Report(std::vector<fuchsia::legacymetrics::Event> additional_metrics);
void OnMetricsRecorderDisconnected(zx_status_t status);
+ void OnCloseSoon();
- // Incrementally sends the contents of |buffer| to |metrics_recorder|, and
- // invokes |done_cb| when finished.
- void DrainBuffer(std::vector<fuchsia::legacymetrics::Event> buffer);
+ // Incrementally sends the contents of |to_send_| to |metrics_recorder_|.
+ void DrainBuffer();
base::TimeDelta report_interval_;
ReportAdditionalMetricsCallback report_additional_callback_;
+ NotifyFlushCallback notify_flush_callback_;
+ bool is_flushing_ = false;
+ bool record_ack_pending_ = false;
+ std::vector<fuchsia::legacymetrics::Event> to_send_;
std::unique_ptr<LegacyMetricsUserActionRecorder> user_events_recorder_;
fuchsia::legacymetrics::MetricsRecorderPtr metrics_recorder_;
diff --git a/chromium/fuchsia/base/legacymetrics_client_unittest.cc b/chromium/fuchsia/base/legacymetrics_client_unittest.cc
index 8c735bbbffe..1b48827418a 100644
--- a/chromium/fuchsia/base/legacymetrics_client_unittest.cc
+++ b/chromium/fuchsia/base/legacymetrics_client_unittest.cc
@@ -14,6 +14,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "fuchsia/base/legacymetrics_client.h"
#include "fuchsia/base/legacymetrics_histogram_flattener.h"
+#include "fuchsia/base/result_receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cr_fuchsia {
@@ -45,10 +46,21 @@ class TestMetricsRecorder
ack_callback_ = base::nullopt;
}
+ void set_expect_ack_dropped(bool expect_dropped) {
+ expect_ack_dropped_ = expect_dropped;
+ }
+
// fuchsia::legacymetrics::MetricsRecorder implementation.
void Record(std::vector<fuchsia::legacymetrics::Event> events,
RecordCallback callback) override {
- recorded_events_ = std::move(events);
+ std::move(events.begin(), events.end(),
+ std::back_inserter(recorded_events_));
+
+ // Received a call to Record() before the previous one was acknowledged,
+ // which can happen in some cases (e.g. flushing).
+ if (ack_callback_)
+ EXPECT_TRUE(expect_ack_dropped_);
+
ack_callback_ = std::move(callback);
if (on_record_cb_)
@@ -61,6 +73,7 @@ class TestMetricsRecorder
std::vector<fuchsia::legacymetrics::Event> recorded_events_;
base::OnceClosure on_record_cb_;
base::Optional<RecordCallback> ack_callback_;
+ bool expect_ack_dropped_ = false;
};
class LegacyMetricsClientTest : public testing::Test {
@@ -71,9 +84,10 @@ class LegacyMetricsClientTest : public testing::Test {
~LegacyMetricsClientTest() override = default;
void SetUp() override {
- service_binding_ = std::make_unique<base::fuchsia::ScopedServiceBinding<
- fuchsia::legacymetrics::MetricsRecorder>>(
- test_context_.additional_services(), &test_recorder_);
+ service_binding_ =
+ std::make_unique<base::fuchsia::ScopedSingleClientServiceBinding<
+ fuchsia::legacymetrics::MetricsRecorder>>(
+ test_context_.additional_services(), &test_recorder_);
base::SetRecordActionTaskRunner(base::ThreadTaskRunnerHandle::Get());
// Flush any dirty histograms from previous test runs in this process.
@@ -84,7 +98,7 @@ class LegacyMetricsClientTest : public testing::Test {
base::test::TaskEnvironment task_environment_;
base::TestComponentContextForProcess test_context_;
TestMetricsRecorder test_recorder_;
- std::unique_ptr<base::fuchsia::ScopedServiceBinding<
+ std::unique_ptr<base::fuchsia::ScopedSingleClientServiceBinding<
fuchsia::legacymetrics::MetricsRecorder>>
service_binding_;
LegacyMetricsClient client_;
@@ -216,5 +230,92 @@ TEST_F(LegacyMetricsClientTest, Batching) {
test_recorder_.SendAck();
}
+TEST_F(LegacyMetricsClientTest, FlushWithPending) {
+ client_.Start(kReportInterval);
+ base::RunLoop().RunUntilIdle();
+
+ UMA_HISTOGRAM_COUNTS_1M("foo", 20);
+
+ EXPECT_FALSE(test_recorder_.IsRecordInFlight());
+ service_binding_->events().OnCloseSoon();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(test_recorder_.IsRecordInFlight());
+
+ // The service should be unbound once all data is drained.
+ EXPECT_TRUE(service_binding_->has_clients());
+ auto events = test_recorder_.WaitForEvents();
+ test_recorder_.SendAck();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1u, events.size());
+ EXPECT_EQ("foo", events[0].histogram().name());
+ EXPECT_FALSE(service_binding_->has_clients());
+}
+
+TEST_F(LegacyMetricsClientTest, FlushNoData) {
+ client_.Start(kReportInterval);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(service_binding_->has_clients());
+ EXPECT_FALSE(test_recorder_.IsRecordInFlight());
+ service_binding_->events().OnCloseSoon();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(service_binding_->has_clients());
+}
+
+TEST_F(LegacyMetricsClientTest, FlushWithOutstandingAck) {
+ client_.Start(kReportInterval);
+ base::RunLoop().RunUntilIdle();
+
+ // Send "foo", but don't ack.
+ UMA_HISTOGRAM_COUNTS_1M("foo", 20);
+ task_environment_.FastForwardBy(kReportInterval);
+ EXPECT_TRUE(test_recorder_.IsRecordInFlight());
+
+ // Allow the flush operation to call Record() without waiting for a prior ack.
+ test_recorder_.set_expect_ack_dropped(true);
+
+ // Buffer another event and trigger a flush.
+ UMA_HISTOGRAM_COUNTS_1M("bar", 20);
+ EXPECT_TRUE(service_binding_->has_clients());
+ service_binding_->events().OnCloseSoon();
+
+ // Simulate an asynchronous ack from the recorder, which be delivered around
+ // the same time as the flush's Record() call. The ack should be gracefully
+ // ignored by the client.
+ test_recorder_.SendAck();
+
+ base::RunLoop().RunUntilIdle();
+
+ auto events = test_recorder_.WaitForEvents();
+ test_recorder_.SendAck();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(2u, events.size());
+ EXPECT_EQ("foo", events[0].histogram().name());
+ EXPECT_EQ("bar", events[1].histogram().name());
+ EXPECT_FALSE(service_binding_->has_clients());
+}
+
+TEST_F(LegacyMetricsClientTest, ExternalFlushSignal) {
+ ResultReceiver<base::OnceClosure> flush_receiver;
+ client_.SetNotifyFlushCallback(flush_receiver.GetReceiveCallback());
+ client_.Start(kReportInterval);
+ base::RunLoop().RunUntilIdle();
+
+ UMA_HISTOGRAM_COUNTS_1M("foo", 20);
+
+ // Verify that reporting does not start until the flush completion callback is
+ // run.
+ EXPECT_FALSE(test_recorder_.IsRecordInFlight());
+ service_binding_->events().OnCloseSoon();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(test_recorder_.IsRecordInFlight());
+
+ // Verify that invoking the completion callback unblocks reporting.
+ EXPECT_TRUE(flush_receiver.has_value());
+ std::move(*flush_receiver).Run();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(test_recorder_.IsRecordInFlight());
+}
+
} // namespace
} // namespace cr_fuchsia
diff --git a/chromium/fuchsia/base/legacymetrics_histogram_flattener.cc b/chromium/fuchsia/base/legacymetrics_histogram_flattener.cc
index e05d87ced9a..b6d728143c1 100644
--- a/chromium/fuchsia/base/legacymetrics_histogram_flattener.cc
+++ b/chromium/fuchsia/base/legacymetrics_histogram_flattener.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "base/logging.h"
#include "base/metrics/statistics_recorder.h"
namespace cr_fuchsia {