blob: 39c3f9b69baf95176737805658cadeb8ad41c2e1 [file] [log] [blame]
// Copyright 2021 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 "remoting/host/remote_open_url_message_handler.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "remoting/base/compound_buffer.h"
#include "remoting/protocol/message_serialization.h"
#include "url/gurl.h"
namespace remoting {
namespace {
using OpenUrlResponse = protocol::RemoteOpenUrl::OpenUrlResponse;
mojom::OpenUrlResult ToMojomOpenUrlResult(
OpenUrlResponse::Result protobuf_result) {
switch (protobuf_result) {
case OpenUrlResponse::UNSPECIFIED_OPEN_URL_RESULT:
return mojom::OpenUrlResult::UNSPECIFIED_OPEN_URL_RESULT;
case OpenUrlResponse::SUCCESS:
return mojom::OpenUrlResult::SUCCESS;
case OpenUrlResponse::FAILURE:
return mojom::OpenUrlResult::FAILURE;
case OpenUrlResponse::LOCAL_FALLBACK:
return mojom::OpenUrlResult::LOCAL_FALLBACK;
}
}
} // namespace
RemoteOpenUrlMessageHandler::RemoteOpenUrlMessageHandler(
const std::string& name,
std::unique_ptr<protocol::MessagePipe> pipe)
: protocol::NamedMessagePipeHandler(name, std::move(pipe)) {
ipc_server_.set_disconnect_handler(base::BindRepeating(
&RemoteOpenUrlMessageHandler::OnIpcDisconnected, base::Unretained(this)));
}
RemoteOpenUrlMessageHandler::~RemoteOpenUrlMessageHandler() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
OnDisconnecting();
}
void RemoteOpenUrlMessageHandler::OnConnected() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ipc_server_.StartServer();
}
void RemoteOpenUrlMessageHandler::OnIncomingMessage(
std::unique_ptr<CompoundBuffer> message) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto remote_open_url =
protocol::ParseMessage<protocol::RemoteOpenUrl>(message.get());
if (!remote_open_url->has_open_url_response()) {
LOG(WARNING)
<< "Received a RemoteOpenUrl message without open_url_response.";
return;
}
const auto& response = remote_open_url->open_url_response();
auto it = callbacks_.find(response.id());
if (it == callbacks_.end()) {
LOG(WARNING) << "Untracked remote open URL ID: " << response.id();
return;
}
std::move(it->second).Run(ToMojomOpenUrlResult(response.result()));
callbacks_.erase(it);
ipc_server_.Close(response.id());
}
void RemoteOpenUrlMessageHandler::OnDisconnecting() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ipc_server_.StopServer();
// The remote connection is going away, so inform all IPC clients to open the
// URL locally.
for (auto& entry : callbacks_) {
std::move(entry.second).Run(mojom::OpenUrlResult::LOCAL_FALLBACK);
}
callbacks_.clear();
}
void RemoteOpenUrlMessageHandler::OnIpcDisconnected() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = callbacks_.find(ipc_server_.current_receiver());
if (it != callbacks_.end()) {
LOG(WARNING)
<< "The client has disconnected before the response is received.";
callbacks_.erase(it);
}
}
void RemoteOpenUrlMessageHandler::OpenUrl(const GURL& url,
OpenUrlCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!url.is_valid()) {
std::move(callback).Run(mojom::OpenUrlResult::FAILURE);
return;
}
mojo::ReceiverId id = ipc_server_.current_receiver();
DCHECK(callbacks_.find(id) == callbacks_.end())
<< "The client has made more than one call to OpenUrl().";
protocol::RemoteOpenUrl remote_open_url;
remote_open_url.mutable_open_url_request()->set_id(id);
remote_open_url.mutable_open_url_request()->set_url(url.spec());
Send(remote_open_url, base::DoNothing());
callbacks_[id] = std::move(callback);
}
} // namespace remoting