1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/profiles/profile.h"
#include <stddef.h>
#include <memory>
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_path_watcher.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/run_loop.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/ui/android/tab_model/tab_model.h"
#include "chrome/browser/ui/android/tab_model/tab_model_list.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/test/base/android/android_browser_test.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
class ProfileDeleteMediaBrowserTest : public AndroidBrowserTest {
protected:
void SetUp() override {
// This needs to happen before AndroidBrowserTest::SetUp(), since that
// invokes deletion. Luckily on Android chrome::GetUserCacheDirectory()
// doesn't actually look at its input. (This would be cleaner as a PRE_
// test, but that doesn't appear to be supported here).
chrome::GetUserCacheDirectory(base::FilePath(), &cache_base_);
base::FilePath media_cache_path =
cache_base_.Append(chrome::kMediaCacheDirname);
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_TRUE(base::CreateDirectory(media_cache_path));
std::string data = "foo";
base::WriteFile(media_cache_path.AppendASCII("foo"), data);
AndroidBrowserTest::SetUp();
}
base::FilePath cache_base_;
};
namespace {
// Watches for the destruction of the specified path (Which, in the tests that
// use it, is typically a directory), and expects the parent directory not to be
// deleted.
//
// The public methods are called on the UI thread, the private ones called on a
// separate SequencedTaskRunner.
class FileDestructionWatcher {
public:
explicit FileDestructionWatcher(const base::FilePath& watched_file_path)
: watched_file_path_(watched_file_path) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
FileDestructionWatcher(const FileDestructionWatcher&) = delete;
FileDestructionWatcher& operator=(const FileDestructionWatcher&) = delete;
void WaitForDestruction() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(!watcher_);
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})
->PostTask(FROM_HERE,
base::BindOnce(&FileDestructionWatcher::StartWatchingPath,
base::Unretained(this)));
run_loop_.Run();
// The watcher should be destroyed before quitting the run loop, once the
// file has been destroyed.
DCHECK(!watcher_);
// Double check that the file was destroyed, and that the parent directory
// was not.
base::ScopedAllowBlockingForTesting allow_blocking;
EXPECT_FALSE(base::PathExists(watched_file_path_));
EXPECT_TRUE(base::PathExists(watched_file_path_.DirName()));
}
private:
void StartWatchingPath() {
DCHECK(!watcher_);
watcher_ = std::make_unique<base::FilePathWatcher>();
// Start watching before checking if the file exists, as the file could be
// destroyed between the existence check and when we start watching, if the
// order were reversed.
EXPECT_TRUE(watcher_->Watch(
watched_file_path_, base::FilePathWatcher::Type::kNonRecursive,
base::BindRepeating(&FileDestructionWatcher::OnPathChanged,
base::Unretained(this))));
CheckIfPathExists();
}
void OnPathChanged(const base::FilePath& path, bool error) {
EXPECT_EQ(watched_file_path_, path);
EXPECT_FALSE(error);
CheckIfPathExists();
}
// Checks if the path exists, and if so, destroys the watcher and quits
// |run_loop_|.
void CheckIfPathExists() {
if (!base::PathExists(watched_file_path_)) {
watcher_.reset();
run_loop_.Quit();
return;
}
}
base::RunLoop run_loop_;
const base::FilePath watched_file_path_;
// Created and destroyed off of the UI thread, on the sequence used to watch
// for changes.
std::unique_ptr<base::FilePathWatcher> watcher_;
};
} // namespace
IN_PROC_BROWSER_TEST_F(ProfileDeleteMediaBrowserTest, DeleteMediaCache) {
// Make sure the legacy media cache directory (created in SetUp) gets deleted
// properly.
base::FilePath cache_base;
chrome::GetUserCacheDirectory(
TabModelList::models()[0]->GetProfile()->GetPath(), &cache_base);
// |cache_base_| computation in SetUp() makes assumptions on implementation
// details to be able to run that early, so verify its result is sane.
EXPECT_EQ(cache_base, cache_base_);
base::FilePath media_cache_path =
cache_base.Append(chrome::kMediaCacheDirname);
base::ScopedAllowBlockingForTesting allow_blocking;
FileDestructionWatcher destruction_watcher(media_cache_path);
destruction_watcher.WaitForDestruction();
}
|