blob: 7083421a769418b588a78b539b48725f12bd7031 [file] [log] [blame]
// Copyright 2020 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/web_applications/components/web_app_run_on_os_login.h"
#import <Cocoa/Cocoa.h>
#include <errno.h>
#include <stddef.h>
#include <sys/xattr.h>
#include <memory>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/mac/foundation_util.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/web_applications/components/web_app_shortcut.h"
#include "chrome/browser/web_applications/components/web_app_shortcut_mac.h"
#include "chrome/browser/web_applications/test/web_app_test.h"
#include "chrome/common/chrome_paths.h"
#include "components/version_info/version_info.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
namespace web_app {
namespace {
constexpr char kFakeChromeBundleId[] = {"fake.cfbundleidentifier"};
constexpr char kAppTitle[] = {"app"};
class WebAppAutoLoginUtilMock : public WebAppAutoLoginUtil {
public:
WebAppAutoLoginUtilMock() = default;
WebAppAutoLoginUtilMock(const WebAppAutoLoginUtilMock&) = delete;
WebAppAutoLoginUtilMock& operator=(const WebAppAutoLoginUtilMock&) = delete;
void AddToLoginItems(const base::FilePath& app_bundle_path,
bool hide_on_startup) override {
EXPECT_TRUE(base::PathExists(app_bundle_path));
EXPECT_FALSE(hide_on_startup);
add_to_login_items_called_count_++;
}
void RemoveFromLoginItems(const base::FilePath& app_bundle_path) override {
EXPECT_TRUE(base::PathExists(app_bundle_path));
remove_from_login_items_called_count_++;
}
void ResetCounts() {
add_to_login_items_called_count_ = 0;
remove_from_login_items_called_count_ = 0;
}
int GetAddToLoginItemsCalledCount() const {
return add_to_login_items_called_count_;
}
int GetRemoveFromLoginItemsCalledCount() const {
return remove_from_login_items_called_count_;
}
private:
int add_to_login_items_called_count_ = 0;
int remove_from_login_items_called_count_ = 0;
};
} // namespace
class WebAppRunOnOsLoginMacTest : public WebAppTest {
public:
void SetUp() override {
WebAppTest::SetUp();
base::mac::SetBaseBundleID(kFakeChromeBundleId);
EXPECT_TRUE(temp_destination_dir_.CreateUniqueTempDir());
EXPECT_TRUE(temp_user_data_dir_.CreateUniqueTempDir());
destination_dir_ = temp_destination_dir_.GetPath();
user_data_dir_ = temp_user_data_dir_.GetPath();
// Recreate the directory structure as it would be created for the
// ShortcutInfo created in the above GetShortcutInfo.
app_data_dir_ = user_data_dir_.Append("Profile 1")
.Append("Web Applications")
.Append("_crx_app-id");
EXPECT_TRUE(base::CreateDirectory(app_data_dir_));
// When using base::PathService::Override, it calls
// base::MakeAbsoluteFilePath. On Mac this prepends "/private" to the path,
// but points to the same directory in the file system.
EXPECT_TRUE(
base::PathService::Override(chrome::DIR_USER_DATA, user_data_dir_));
user_data_dir_ = base::MakeAbsoluteFilePath(user_data_dir_);
app_data_dir_ = base::MakeAbsoluteFilePath(app_data_dir_);
SetChromeAppsFolderForTesting(destination_dir_);
info_ = GetShortcutInfo();
base::FilePath shim_base_name =
base::FilePath(base::UTF16ToUTF8(info_->title) + ".app");
shim_path_ = destination_dir_.Append(shim_base_name);
auto_login_util_mock_ = std::make_unique<WebAppAutoLoginUtilMock>();
WebAppAutoLoginUtil::SetInstanceForTesting(auto_login_util_mock_.get());
}
void TearDown() override {
WebAppAutoLoginUtil::SetInstanceForTesting(nullptr);
SetChromeAppsFolderForTesting(base::FilePath());
WebAppTest::TearDown();
}
std::unique_ptr<ShortcutInfo> GetShortcutInfo() {
std::unique_ptr<ShortcutInfo> info(new ShortcutInfo);
info->extension_id = "app-id";
info->title = base::UTF8ToUTF16(kAppTitle);
info->url = GURL("http://example.com/");
info->profile_path = user_data_dir_.Append("Profile 1");
info->profile_name = "profile name";
info->version_for_display = "stable 1.0";
info->is_multi_profile = true;
return info;
}
protected:
base::ScopedTempDir temp_destination_dir_;
base::ScopedTempDir temp_user_data_dir_;
base::FilePath app_data_dir_;
base::FilePath destination_dir_;
base::FilePath user_data_dir_;
std::unique_ptr<WebAppAutoLoginUtilMock> auto_login_util_mock_;
std::unique_ptr<ShortcutInfo> info_;
base::FilePath shim_path_;
};
TEST_F(WebAppRunOnOsLoginMacTest, Register) {
auto_login_util_mock_->ResetCounts();
EXPECT_FALSE(base::PathExists(shim_path_));
EXPECT_TRUE(internals::RegisterRunOnOsLogin(*info_));
EXPECT_TRUE(base::PathExists(shim_path_));
EXPECT_EQ(auto_login_util_mock_->GetAddToLoginItemsCalledCount(), 1);
EXPECT_TRUE(base::PathExists(shim_path_));
EXPECT_TRUE(base::DeletePathRecursively(shim_path_));
}
TEST_F(WebAppRunOnOsLoginMacTest, Unregister) {
auto_login_util_mock_->ResetCounts();
EXPECT_FALSE(base::PathExists(shim_path_));
EXPECT_TRUE(internals::RegisterRunOnOsLogin(*info_));
EXPECT_TRUE(base::PathExists(shim_path_));
EXPECT_EQ(auto_login_util_mock_->GetAddToLoginItemsCalledCount(), 1);
EXPECT_EQ(auto_login_util_mock_->GetRemoveFromLoginItemsCalledCount(), 0);
auto_login_util_mock_->ResetCounts();
EXPECT_TRUE(internals::UnregisterRunOnOsLogin(
info_->extension_id, info_->profile_path, info_->title));
EXPECT_EQ(auto_login_util_mock_->GetRemoveFromLoginItemsCalledCount(), 1);
EXPECT_TRUE(base::PathExists(shim_path_));
EXPECT_TRUE(base::DeletePathRecursively(shim_path_));
}
} // namespace web_app