chromium/chrome/browser/downgrade/user_data_snapshot_browsertest.cc

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

#include <map>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/test/mock_callback.h"
#include "base/time/time.h"
#include "base/version.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/downgrade/downgrade_manager.h"
#include "chrome/browser/downgrade/user_data_downgrade.h"
#include "chrome/browser/first_run/scoped_relaunch_chrome_browser_override.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_result_codes.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node.h"
#include "components/bookmarks/test/bookmark_test_helpers.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_types.h"
#include "components/keyed_service/core/service_access_type.h"
#include "components/prefs/pref_service.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/referrer.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"

#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
#include "base/threading/thread_restrictions.h"
#include "chrome/install_static/install_modes.h"
#include "chrome/install_static/test/scoped_install_details.h"
#endif

namespace downgrade {

namespace {

// A gMock matcher that is satisfied when its argument is a command line
// containing a given switch.
MATCHER_P(HasSwitch, switch_name, "") {}

int GetPrePrefixCount(std::string_view test_name) {}

}  // namespace

// A base test fixture for User data snapshot tests. This test that the browser
// behaves the same way after restoring a snapshot. First some user actions are
// simulated using the pure virtual function SimulateUserActions(). Second, an
// update is simulated to trigger a snapshot. Third a downgrade is simulated in
// order to trigger the downgrade processing and snapshot restoration. Last, the
// browser is started to verify that the browser behave the same as before the
// downgrade. At each step the pure virtual function ValidateUserActions() is
// called to verify that the browser behaves the same at each version. To test
// that a feature is supported by snapshots, create a test fixture that inherits
// UserDataSnapshotBrowserTestBase and overload SimulateUserActions() and
// ValidateUserActions() to validate the browser's behavior after a snapshot.
class UserDataSnapshotBrowserTestBase : public InProcessBrowserTest {};

class BookmarksSnapshotTest : public UserDataSnapshotBrowserTestBase {};

IN_PROC_BROWSER_TEST_F(BookmarksSnapshotTest, PRE_PRE_PRE_Test) {}
IN_PROC_BROWSER_TEST_F(BookmarksSnapshotTest, PRE_PRE_Test) {}
IN_PROC_BROWSER_TEST_F(BookmarksSnapshotTest, PRE_Test) {}
// TODO(crbug.com/326168468): Flaky on TSan.
#if defined(THREAD_SANITIZER)
#define MAYBE_Test
#else
#define MAYBE_Test
#endif
IN_PROC_BROWSER_TEST_F(BookmarksSnapshotTest, MAYBE_Test) {}
#undef MAYBE_Test

class HistorySnapshotTest : public UserDataSnapshotBrowserTestBase {};

IN_PROC_BROWSER_TEST_F(HistorySnapshotTest, PRE_PRE_PRE_Test) {}
IN_PROC_BROWSER_TEST_F(HistorySnapshotTest, PRE_PRE_Test) {}
IN_PROC_BROWSER_TEST_F(HistorySnapshotTest, PRE_Test) {}
// TODO(crbug.com/326168468): Flaky on TSan.
#if defined(THREAD_SANITIZER)
#define MAYBE_Test
#else
#define MAYBE_Test
#endif
IN_PROC_BROWSER_TEST_F(HistorySnapshotTest, MAYBE_Test) {}
#undef MAYBE_Test

class TabsSnapshotTest : public UserDataSnapshotBrowserTestBase {};

IN_PROC_BROWSER_TEST_F(TabsSnapshotTest, PRE_PRE_PRE_Test) {}
IN_PROC_BROWSER_TEST_F(TabsSnapshotTest, PRE_PRE_Test) {}
IN_PROC_BROWSER_TEST_F(TabsSnapshotTest, PRE_Test) {}
// TODO(crbug.com/326168468): Flaky on TSan.
#if defined(THREAD_SANITIZER)
#define MAYBE_Test
#else
#define MAYBE_Test
#endif
IN_PROC_BROWSER_TEST_F(TabsSnapshotTest, MAYBE_Test) {}
#undef MAYBE_Test

// Tests that Google Chrome does not takes snapshots on mid-milestone updates.
IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, SameMilestoneSnapshot) {}

#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
// Tests that Google Chrome canary takes snapshots on mid-milestone updates.
IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, CanarySameMilestoneSnapshot) {
  DowngradeManager::EnableSnapshotsForTesting(true);
  install_static::ScopedInstallDetails install_details(
      /*system_level=*/false, install_static::CANARY_INDEX);
  base::ScopedAllowBlockingForTesting scoped_allow_blocking;
  base::FilePath user_data_dir;
  ASSERT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
  auto current_version = version_info::GetVersion().GetString();

  downgrade::DowngradeManager downgrade_manager;

  // No snapshots for same version.
  base::WriteFile(user_data_dir.Append(kDowngradeLastVersionFile),
                  current_version);
  EXPECT_FALSE(downgrade_manager.PrepareUserDataDirectoryForCurrentVersion(
      user_data_dir));
  EXPECT_FALSE(
      base::PathExists(user_data_dir.Append(downgrade::kSnapshotsDir)));

  // Snapshot taken for minor update
  std::vector<uint32_t> last_minor_version_components;
  for (const auto& component : version_info::GetVersion().components()) {
    // Decrement all but the major version.
    last_minor_version_components.push_back(
        !last_minor_version_components.empty() && component > 0 ? component - 1
                                                                : component);
  }
  auto last_minor_version =
      base::Version(last_minor_version_components).GetString();
  base::WriteFile(user_data_dir.Append(kDowngradeLastVersionFile),
                  last_minor_version);

  EXPECT_FALSE(downgrade_manager.PrepareUserDataDirectoryForCurrentVersion(
      user_data_dir));
  EXPECT_TRUE(base::PathExists(user_data_dir.Append(downgrade::kSnapshotsDir)));
}
#endif  // BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)

}  // namespace downgrade