Skip to content

Commit

Permalink
[extensions] Port GetMessageBundle over to mojom
Browse files Browse the repository at this point in the history
Acquire the associated RendererHost in the i18n hooks and send
the message to the browser via a sync mojo call.

Bug: 993189
Change-Id: I1d7e06bdb9eefaeba024f1bd029f77398cda1e7a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4956841
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Reviewed-by: Colin Blundell <blundell@chromium.org>
Reviewed-by: Dominic Farolino <dom@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1216243}
  • Loading branch information
dtapuska authored and Chromium LUCI CQ committed Oct 27, 2023
1 parent e8bd9fd commit c4acdf0
Show file tree
Hide file tree
Showing 14 changed files with 214 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -737,8 +737,8 @@ void ChromeContentBrowserClientExtensionsPart::RenderProcessWillLaunch(
return;
}

host->AddFilter(new ChromeExtensionMessageFilter(profile));
#if BUILDFLAG(ENABLE_EXTENSIONS_LEGACY_IPC)
host->AddFilter(new ChromeExtensionMessageFilter(profile));
int id = host->GetID();
host->AddFilter(new ExtensionMessageFilter(id, profile));
host->AddFilter(new ExtensionServiceWorkerMessageFilter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include "extensions/common/manifest_handlers/shared_module_info.h"
#include "extensions/common/message_bundle.h"

#if BUILDFLAG(ENABLE_EXTENSIONS_LEGACY_IPC)

using content::BrowserThread;

namespace {
Expand Down Expand Up @@ -164,3 +166,5 @@ void ChromeExtensionMessageFilter::OnProfileWillBeDestroyed(Profile* profile) {
observed_profile_.Reset();
profile_ = nullptr;
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
#include "chrome/browser/profiles/profile_observer.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension_l10n_util.h"

#if BUILDFLAG(ENABLE_EXTENSIONS_LEGACY_IPC)

// This class filters out incoming Chrome-specific IPC messages from the
// extension process on the IPC thread.
class ChromeExtensionMessageFilter : public content::BrowserMessageFilter,
Expand Down Expand Up @@ -64,5 +67,6 @@ class ChromeExtensionMessageFilter : public content::BrowserMessageFilter,

base::ScopedObservation<Profile, ProfileObserver> observed_profile_{this};
};
#endif

#endif // CHROME_BROWSER_RENDERER_HOST_CHROME_EXTENSION_MESSAGE_FILTER_H_
3 changes: 2 additions & 1 deletion chrome/renderer/url_loader_throttle_provider_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ URLLoaderThrottleProviderImpl::CreateThrottles(
throttles.emplace_back(std::move(throttle));
}
std::unique_ptr<blink::URLLoaderThrottle> localization_throttle =
extensions::ExtensionLocalizationThrottle::MaybeCreate(request.Url());
extensions::ExtensionLocalizationThrottle::MaybeCreate(render_frame_id,
request.Url());
if (localization_throttle) {
throttles.emplace_back(std::move(localization_throttle));
}
Expand Down
94 changes: 94 additions & 0 deletions extensions/browser/renderer_startup_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
#include <utility>
#include <vector>

#include "base/containers/adapters.h"
#include "base/containers/contains.h"
#include "base/debug/dump_without_crashing.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/task/thread_pool.h"
#include "base/unguessable_token.h"
#include "base/values.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
Expand All @@ -24,18 +27,23 @@
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/guest_view/web_view/web_view_guest.h"
#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
#include "extensions/browser/l10n_file_util.h"
#include "extensions/browser/network_permissions_updater.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_manager_factory.h"
#include "extensions/browser/service_worker_task_queue.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension_l10n_util.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/extensions_client.h"
#include "extensions/common/features/feature_channel.h"
#include "extensions/common/features/feature_developer_mode_only.h"
#include "extensions/common/features/feature_session_type.h"
#include "extensions/common/manifest_handlers/background_info.h"
#include "extensions/common/manifest_handlers/default_locale_handler.h"
#include "extensions/common/manifest_handlers/shared_module_info.h"
#include "extensions/common/message_bundle.h"
#include "extensions/common/permissions/permissions_data.h"
#include "ipc/ipc_channel_proxy.h"
#include "ui/base/webui/web_ui_util.h"
Expand Down Expand Up @@ -91,6 +99,13 @@ mojom::ExtensionLoadedParamsPtr CreateExtensionLoadedParams(
extension.creation_flags(), extension.guid());
}

#if !BUILDFLAG(ENABLE_EXTENSIONS_LEGACY_IPC)
base::flat_map<std::string, std::string> ToFlatMap(
const std::map<std::string, std::string>& map) {
return {map.begin(), map.end()};
}
#endif

} // namespace

RendererStartupHelper::RendererStartupHelper(BrowserContext* browser_context)
Expand Down Expand Up @@ -504,6 +519,85 @@ void RendererStartupHelper::WakeEventPage(const ExtensionId& extension_id,
#endif
}

void RendererStartupHelper::GetMessageBundle(
const std::string& extension_id,
GetMessageBundleCallback callback) {
#if BUILDFLAG(ENABLE_EXTENSIONS_LEGACY_IPC)
auto* process =
content::RenderProcessHost::FromID(receivers_.current_context());
if (!process) {
return;
}
bad_message::ReceivedBadMessage(process, bad_message::LEGACY_IPC_MISMATCH);
return;
#else
auto* browser_context = GetRendererBrowserContext();
if (!browser_context) {
std::move(callback).Run({});
return;
}

const ExtensionSet& extension_set =
ExtensionRegistry::Get(browser_context)->enabled_extensions();
const Extension* extension = extension_set.GetByID(extension_id);

if (!extension) { // The extension has gone.
std::move(callback).Run({});
return;
}

const std::string& default_locale = LocaleInfo::GetDefaultLocale(extension);
if (default_locale.empty()) {
// A little optimization: send the answer here to avoid an extra thread hop.
std::unique_ptr<MessageBundle::SubstitutionMap> dictionary_map(
l10n_file_util::LoadNonLocalizedMessageBundleSubstitutionMap(
extension_id));
std::move(callback).Run(ToFlatMap(*dictionary_map));
return;
}

std::vector<base::FilePath> paths_to_load;
paths_to_load.push_back(extension->path());

auto imports = SharedModuleInfo::GetImports(extension);
// Iterate through the imports in reverse. This will allow later imported
// modules to override earlier imported modules, as the list order is
// maintained from the definition in manifest.json of the imports.
for (const SharedModuleInfo::ImportInfo& import : base::Reversed(imports)) {
const Extension* imported_extension =
extension_set.GetByID(import.extension_id);
if (!imported_extension) {
NOTREACHED() << "Missing shared module " << import.extension_id;
continue;
}
paths_to_load.push_back(imported_extension->path());
}

// This blocks tab loading. Priority is inherited from the calling context.
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock()},
base::BindOnce(
[](const std::vector<base::FilePath>& extension_paths,
const std::string& main_extension_id,
const std::string& default_locale,
extension_l10n_util::GzippedMessagesPermission gzip_permission) {
return base::WrapUnique<MessageBundle::SubstitutionMap>(
l10n_file_util::LoadMessageBundleSubstitutionMapFromPaths(
extension_paths, main_extension_id, default_locale,
gzip_permission));
},
paths_to_load, extension_id, default_locale,
extension_l10n_util::GetGzippedMessagesPermissionForExtension(
extension)),
base::BindOnce(
[](GetMessageBundleCallback callback,
std::unique_ptr<MessageBundle::SubstitutionMap> dictionary_map) {
std::move(callback).Run(ToFlatMap(*dictionary_map));
},
std::move(callback)));
#endif
}

//////////////////////////////////////////////////////////////////////////////

// static
Expand Down
2 changes: 2 additions & 0 deletions extensions/browser/renderer_startup_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ class RendererStartupHelper : public KeyedService,
int32_t call_type) override;
void WakeEventPage(const std::string& extension_id,
WakeEventPageCallback callback) override;
void GetMessageBundle(const std::string& extension_id,
GetMessageBundleCallback callback) override;

// Sends a message to the specified |process| activating the given extension
// once the process is initialized. OnExtensionLoaded should have already been
Expand Down
2 changes: 0 additions & 2 deletions extensions/common/extension_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,15 +277,13 @@ IPC_MESSAGE_CONTROL2(ExtensionHostMsg_PostMessage,
IPC_MESSAGE_CONTROL2(ExtensionHostMsg_ResponsePending,
extensions::PortContext /* port_context */,
extensions::PortId /*port_id */)
#endif

// Used to get the extension message bundle.
IPC_SYNC_MESSAGE_CONTROL1_1(
ExtensionHostMsg_GetMessageBundle,
std::string /* extension id */,
extensions::MessageBundle::SubstitutionMap /* message bundle */)

#if BUILDFLAG(ENABLE_EXTENSIONS_LEGACY_IPC)
// Asks the browser to wake the event page of an extension.
// The browser will reply with ExtensionHostMsg_WakeEventPageResponse.
IPC_MESSAGE_CONTROL2(ExtensionHostMsg_WakeEventPage,
Expand Down
4 changes: 4 additions & 0 deletions extensions/common/mojom/renderer_host.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ interface RendererHost {

// Asks the browser to wake the event page of an extension.
WakeEventPage(string extension_id) => (bool success);

// Retrieves the message bundle for an extension from the browser.
[Sync]
GetMessageBundle(string extension_id) => (map<string, string> message_map);
};
29 changes: 20 additions & 9 deletions extensions/renderer/api/i18n_hooks_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
#include "extensions/common/message_bundle.h"
#include "extensions/renderer/bindings/api_binding_types.h"
#include "extensions/renderer/bindings/js_runner.h"
#include "extensions/renderer/extension_frame_helper.h"
#include "extensions/renderer/get_script_context.h"
#include "extensions/renderer/script_context.h"
#include "extensions/renderer/service_worker_data.h"
#include "extensions/renderer/shared_l10n_map.h"
#include "extensions/renderer/worker_thread_dispatcher.h"
#include "gin/converter.h"
Expand Down Expand Up @@ -149,12 +151,12 @@ v8::Local<v8::Value> GetI18nMessage(const std::string& message_name,
const std::string& extension_id,
v8::Local<v8::Value> v8_substitutions,
v8::Local<v8::Value> v8_options,
IPC::Sender* message_sender,
SharedL10nMap::IPCTarget* ipc_target,
v8::Local<v8::Context> context) {
v8::Isolate* isolate = context->GetIsolate();

std::string message = SharedL10nMap::GetInstance().GetMessage(
extension_id, message_name, message_sender);
extension_id, message_name, ipc_target);

std::vector<std::string> substitutions;
// For now, we just suppress all errors, but that's really not the best.
Expand Down Expand Up @@ -285,17 +287,26 @@ RequestResult I18nHooksDelegate::HandleGetMessage(
DCHECK(script_context->extension());
DCHECK(arguments[0]->IsString());

IPC::Sender* message_sender = nullptr;
SharedL10nMap::IPCTarget* ipc_target = nullptr;
#if BUILDFLAG(ENABLE_EXTENSIONS_LEGACY_IPC)
if (script_context->IsForServiceWorker()) {
message_sender = WorkerThreadDispatcher::Get();
ipc_target = WorkerThreadDispatcher::Get();
} else {
message_sender = script_context->GetRenderFrame();
ipc_target = script_context->GetRenderFrame();
}
#else
if (script_context->IsForServiceWorker()) {
ipc_target =
WorkerThreadDispatcher::GetServiceWorkerData()->GetRendererHost();
} else if (auto* frame = script_context->GetRenderFrame()) {
ipc_target = ExtensionFrameHelper::Get(frame)->GetRendererHost();
}
#endif

v8::Local<v8::Value> message = GetI18nMessage(
gin::V8ToString(script_context->isolate(), arguments[0]),
script_context->extension()->id(), arguments[1], arguments[2],
message_sender, script_context->v8_context());
v8::Local<v8::Value> message =
GetI18nMessage(gin::V8ToString(script_context->isolate(), arguments[0]),
script_context->extension()->id(), arguments[1],
arguments[2], ipc_target, script_context->v8_context());

RequestResult result(RequestResult::HANDLED);
result.return_value = message;
Expand Down
32 changes: 25 additions & 7 deletions extensions/renderer/extension_localization_throttle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_id.h"
#include "extensions/renderer/extension_frame_helper.h"
#include "extensions/renderer/shared_l10n_map.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
Expand All @@ -34,10 +36,12 @@ class ExtensionLocalizationURLLoader : public network::mojom::URLLoaderClient,
public mojo::DataPipeDrainer::Client {
public:
ExtensionLocalizationURLLoader(
int render_frame_id,
const std::string& extension_id,
mojo::PendingRemote<network::mojom::URLLoaderClient>
destination_url_loader_client)
: extension_id_(extension_id),
: render_frame_id_(render_frame_id),
extension_id_(extension_id),
destination_url_loader_client_(
std::move(destination_url_loader_client)) {}
~ExtensionLocalizationURLLoader() override = default;
Expand Down Expand Up @@ -177,11 +181,22 @@ class ExtensionLocalizationURLLoader : public network::mojom::URLLoaderClient,
}

void ReplaceMessages() {
IPC::Sender* message_sender = content::RenderThread::Get();
extensions::SharedL10nMap::IPCTarget* ipc_target = nullptr;
#if BUILDFLAG(ENABLE_EXTENSIONS_LEGACY_IPC)
ipc_target = content::RenderThread::Get();
(void)render_frame_id_;
#else
content::RenderFrame* render_frame =
content::RenderFrame::FromRoutingID(render_frame_id_);
if (render_frame) {
ipc_target = ExtensionFrameHelper::Get(render_frame)->GetRendererHost();
}
#endif
extensions::SharedL10nMap::GetInstance().ReplaceMessages(
extension_id_, &data_, message_sender);
extension_id_, &data_, ipc_target);
}

const int render_frame_id_;
const ExtensionId extension_id_;
std::unique_ptr<mojo::DataPipeDrainer> data_drainer_;
mojo::ScopedDataPipeProducerHandle producer_handle_;
Expand All @@ -201,14 +216,17 @@ class ExtensionLocalizationURLLoader : public network::mojom::URLLoaderClient,

// static
std::unique_ptr<ExtensionLocalizationThrottle>
ExtensionLocalizationThrottle::MaybeCreate(const blink::WebURL& request_url) {
ExtensionLocalizationThrottle::MaybeCreate(int render_frame_id,
const blink::WebURL& request_url) {
if (!request_url.ProtocolIs(extensions::kExtensionScheme)) {
return nullptr;
}
return base::WrapUnique(new ExtensionLocalizationThrottle());
return base::WrapUnique(new ExtensionLocalizationThrottle(render_frame_id));
}

ExtensionLocalizationThrottle::ExtensionLocalizationThrottle() = default;
ExtensionLocalizationThrottle::ExtensionLocalizationThrottle(
int render_frame_id)
: render_frame_id_(render_frame_id) {}

ExtensionLocalizationThrottle::~ExtensionLocalizationThrottle() = default;

Expand Down Expand Up @@ -251,7 +269,7 @@ void ExtensionLocalizationThrottle::WillProcessResponse(
mojo::PendingReceiver<network::mojom::URLLoaderClient> source_client_receiver;

auto loader = std::make_unique<ExtensionLocalizationURLLoader>(
response_url.host(), std::move(url_loader_client));
render_frame_id_, response_url.host(), std::move(url_loader_client));

ExtensionLocalizationURLLoader* loader_rawptr = loader.get();
// `loader` will be deleted when `new_remote` is disconnected.
Expand Down
4 changes: 3 additions & 1 deletion extensions/renderer/extension_localization_throttle.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class ExtensionLocalizationThrottle : public blink::URLLoaderThrottle {
// Creates a ExtensionLocalizationThrottle only when `request_url`
// is a chrome-extention scheme URL.
static std::unique_ptr<ExtensionLocalizationThrottle> MaybeCreate(
int render_frame_id,
const blink::WebURL& request_url);

~ExtensionLocalizationThrottle() override;
Expand All @@ -38,10 +39,11 @@ class ExtensionLocalizationThrottle : public blink::URLLoaderThrottle {
void ForceCreateDataPipeErrorForTest() { force_error_for_test_ = true; }

private:
ExtensionLocalizationThrottle();
explicit ExtensionLocalizationThrottle(int render_frame_id);
void DeferredCancelWithError(int error_code);

bool force_error_for_test_ = false;
const int render_frame_id_;
base::WeakPtrFactory<ExtensionLocalizationThrottle> weak_factory_{this};
};

Expand Down

0 comments on commit c4acdf0

Please sign in to comment.