blob: 038a0f61cc95f4ae6b54bbbdfa90241e1950ef8b [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/web/content/js_messaging/ios_web_message_host_factory.h"
#import <string>
#import "base/functional/overloaded.h"
#import "base/json/json_reader.h"
#import "base/strings/utf_string_conversions.h"
#import "components/js_injection/browser/js_communication_host.h"
#import "components/js_injection/browser/web_message.h"
#import "components/js_injection/browser/web_message_host.h"
#import "third_party/abseil-cpp/absl/types/variant.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace web {
namespace {
// Created when a message is received from JavaScript.
class IOSWebMessageHost : public js_injection::WebMessageHost {
public:
IOSWebMessageHost(
const std::string& origin_string,
bool is_main_frame,
IOSWebMessageHostFactory::WebMessageCallback message_callback)
: origin_string_(origin_string),
is_main_frame_(is_main_frame),
message_callback_(message_callback) {}
~IOSWebMessageHost() override = default;
// js_injection::WebMessageHost:
void OnPostMessage(
std::unique_ptr<js_injection::WebMessage> web_message) override {
absl::optional<std::u16string> received_message;
absl::visit(
base::Overloaded{
[&received_message](const std::u16string& str) {
received_message = str;
},
[](const std::unique_ptr<blink::WebMessageArrayBufferPayload>&
array_buffer) {
// Do nothing if the received message is not a string.
}},
web_message->message);
if (!received_message) {
return;
}
// TODO(crbug.com/1423527): Move this parsing to the renderer process.
absl::optional<base::Value> message_value =
base::JSONReader::Read(base::UTF16ToUTF8(*received_message));
if (!message_value) {
return;
}
// TODO(crbug.com/1423527): Determine whether the user has interacted with
// the source page.
bool is_user_interacting = false;
ScriptMessage script_message(
std::make_unique<base::Value>(std::move(*message_value)),
is_user_interacting, is_main_frame_, GURL(origin_string_));
message_callback_.Run(script_message);
}
private:
// The origin of the page that sent the message.
std::string origin_string_;
// Whether the page that sent the message is a main frame.
bool is_main_frame_ = false;
// Called with the message received from JavaScript.
IOSWebMessageHostFactory::WebMessageCallback message_callback_;
};
} // namespace
IOSWebMessageHostFactory::IOSWebMessageHostFactory(
WebMessageCallback message_callback)
: message_callback_(message_callback) {}
IOSWebMessageHostFactory::~IOSWebMessageHostFactory() = default;
std::unique_ptr<js_injection::WebMessageHost>
IOSWebMessageHostFactory::CreateHost(
const std::string& origin_string,
bool is_main_frame,
js_injection::WebMessageReplyProxy* proxy) {
return std::make_unique<IOSWebMessageHost>(origin_string, is_main_frame,
message_callback_);
}
} // namespace web