// Copyright 2017 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/notifications/notification_platform_bridge_linux.h"

#include <memory>
#include <vector>

#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/i18n/number_formatting.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/notifications/notification.h"
#include "chrome/browser/notifications/notification_test_util.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "dbus/mock_bus.h"
#include "dbus/mock_object_proxy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/re2/src/re2/re2.h"
#include "ui/gfx/image/image_skia.h"

using testing::_;
using testing::Return;
using testing::StrictMock;

namespace {

const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications";
const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications";

class NotificationBuilder {
 public:
  explicit NotificationBuilder(const std::string& id)
      : notification_(message_center::NOTIFICATION_TYPE_SIMPLE,
                      base::string16(),
                      base::string16(),
                      gfx::Image(),
                      message_center::NotifierId(GURL()),
                      base::string16(),
                      GURL(),
                      id,
                      message_center::RichNotificationData(),
                      new MockNotificationDelegate(id)) {}

  Notification GetResult() { return notification_; }

  NotificationBuilder& SetImage(const gfx::Image& image) {
    notification_.set_image(image);
    return *this;
  }

  NotificationBuilder& SetItems(
      const std::vector<message_center::NotificationItem>& items) {
    notification_.set_items(items);
    return *this;
  }

  NotificationBuilder& SetMessage(const base::string16& message) {
    notification_.set_message(message);
    return *this;
  }

  NotificationBuilder& SetNeverTimeout(bool never_timeout) {
    notification_.set_never_timeout(never_timeout);
    return *this;
  }

  NotificationBuilder& SetOriginUrl(const GURL& origin_url) {
    notification_.set_origin_url(origin_url);
    return *this;
  }

  NotificationBuilder& SetProgress(int progress) {
    notification_.set_progress(progress);
    return *this;
  }

  NotificationBuilder& SetTitle(const base::string16& title) {
    notification_.set_title(title);
    return *this;
  }

  NotificationBuilder& SetType(message_center::NotificationType type) {
    notification_.set_type(type);
    return *this;
  }

 private:
  Notification notification_;
};

struct NotificationRequest {
  std::string summary;
  std::string body;
  int32_t expire_timeout = 0;
};

const SkBitmap CreateBitmap(int width, int height) {
  SkBitmap bitmap;
  bitmap.allocN32Pixels(width, height);
  bitmap.eraseARGB(255, 0, 255, 0);
  return bitmap;
}

gfx::ImageSkia CreateImageSkia(int width, int height) {
  return gfx::ImageSkia::CreateFrom1xBitmap(CreateBitmap(width, height));
}

NotificationRequest ParseRequest(dbus::MethodCall* method_call) {
  // The "Notify" message must have type (susssasa{sv}i).
  // https://developer.gnome.org/notification-spec/#command-notify
  NotificationRequest request;

  dbus::MessageReader reader(method_call);
  std::string str;
  uint32_t uint32;
  EXPECT_TRUE(reader.PopString(&str));              // app_name
  EXPECT_TRUE(reader.PopUint32(&uint32));           // replaces_id
  EXPECT_TRUE(reader.PopString(&str));              // app_icon
  EXPECT_TRUE(reader.PopString(&request.summary));  // summary
  EXPECT_TRUE(reader.PopString(&request.body));     // body

  {
    dbus::MessageReader actions_reader(nullptr);
    EXPECT_TRUE(reader.PopArray(&actions_reader));
    while (actions_reader.HasMoreData()) {
      // Actions come in pairs.
      EXPECT_TRUE(actions_reader.PopString(&str));
      EXPECT_TRUE(actions_reader.PopString(&str));
    }
  }

  {
    dbus::MessageReader hints_reader(nullptr);
    EXPECT_TRUE(reader.PopArray(&hints_reader));
    while (hints_reader.HasMoreData()) {
      dbus::MessageReader dict_entry_reader(nullptr);
      EXPECT_TRUE(hints_reader.PopDictEntry(&dict_entry_reader));
      EXPECT_TRUE(dict_entry_reader.PopString(&str));
      dbus::MessageReader variant_reader(nullptr);
      EXPECT_TRUE(dict_entry_reader.PopVariant(&variant_reader));
      EXPECT_FALSE(dict_entry_reader.HasMoreData());
    }
  }

  EXPECT_TRUE(reader.PopInt32(&request.expire_timeout));
  EXPECT_FALSE(reader.HasMoreData());

  return request;
}

dbus::Response* GetIdResponse(uint32_t id) {
  dbus::Response* response = dbus::Response::CreateEmpty().release();
  dbus::MessageWriter writer(response);
  writer.AppendUint32(id);
  return response;
}

ACTION_P(RegisterSignalCallback, callback_addr) {
  *callback_addr = arg2;
  arg3.Run("" /* interface_name */, "" /* signal_name */, true /* success */);
}

ACTION_P(OnGetCapabilities, capabilities) {
  // MockObjectProxy::CallMethodAndBlock will wrap the return value in
  // a unique_ptr.
  dbus::Response* response = dbus::Response::CreateEmpty().release();
  dbus::MessageWriter writer(response);
  writer.AppendArrayOfStrings(capabilities);
  return response;
}

ACTION_P2(OnNotify, verifier, id) {
  verifier(ParseRequest(arg0));
  return GetIdResponse(id);
}

ACTION(OnCloseNotification) {
  // The "CloseNotification" message must have type (u).
  // https://developer.gnome.org/notification-spec/#command-close-notification
  dbus::MethodCall* method_call = arg0;
  dbus::MessageReader reader(method_call);
  uint32_t uint32;
  EXPECT_TRUE(reader.PopUint32(&uint32));
  EXPECT_FALSE(reader.HasMoreData());

  return dbus::Response::CreateEmpty().release();
}

ACTION_P(OnNotificationBridgeReady, success) {
  EXPECT_EQ(success, arg0);
}

// Matches a method call to the specified dbus target.
MATCHER_P(Calls, member, "") {
  return arg->GetMember() == member;
}

}  // namespace

class NotificationPlatformBridgeLinuxTest : public testing::Test {
 public:
  NotificationPlatformBridgeLinuxTest() = default;
  ~NotificationPlatformBridgeLinuxTest() override = default;

  void SetUp() override {
    mock_bus_ = new dbus::MockBus(dbus::Bus::Options());
    mock_notification_proxy_ = new StrictMock<dbus::MockObjectProxy>(
        mock_bus_.get(), kFreedesktopNotificationsName,
        dbus::ObjectPath(kFreedesktopNotificationsPath));
  }

  void TearDown() override {
    notification_bridge_linux_->CleanUp();
    content::RunAllBlockingPoolTasksUntilIdle();
    notification_bridge_linux_.reset();
    mock_notification_proxy_ = nullptr;
    mock_bus_ = nullptr;
  }

 protected:
  void CreateNotificationBridgeLinux() {
    CreateNotificationBridgeLinux(
        std::vector<std::string>{"actions", "body", "body-hyperlinks",
                                 "body-images", "body-markup"},
        true, true, true);
  }

  void CreateNotificationBridgeLinux(
      const std::vector<std::string>& capabilities,
      bool expect_init_success,
      bool expect_shutdown,
      bool connect_signals) {
    EXPECT_CALL(*mock_bus_.get(),
                GetObjectProxy(kFreedesktopNotificationsName,
                               dbus::ObjectPath(kFreedesktopNotificationsPath)))
        .WillOnce(Return(mock_notification_proxy_.get()));

    EXPECT_CALL(*mock_notification_proxy_.get(),
                MockCallMethodAndBlock(Calls("GetCapabilities"), _))
        .WillOnce(OnGetCapabilities(capabilities));

    if (connect_signals) {
      EXPECT_CALL(
          *mock_notification_proxy_.get(),
          ConnectToSignal(kFreedesktopNotificationsName, "ActionInvoked", _, _))
          .WillOnce(RegisterSignalCallback(&action_invoked_callback_));

      EXPECT_CALL(*mock_notification_proxy_.get(),
                  ConnectToSignal(kFreedesktopNotificationsName,
                                  "NotificationClosed", _, _))
          .WillOnce(RegisterSignalCallback(&notification_closed_callback_));
    }

    EXPECT_CALL(*this, MockableNotificationBridgeReadyCallback(_))
        .WillOnce(OnNotificationBridgeReady(expect_init_success));

    if (expect_shutdown)
      EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock());

    notification_bridge_linux_ =
        base::WrapUnique(new NotificationPlatformBridgeLinux(mock_bus_));
    notification_bridge_linux_->SetReadyCallback(
        base::BindOnce(&NotificationPlatformBridgeLinuxTest::
                           MockableNotificationBridgeReadyCallback,
                       base::Unretained(this)));
    content::RunAllBlockingPoolTasksUntilIdle();
  }

  MOCK_METHOD1(MockableNotificationBridgeReadyCallback, void(bool));

  content::TestBrowserThreadBundle thread_bundle_;

  scoped_refptr<dbus::MockBus> mock_bus_;
  scoped_refptr<dbus::MockObjectProxy> mock_notification_proxy_;

  base::Callback<void(dbus::Signal*)> action_invoked_callback_;
  base::Callback<void(dbus::Signal*)> notification_closed_callback_;

  std::unique_ptr<NotificationPlatformBridgeLinux> notification_bridge_linux_;

 private:
  DISALLOW_COPY_AND_ASSIGN(NotificationPlatformBridgeLinuxTest);
};

TEST_F(NotificationPlatformBridgeLinuxTest, SetUpAndTearDown) {
  CreateNotificationBridgeLinux();
}

TEST_F(NotificationPlatformBridgeLinuxTest, NotifyAndCloseFormat) {
  EXPECT_CALL(*mock_notification_proxy_.get(),
              MockCallMethodAndBlock(Calls("Notify"), _))
      .WillOnce(OnNotify([](const NotificationRequest&) {}, 1));
  EXPECT_CALL(*mock_notification_proxy_.get(),
              MockCallMethodAndBlock(Calls("CloseNotification"), _))
      .WillOnce(OnCloseNotification());

  CreateNotificationBridgeLinux();
  notification_bridge_linux_->Display(NotificationCommon::PERSISTENT, "", "",
                                      false,
                                      NotificationBuilder("").GetResult());
  notification_bridge_linux_->Close("", "");
}

TEST_F(NotificationPlatformBridgeLinuxTest, ProgressPercentageAddedToSummary) {
  EXPECT_CALL(*mock_notification_proxy_.get(),
              MockCallMethodAndBlock(Calls("Notify"), _))
      .WillOnce(OnNotify(
          [](const NotificationRequest& request) {
            EXPECT_EQ(
                base::UTF16ToUTF8(base::FormatPercent(42)) + " - The Title",
                request.summary);
          },
          1));

  CreateNotificationBridgeLinux();
  notification_bridge_linux_->Display(
      NotificationCommon::PERSISTENT, "", "", false,
      NotificationBuilder("")
          .SetType(message_center::NOTIFICATION_TYPE_PROGRESS)
          .SetProgress(42)
          .SetTitle(base::UTF8ToUTF16("The Title"))
          .GetResult());
}

TEST_F(NotificationPlatformBridgeLinuxTest, NotificationListItemsInBody) {
  EXPECT_CALL(*mock_notification_proxy_.get(),
              MockCallMethodAndBlock(Calls("Notify"), _))
      .WillOnce(OnNotify(
          [](const NotificationRequest& request) {
            EXPECT_EQ("<b>abc</b> 123\n<b>def</b> 456", request.body);
          },
          1));

  CreateNotificationBridgeLinux();
  notification_bridge_linux_->Display(
      NotificationCommon::PERSISTENT, "", "", false,
      NotificationBuilder("")
          .SetType(message_center::NOTIFICATION_TYPE_MULTIPLE)
          .SetItems(std::vector<message_center::NotificationItem>{
              {base::UTF8ToUTF16("abc"), base::UTF8ToUTF16("123")},
              {base::UTF8ToUTF16("def"), base::UTF8ToUTF16("456")}})
          .GetResult());
}

TEST_F(NotificationPlatformBridgeLinuxTest, NotificationTimeouts) {
  const int32_t kExpireTimeoutDefault = -1;
  const int32_t kExpireTimeoutNever = 0;
  EXPECT_CALL(*mock_notification_proxy_.get(),
              MockCallMethodAndBlock(Calls("Notify"), _))
      .WillOnce(OnNotify(
          [=](const NotificationRequest& request) {
            EXPECT_EQ(kExpireTimeoutDefault, request.expire_timeout);
          },
          1))
      .WillOnce(OnNotify(
          [=](const NotificationRequest& request) {
            EXPECT_EQ(kExpireTimeoutNever, request.expire_timeout);
          },
          2));

  CreateNotificationBridgeLinux();
  notification_bridge_linux_->Display(
      NotificationCommon::PERSISTENT, "", "", false,
      NotificationBuilder("1").SetNeverTimeout(false).GetResult());
  notification_bridge_linux_->Display(
      NotificationCommon::PERSISTENT, "", "", false,
      NotificationBuilder("2").SetNeverTimeout(true).GetResult());
}

TEST_F(NotificationPlatformBridgeLinuxTest, NotificationImages) {
  const int kMaxImageWidth = 200;
  const int kMaxImageHeight = 100;

  const int original_width = kMaxImageWidth * 2;
  const int original_height = kMaxImageHeight;
  const int expected_width = kMaxImageWidth;
  const int expected_height = kMaxImageHeight / 2;

  gfx::Image original_image =
      gfx::Image(CreateImageSkia(original_width, original_height));

  EXPECT_CALL(*mock_notification_proxy_.get(),
              MockCallMethodAndBlock(Calls("Notify"), _))
      .WillOnce(OnNotify(
          [=](const NotificationRequest& request) {
            std::string file_name;
            EXPECT_TRUE(RE2::FullMatch(
                request.body, "\\<img src=\\\"(.+)\\\" alt=\\\".*\\\"/\\>",
                &file_name));
            std::string file_contents;
            EXPECT_TRUE(base::ReadFileToString(base::FilePath(file_name),
                                               &file_contents));
            gfx::Image image = gfx::Image::CreateFrom1xPNGBytes(
                reinterpret_cast<const unsigned char*>(file_contents.c_str()),
                file_contents.size());
            EXPECT_EQ(expected_width, image.Width());
            EXPECT_EQ(expected_height, image.Height());
          },
          1));

  CreateNotificationBridgeLinux();
  notification_bridge_linux_->Display(
      NotificationCommon::PERSISTENT, "", "", false,
      NotificationBuilder("")
          .SetType(message_center::NOTIFICATION_TYPE_IMAGE)
          .SetImage(original_image)
          .GetResult());
}

TEST_F(NotificationPlatformBridgeLinuxTest, NotificationAttribution) {
  EXPECT_CALL(*mock_notification_proxy_.get(),
              MockCallMethodAndBlock(Calls("Notify"), _))
      .WillOnce(OnNotify(
          [](const NotificationRequest& request) {
            EXPECT_EQ(
                "<a href=\"https%3A//google.com/"
                "search%3Fq=test&ie=UTF8\">google.com</a>\nBody text",
                request.body);
          },
          1));

  CreateNotificationBridgeLinux();
  notification_bridge_linux_->Display(
      NotificationCommon::PERSISTENT, "", "", false,
      NotificationBuilder("")
          .SetMessage(base::ASCIIToUTF16("Body text"))
          .SetOriginUrl(GURL("https://google.com/search?q=test&ie=UTF8"))
          .GetResult());
}

TEST_F(NotificationPlatformBridgeLinuxTest, MissingActionsCapability) {
  CreateNotificationBridgeLinux(std::vector<std::string>{"body"}, false, true,
                                false);
}

TEST_F(NotificationPlatformBridgeLinuxTest, MissingBodyCapability) {
  CreateNotificationBridgeLinux(std::vector<std::string>{"actions"}, false,
                                true, false);
}
