// Copyright 2019 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 "chrome/browser/chromeos/diagnosticsd/diagnosticsd_messaging.h"

#include <algorithm>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/unguessable_token.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/diagnosticsd/diagnosticsd_bridge.h"
#include "chrome/browser/chromeos/diagnosticsd/mojo_utils.h"
#include "chrome/browser/extensions/api/messaging/native_message_port.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/services/diagnosticsd/public/mojom/diagnosticsd.mojom.h"
#include "extensions/browser/api/messaging/message_service.h"
#include "extensions/browser/api/messaging/native_message_host.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/api/messaging/messaging_endpoint.h"
#include "extensions/common/extension.h"
#include "mojo/public/cpp/system/handle.h"
#include "url/gurl.h"

class Profile;

namespace chromeos {

// Native application name that is used for passing UI messages between the
// diagnostics_processor daemon and extensions.
const char kDiagnosticsdUiMessageHost[] = "com.google.wilco_dtc";

// Error messages sent to the extension:
const char kDiagnosticsdUiMessageTooBigExtensionsError[] =
    "Message is too big.";
const char kDiagnosticsdUiExtraMessagesExtensionsError[] =
    "At most one message must be sent through the message channel.";

// Maximum allowed size of UI messages passed between the diagnostics_processor
// daemon and extensions.
const int kDiagnosticsdUiMessageMaxSize = 1000000;

namespace {

// List of extension IDs that will receive UI messages from the
// diagnostics_processor through the extensions native messaging system.
//
// Note: the list must be kept in sync with the allowed origins list in
// src/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc.
//
// TODO(crbug.com/907932,b/123926112): Populate the list once extension IDs are
// determined.
const char* const kAllowedExtensionIds[] = {};

// Extensions native message host implementation that is used when an
// extension requests a message channel to the diagnostics_processor daemon.
//
// The message is transmitted via the diagnosticsd daemon. One instance of this
// class allows only one message to be sent; at most one message will be sent in
// the reverse direction: it will contain the daemon's response.
class DiagnosticsdExtensionOwnedMessageHost final
    : public extensions::NativeMessageHost {
 public:
  DiagnosticsdExtensionOwnedMessageHost() = default;
  ~DiagnosticsdExtensionOwnedMessageHost() override = default;

  // extensions::NativeMessageHost:

  void Start(Client* client) override {
    DCHECK(!client_);
    client_ = client;
  }

  void OnMessage(const std::string& request_string) override {
    DCHECK(client_);

    if (is_disposed_) {
      // We already called CloseChannel() before so ignore messages arriving at
      // this point. This corner case can happen because CloseChannel() does its
      // job asynchronously.
      return;
    }

    if (message_from_extension_received_) {
      // Our implementation doesn't allow sending multiple messages from the
      // extension over the same instance.
      DisposeSelf(kDiagnosticsdUiExtraMessagesExtensionsError);
      return;
    }
    message_from_extension_received_ = true;

    if (request_string.size() > kDiagnosticsdUiMessageMaxSize) {
      DisposeSelf(kDiagnosticsdUiMessageTooBigExtensionsError);
      return;
    }

    DiagnosticsdBridge* const diagnosticsd_bridge = DiagnosticsdBridge::Get();
    if (!diagnosticsd_bridge) {
      VLOG(0) << "Cannot send message - no bridge to the daemon";
      DisposeSelf(kNotFoundError);
      return;
    }

    diagnosticsd::mojom::DiagnosticsdServiceProxy* const
        diagnosticsd_mojo_proxy =
            diagnosticsd_bridge->diagnosticsd_service_mojo_proxy();
    if (!diagnosticsd_mojo_proxy) {
      VLOG(0) << "Cannot send message - Mojo connection to the daemon isn't "
                 "bootstrapped yet";
      DisposeSelf(kNotFoundError);
      return;
    }

    mojo::ScopedHandle json_message_mojo_handle =
        CreateReadOnlySharedMemoryMojoHandle(request_string);
    if (!json_message_mojo_handle) {
      LOG(ERROR) << "Cannot create Mojo shared memory handle from string";
      DisposeSelf(kHostInputOutputError);
      return;
    }

    diagnosticsd_mojo_proxy->SendUiMessageToDiagnosticsProcessor(
        std::move(json_message_mojo_handle),
        base::BindOnce(&DiagnosticsdExtensionOwnedMessageHost::
                           OnResponseReceivedFromDaemon,
                       weak_ptr_factory_.GetWeakPtr()));
  }

  scoped_refptr<base::SingleThreadTaskRunner> task_runner() const override {
    return task_runner_;
  }

 private:
  void DisposeSelf(const std::string& error_message) {
    DCHECK(!is_disposed_);
    is_disposed_ = true;
    client_->CloseChannel(error_message);
    // Prevent the Mojo call result, if it's still in flight, from being
    // forwarded to the extension.
    weak_ptr_factory_.InvalidateWeakPtrs();
  }

  void OnResponseReceivedFromDaemon(mojo::ScopedHandle response_json_message) {
    DCHECK(client_);
    DCHECK(!is_disposed_);

    if (!response_json_message) {
      // The call to the diagnostics_processor daemon failed or the daemon
      // provided no response, so just close the extension message channel as
      // it's intended to be used for one-time messages only.
      VLOG(1) << "Empty response, closing the extension message channel";
      DisposeSelf(std::string() /* error_message */);
      return;
    }

    std::unique_ptr<base::SharedMemory> response_json_shared_memory;
    base::StringPiece response_json_string = GetStringPieceFromMojoHandle(
        std::move(response_json_message), &response_json_shared_memory);
    if (response_json_string.empty()) {
      LOG(ERROR) << "Cannot read response from Mojo shared memory";
      DisposeSelf(kHostInputOutputError);
      return;
    }

    if (response_json_string.size() > kDiagnosticsdUiMessageMaxSize) {
      LOG(ERROR) << "The message received from the daemon is too big";
      DisposeSelf(kDiagnosticsdUiMessageTooBigExtensionsError);
      return;
    }

    if (response_json_string.size() > kDiagnosticsdUiMessageMaxSize) {
      LOG(ERROR) << "The message received from the daemon is too big";
      client_->CloseChannel(kHostInputOutputError);
      return;
    }

    client_->PostMessageFromNativeHost(response_json_string.as_string());
    DisposeSelf(std::string() /* error_message */);
  }

  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_ =
      base::ThreadTaskRunnerHandle::Get();

  // Unowned.
  Client* client_ = nullptr;

  // Whether a message has already been received from the extension.
  bool message_from_extension_received_ = false;
  // Whether DisposeSelf() has already been called.
  bool is_disposed_ = false;

  // Must be the last member.
  base::WeakPtrFactory<DiagnosticsdExtensionOwnedMessageHost> weak_ptr_factory_{
      this};

  DISALLOW_COPY_AND_ASSIGN(DiagnosticsdExtensionOwnedMessageHost);
};

// Extensions native message host implementation that is used when the
// diagnostics_processor daemon sends (via the diagnosticsd daemon) a message to
// the extension.
//
// A new instance of this class should be created for each instance of the
// extension(s) that are allowed to receive messages from the
// diagnostics_processor daemon. Once the extension responds by posting a
// message back to this message channel, |send_response_callback| will be
// called.
class DiagnosticsdDaemonOwnedMessageHost final
    : public extensions::NativeMessageHost {
 public:
  DiagnosticsdDaemonOwnedMessageHost(
      const std::string& json_message_to_send,
      base::OnceCallback<void(const std::string& response)>
          send_response_callback)
      : json_message_to_send_(json_message_to_send),
        send_response_callback_(std::move(send_response_callback)) {
    DCHECK(send_response_callback_);
  }

  ~DiagnosticsdDaemonOwnedMessageHost() override {
    if (send_response_callback_) {
      // If no response was received from the extension, pass the empty result
      // to the callback to signal the error.
      std::move(send_response_callback_).Run(std::string() /* response */);
    }
  }

  // extensions::NativeMessageHost:

  void Start(Client* client) override {
    DCHECK(!client_);
    client_ = client;
    client_->PostMessageFromNativeHost(json_message_to_send_);
  }

  void OnMessage(const std::string& request_string) override {
    DCHECK(client_);
    if (!send_response_callback_) {
      // This happens when the extension sent more than one message via the
      // message channel, which is not supported in our case - therefore simply
      // discard these extra messages.
      return;
    }
    if (request_string.size() > kDiagnosticsdUiMessageMaxSize) {
      std::move(send_response_callback_).Run(std::string() /* response */);
      client_->CloseChannel(kDiagnosticsdUiMessageTooBigExtensionsError);
      return;
    }
    std::move(send_response_callback_).Run(request_string /* response */);
    client_->CloseChannel(std::string() /* error_message */);
  }

  scoped_refptr<base::SingleThreadTaskRunner> task_runner() const override {
    return task_runner_;
  }

 private:
  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_ =
      base::ThreadTaskRunnerHandle::Get();
  const std::string json_message_to_send_;
  base::OnceCallback<void(const std::string& response)> send_response_callback_;
  // Unowned.
  Client* client_ = nullptr;

  DISALLOW_COPY_AND_ASSIGN(DiagnosticsdDaemonOwnedMessageHost);
};

// Helper that wraps the specified OnceCallback and encapsulates logic that
// executes it once either of the following becomes true (whichever happens to
// be earlier):
// * Non-empty data was provided to this class via the ProcessResponse() method;
// * The ProcessResponse() method has been called the |wrapper_callback_count|
//   number of times.
class FirstNonEmptyMessageCallbackWrapper final {
 public:
  FirstNonEmptyMessageCallbackWrapper(
      base::OnceCallback<void(const std::string& response)> original_callback,
      int wrapper_callback_count)
      : original_callback_(std::move(original_callback)),
        pending_callback_count_(wrapper_callback_count) {
    DCHECK(original_callback_);
    DCHECK_GE(pending_callback_count_, 0);
    if (!pending_callback_count_)
      std::move(original_callback_).Run(std::string() /* response */);
  }

  ~FirstNonEmptyMessageCallbackWrapper() {
    if (original_callback_) {
      // Not all responses were received before this instance is destroyed, so
      // run the callback with an error result here.
      std::move(original_callback_).Run(std::string() /* response */);
    }
  }

  void ProcessResponse(const std::string& response) {
    if (!original_callback_) {
      // The response was already passed in one of the previous invocations.
      return;
    }
    if (!response.empty()) {
      std::move(original_callback_).Run(response);
      return;
    }
    --pending_callback_count_;
    DCHECK_GE(pending_callback_count_, 0);
    if (pending_callback_count_ == 0) {
      // This is the last response and all responses have been empty, so pass
      // the empty response.
      std::move(original_callback_).Run(std::string() /* response */);
      return;
    }
  }

 private:
  base::OnceCallback<void(const std::string& response)> original_callback_;
  int pending_callback_count_;

  DISALLOW_COPY_AND_ASSIGN(FirstNonEmptyMessageCallbackWrapper);
};

void DeliverMessageToExtension(
    Profile* profile,
    const std::string& extension_id,
    const std::string& json_message,
    base::OnceCallback<void(const std::string& response)>
        send_response_callback) {
  const extensions::PortId port_id(base::UnguessableToken::Create(),
                                   1 /* port_number */, true /* is_opener */);
  extensions::MessageService* const message_service =
      extensions::MessageService::Get(profile);
  auto native_message_host =
      std::make_unique<DiagnosticsdDaemonOwnedMessageHost>(
          json_message, std::move(send_response_callback));
  auto native_message_port = std::make_unique<extensions::NativeMessagePort>(
      message_service->GetChannelDelegate(), port_id,
      std::move(native_message_host));
  message_service->OpenChannelToExtension(
      -1 /* source_process_id */, -1 /* source_routing_id */, port_id,
      extensions::MessagingEndpoint::ForNativeApp(kDiagnosticsdUiMessageHost),
      std::move(native_message_port), extension_id, GURL(),
      std::string() /* channel_name */);
}

}  // namespace

std::unique_ptr<extensions::NativeMessageHost>
CreateExtensionOwnedDiagnosticsdMessageHost() {
  return std::make_unique<DiagnosticsdExtensionOwnedMessageHost>();
}

void DeliverDiagnosticsdUiMessageToExtensions(
    const std::string& json_message,
    base::OnceCallback<void(const std::string& response)>
        send_response_callback) {
  if (json_message.size() > kDiagnosticsdUiMessageMaxSize) {
    VLOG(1) << "Message received from the daemon is too big";
    return;
  }

  // Determine beforehand which extension instances should receive the event, in
  // order to be able to construct the wrapper callback with the needed counter.
  std::vector<std::pair<Profile*, std::string>> recipient_extensions;
  for (auto* profile :
       g_browser_process->profile_manager()->GetLoadedProfiles()) {
    for (const auto* extension_id : kAllowedExtensionIds) {
      if (extensions::ExtensionRegistry::Get(profile)
              ->enabled_extensions()
              .GetByID(extension_id)) {
        recipient_extensions.emplace_back(profile, extension_id);
      }
    }
  }

  // Build the wrapper callback in order to call |send_response_callback| once
  // when:
  // * either the first non-empty response is received from one of the
  //   extensions;
  // * or requests to all extensions completed with no response.
  base::RepeatingCallback<void(const std::string& response)>
      first_non_empty_message_forwarding_callback = base::BindRepeating(
          &FirstNonEmptyMessageCallbackWrapper::ProcessResponse,
          base::Owned(new FirstNonEmptyMessageCallbackWrapper(
              std::move(send_response_callback),
              static_cast<int>(recipient_extensions.size()))));

  for (const auto& profile_and_extension : recipient_extensions) {
    DeliverMessageToExtension(profile_and_extension.first,
                              profile_and_extension.second, json_message,
                              first_non_empty_message_forwarding_callback);
  }
}

}  // namespace chromeos
