// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/invalidation/impl/fcm_invalidation_service.h"

#include <memory>
#include <utility>

#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/strcat.h"
#include "base/test/task_environment.h"
#include "base/values.h"
#include "components/gcm_driver/fake_gcm_driver.h"
#include "components/gcm_driver/gcm_driver.h"
#include "components/gcm_driver/instance_id/instance_id.h"
#include "components/gcm_driver/instance_id/instance_id_driver.h"
#include "components/invalidation/impl/fake_invalidation_handler.h"
#include "components/invalidation/impl/fcm_invalidation_listener.h"
#include "components/invalidation/impl/fcm_network_handler.h"
#include "components/invalidation/impl/fcm_sync_network_channel.h"
#include "components/invalidation/impl/invalidation_prefs.h"
#include "components/invalidation/impl/invalidation_service_test_template.h"
#include "components/invalidation/impl/profile_identity_provider.h"
#include "components/invalidation/public/topic_invalidation_map.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using instance_id::InstanceID;
using instance_id::InstanceIDDriver;
using testing::_;

namespace invalidation {

namespace {

class TestFCMSyncNetworkChannel : public FCMSyncNetworkChannel {
 public:
  void StartListening() override {}
  void StopListening() override {}

  void RequestDetailedStatus(
      const base::RepeatingCallback<void(base::Value::Dict)>& callback)
      override {}
};

// TODO: Make FCMInvalidationListener class abstract and explicitly make all the
// methods virtual. Provide FCMInvalidationListenerImpl and
// FakeFCMInvalidationListener classes that will inherit from
// FCMInvalidationListener. The reason for such a change is that
// FCMInvalidationService relies of FCMInvalidationListener class.
class FakeFCMInvalidationListener : public FCMInvalidationListener {
 public:
  explicit FakeFCMInvalidationListener(
      std::unique_ptr<FCMSyncNetworkChannel> network_channel)
      : FCMInvalidationListener(std::move(network_channel)) {}
  ~FakeFCMInvalidationListener() override = default;

  void RequestDetailedStatus(
      const base::RepeatingCallback<void(base::Value::Dict)>& callback)
      const override {
    callback.Run(base::Value::Dict());
  }
};

}  // namespace

const char kApplicationName[] = "com.google.chrome.fcm.invalidations";
const char kSenderId[] = "invalidations-sender-id";

class MockInstanceID : public InstanceID {
 public:
  MockInstanceID() : InstanceID("app_id", /*gcm_driver=*/nullptr) {}
  ~MockInstanceID() override = default;

  MOCK_METHOD1(GetID, void(GetIDCallback callback));
  MOCK_METHOD1(GetCreationTime, void(GetCreationTimeCallback callback));
  MOCK_METHOD5(GetToken,
               void(const std::string& authorized_entity,
                    const std::string& scope,
                    base::TimeDelta time_to_live,
                    std::set<Flags> flags,
                    GetTokenCallback callback));
  MOCK_METHOD4(ValidateToken,
               void(const std::string& authorized_entity,
                    const std::string& scope,
                    const std::string& token,
                    ValidateTokenCallback callback));

  MOCK_METHOD3(DeleteTokenImpl,
               void(const std::string& authorized_entity,
                    const std::string& scope,
                    DeleteTokenCallback callback));
  MOCK_METHOD1(DeleteIDImpl, void(DeleteIDCallback callback));
};

class MockInstanceIDDriver : public InstanceIDDriver {
 public:
  MockInstanceIDDriver() : InstanceIDDriver(/*gcm_driver=*/nullptr) {}
  ~MockInstanceIDDriver() override = default;

  MOCK_METHOD1(GetInstanceID, InstanceID*(const std::string& app_id));
  MOCK_METHOD1(RemoveInstanceID, void(const std::string& app_id));
  MOCK_CONST_METHOD1(ExistsInstanceID, bool(const std::string& app_id));
};

class FCMInvalidationServiceTestDelegate {
 public:
  FCMInvalidationServiceTestDelegate() {
    pref_service_.registry()->RegisterDictionaryPref(
        prefs::kInvalidationClientIDCache);
    InvalidatorRegistrarWithMemory::RegisterProfilePrefs(
        pref_service_.registry());
  }

  ~FCMInvalidationServiceTestDelegate() = default;

  void CreateInvalidationService() {
    CreateUninitializedInvalidationService();
    InitializeInvalidationService();
  }

  void CreateUninitializedInvalidationService() {
    gcm_driver_ = std::make_unique<gcm::FakeGCMDriver>();

    identity_provider_ = std::make_unique<ProfileIdentityProvider>(
        identity_test_env_.identity_manager());

    mock_instance_id_driver_ =
        std::make_unique<testing::NiceMock<MockInstanceIDDriver>>();
    mock_instance_id_ = std::make_unique<testing::NiceMock<MockInstanceID>>();
    ON_CALL(*mock_instance_id_driver_,
            GetInstanceID(base::StrCat({kApplicationName, "-", kSenderId})))
        .WillByDefault(testing::Return(mock_instance_id_.get()));
    ON_CALL(*mock_instance_id_, GetID(_))
        .WillByDefault(testing::WithArg<0>(
            testing::Invoke([](InstanceID::GetIDCallback callback) {
              std::move(callback).Run("FakeIID");
            })));

    invalidation_service_ = std::make_unique<FCMInvalidationService>(
        identity_provider_.get(),
        base::BindRepeating(&FCMNetworkHandler::Create, gcm_driver_.get(),
                            mock_instance_id_driver_.get()),
        base::BindRepeating(&PerUserTopicSubscriptionManager::Create,
                            identity_provider_.get(), &pref_service_,
                            &url_loader_factory_),
        mock_instance_id_driver_.get(), &pref_service_, kSenderId);
  }

  void InitializeInvalidationService() {
    fake_listener_ = new FakeFCMInvalidationListener(
        std::make_unique<TestFCMSyncNetworkChannel>());
    invalidation_service_->InitForTest(base::WrapUnique(fake_listener_.get()));
  }

  FCMInvalidationService* GetInvalidationService() {
    return invalidation_service_.get();
  }

  void DestroyInvalidationService() { invalidation_service_.reset(); }

  void TriggerOnInvalidatorStateChange(InvalidatorState state) {
    fake_listener_->EmitStateChangeForTest(state);
  }

  void TriggerOnIncomingInvalidation(
      const TopicInvalidationMap& invalidation_map) {
    fake_listener_->EmitSavedInvalidationsForTest(invalidation_map);
  }

  base::test::TaskEnvironment task_environment_;
  data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
  std::unique_ptr<gcm::GCMDriver> gcm_driver_;
  std::unique_ptr<MockInstanceIDDriver> mock_instance_id_driver_;
  std::unique_ptr<MockInstanceID> mock_instance_id_;
  signin::IdentityTestEnvironment identity_test_env_;
  std::unique_ptr<IdentityProvider> identity_provider_;
  raw_ptr<FCMInvalidationListener> fake_listener_;  // Owned by the service.
  network::TestURLLoaderFactory url_loader_factory_;
  TestingPrefServiceSimple pref_service_;

  // The service has to be below the provider since the service keeps
  // a non-owned pointer to the provider.
  std::unique_ptr<FCMInvalidationService> invalidation_service_;
};

INSTANTIATE_TYPED_TEST_SUITE_P(FCMInvalidationServiceTest,
                               InvalidationServiceTest,
                               FCMInvalidationServiceTestDelegate);

TEST(FCMInvalidationServiceTest, NotifiesAboutInstanceID) {
  auto delegate = std::make_unique<FCMInvalidationServiceTestDelegate>();

  // Set up a cached InstanceID aka client ID stored in prefs.
  {
    ScopedDictPrefUpdate update(&delegate->pref_service_,
                                prefs::kInvalidationClientIDCache);
    update->Set(kSenderId, "InstanceIDFromPrefs");
  }

  // Create the invalidation service, but do not initialize it yet.
  delegate->CreateUninitializedInvalidationService();
  FCMInvalidationService* invalidation_service =
      delegate->GetInvalidationService();
  ASSERT_TRUE(invalidation_service->GetInvalidatorClientId().empty());

  // Register a handler *before* initializing the invalidation service.
  FakeInvalidationHandler handler("owner_1");
  invalidation_service->RegisterInvalidationHandler(&handler);

  // Because the invalidation service hasn't been initialized, the client ID is
  // still empty.
  EXPECT_TRUE(handler.GetInvalidatorClientId().empty());

  // Make sure the MockInstanceID doesn't immediately provide a fresh client ID.
  InstanceID::GetIDCallback get_id_callback;
  EXPECT_CALL(*delegate->mock_instance_id_, GetID(_))
      .WillOnce([&](InstanceID::GetIDCallback callback) {
        get_id_callback = std::move(callback);
      });

  // Initialize the service. It should read the client ID from prefs.
  delegate->InitializeInvalidationService();
  // The invalidation service has requested a fresh client ID.
  ASSERT_FALSE(get_id_callback.is_null());

  // The invalidation service should have restored the client ID from prefs, and
  // passed it on to the handler.
  EXPECT_EQ(handler.GetInvalidatorClientId(), "InstanceIDFromPrefs");

  // Once the invalidation service receives a fresh client ID, it should notify
  // the handler again. (Note that in practice, the fresh ID will almost always
  // be identical to the cached one.)
  std::move(get_id_callback).Run("FreshInstanceID");
  EXPECT_EQ(handler.GetInvalidatorClientId(), "FreshInstanceID");

  // Another handler that gets registered should immediately be informed of the
  // client ID.
  FakeInvalidationHandler handler2(/*owner=*/"owner_2");
  invalidation_service->RegisterInvalidationHandler(&handler2);
  EXPECT_EQ(handler2.GetInvalidatorClientId(), "FreshInstanceID");

  invalidation_service->UnregisterInvalidationHandler(&handler2);
  invalidation_service->UnregisterInvalidationHandler(&handler);
}

TEST(FCMInvalidationServiceTest, ClearsInstanceIDOnSignout) {
  // Set up an invalidation service and make sure it generated a client ID (aka
  // InstanceID).
  auto delegate = std::make_unique<FCMInvalidationServiceTestDelegate>();
  delegate->CreateInvalidationService();
  FCMInvalidationService* invalidation_service =
      delegate->GetInvalidationService();
  ASSERT_FALSE(invalidation_service->GetInvalidatorClientId().empty());

  // Remove the active account (in practice, this means disabling
  // Sync-the-feature, or just signing out of the content are if only
  // Sync-the-transport was running). This should trigger deleting the
  // InstanceID.
  EXPECT_CALL(*delegate->mock_instance_id_, DeleteIDImpl(_));
  invalidation_service->OnActiveAccountLogout();

  // Also the cached InstanceID (aka ClientID) in the invalidation service
  // should be gone. (Right now, the invalidation service clears its cache
  // immediately. In the future, it might be changed to first wait for the
  // asynchronous DeleteID operation to complete, in which case this test will
  // have to be updated.)
  EXPECT_TRUE(invalidation_service->GetInvalidatorClientId().empty());
}

namespace internal {

class FakeCallbackContainer {
 public:
  void FakeCallback(base::Value::Dict value) { called_ = true; }

  bool called_ = false;
  base::WeakPtrFactory<FakeCallbackContainer> weak_ptr_factory_{this};
};

}  // namespace internal

// Test that requesting for detailed status doesn't crash even if the
// underlying invalidator is not initialized.
TEST(FCMInvalidationServiceLoggingTest, DetailedStatusCallbacksWork) {
  std::unique_ptr<FCMInvalidationServiceTestDelegate> delegate(
      new FCMInvalidationServiceTestDelegate());

  delegate->CreateUninitializedInvalidationService();
  InvalidationService* const invalidator = delegate->GetInvalidationService();

  internal::FakeCallbackContainer fake_container;
  invalidator->RequestDetailedStatus(
      base::BindRepeating(&internal::FakeCallbackContainer::FakeCallback,
                          fake_container.weak_ptr_factory_.GetWeakPtr()));
  EXPECT_TRUE(fake_container.called_);

  delegate->InitializeInvalidationService();

  invalidator->RequestDetailedStatus(
      base::BindRepeating(&internal::FakeCallbackContainer::FakeCallback,
                          fake_container.weak_ptr_factory_.GetWeakPtr()));
  EXPECT_TRUE(fake_container.called_);
}

}  // namespace invalidation
