remote_open_url_message_handler.cc 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "remoting/host/remote_open_url/remote_open_url_message_handler.h"
  5. #include "base/bind.h"
  6. #include "base/callback_helpers.h"
  7. #include "base/logging.h"
  8. #include "remoting/base/compound_buffer.h"
  9. #include "remoting/protocol/message_serialization.h"
  10. #include "url/gurl.h"
  11. namespace remoting {
  12. namespace {
  13. using OpenUrlResponse = protocol::RemoteOpenUrl::OpenUrlResponse;
  14. mojom::OpenUrlResult ToMojomOpenUrlResult(
  15. OpenUrlResponse::Result protobuf_result) {
  16. switch (protobuf_result) {
  17. case OpenUrlResponse::UNSPECIFIED_OPEN_URL_RESULT:
  18. return mojom::OpenUrlResult::UNSPECIFIED_OPEN_URL_RESULT;
  19. case OpenUrlResponse::SUCCESS:
  20. return mojom::OpenUrlResult::SUCCESS;
  21. case OpenUrlResponse::FAILURE:
  22. return mojom::OpenUrlResult::FAILURE;
  23. case OpenUrlResponse::LOCAL_FALLBACK:
  24. return mojom::OpenUrlResult::LOCAL_FALLBACK;
  25. }
  26. }
  27. } // namespace
  28. RemoteOpenUrlMessageHandler::RemoteOpenUrlMessageHandler(
  29. const std::string& name,
  30. std::unique_ptr<protocol::MessagePipe> pipe)
  31. : protocol::NamedMessagePipeHandler(name, std::move(pipe)) {
  32. receivers_.set_disconnect_handler(base::BindRepeating(
  33. &RemoteOpenUrlMessageHandler::OnIpcDisconnected, base::Unretained(this)));
  34. }
  35. RemoteOpenUrlMessageHandler::~RemoteOpenUrlMessageHandler() {
  36. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  37. OnDisconnecting();
  38. }
  39. void RemoteOpenUrlMessageHandler::AddReceiver(
  40. mojo::PendingReceiver<mojom::RemoteUrlOpener> receiver) {
  41. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  42. AddReceiverAndGetReceiverId(std::move(receiver));
  43. }
  44. void RemoteOpenUrlMessageHandler::ClearReceivers() {
  45. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  46. receivers_.Clear();
  47. }
  48. void RemoteOpenUrlMessageHandler::OnIncomingMessage(
  49. std::unique_ptr<CompoundBuffer> message) {
  50. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  51. auto remote_open_url =
  52. protocol::ParseMessage<protocol::RemoteOpenUrl>(message.get());
  53. if (!remote_open_url->has_open_url_response()) {
  54. LOG(WARNING)
  55. << "Received a RemoteOpenUrl message without open_url_response.";
  56. return;
  57. }
  58. const auto& response = remote_open_url->open_url_response();
  59. auto it = callbacks_.find(response.id());
  60. if (it == callbacks_.end()) {
  61. LOG(WARNING) << "Untracked remote open URL ID: " << response.id();
  62. return;
  63. }
  64. std::move(it->second).Run(ToMojomOpenUrlResult(response.result()));
  65. callbacks_.erase(it);
  66. receivers_.Remove(response.id());
  67. }
  68. void RemoteOpenUrlMessageHandler::OnDisconnecting() {
  69. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  70. // The remote connection is going away, so inform all IPC clients to open the
  71. // URL locally.
  72. for (auto& entry : callbacks_) {
  73. std::move(entry.second).Run(mojom::OpenUrlResult::LOCAL_FALLBACK);
  74. }
  75. callbacks_.clear();
  76. receivers_.Clear();
  77. }
  78. base::WeakPtr<RemoteOpenUrlMessageHandler>
  79. RemoteOpenUrlMessageHandler::GetWeakPtr() {
  80. return weak_factory_.GetWeakPtr();
  81. }
  82. mojo::ReceiverId RemoteOpenUrlMessageHandler::AddReceiverAndGetReceiverId(
  83. mojo::PendingReceiver<mojom::RemoteUrlOpener> receiver) {
  84. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  85. if (!connected()) {
  86. LOG(WARNING) << "RemoteOpenUrlMessageHandler has not been connected";
  87. return 0u;
  88. }
  89. return receivers_.Add(this, std::move(receiver));
  90. }
  91. void RemoteOpenUrlMessageHandler::OnIpcDisconnected() {
  92. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  93. auto it = callbacks_.find(receivers_.current_receiver());
  94. if (it != callbacks_.end()) {
  95. LOG(WARNING)
  96. << "The client has disconnected before the response is received.";
  97. callbacks_.erase(it);
  98. }
  99. }
  100. void RemoteOpenUrlMessageHandler::OpenUrl(const GURL& url,
  101. OpenUrlCallback callback) {
  102. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  103. if (!url.is_valid()) {
  104. std::move(callback).Run(mojom::OpenUrlResult::FAILURE);
  105. receivers_.Remove(receivers_.current_receiver());
  106. return;
  107. }
  108. mojo::ReceiverId id = receivers_.current_receiver();
  109. DCHECK(callbacks_.find(id) == callbacks_.end())
  110. << "The client has made more than one call to OpenUrl().";
  111. protocol::RemoteOpenUrl remote_open_url;
  112. remote_open_url.mutable_open_url_request()->set_id(id);
  113. remote_open_url.mutable_open_url_request()->set_url(url.spec());
  114. Send(remote_open_url, base::DoNothing());
  115. callbacks_[id] = std::move(callback);
  116. }
  117. } // namespace remoting