blob: c29e732bcd24adcda03fb15ace017a92710836ff [file] [log] [blame]
// Copyright 2024 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/language_detection/content/renderer/language_detection_agent.h"
#include "base/functional/bind.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "components/language_detection/core/language_detection_model.h"
#include "components/language_detection/core/language_detection_provider.h"
#include "content/public/renderer/render_frame.h"
#include "third_party/blink/public/platform/browser_interface_broker_proxy.h"
namespace language_detection {
LanguageDetectionAgent::LanguageDetectionAgent(
content::RenderFrame* render_frame)
: content::RenderFrameObserver(render_frame),
waiting_for_first_foreground_(render_frame->IsHidden()) {
language_detection::LanguageDetectionModel& language_detection_model =
language_detection::GetLanguageDetectionModel();
// If the language detection model is available, we do not
// worry about requesting the model.
if (language_detection_model.IsAvailable()) {
return;
}
UMA_HISTOGRAM_BOOLEAN("LanguageDetection.TFLiteModel.WasModelRequestDeferred",
waiting_for_first_foreground_);
// Ensure the render frame is visible, otherwise the browser-side
// driver may not exist yet (https://crbug.com/1199397).
if (!waiting_for_first_foreground_) {
GetLanguageDetectionHandler()->GetLanguageDetectionModel(
base::BindOnce(&LanguageDetectionAgent::UpdateLanguageDetectionModel,
weak_pointer_factory_.GetWeakPtr()));
}
}
LanguageDetectionAgent::~LanguageDetectionAgent() = default;
const mojo::Remote<mojom::ContentLanguageDetectionDriver>&
LanguageDetectionAgent::GetLanguageDetectionHandler() {
if (language_detection_handler_) {
if (language_detection_handler_.is_connected()) {
return language_detection_handler_;
}
// The handler can become unbound or disconnected in testing so this catches
// that case and reconnects so `this` can connect to the driver in the
// browser.
language_detection_handler_.reset();
}
render_frame()->GetBrowserInterfaceBroker().GetInterface(
language_detection_handler_.BindNewPipeAndPassReceiver());
return language_detection_handler_;
}
void LanguageDetectionAgent::UpdateLanguageDetectionModel(
base::File model_file) {
TRACE_EVENT("browser", "TranslateAgent::UpdateLanguageDetectionModel");
base::ScopedUmaHistogramTimer timer(
"LanguageDetection.TFLiteModel.UpdateLanaguageDetectionModelTime");
language_detection::LanguageDetectionModel& language_detection_model =
language_detection::GetLanguageDetectionModel();
language_detection_model.UpdateWithFile(std::move(model_file));
}
void LanguageDetectionAgent::WasShown() {
// Check if the the render frame was initially hidden and
// the model request was delayed until the frame was in
// the foreground.
if (!waiting_for_first_foreground_) {
return;
}
waiting_for_first_foreground_ = false;
language_detection::LanguageDetectionModel& language_detection_model =
language_detection::GetLanguageDetectionModel();
if (language_detection_model.IsAvailable()) {
return;
}
// The model request was deferred because the frame was hidden
// and now the model is visible and the model is still not available.
// The browser-side translate driver should always be available at
// this point so we should make the request and race to get the
// model loaded for when the page content is available.
GetLanguageDetectionHandler()->GetLanguageDetectionModel(
base::BindOnce(&LanguageDetectionAgent::UpdateLanguageDetectionModel,
weak_pointer_factory_.GetWeakPtr()));
}
void LanguageDetectionAgent::OnDestruct() {
delete this;
}
} // namespace language_detection