obfuscated_file_util_unittest.cc 112 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "storage/browser/file_system/obfuscated_file_util.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <limits>
  8. #include <memory>
  9. #include <set>
  10. #include <string>
  11. #include <utility>
  12. #include <vector>
  13. #include "base/bind.h"
  14. #include "base/callback_helpers.h"
  15. #include "base/files/file.h"
  16. #include "base/files/file_path.h"
  17. #include "base/files/file_util.h"
  18. #include "base/files/scoped_temp_dir.h"
  19. #include "base/memory/raw_ptr.h"
  20. #include "base/memory/scoped_refptr.h"
  21. #include "base/run_loop.h"
  22. #include "base/task/thread_pool.h"
  23. #include "base/test/bind.h"
  24. #include "base/test/scoped_feature_list.h"
  25. #include "base/test/task_environment.h"
  26. #include "base/test/test_future.h"
  27. #include "base/threading/thread_restrictions.h"
  28. #include "base/threading/thread_task_runner_handle.h"
  29. #include "build/build_config.h"
  30. #include "components/services/filesystem/public/mojom/types.mojom.h"
  31. #include "net/base/features.h"
  32. #include "net/base/io_buffer.h"
  33. #include "storage/browser/file_system/external_mount_points.h"
  34. #include "storage/browser/file_system/file_system_backend.h"
  35. #include "storage/browser/file_system/file_system_context.h"
  36. #include "storage/browser/file_system/file_system_operation_context.h"
  37. #include "storage/browser/file_system/file_system_url.h"
  38. #include "storage/browser/file_system/file_system_usage_cache.h"
  39. #include "storage/browser/file_system/obfuscated_file_util_memory_delegate.h"
  40. #include "storage/browser/file_system/sandbox_directory_database.h"
  41. #include "storage/browser/file_system/sandbox_file_system_backend_delegate.h"
  42. #include "storage/browser/file_system/sandbox_origin_database.h"
  43. #include "storage/browser/quota/quota_manager.h"
  44. #include "storage/browser/quota/quota_manager_proxy.h"
  45. #include "storage/browser/test/async_file_test_helper.h"
  46. #include "storage/browser/test/file_system_test_file_set.h"
  47. #include "storage/browser/test/mock_file_change_observer.h"
  48. #include "storage/browser/test/mock_special_storage_policy.h"
  49. #include "storage/browser/test/sandbox_file_system_test_helper.h"
  50. #include "storage/browser/test/test_file_system_context.h"
  51. #include "storage/common/database/database_identifier.h"
  52. #include "storage/common/file_system/file_system_types.h"
  53. #include "testing/gtest/include/gtest/gtest.h"
  54. #include "third_party/blink/public/common/storage_key/storage_key.h"
  55. #include "third_party/leveldatabase/leveldb_chrome.h"
  56. #include "url/gurl.h"
  57. using url::Origin;
  58. namespace storage {
  59. namespace {
  60. enum TestMode {
  61. kRegularFirstParty,
  62. kRegularFirstPartyNonDefaultBucket,
  63. kRegularThirdParty,
  64. kRegularThirdPartyNonDefaultBucket,
  65. kIncognitoFirstParty,
  66. kIncognitoFirstPartyNonDefaultBucket,
  67. kIncognitoThirdParty,
  68. kIncognitoThirdPartyNonDefaultBucket
  69. };
  70. bool FileExists(const base::FilePath& path) {
  71. return base::PathExists(path) && !base::DirectoryExists(path);
  72. }
  73. int64_t GetLocalFileSize(const base::FilePath& path) {
  74. int64_t size;
  75. EXPECT_TRUE(base::GetFileSize(path, &size));
  76. return size;
  77. }
  78. // After a move, the dest exists and the source doesn't.
  79. // After a copy, both source and dest exist.
  80. struct CopyMoveTestCaseRecord {
  81. bool is_copy_not_move;
  82. const char source_path[64];
  83. const char dest_path[64];
  84. bool cause_overwrite;
  85. };
  86. const CopyMoveTestCaseRecord kCopyMoveTestCases[] = {
  87. // This is the combinatoric set of:
  88. // rename vs. same-name
  89. // different directory vs. same directory
  90. // overwrite vs. no-overwrite
  91. // copy vs. move
  92. // We can never be called with source and destination paths identical, so
  93. // those cases are omitted.
  94. {true, "dir0/file0", "dir0/file1", false},
  95. {false, "dir0/file0", "dir0/file1", false},
  96. {true, "dir0/file0", "dir0/file1", true},
  97. {false, "dir0/file0", "dir0/file1", true},
  98. {true, "dir0/file0", "dir1/file0", false},
  99. {false, "dir0/file0", "dir1/file0", false},
  100. {true, "dir0/file0", "dir1/file0", true},
  101. {false, "dir0/file0", "dir1/file0", true},
  102. {true, "dir0/file0", "dir1/file1", false},
  103. {false, "dir0/file0", "dir1/file1", false},
  104. {true, "dir0/file0", "dir1/file1", true},
  105. {false, "dir0/file0", "dir1/file1", true},
  106. };
  107. struct OriginEnumerationTestRecord {
  108. std::string origin_url;
  109. bool has_temporary;
  110. bool has_persistent;
  111. };
  112. const OriginEnumerationTestRecord kOriginEnumerationTestRecords[] = {
  113. {"http://example.com/", false, true},
  114. {"http://example1.com/", true, false},
  115. {"https://example1.com/", true, true},
  116. {"file:///", false, true},
  117. {"http://example.com:8000/", false, true},
  118. };
  119. FileSystemURL FileSystemURLAppend(const FileSystemURL& url,
  120. const base::FilePath::StringType& child) {
  121. FileSystemURL new_url = FileSystemURL::CreateForTest(
  122. url.storage_key(), url.mount_type(), url.virtual_path().Append(child));
  123. if (url.bucket().has_value())
  124. new_url.SetBucket(url.bucket().value());
  125. return new_url;
  126. }
  127. FileSystemURL FileSystemURLAppendUTF8(const FileSystemURL& url,
  128. const std::string& child) {
  129. FileSystemURL new_url = FileSystemURL::CreateForTest(
  130. url.storage_key(), url.mount_type(),
  131. url.virtual_path().Append(base::FilePath::FromUTF8Unsafe(child)));
  132. if (url.bucket().has_value())
  133. new_url.SetBucket(url.bucket().value());
  134. return new_url;
  135. }
  136. FileSystemURL FileSystemURLDirName(const FileSystemURL& url) {
  137. FileSystemURL new_url =
  138. FileSystemURL::CreateForTest(url.storage_key(), url.mount_type(),
  139. VirtualPath::DirName(url.virtual_path()));
  140. if (url.bucket().has_value())
  141. new_url.SetBucket(url.bucket().value());
  142. return new_url;
  143. }
  144. std::string GetTypeString(FileSystemType type) {
  145. return SandboxFileSystemBackendDelegate::GetTypeString(type);
  146. }
  147. bool HasFileSystemType(
  148. ObfuscatedFileUtil::AbstractStorageKeyEnumerator* enumerator,
  149. FileSystemType type) {
  150. return enumerator->HasTypeDirectory(GetTypeString(type));
  151. }
  152. } // namespace
  153. // TODO(ericu): The vast majority of this and the other FSFU subclass tests
  154. // could theoretically be shared. It would basically be a FSFU interface
  155. // compliance test, and only the subclass-specific bits that look into the
  156. // implementation would need to be written per-subclass.
  157. class ObfuscatedFileUtilTest : public testing::Test,
  158. public ::testing::WithParamInterface<TestMode> {
  159. public:
  160. ObfuscatedFileUtilTest()
  161. : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
  162. storage_key_(blink::StorageKey::CreateFromStringForTesting(
  163. "http://www.example.com")),
  164. type_(kFileSystemTypeTemporary),
  165. sandbox_file_system_(storage_key_, type_),
  166. quota_status_(blink::mojom::QuotaStatusCode::kUnknown),
  167. usage_(-1) {
  168. if (is_third_party_context()) {
  169. scoped_feature_list_.InitAndEnableFeature(
  170. net::features::kThirdPartyStoragePartitioning);
  171. // Once we enable third-party storage partitioning, we can create a
  172. // third-party StorageKey and re-assign the StorageKey value in the
  173. // SandboxFileSystem with this value in SetUp for default buckets.
  174. storage_key_ = blink::StorageKey::CreateWithOptionalNonce(
  175. storage_key_.origin(), storage_key_.top_level_site(), nullptr,
  176. blink::mojom::AncestorChainBit::kCrossSite);
  177. }
  178. }
  179. ObfuscatedFileUtilTest(const ObfuscatedFileUtilTest&) = delete;
  180. ObfuscatedFileUtilTest& operator=(const ObfuscatedFileUtilTest&) = delete;
  181. ~ObfuscatedFileUtilTest() override = default;
  182. bool is_incognito() {
  183. return GetParam() == TestMode::kIncognitoFirstParty ||
  184. (GetParam() == TestMode::kIncognitoFirstPartyNonDefaultBucket) ||
  185. (GetParam() == TestMode::kIncognitoThirdParty) ||
  186. (GetParam() == TestMode::kIncognitoThirdPartyNonDefaultBucket);
  187. }
  188. bool is_third_party_context() {
  189. return GetParam() == TestMode::kRegularThirdParty ||
  190. (GetParam() == TestMode::kRegularThirdPartyNonDefaultBucket) ||
  191. (GetParam() == TestMode::kIncognitoThirdParty) ||
  192. (GetParam() == TestMode::kIncognitoThirdPartyNonDefaultBucket);
  193. }
  194. bool is_non_default_bucket() {
  195. return GetParam() == TestMode::kRegularFirstPartyNonDefaultBucket ||
  196. (GetParam() == TestMode::kRegularThirdPartyNonDefaultBucket) ||
  197. (GetParam() == TestMode::kIncognitoFirstPartyNonDefaultBucket) ||
  198. (GetParam() == TestMode::kIncognitoThirdPartyNonDefaultBucket);
  199. }
  200. void SetUp() override {
  201. ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
  202. storage_policy_ = base::MakeRefCounted<MockSpecialStoragePolicy>();
  203. quota_manager_task_runner_ =
  204. base::ThreadPool::CreateSingleThreadTaskRunner({base::MayBlock()});
  205. quota_manager_ = base::MakeRefCounted<QuotaManager>(
  206. is_incognito(), data_dir_.GetPath(), quota_manager_task_runner_,
  207. /*quota_change_callback=*/base::DoNothing(), storage_policy_,
  208. GetQuotaSettingsFunc());
  209. quota_manager_task_runner_->PostTask(
  210. FROM_HERE, base::BindOnce(
  211. [](const scoped_refptr<QuotaManager>& quota_manager) {
  212. QuotaSettings settings;
  213. settings.per_host_quota = 25 * 1024 * 1024;
  214. settings.pool_size = settings.per_host_quota * 5;
  215. settings.must_remain_available = 10 * 1024 * 1024;
  216. settings.refresh_interval = base::TimeDelta::Max();
  217. quota_manager->SetQuotaSettings(settings);
  218. },
  219. quota_manager_));
  220. // Every time we create a new sandbox_file_system helper,
  221. // it creates another context, which creates another path manager,
  222. // another sandbox_backend, and another OFU.
  223. // We need to pass in the context to skip all that.
  224. file_system_context_ =
  225. is_incognito() ? CreateIncognitoFileSystemContextForTesting(
  226. base::ThreadTaskRunnerHandle::Get(),
  227. base::ThreadTaskRunnerHandle::Get(),
  228. quota_manager_->proxy(), data_dir_.GetPath())
  229. : CreateFileSystemContextForTesting(
  230. quota_manager_->proxy(), data_dir_.GetPath());
  231. // Create the default bucket member corresponding to the StorageKey member
  232. // we created.
  233. base::test::TestFuture<QuotaErrorOr<BucketInfo>> default_future;
  234. quota_manager_->proxy()->UpdateOrCreateBucket(
  235. BucketInitParams::ForDefaultBucket(storage_key()),
  236. base::SequencedTaskRunnerHandle::Get(), default_future.GetCallback());
  237. QuotaErrorOr<BucketInfo> default_bucket = default_future.Take();
  238. CHECK(default_bucket.ok());
  239. default_bucket_ = default_bucket.value().ToBucketLocator();
  240. // Create a non-default bucket member corresponding to the StorageKey
  241. // member we created.
  242. base::test::TestFuture<QuotaErrorOr<BucketInfo>> custom_future;
  243. BucketInitParams params = BucketInitParams::ForDefaultBucket(storage_key());
  244. params.name = "non-default bucket";
  245. quota_manager_->proxy()->UpdateOrCreateBucket(
  246. params, base::SequencedTaskRunnerHandle::Get(),
  247. custom_future.GetCallback());
  248. QuotaErrorOr<BucketInfo> custom_bucket = custom_future.Take();
  249. CHECK(custom_bucket.ok());
  250. custom_bucket_ = custom_bucket.value().ToBucketLocator();
  251. // Create an alternate non-default bucket member corresponding to the
  252. // StorageKey member we created.
  253. base::test::TestFuture<QuotaErrorOr<BucketInfo>> alternate_future;
  254. params.name = "alternate non-default bucket";
  255. quota_manager_->proxy()->UpdateOrCreateBucket(
  256. params, base::SequencedTaskRunnerHandle::Get(),
  257. alternate_future.GetCallback());
  258. QuotaErrorOr<BucketInfo> alternate_bucket = alternate_future.Take();
  259. CHECK(alternate_bucket.ok());
  260. alternate_custom_bucket_ = alternate_bucket.value().ToBucketLocator();
  261. is_non_default_bucket()
  262. ? sandbox_file_system_.SetUp(file_system_context_, custom_bucket_)
  263. : sandbox_file_system_.SetUp(file_system_context_, storage_key_);
  264. change_observers_ = MockFileChangeObserver::CreateList(&change_observer_);
  265. if (is_incognito())
  266. incognito_leveldb_environment_ = leveldb_chrome::NewMemEnv("FileSystem");
  267. }
  268. void TearDown() override {
  269. if (is_incognito())
  270. ASSERT_TRUE(IsDirectoryEmpty(data_dir_.GetPath()));
  271. quota_manager_ = nullptr;
  272. task_environment_.RunUntilIdle();
  273. sandbox_file_system_.TearDown();
  274. }
  275. std::unique_ptr<FileSystemOperationContext> LimitedContext(
  276. int64_t allowed_bytes_growth) {
  277. std::unique_ptr<FileSystemOperationContext> context(
  278. sandbox_file_system_.NewOperationContext());
  279. context->set_allowed_bytes_growth(allowed_bytes_growth);
  280. return context;
  281. }
  282. std::unique_ptr<FileSystemOperationContext> UnlimitedContext() {
  283. return LimitedContext(std::numeric_limits<int64_t>::max());
  284. }
  285. std::unique_ptr<FileSystemOperationContext> NewContext(
  286. SandboxFileSystemTestHelper* file_system) {
  287. change_observer()->ResetCount();
  288. std::unique_ptr<FileSystemOperationContext> context;
  289. if (file_system)
  290. context = file_system->NewOperationContext();
  291. else
  292. context = sandbox_file_system_.NewOperationContext();
  293. // Setting allowed_bytes_growth big enough for all tests.
  294. context->set_allowed_bytes_growth(1024 * 1024);
  295. context->set_change_observers(change_observers());
  296. return context;
  297. }
  298. const ChangeObserverList& change_observers() const {
  299. return change_observers_;
  300. }
  301. MockFileChangeObserver* change_observer() { return &change_observer_; }
  302. // This can only be used after SetUp has run and created file_system_context_
  303. // and obfuscated_file_util_.
  304. // Use this for tests which need to run in multiple StorageKeys; we need a
  305. // test helper per StorageKey.
  306. std::unique_ptr<SandboxFileSystemTestHelper> NewFileSystem(
  307. const blink::StorageKey& storage_key,
  308. FileSystemType type) {
  309. auto file_system =
  310. std::make_unique<SandboxFileSystemTestHelper>(storage_key, type);
  311. file_system->SetUp(file_system_context_);
  312. return file_system;
  313. }
  314. // This can only be used after SetUp has run and created file_system_context_
  315. // and obfuscated_file_util_.
  316. // Use this for tests which need to run in multiple BucketLocators; we need a
  317. // test helper per BucketLocator.
  318. std::unique_ptr<SandboxFileSystemTestHelper> NewFileSystem(
  319. const BucketLocator& bucket_locator,
  320. FileSystemType type) {
  321. auto file_system = std::make_unique<SandboxFileSystemTestHelper>(
  322. bucket_locator.storage_key, type);
  323. file_system->SetUp(file_system_context_, bucket_locator);
  324. return file_system;
  325. }
  326. std::unique_ptr<ObfuscatedFileUtil> CreateObfuscatedFileUtil(
  327. scoped_refptr<SpecialStoragePolicy> storage_policy) {
  328. return ObfuscatedFileUtil::CreateForTesting(
  329. std::move(storage_policy), data_dir_path(),
  330. is_incognito() ? incognito_leveldb_environment_.get() : nullptr,
  331. is_incognito());
  332. }
  333. ObfuscatedFileUtil* ofu() {
  334. return static_cast<ObfuscatedFileUtil*>(sandbox_file_system_.file_util());
  335. }
  336. const base::FilePath& test_directory() const { return data_dir_.GetPath(); }
  337. const blink::StorageKey& storage_key() const { return storage_key_; }
  338. const Origin& origin() const { return storage_key_.origin(); }
  339. FileSystemType type() const { return type_; }
  340. std::string type_string() const { return GetTypeString(type_); }
  341. int64_t ComputeTotalFileSize() {
  342. return sandbox_file_system_.ComputeCurrentStorageKeyUsage() -
  343. sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
  344. }
  345. void GetUsageFromQuotaManager() {
  346. int64_t quota = -1;
  347. quota_status_ = AsyncFileTestHelper::GetUsageAndQuota(
  348. quota_manager_->proxy(), storage_key(), sandbox_file_system_.type(),
  349. &usage_, &quota);
  350. EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, quota_status_);
  351. }
  352. void RevokeUsageCache() {
  353. quota_manager_task_runner_->PostTask(
  354. FROM_HERE, base::BindOnce(
  355. [](const scoped_refptr<QuotaManager>& quota_manager,
  356. SandboxFileSystemTestHelper* sandbox_file_system) {
  357. quota_manager->ResetUsageTracker(
  358. sandbox_file_system->storage_type());
  359. },
  360. quota_manager_, &sandbox_file_system_));
  361. base::FileErrorOr<base::FilePath> path =
  362. sandbox_file_system_.GetUsageCachePath();
  363. if (!path.is_error())
  364. usage_cache()->Delete(path.value());
  365. }
  366. int64_t SizeByQuotaUtil() { return sandbox_file_system_.GetCachedUsage(); }
  367. int64_t SizeInUsageFile() {
  368. task_environment_.RunUntilIdle();
  369. int64_t usage = 0;
  370. base::FileErrorOr<base::FilePath> path =
  371. sandbox_file_system_.GetUsageCachePath();
  372. if (path.is_error())
  373. return -1;
  374. return usage_cache()->GetUsage(path.value(), &usage) ? usage : -1;
  375. }
  376. bool PathExists(const FileSystemURL& url) {
  377. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  378. base::File::Info file_info;
  379. base::FilePath platform_path;
  380. base::File::Error error =
  381. ofu()->GetFileInfo(context.get(), url, &file_info, &platform_path);
  382. return error == base::File::FILE_OK;
  383. }
  384. int64_t GetPathSize(const FileSystemURL& url) {
  385. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  386. base::File::Info file_info;
  387. base::FilePath platform_path;
  388. EXPECT_EQ(
  389. base::File::FILE_OK,
  390. ofu()->GetFileInfo(context.get(), url, &file_info, &platform_path));
  391. return file_info.size;
  392. }
  393. bool DirectoryExists(const FileSystemURL& url) {
  394. return AsyncFileTestHelper::DirectoryExists(file_system_context(), url);
  395. }
  396. int64_t usage() const { return usage_; }
  397. FileSystemUsageCache* usage_cache() {
  398. return sandbox_file_system_.usage_cache();
  399. }
  400. FileSystemURL CreateURL(const base::FilePath& path) {
  401. FileSystemURL test_url = sandbox_file_system_.CreateURL(path);
  402. if (is_non_default_bucket())
  403. test_url.SetBucket(custom_bucket_);
  404. return test_url;
  405. }
  406. FileSystemURL CreateURLFromUTF8(const std::string& path) {
  407. FileSystemURL test_url = sandbox_file_system_.CreateURLFromUTF8(path);
  408. if (is_non_default_bucket())
  409. test_url.SetBucket(custom_bucket_);
  410. return test_url;
  411. }
  412. int64_t PathCost(const FileSystemURL& url) {
  413. return ObfuscatedFileUtil::ComputeFilePathCost(url.path());
  414. }
  415. void CheckFile(const FileSystemURL& url) {
  416. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  417. base::FilePath local_path;
  418. EXPECT_EQ(base::File::FILE_OK,
  419. ofu()->GetLocalFilePath(context.get(), url, &local_path));
  420. EXPECT_EQ(0, GetPathSize(url));
  421. base::File::Info file_info0;
  422. base::FilePath data_path;
  423. EXPECT_EQ(base::File::FILE_OK,
  424. ofu()->GetFileInfo(context.get(), url, &file_info0, &data_path));
  425. EXPECT_EQ(data_path, local_path);
  426. EXPECT_EQ(!is_incognito(), FileExists(data_path));
  427. const char data[] = "test data";
  428. const int length = std::size(data) - 1;
  429. base::File file = ofu()->CreateOrOpen(
  430. context.get(), url, base::File::FLAG_WRITE | base::File::FLAG_OPEN);
  431. if (is_incognito()) {
  432. ASSERT_FALSE(file.IsValid());
  433. auto* memory_delegate =
  434. static_cast<ObfuscatedFileUtilMemoryDelegate*>(ofu()->delegate());
  435. ASSERT_EQ(
  436. length,
  437. memory_delegate->WriteFile(
  438. local_path, 0,
  439. base::MakeRefCounted<net::StringIOBuffer>(data).get(), length));
  440. } else {
  441. ASSERT_TRUE(file.IsValid());
  442. ASSERT_EQ(length, file.Write(0, data, length));
  443. file.Close();
  444. }
  445. base::File::Info file_info1;
  446. if (!is_incognito())
  447. EXPECT_EQ(length, GetLocalFileSize(data_path));
  448. EXPECT_EQ(length, GetPathSize(url));
  449. context = NewContext(nullptr);
  450. EXPECT_EQ(base::File::FILE_OK,
  451. ofu()->GetFileInfo(context.get(), url, &file_info1, &data_path));
  452. EXPECT_EQ(data_path, local_path);
  453. EXPECT_FALSE(file_info0.is_directory);
  454. EXPECT_FALSE(file_info1.is_directory);
  455. EXPECT_FALSE(file_info0.is_symbolic_link);
  456. EXPECT_FALSE(file_info1.is_symbolic_link);
  457. EXPECT_EQ(0, file_info0.size);
  458. EXPECT_EQ(length, file_info1.size);
  459. EXPECT_LE(file_info0.last_modified, file_info1.last_modified);
  460. context = NewContext(nullptr);
  461. EXPECT_EQ(base::File::FILE_OK,
  462. ofu()->Truncate(context.get(), url, length * 2));
  463. EXPECT_EQ(length * 2, GetPathSize(url));
  464. context = NewContext(nullptr);
  465. EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 0));
  466. EXPECT_EQ(0, GetPathSize(url));
  467. }
  468. void ValidateTestDirectory(
  469. const FileSystemURL& root_url,
  470. const std::set<base::FilePath::StringType>& files,
  471. const std::set<base::FilePath::StringType>& directories) {
  472. std::unique_ptr<FileSystemOperationContext> context;
  473. for (const auto& file : files) {
  474. bool created = true;
  475. context = NewContext(nullptr);
  476. ASSERT_EQ(
  477. base::File::FILE_OK,
  478. ofu()->EnsureFileExists(
  479. context.get(), FileSystemURLAppend(root_url, file), &created));
  480. ASSERT_FALSE(created);
  481. }
  482. for (const auto& directory : directories) {
  483. context = NewContext(nullptr);
  484. EXPECT_TRUE(DirectoryExists(FileSystemURLAppend(root_url, directory)));
  485. }
  486. }
  487. class UsageVerifyHelper {
  488. public:
  489. UsageVerifyHelper(std::unique_ptr<FileSystemOperationContext> context,
  490. SandboxFileSystemTestHelper* file_system,
  491. int64_t expected_usage,
  492. ObfuscatedFileUtilTest* test)
  493. : context_(std::move(context)),
  494. sandbox_file_system_(file_system),
  495. expected_usage_(expected_usage),
  496. test_(test) {}
  497. ~UsageVerifyHelper() {
  498. test_->task_environment_.RunUntilIdle();
  499. Check();
  500. }
  501. FileSystemOperationContext* context() { return context_.get(); }
  502. private:
  503. void Check() {
  504. ASSERT_EQ(expected_usage_, sandbox_file_system_->GetCachedUsage());
  505. }
  506. std::unique_ptr<FileSystemOperationContext> context_;
  507. raw_ptr<SandboxFileSystemTestHelper> sandbox_file_system_;
  508. int64_t expected_usage_;
  509. const raw_ptr<ObfuscatedFileUtilTest> test_;
  510. };
  511. std::unique_ptr<UsageVerifyHelper> AllowUsageIncrease(
  512. int64_t requested_growth) {
  513. int64_t usage = sandbox_file_system_.GetCachedUsage();
  514. return std::make_unique<UsageVerifyHelper>(LimitedContext(requested_growth),
  515. &sandbox_file_system_,
  516. usage + requested_growth, this);
  517. }
  518. std::unique_ptr<UsageVerifyHelper> DisallowUsageIncrease(
  519. int64_t requested_growth) {
  520. int64_t usage = sandbox_file_system_.GetCachedUsage();
  521. return std::make_unique<UsageVerifyHelper>(
  522. LimitedContext(requested_growth - 1), &sandbox_file_system_, usage,
  523. this);
  524. }
  525. void FillTestDirectory(const FileSystemURL& root_url,
  526. std::set<base::FilePath::StringType>* files,
  527. std::set<base::FilePath::StringType>* directories) {
  528. std::unique_ptr<FileSystemOperationContext> context;
  529. std::vector<filesystem::mojom::DirectoryEntry> entries;
  530. EXPECT_EQ(base::File::FILE_OK,
  531. AsyncFileTestHelper::ReadDirectory(file_system_context(),
  532. root_url, &entries));
  533. EXPECT_EQ(0UL, entries.size());
  534. files->clear();
  535. files->insert(FILE_PATH_LITERAL("first"));
  536. files->insert(FILE_PATH_LITERAL("second"));
  537. files->insert(FILE_PATH_LITERAL("third"));
  538. directories->clear();
  539. directories->insert(FILE_PATH_LITERAL("fourth"));
  540. directories->insert(FILE_PATH_LITERAL("fifth"));
  541. directories->insert(FILE_PATH_LITERAL("sixth"));
  542. for (const auto& file : *files) {
  543. bool created = false;
  544. context = NewContext(nullptr);
  545. ASSERT_EQ(
  546. base::File::FILE_OK,
  547. ofu()->EnsureFileExists(
  548. context.get(), FileSystemURLAppend(root_url, file), &created));
  549. ASSERT_TRUE(created);
  550. }
  551. for (const auto& directory : *directories) {
  552. bool exclusive = true;
  553. bool recursive = false;
  554. context = NewContext(nullptr);
  555. EXPECT_EQ(base::File::FILE_OK,
  556. ofu()->CreateDirectory(context.get(),
  557. FileSystemURLAppend(root_url, directory),
  558. exclusive, recursive));
  559. }
  560. ValidateTestDirectory(root_url, *files, *directories);
  561. }
  562. void TestReadDirectoryHelper(const FileSystemURL& root_url) {
  563. std::set<base::FilePath::StringType> files;
  564. std::set<base::FilePath::StringType> directories;
  565. FillTestDirectory(root_url, &files, &directories);
  566. std::unique_ptr<FileSystemOperationContext> context;
  567. std::vector<filesystem::mojom::DirectoryEntry> entries;
  568. context = NewContext(nullptr);
  569. EXPECT_EQ(base::File::FILE_OK,
  570. AsyncFileTestHelper::ReadDirectory(file_system_context(),
  571. root_url, &entries));
  572. EXPECT_EQ(files.size() + directories.size(), entries.size());
  573. EXPECT_TRUE(change_observer()->HasNoChange());
  574. for (const filesystem::mojom::DirectoryEntry& entry : entries) {
  575. auto iter = files.find(entry.name.value());
  576. if (iter != files.end()) {
  577. EXPECT_EQ(entry.type, filesystem::mojom::FsFileType::REGULAR_FILE);
  578. files.erase(iter);
  579. continue;
  580. }
  581. iter = directories.find(entry.name.value());
  582. EXPECT_FALSE(directories.end() == iter);
  583. EXPECT_EQ(entry.type, filesystem::mojom::FsFileType::DIRECTORY);
  584. directories.erase(iter);
  585. }
  586. }
  587. void TestTouchHelper(const FileSystemURL& url, bool is_file) {
  588. base::Time last_access_time = base::Time::Now();
  589. base::Time last_modified_time = base::Time::Now();
  590. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  591. EXPECT_EQ(
  592. base::File::FILE_OK,
  593. ofu()->Touch(context.get(), url, last_access_time, last_modified_time));
  594. // Currently we fire no change notifications for Touch.
  595. EXPECT_TRUE(change_observer()->HasNoChange());
  596. base::FilePath local_path;
  597. base::File::Info file_info;
  598. context = NewContext(nullptr);
  599. EXPECT_EQ(base::File::FILE_OK,
  600. ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
  601. // We compare as time_t here to lower our resolution, to avoid false
  602. // negatives caused by conversion to the local filesystem's native
  603. // representation and back.
  604. EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
  605. context = NewContext(nullptr);
  606. last_modified_time += base::Hours(1);
  607. last_access_time += base::Hours(14);
  608. EXPECT_EQ(
  609. base::File::FILE_OK,
  610. ofu()->Touch(context.get(), url, last_access_time, last_modified_time));
  611. EXPECT_TRUE(change_observer()->HasNoChange());
  612. context = NewContext(nullptr);
  613. EXPECT_EQ(base::File::FILE_OK,
  614. ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
  615. EXPECT_EQ(file_info.last_modified.ToTimeT(), last_modified_time.ToTimeT());
  616. if (is_file) // Directories in OFU don't support atime.
  617. EXPECT_EQ(file_info.last_accessed.ToTimeT(), last_access_time.ToTimeT());
  618. }
  619. void TestCopyInForeignFileHelper(bool overwrite) {
  620. base::ScopedTempDir source_dir;
  621. ASSERT_TRUE(source_dir.CreateUniqueTempDir());
  622. base::FilePath root_file_path = source_dir.GetPath();
  623. base::FilePath src_file_path = root_file_path.AppendASCII("file_name");
  624. FileSystemURL dest_url = CreateURLFromUTF8("new file");
  625. int64_t src_file_length = 87;
  626. base::File file(src_file_path,
  627. base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  628. ASSERT_TRUE(file.IsValid());
  629. EXPECT_TRUE(file.created());
  630. ASSERT_TRUE(file.SetLength(src_file_length));
  631. file.Close();
  632. std::unique_ptr<FileSystemOperationContext> context;
  633. if (overwrite) {
  634. context = NewContext(nullptr);
  635. bool created = false;
  636. EXPECT_EQ(base::File::FILE_OK,
  637. ofu()->EnsureFileExists(context.get(), dest_url, &created));
  638. EXPECT_TRUE(created);
  639. // We must have observed one (and only one) create_file_count.
  640. EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
  641. EXPECT_TRUE(change_observer()->HasNoChange());
  642. }
  643. const int64_t path_cost =
  644. ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path());
  645. if (!overwrite) {
  646. // Verify that file creation requires sufficient quota for the path.
  647. context = NewContext(nullptr);
  648. context->set_allowed_bytes_growth(path_cost + src_file_length - 1);
  649. EXPECT_EQ(
  650. base::File::FILE_ERROR_NO_SPACE,
  651. ofu()->CopyInForeignFile(context.get(), src_file_path, dest_url));
  652. }
  653. context = NewContext(nullptr);
  654. context->set_allowed_bytes_growth(path_cost + src_file_length);
  655. EXPECT_EQ(base::File::FILE_OK,
  656. ofu()->CopyInForeignFile(context.get(), src_file_path, dest_url));
  657. EXPECT_TRUE(PathExists(dest_url));
  658. EXPECT_FALSE(DirectoryExists(dest_url));
  659. context = NewContext(nullptr);
  660. base::File::Info file_info;
  661. base::FilePath data_path;
  662. EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo(context.get(), dest_url,
  663. &file_info, &data_path));
  664. EXPECT_NE(data_path, src_file_path);
  665. EXPECT_TRUE(PathExists(dest_url));
  666. EXPECT_EQ(src_file_length, GetPathSize(dest_url));
  667. EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), dest_url));
  668. }
  669. void ClearTimestamp(const FileSystemURL& url) {
  670. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  671. EXPECT_EQ(base::File::FILE_OK,
  672. ofu()->Touch(context.get(), url, base::Time(), base::Time()));
  673. EXPECT_EQ(base::Time(), GetModifiedTime(url));
  674. }
  675. base::Time GetModifiedTime(const FileSystemURL& url) {
  676. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  677. base::FilePath data_path;
  678. base::File::Info file_info;
  679. context = NewContext(nullptr);
  680. EXPECT_EQ(base::File::FILE_OK,
  681. ofu()->GetFileInfo(context.get(), url, &file_info, &data_path));
  682. EXPECT_TRUE(change_observer()->HasNoChange());
  683. return file_info.last_modified;
  684. }
  685. void TestDirectoryTimestampHelper(const FileSystemURL& base_dir,
  686. bool copy,
  687. bool overwrite) {
  688. std::unique_ptr<FileSystemOperationContext> context;
  689. const FileSystemURL src_dir_url(
  690. FileSystemURLAppendUTF8(base_dir, "foo_dir"));
  691. const FileSystemURL dest_dir_url(
  692. FileSystemURLAppendUTF8(base_dir, "bar_dir"));
  693. const FileSystemURL src_file_url(
  694. FileSystemURLAppendUTF8(src_dir_url, "hoge"));
  695. const FileSystemURL dest_file_url(
  696. FileSystemURLAppendUTF8(dest_dir_url, "fuga"));
  697. context = NewContext(nullptr);
  698. EXPECT_EQ(base::File::FILE_OK,
  699. ofu()->CreateDirectory(context.get(), src_dir_url, true, true));
  700. context = NewContext(nullptr);
  701. EXPECT_EQ(base::File::FILE_OK,
  702. ofu()->CreateDirectory(context.get(), dest_dir_url, true, true));
  703. bool created = false;
  704. context = NewContext(nullptr);
  705. EXPECT_EQ(base::File::FILE_OK,
  706. ofu()->EnsureFileExists(context.get(), src_file_url, &created));
  707. if (overwrite) {
  708. context = NewContext(nullptr);
  709. EXPECT_EQ(
  710. base::File::FILE_OK,
  711. ofu()->EnsureFileExists(context.get(), dest_file_url, &created));
  712. }
  713. ClearTimestamp(src_dir_url);
  714. ClearTimestamp(dest_dir_url);
  715. context = NewContext(nullptr);
  716. EXPECT_EQ(base::File::FILE_OK,
  717. ofu()->CopyOrMoveFile(context.get(), src_file_url, dest_file_url,
  718. FileSystemOperation::CopyOrMoveOptionSet(),
  719. copy));
  720. if (copy)
  721. EXPECT_EQ(base::Time(), GetModifiedTime(src_dir_url));
  722. else
  723. EXPECT_NE(base::Time(), GetModifiedTime(src_dir_url));
  724. EXPECT_NE(base::Time(), GetModifiedTime(dest_dir_url));
  725. }
  726. void MaybeDropDatabasesAliveCaseTestBody() {
  727. std::unique_ptr<ObfuscatedFileUtil> file_util =
  728. CreateObfuscatedFileUtil(/*storage_policy=*/nullptr);
  729. file_util->InitOriginDatabase(url::Origin(), true /*create*/);
  730. ASSERT_TRUE(file_util->origin_database_ != nullptr);
  731. // Callback to Drop DB is called while ObfuscatedFileUtilTest is
  732. // still alive.
  733. file_util->db_flush_delay_seconds_ = 0;
  734. file_util->MarkUsed();
  735. task_environment_.RunUntilIdle();
  736. ASSERT_TRUE(file_util->origin_database_ == nullptr);
  737. }
  738. void MaybeDropDatabasesAlreadyDeletedCaseTestBody() {
  739. // Run message loop after OFU is already deleted to make sure callback
  740. // doesn't cause a crash for use after free.
  741. {
  742. std::unique_ptr<ObfuscatedFileUtil> file_util =
  743. CreateObfuscatedFileUtil(/*storage_policy=*/nullptr);
  744. file_util->InitOriginDatabase(url::Origin(), true /*create*/);
  745. file_util->db_flush_delay_seconds_ = 0;
  746. file_util->MarkUsed();
  747. }
  748. // At this point the callback is still in the message queue but OFU is gone.
  749. task_environment_.RunUntilIdle();
  750. }
  751. void DestroyDirectoryDatabase_IsolatedTestBody() {
  752. storage_policy_->AddIsolated(origin().GetURL());
  753. FileSystemURL url = FileSystemURL::CreateForTest(
  754. storage_key(), kFileSystemTypePersistent, base::FilePath());
  755. if (is_non_default_bucket())
  756. url.SetBucket(custom_bucket_);
  757. // Create DirectoryDatabase for isolated origin.
  758. SandboxDirectoryDatabase* db =
  759. ofu()->GetDirectoryDatabase(url, true /* create */);
  760. ASSERT_TRUE(db != nullptr);
  761. // Destroy it.
  762. (is_non_default_bucket()) ? ofu()->DestroyDirectoryDatabaseForBucket(
  763. url.bucket().value(), url.type())
  764. : ofu()->DestroyDirectoryDatabaseForStorageKey(
  765. url.storage_key(), url.type());
  766. ASSERT_TRUE(ofu()->directories_.empty());
  767. }
  768. void GetDirectoryDatabase_IsolatedTestBody() {
  769. storage_policy_->AddIsolated(origin().GetURL());
  770. FileSystemURL url = FileSystemURL::CreateForTest(
  771. blink::StorageKey(origin()), kFileSystemTypePersistent,
  772. base::FilePath());
  773. if (is_non_default_bucket())
  774. url.SetBucket(custom_bucket_);
  775. // Create DirectoryDatabase for isolated origin.
  776. SandboxDirectoryDatabase* db =
  777. ofu()->GetDirectoryDatabase(url, true /* create */);
  778. ASSERT_TRUE(db != nullptr);
  779. ASSERT_EQ(1U, ofu()->directories_.size());
  780. // Remove isolated.
  781. storage_policy_->RemoveIsolated(url.origin().GetURL());
  782. // This should still get the same database.
  783. SandboxDirectoryDatabase* db2 =
  784. ofu()->GetDirectoryDatabase(url, false /* create */);
  785. ASSERT_EQ(db, db2);
  786. }
  787. int64_t ComputeCurrentUsage() {
  788. return sandbox_file_system_.ComputeCurrentStorageKeyUsage() -
  789. sandbox_file_system_.ComputeCurrentDirectoryDatabaseUsage();
  790. }
  791. FileSystemContext* file_system_context() {
  792. return sandbox_file_system_.file_system_context();
  793. }
  794. const base::FilePath& data_dir_path() const { return data_dir_.GetPath(); }
  795. void CheckFileSize(FileSystemURL& url,
  796. base::FilePath& local_path,
  797. int64_t expected_size) {
  798. if (!is_incognito())
  799. EXPECT_EQ(expected_size, GetLocalFileSize(local_path));
  800. EXPECT_EQ(expected_size, GetPathSize(url));
  801. }
  802. protected:
  803. base::test::ScopedFeatureList scoped_feature_list_;
  804. std::unique_ptr<leveldb::Env> incognito_leveldb_environment_;
  805. base::test::TaskEnvironment task_environment_;
  806. base::ScopedTempDir data_dir_;
  807. scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
  808. scoped_refptr<QuotaManager> quota_manager_;
  809. scoped_refptr<base::SingleThreadTaskRunner> quota_manager_task_runner_;
  810. scoped_refptr<FileSystemContext> file_system_context_;
  811. blink::StorageKey storage_key_;
  812. BucketLocator default_bucket_;
  813. BucketLocator custom_bucket_;
  814. BucketLocator alternate_custom_bucket_;
  815. FileSystemType type_;
  816. SandboxFileSystemTestHelper sandbox_file_system_;
  817. blink::mojom::QuotaStatusCode quota_status_;
  818. int64_t usage_;
  819. MockFileChangeObserver change_observer_;
  820. ChangeObserverList change_observers_;
  821. base::WeakPtrFactory<ObfuscatedFileUtilTest> weak_factory_{this};
  822. };
  823. INSTANTIATE_TEST_SUITE_P(
  824. All,
  825. ObfuscatedFileUtilTest,
  826. testing::Values(TestMode::kRegularFirstParty,
  827. TestMode::kRegularFirstPartyNonDefaultBucket,
  828. TestMode::kRegularThirdParty,
  829. TestMode::kRegularThirdPartyNonDefaultBucket,
  830. TestMode::kIncognitoFirstParty,
  831. TestMode::kIncognitoFirstPartyNonDefaultBucket,
  832. TestMode::kIncognitoThirdParty,
  833. TestMode::kIncognitoThirdPartyNonDefaultBucket));
  834. TEST_P(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) {
  835. FileSystemURL url = CreateURLFromUTF8("fake/file");
  836. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  837. bool created;
  838. base::File::Error result =
  839. ofu()->EnsureFileExists(context.get(), url, &created);
  840. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, result);
  841. context = NewContext(nullptr);
  842. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  843. ofu()->DeleteFile(context.get(), url));
  844. url = CreateURLFromUTF8("test file");
  845. EXPECT_TRUE(change_observer()->HasNoChange());
  846. // Verify that file creation requires sufficient quota for the path.
  847. context = NewContext(nullptr);
  848. context->set_allowed_bytes_growth(
  849. ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
  850. result = ofu()->EnsureFileExists(context.get(), url, &created);
  851. ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE, result);
  852. context = NewContext(nullptr);
  853. context->set_allowed_bytes_growth(
  854. ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
  855. created = false;
  856. result = ofu()->EnsureFileExists(context.get(), url, &created);
  857. ASSERT_EQ(base::File::FILE_OK, result);
  858. ASSERT_TRUE(created);
  859. EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
  860. CheckFile(url);
  861. context = NewContext(nullptr);
  862. base::FilePath local_path;
  863. EXPECT_EQ(base::File::FILE_OK,
  864. ofu()->GetLocalFilePath(context.get(), url, &local_path));
  865. EXPECT_NE(is_incognito(), base::PathExists(local_path));
  866. EXPECT_TRUE(PathExists(url));
  867. // Verify that deleting a file isn't stopped by zero quota, and that it frees
  868. // up quote from its path.
  869. context = NewContext(nullptr);
  870. context->set_allowed_bytes_growth(0);
  871. EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url));
  872. EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
  873. EXPECT_FALSE(PathExists(url));
  874. EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
  875. context->allowed_bytes_growth());
  876. context = NewContext(nullptr);
  877. bool exclusive = true;
  878. bool recursive = true;
  879. FileSystemURL directory_url = CreateURLFromUTF8("series/of/directories");
  880. url = FileSystemURLAppendUTF8(directory_url, "file name");
  881. EXPECT_EQ(base::File::FILE_OK,
  882. ofu()->CreateDirectory(context.get(), directory_url, exclusive,
  883. recursive));
  884. // The oepration created 3 directories recursively.
  885. EXPECT_EQ(3, change_observer()->get_and_reset_create_directory_count());
  886. context = NewContext(nullptr);
  887. created = false;
  888. result = ofu()->EnsureFileExists(context.get(), url, &created);
  889. ASSERT_TRUE(created);
  890. ASSERT_EQ(base::File::FILE_OK, result);
  891. EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
  892. CheckFile(url);
  893. context = NewContext(nullptr);
  894. EXPECT_EQ(base::File::FILE_OK,
  895. ofu()->GetLocalFilePath(context.get(), url, &local_path));
  896. EXPECT_NE(is_incognito(), base::PathExists(local_path));
  897. EXPECT_TRUE(PathExists(url));
  898. context = NewContext(nullptr);
  899. EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url));
  900. EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count());
  901. EXPECT_FALSE(PathExists(url));
  902. // Make sure we have no unexpected changes.
  903. EXPECT_TRUE(change_observer()->HasNoChange());
  904. }
  905. TEST_P(ObfuscatedFileUtilTest, TestTruncate) {
  906. bool created = false;
  907. FileSystemURL url = CreateURLFromUTF8("file");
  908. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  909. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  910. ofu()->Truncate(context.get(), url, 4));
  911. context = NewContext(nullptr);
  912. ASSERT_EQ(base::File::FILE_OK,
  913. ofu()->EnsureFileExists(context.get(), url, &created));
  914. ASSERT_TRUE(created);
  915. EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
  916. context = NewContext(nullptr);
  917. base::FilePath local_path;
  918. EXPECT_EQ(base::File::FILE_OK,
  919. ofu()->GetLocalFilePath(context.get(), url, &local_path));
  920. CheckFileSize(url, local_path, 0);
  921. context = NewContext(nullptr);
  922. EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 10));
  923. EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
  924. CheckFileSize(url, local_path, 10);
  925. context = NewContext(nullptr);
  926. EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), url, 1));
  927. EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
  928. CheckFileSize(url, local_path, 1);
  929. EXPECT_FALSE(DirectoryExists(url));
  930. EXPECT_TRUE(PathExists(url));
  931. // Make sure we have no unexpected changes.
  932. EXPECT_TRUE(change_observer()->HasNoChange());
  933. }
  934. TEST_P(ObfuscatedFileUtilTest, TestQuotaOnTruncation) {
  935. bool created = false;
  936. FileSystemURL url = CreateURLFromUTF8("file");
  937. ASSERT_EQ(base::File::FILE_OK,
  938. ofu()->EnsureFileExists(
  939. AllowUsageIncrease(PathCost(url))->context(), url, &created));
  940. ASSERT_TRUE(created);
  941. ASSERT_EQ(0, ComputeTotalFileSize());
  942. ASSERT_EQ(base::File::FILE_OK,
  943. ofu()->Truncate(AllowUsageIncrease(1020)->context(), url, 1020));
  944. ASSERT_EQ(1020, ComputeTotalFileSize());
  945. ASSERT_EQ(base::File::FILE_OK,
  946. ofu()->Truncate(AllowUsageIncrease(-1020)->context(), url, 0));
  947. ASSERT_EQ(0, ComputeTotalFileSize());
  948. EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
  949. ofu()->Truncate(DisallowUsageIncrease(1021)->context(), url, 1021));
  950. ASSERT_EQ(0, ComputeTotalFileSize());
  951. EXPECT_EQ(base::File::FILE_OK,
  952. ofu()->Truncate(AllowUsageIncrease(1020)->context(), url, 1020));
  953. ASSERT_EQ(1020, ComputeTotalFileSize());
  954. EXPECT_EQ(base::File::FILE_OK,
  955. ofu()->Truncate(AllowUsageIncrease(0)->context(), url, 1020));
  956. ASSERT_EQ(1020, ComputeTotalFileSize());
  957. // quota exceeded
  958. {
  959. std::unique_ptr<UsageVerifyHelper> helper = AllowUsageIncrease(-1);
  960. helper->context()->set_allowed_bytes_growth(
  961. helper->context()->allowed_bytes_growth() - 1);
  962. EXPECT_EQ(base::File::FILE_OK,
  963. ofu()->Truncate(helper->context(), url, 1019));
  964. ASSERT_EQ(1019, ComputeTotalFileSize());
  965. }
  966. if (!is_incognito()) {
  967. // Delete backing file to make following truncation fail.
  968. base::FilePath local_path;
  969. ASSERT_EQ(
  970. base::File::FILE_OK,
  971. ofu()->GetLocalFilePath(UnlimitedContext().get(), url, &local_path));
  972. ASSERT_FALSE(local_path.empty());
  973. ASSERT_TRUE(base::DeleteFile(local_path));
  974. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  975. ofu()->Truncate(LimitedContext(1234).get(), url, 1234));
  976. } else {
  977. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  978. EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url));
  979. }
  980. ASSERT_EQ(0, ComputeTotalFileSize());
  981. }
  982. TEST_P(ObfuscatedFileUtilTest, TestEnsureFileExists) {
  983. FileSystemURL url = CreateURLFromUTF8("fake/file");
  984. bool created = false;
  985. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  986. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  987. ofu()->EnsureFileExists(context.get(), url, &created));
  988. EXPECT_TRUE(change_observer()->HasNoChange());
  989. // Verify that file creation requires sufficient quota for the path.
  990. context = NewContext(nullptr);
  991. url = CreateURLFromUTF8("test file");
  992. created = false;
  993. context->set_allowed_bytes_growth(
  994. ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
  995. ASSERT_EQ(base::File::FILE_ERROR_NO_SPACE,
  996. ofu()->EnsureFileExists(context.get(), url, &created));
  997. ASSERT_FALSE(created);
  998. EXPECT_TRUE(change_observer()->HasNoChange());
  999. context = NewContext(nullptr);
  1000. context->set_allowed_bytes_growth(
  1001. ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
  1002. ASSERT_EQ(base::File::FILE_OK,
  1003. ofu()->EnsureFileExists(context.get(), url, &created));
  1004. ASSERT_TRUE(created);
  1005. EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
  1006. CheckFile(url);
  1007. context = NewContext(nullptr);
  1008. ASSERT_EQ(base::File::FILE_OK,
  1009. ofu()->EnsureFileExists(context.get(), url, &created));
  1010. ASSERT_FALSE(created);
  1011. EXPECT_TRUE(change_observer()->HasNoChange());
  1012. // Also test in a subdirectory.
  1013. url = CreateURLFromUTF8("path/to/file.txt");
  1014. context = NewContext(nullptr);
  1015. bool exclusive = true;
  1016. bool recursive = true;
  1017. EXPECT_EQ(base::File::FILE_OK,
  1018. ofu()->CreateDirectory(context.get(), FileSystemURLDirName(url),
  1019. exclusive, recursive));
  1020. // 2 directories: path/ and path/to.
  1021. EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
  1022. context = NewContext(nullptr);
  1023. ASSERT_EQ(base::File::FILE_OK,
  1024. ofu()->EnsureFileExists(context.get(), url, &created));
  1025. ASSERT_TRUE(created);
  1026. EXPECT_FALSE(DirectoryExists(url));
  1027. EXPECT_TRUE(PathExists(url));
  1028. EXPECT_TRUE(change_observer()->HasNoChange());
  1029. }
  1030. TEST_P(ObfuscatedFileUtilTest, TestDirectoryOps) {
  1031. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1032. bool exclusive = false;
  1033. bool recursive = false;
  1034. FileSystemURL url = CreateURLFromUTF8("foo/bar");
  1035. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  1036. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1037. context = NewContext(nullptr);
  1038. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  1039. ofu()->DeleteDirectory(context.get(), url));
  1040. FileSystemURL root = CreateURLFromUTF8(std::string());
  1041. EXPECT_FALSE(DirectoryExists(url));
  1042. EXPECT_FALSE(PathExists(url));
  1043. context = NewContext(nullptr);
  1044. EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), root));
  1045. context = NewContext(nullptr);
  1046. exclusive = false;
  1047. recursive = true;
  1048. EXPECT_EQ(base::File::FILE_OK,
  1049. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1050. EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
  1051. EXPECT_TRUE(DirectoryExists(url));
  1052. EXPECT_TRUE(PathExists(url));
  1053. context = NewContext(nullptr);
  1054. EXPECT_FALSE(ofu()->IsDirectoryEmpty(context.get(), root));
  1055. EXPECT_TRUE(DirectoryExists(FileSystemURLDirName(url)));
  1056. context = NewContext(nullptr);
  1057. EXPECT_FALSE(
  1058. ofu()->IsDirectoryEmpty(context.get(), FileSystemURLDirName(url)));
  1059. // Can't remove a non-empty directory.
  1060. context = NewContext(nullptr);
  1061. EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
  1062. ofu()->DeleteDirectory(context.get(), FileSystemURLDirName(url)));
  1063. EXPECT_TRUE(change_observer()->HasNoChange());
  1064. base::File::Info file_info;
  1065. base::FilePath local_path;
  1066. EXPECT_EQ(base::File::FILE_OK,
  1067. ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
  1068. EXPECT_TRUE(local_path.empty());
  1069. EXPECT_TRUE(file_info.is_directory);
  1070. EXPECT_FALSE(file_info.is_symbolic_link);
  1071. // Same create again should succeed, since exclusive is false.
  1072. context = NewContext(nullptr);
  1073. EXPECT_EQ(base::File::FILE_OK,
  1074. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1075. EXPECT_TRUE(change_observer()->HasNoChange());
  1076. exclusive = true;
  1077. recursive = true;
  1078. context = NewContext(nullptr);
  1079. EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
  1080. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1081. EXPECT_TRUE(change_observer()->HasNoChange());
  1082. // Verify that deleting a directory isn't stopped by zero quota, and that it
  1083. // frees up quota from its path.
  1084. context = NewContext(nullptr);
  1085. context->set_allowed_bytes_growth(0);
  1086. EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url));
  1087. EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
  1088. EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()),
  1089. context->allowed_bytes_growth());
  1090. url = CreateURLFromUTF8("foo/bop");
  1091. EXPECT_FALSE(DirectoryExists(url));
  1092. EXPECT_FALSE(PathExists(url));
  1093. context = NewContext(nullptr);
  1094. EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
  1095. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  1096. ofu()->GetFileInfo(context.get(), url, &file_info, &local_path));
  1097. // Verify that file creation requires sufficient quota for the path.
  1098. exclusive = true;
  1099. recursive = false;
  1100. context = NewContext(nullptr);
  1101. context->set_allowed_bytes_growth(
  1102. ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1);
  1103. EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
  1104. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1105. EXPECT_TRUE(change_observer()->HasNoChange());
  1106. context = NewContext(nullptr);
  1107. context->set_allowed_bytes_growth(
  1108. ObfuscatedFileUtil::ComputeFilePathCost(url.path()));
  1109. EXPECT_EQ(base::File::FILE_OK,
  1110. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1111. EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
  1112. EXPECT_TRUE(DirectoryExists(url));
  1113. EXPECT_TRUE(PathExists(url));
  1114. exclusive = true;
  1115. recursive = false;
  1116. context = NewContext(nullptr);
  1117. EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
  1118. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1119. EXPECT_TRUE(change_observer()->HasNoChange());
  1120. exclusive = true;
  1121. recursive = false;
  1122. url = CreateURLFromUTF8("foo");
  1123. context = NewContext(nullptr);
  1124. EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
  1125. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1126. EXPECT_TRUE(change_observer()->HasNoChange());
  1127. url = CreateURLFromUTF8("blah");
  1128. EXPECT_FALSE(DirectoryExists(url));
  1129. EXPECT_FALSE(PathExists(url));
  1130. exclusive = true;
  1131. recursive = false;
  1132. context = NewContext(nullptr);
  1133. EXPECT_EQ(base::File::FILE_OK,
  1134. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1135. EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
  1136. EXPECT_TRUE(DirectoryExists(url));
  1137. EXPECT_TRUE(PathExists(url));
  1138. exclusive = true;
  1139. recursive = false;
  1140. context = NewContext(nullptr);
  1141. EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
  1142. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1143. EXPECT_TRUE(change_observer()->HasNoChange());
  1144. }
  1145. TEST_P(ObfuscatedFileUtilTest, TestReadDirectory) {
  1146. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1147. bool exclusive = true;
  1148. bool recursive = true;
  1149. FileSystemURL url = CreateURLFromUTF8("directory/to/use");
  1150. EXPECT_EQ(base::File::FILE_OK,
  1151. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1152. TestReadDirectoryHelper(url);
  1153. }
  1154. TEST_P(ObfuscatedFileUtilTest, TestReadRootWithSlash) {
  1155. TestReadDirectoryHelper(CreateURLFromUTF8(std::string()));
  1156. }
  1157. TEST_P(ObfuscatedFileUtilTest, TestReadRootWithEmptyString) {
  1158. TestReadDirectoryHelper(CreateURLFromUTF8("/"));
  1159. }
  1160. TEST_P(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) {
  1161. FileSystemURL url = CreateURLFromUTF8("file");
  1162. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1163. bool created = false;
  1164. ASSERT_EQ(base::File::FILE_OK,
  1165. ofu()->EnsureFileExists(context.get(), url, &created));
  1166. ASSERT_TRUE(created);
  1167. std::vector<filesystem::mojom::DirectoryEntry> entries;
  1168. EXPECT_EQ(
  1169. base::File::FILE_ERROR_NOT_A_DIRECTORY,
  1170. AsyncFileTestHelper::ReadDirectory(file_system_context(), url, &entries));
  1171. EXPECT_TRUE(ofu()->IsDirectoryEmpty(context.get(), url));
  1172. }
  1173. // TODO(https://crbug.com/702990): Remove this test once last_access_time has
  1174. // been removed after PPAPI has been deprecated. Fuchsia does not support touch,
  1175. // which breaks this test that relies on it. Since PPAPI is being deprecated,
  1176. // this test is excluded from the Fuchsia build.
  1177. // See https://crbug.com/1077456 for details.
  1178. #if !BUILDFLAG(IS_FUCHSIA)
  1179. TEST_P(ObfuscatedFileUtilTest, TestTouch) {
  1180. FileSystemURL url = CreateURLFromUTF8("file");
  1181. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1182. base::Time last_access_time = base::Time::Now();
  1183. base::Time last_modified_time = base::Time::Now();
  1184. // It's not there yet.
  1185. EXPECT_EQ(
  1186. base::File::FILE_ERROR_NOT_FOUND,
  1187. ofu()->Touch(context.get(), url, last_access_time, last_modified_time));
  1188. // OK, now create it.
  1189. context = NewContext(nullptr);
  1190. bool created = false;
  1191. ASSERT_EQ(base::File::FILE_OK,
  1192. ofu()->EnsureFileExists(context.get(), url, &created));
  1193. ASSERT_TRUE(created);
  1194. TestTouchHelper(url, true);
  1195. // Now test a directory:
  1196. context = NewContext(nullptr);
  1197. bool exclusive = true;
  1198. bool recursive = false;
  1199. url = CreateURLFromUTF8("dir");
  1200. ASSERT_EQ(base::File::FILE_OK,
  1201. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1202. TestTouchHelper(url, false);
  1203. }
  1204. #endif // !BUILDFLAG(IS_FUCHSIA)
  1205. TEST_P(ObfuscatedFileUtilTest, TestPathQuotas) {
  1206. FileSystemURL url = CreateURLFromUTF8("fake/file");
  1207. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1208. url = CreateURLFromUTF8("file name");
  1209. context->set_allowed_bytes_growth(5);
  1210. bool created = false;
  1211. EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
  1212. ofu()->EnsureFileExists(context.get(), url, &created));
  1213. EXPECT_FALSE(created);
  1214. context->set_allowed_bytes_growth(1024);
  1215. EXPECT_EQ(base::File::FILE_OK,
  1216. ofu()->EnsureFileExists(context.get(), url, &created));
  1217. EXPECT_TRUE(created);
  1218. int64_t path_cost = ObfuscatedFileUtil::ComputeFilePathCost(url.path());
  1219. EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
  1220. context->set_allowed_bytes_growth(1024);
  1221. bool exclusive = true;
  1222. bool recursive = true;
  1223. url = CreateURLFromUTF8("directory/to/use");
  1224. path_cost = 0;
  1225. for (const auto& component : url.path().GetComponents()) {
  1226. path_cost +=
  1227. ObfuscatedFileUtil::ComputeFilePathCost(base::FilePath(component));
  1228. }
  1229. context = NewContext(nullptr);
  1230. context->set_allowed_bytes_growth(1024);
  1231. EXPECT_EQ(base::File::FILE_OK,
  1232. ofu()->CreateDirectory(context.get(), url, exclusive, recursive));
  1233. EXPECT_EQ(1024 - path_cost, context->allowed_bytes_growth());
  1234. }
  1235. TEST_P(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) {
  1236. FileSystemURL source_url = CreateURLFromUTF8("path0.txt");
  1237. FileSystemURL dest_url = CreateURLFromUTF8("path1.txt");
  1238. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1239. bool is_copy_not_move = false;
  1240. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  1241. ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
  1242. FileSystemOperation::CopyOrMoveOptionSet(),
  1243. is_copy_not_move));
  1244. EXPECT_TRUE(change_observer()->HasNoChange());
  1245. context = NewContext(nullptr);
  1246. is_copy_not_move = true;
  1247. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  1248. ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
  1249. FileSystemOperation::CopyOrMoveOptionSet(),
  1250. is_copy_not_move));
  1251. EXPECT_TRUE(change_observer()->HasNoChange());
  1252. source_url = CreateURLFromUTF8("dir/dir/file");
  1253. bool exclusive = true;
  1254. bool recursive = true;
  1255. context = NewContext(nullptr);
  1256. ASSERT_EQ(
  1257. base::File::FILE_OK,
  1258. ofu()->CreateDirectory(context.get(), FileSystemURLDirName(source_url),
  1259. exclusive, recursive));
  1260. EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
  1261. is_copy_not_move = false;
  1262. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  1263. ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
  1264. FileSystemOperation::CopyOrMoveOptionSet(),
  1265. is_copy_not_move));
  1266. EXPECT_TRUE(change_observer()->HasNoChange());
  1267. context = NewContext(nullptr);
  1268. is_copy_not_move = true;
  1269. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  1270. ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
  1271. FileSystemOperation::CopyOrMoveOptionSet(),
  1272. is_copy_not_move));
  1273. EXPECT_TRUE(change_observer()->HasNoChange());
  1274. }
  1275. TEST_P(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) {
  1276. const int64_t kSourceLength = 5;
  1277. const int64_t kDestLength = 50;
  1278. for (size_t i = 0; i < std::size(kCopyMoveTestCases); ++i) {
  1279. SCOPED_TRACE(testing::Message() << "kCopyMoveTestCase " << i);
  1280. const CopyMoveTestCaseRecord& test_case = kCopyMoveTestCases[i];
  1281. SCOPED_TRACE(testing::Message()
  1282. << "\t is_copy_not_move " << test_case.is_copy_not_move);
  1283. SCOPED_TRACE(testing::Message()
  1284. << "\t source_path " << test_case.source_path);
  1285. SCOPED_TRACE(testing::Message() << "\t dest_path " << test_case.dest_path);
  1286. SCOPED_TRACE(testing::Message()
  1287. << "\t cause_overwrite " << test_case.cause_overwrite);
  1288. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1289. bool exclusive = false;
  1290. bool recursive = true;
  1291. FileSystemURL source_url = CreateURLFromUTF8(test_case.source_path);
  1292. FileSystemURL dest_url = CreateURLFromUTF8(test_case.dest_path);
  1293. context = NewContext(nullptr);
  1294. ASSERT_EQ(
  1295. base::File::FILE_OK,
  1296. ofu()->CreateDirectory(context.get(), FileSystemURLDirName(source_url),
  1297. exclusive, recursive));
  1298. context = NewContext(nullptr);
  1299. ASSERT_EQ(
  1300. base::File::FILE_OK,
  1301. ofu()->CreateDirectory(context.get(), FileSystemURLDirName(dest_url),
  1302. exclusive, recursive));
  1303. bool created = false;
  1304. context = NewContext(nullptr);
  1305. ASSERT_EQ(base::File::FILE_OK,
  1306. ofu()->EnsureFileExists(context.get(), source_url, &created));
  1307. ASSERT_TRUE(created);
  1308. context = NewContext(nullptr);
  1309. ASSERT_EQ(base::File::FILE_OK,
  1310. ofu()->Truncate(context.get(), source_url, kSourceLength));
  1311. if (test_case.cause_overwrite) {
  1312. context = NewContext(nullptr);
  1313. created = false;
  1314. ASSERT_EQ(base::File::FILE_OK,
  1315. ofu()->EnsureFileExists(context.get(), dest_url, &created));
  1316. ASSERT_TRUE(created);
  1317. context = NewContext(nullptr);
  1318. ASSERT_EQ(base::File::FILE_OK,
  1319. ofu()->Truncate(context.get(), dest_url, kDestLength));
  1320. }
  1321. context = NewContext(nullptr);
  1322. EXPECT_EQ(base::File::FILE_OK,
  1323. ofu()->CopyOrMoveFile(context.get(), source_url, dest_url,
  1324. FileSystemOperation::CopyOrMoveOptionSet(),
  1325. test_case.is_copy_not_move));
  1326. if (test_case.is_copy_not_move) {
  1327. base::File::Info file_info;
  1328. base::FilePath local_path;
  1329. context = NewContext(nullptr);
  1330. EXPECT_EQ(base::File::FILE_OK,
  1331. ofu()->GetFileInfo(context.get(), source_url, &file_info,
  1332. &local_path));
  1333. EXPECT_EQ(kSourceLength, file_info.size);
  1334. EXPECT_EQ(base::File::FILE_OK,
  1335. ofu()->DeleteFile(context.get(), source_url));
  1336. } else {
  1337. base::File::Info file_info;
  1338. base::FilePath local_path;
  1339. context = NewContext(nullptr);
  1340. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  1341. ofu()->GetFileInfo(context.get(), source_url, &file_info,
  1342. &local_path));
  1343. }
  1344. base::File::Info file_info;
  1345. base::FilePath local_path;
  1346. EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo(context.get(), dest_url,
  1347. &file_info, &local_path));
  1348. EXPECT_EQ(kSourceLength, file_info.size);
  1349. EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), dest_url));
  1350. }
  1351. }
  1352. TEST_P(ObfuscatedFileUtilTest, TestCopyPathQuotas) {
  1353. FileSystemURL src_url = CreateURLFromUTF8("src path");
  1354. FileSystemURL dest_url = CreateURLFromUTF8("destination path");
  1355. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1356. bool created = false;
  1357. ASSERT_EQ(base::File::FILE_OK,
  1358. ofu()->EnsureFileExists(context.get(), src_url, &created));
  1359. bool is_copy = true;
  1360. // Copy, no overwrite.
  1361. context->set_allowed_bytes_growth(
  1362. ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) - 1);
  1363. EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
  1364. ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
  1365. FileSystemOperation::CopyOrMoveOptionSet(),
  1366. is_copy));
  1367. context = NewContext(nullptr);
  1368. context->set_allowed_bytes_growth(
  1369. ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()));
  1370. EXPECT_EQ(base::File::FILE_OK,
  1371. ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
  1372. FileSystemOperation::CopyOrMoveOptionSet(),
  1373. is_copy));
  1374. // Copy, with overwrite.
  1375. context = NewContext(nullptr);
  1376. context->set_allowed_bytes_growth(0);
  1377. EXPECT_EQ(base::File::FILE_OK,
  1378. ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
  1379. FileSystemOperation::CopyOrMoveOptionSet(),
  1380. is_copy));
  1381. }
  1382. TEST_P(ObfuscatedFileUtilTest, TestMovePathQuotasWithRename) {
  1383. FileSystemURL src_url = CreateURLFromUTF8("src path");
  1384. FileSystemURL dest_url = CreateURLFromUTF8("destination path");
  1385. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1386. bool created = false;
  1387. ASSERT_EQ(base::File::FILE_OK,
  1388. ofu()->EnsureFileExists(context.get(), src_url, &created));
  1389. bool is_copy = false;
  1390. // Move, rename, no overwrite.
  1391. context = NewContext(nullptr);
  1392. context->set_allowed_bytes_growth(
  1393. ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
  1394. ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()) - 1);
  1395. EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
  1396. ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
  1397. FileSystemOperation::CopyOrMoveOptionSet(),
  1398. is_copy));
  1399. context = NewContext(nullptr);
  1400. context->set_allowed_bytes_growth(
  1401. ObfuscatedFileUtil::ComputeFilePathCost(dest_url.path()) -
  1402. ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()));
  1403. EXPECT_EQ(base::File::FILE_OK,
  1404. ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
  1405. FileSystemOperation::CopyOrMoveOptionSet(),
  1406. is_copy));
  1407. context = NewContext(nullptr);
  1408. ASSERT_EQ(base::File::FILE_OK,
  1409. ofu()->EnsureFileExists(context.get(), src_url, &created));
  1410. // Move, rename, with overwrite.
  1411. context = NewContext(nullptr);
  1412. context->set_allowed_bytes_growth(0);
  1413. EXPECT_EQ(base::File::FILE_OK,
  1414. ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
  1415. FileSystemOperation::CopyOrMoveOptionSet(),
  1416. is_copy));
  1417. }
  1418. TEST_P(ObfuscatedFileUtilTest, TestMovePathQuotasWithoutRename) {
  1419. FileSystemURL src_url = CreateURLFromUTF8("src path");
  1420. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1421. bool created = false;
  1422. ASSERT_EQ(base::File::FILE_OK,
  1423. ofu()->EnsureFileExists(context.get(), src_url, &created));
  1424. bool exclusive = true;
  1425. bool recursive = false;
  1426. FileSystemURL dir_url = CreateURLFromUTF8("directory path");
  1427. context = NewContext(nullptr);
  1428. ASSERT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), dir_url,
  1429. exclusive, recursive));
  1430. FileSystemURL dest_url = FileSystemURLAppend(dir_url, src_url.path().value());
  1431. bool is_copy = false;
  1432. int64_t allowed_bytes_growth = -1000; // Over quota, this should still work.
  1433. // Move, no rename, no overwrite.
  1434. context = NewContext(nullptr);
  1435. context->set_allowed_bytes_growth(allowed_bytes_growth);
  1436. EXPECT_EQ(base::File::FILE_OK,
  1437. ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
  1438. FileSystemOperation::CopyOrMoveOptionSet(),
  1439. is_copy));
  1440. EXPECT_EQ(allowed_bytes_growth, context->allowed_bytes_growth());
  1441. // Move, no rename, with overwrite.
  1442. context = NewContext(nullptr);
  1443. ASSERT_EQ(base::File::FILE_OK,
  1444. ofu()->EnsureFileExists(context.get(), src_url, &created));
  1445. context = NewContext(nullptr);
  1446. context->set_allowed_bytes_growth(allowed_bytes_growth);
  1447. EXPECT_EQ(base::File::FILE_OK,
  1448. ofu()->CopyOrMoveFile(context.get(), src_url, dest_url,
  1449. FileSystemOperation::CopyOrMoveOptionSet(),
  1450. is_copy));
  1451. EXPECT_EQ(allowed_bytes_growth +
  1452. ObfuscatedFileUtil::ComputeFilePathCost(src_url.path()),
  1453. context->allowed_bytes_growth());
  1454. }
  1455. TEST_P(ObfuscatedFileUtilTest, TestCopyInForeignFile) {
  1456. TestCopyInForeignFileHelper(false /* overwrite */);
  1457. TestCopyInForeignFileHelper(true /* overwrite */);
  1458. }
  1459. TEST_P(ObfuscatedFileUtilTest, TestEnumerator) {
  1460. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1461. FileSystemURL src_url = CreateURLFromUTF8("source dir");
  1462. bool exclusive = true;
  1463. bool recursive = false;
  1464. ASSERT_EQ(base::File::FILE_OK, ofu()->CreateDirectory(context.get(), src_url,
  1465. exclusive, recursive));
  1466. std::set<base::FilePath::StringType> files;
  1467. std::set<base::FilePath::StringType> directories;
  1468. FillTestDirectory(src_url, &files, &directories);
  1469. FileSystemURL dest_url = CreateURLFromUTF8("destination dir");
  1470. EXPECT_FALSE(DirectoryExists(dest_url));
  1471. ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::Copy(
  1472. file_system_context(), src_url, dest_url));
  1473. ValidateTestDirectory(dest_url, files, directories);
  1474. EXPECT_TRUE(DirectoryExists(src_url));
  1475. EXPECT_TRUE(DirectoryExists(dest_url));
  1476. recursive = true;
  1477. ASSERT_EQ(
  1478. base::File::FILE_OK,
  1479. AsyncFileTestHelper::Remove(file_system_context(), dest_url, recursive));
  1480. EXPECT_FALSE(DirectoryExists(dest_url));
  1481. }
  1482. TEST_P(ObfuscatedFileUtilTest, TestStorageKeyEnumerator) {
  1483. std::unique_ptr<ObfuscatedFileUtil::AbstractStorageKeyEnumerator> enumerator =
  1484. ofu()->CreateStorageKeyEnumerator();
  1485. // The test helper starts out with a single filesystem.
  1486. EXPECT_TRUE(enumerator.get());
  1487. // This test is not relevant for third-party or non-default buckets code paths
  1488. // because these paths do not add to the OriginDatabase, the structure that
  1489. // populates the enumerator being tested. So in a test environment, this
  1490. // enumerator should not have any additional StorageKeys to access via Next().
  1491. if (is_third_party_context() || is_non_default_bucket()) {
  1492. EXPECT_EQ(absl::nullopt, enumerator->Next());
  1493. return;
  1494. }
  1495. EXPECT_EQ(storage_key(), enumerator->Next());
  1496. ASSERT_TRUE(type() == kFileSystemTypeTemporary);
  1497. EXPECT_TRUE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
  1498. EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
  1499. EXPECT_FALSE(enumerator->Next());
  1500. EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
  1501. EXPECT_FALSE(HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
  1502. std::set<blink::StorageKey> storage_keys_expected;
  1503. storage_keys_expected.insert(storage_key());
  1504. for (size_t i = 0; i < std::size(kOriginEnumerationTestRecords); ++i) {
  1505. SCOPED_TRACE(testing::Message()
  1506. << "Validating kOriginEnumerationTestRecords " << i);
  1507. const OriginEnumerationTestRecord& record =
  1508. kOriginEnumerationTestRecords[i];
  1509. blink::StorageKey storage_key =
  1510. blink::StorageKey::CreateFromStringForTesting(record.origin_url);
  1511. storage_keys_expected.insert(storage_key);
  1512. if (record.has_temporary) {
  1513. std::unique_ptr<SandboxFileSystemTestHelper> file_system =
  1514. NewFileSystem(storage_key, kFileSystemTypeTemporary);
  1515. std::unique_ptr<FileSystemOperationContext> context(
  1516. NewContext(file_system.get()));
  1517. bool created = false;
  1518. ASSERT_EQ(
  1519. base::File::FILE_OK,
  1520. ofu()->EnsureFileExists(
  1521. context.get(), file_system->CreateURLFromUTF8("file"), &created));
  1522. EXPECT_TRUE(created);
  1523. }
  1524. if (record.has_persistent) {
  1525. std::unique_ptr<SandboxFileSystemTestHelper> file_system =
  1526. NewFileSystem(storage_key, kFileSystemTypePersistent);
  1527. std::unique_ptr<FileSystemOperationContext> context(
  1528. NewContext(file_system.get()));
  1529. bool created = false;
  1530. ASSERT_EQ(
  1531. base::File::FILE_OK,
  1532. ofu()->EnsureFileExists(
  1533. context.get(), file_system->CreateURLFromUTF8("file"), &created));
  1534. EXPECT_TRUE(created);
  1535. }
  1536. }
  1537. enumerator = ofu()->CreateStorageKeyEnumerator();
  1538. EXPECT_TRUE(enumerator.get());
  1539. std::set<blink::StorageKey> storage_keys_found;
  1540. absl::optional<blink::StorageKey> enumerator_storage_key;
  1541. while ((enumerator_storage_key = enumerator->Next()).has_value()) {
  1542. storage_keys_found.insert(enumerator_storage_key.value());
  1543. SCOPED_TRACE(testing::Message()
  1544. << "Handling "
  1545. << enumerator_storage_key->origin().Serialize());
  1546. bool found = false;
  1547. for (const auto& record : kOriginEnumerationTestRecords) {
  1548. if (enumerator_storage_key->origin().GetURL() != record.origin_url)
  1549. continue;
  1550. found = true;
  1551. EXPECT_EQ(record.has_temporary,
  1552. HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
  1553. EXPECT_EQ(record.has_persistent,
  1554. HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
  1555. }
  1556. // Deal with the default filesystem created by the test helper.
  1557. if (!found && enumerator_storage_key == storage_key()) {
  1558. ASSERT_TRUE(type() == kFileSystemTypeTemporary);
  1559. EXPECT_TRUE(
  1560. HasFileSystemType(enumerator.get(), kFileSystemTypeTemporary));
  1561. EXPECT_FALSE(
  1562. HasFileSystemType(enumerator.get(), kFileSystemTypePersistent));
  1563. found = true;
  1564. }
  1565. EXPECT_TRUE(found);
  1566. }
  1567. std::set<blink::StorageKey> diff;
  1568. std::set_symmetric_difference(
  1569. storage_keys_expected.begin(), storage_keys_expected.end(),
  1570. storage_keys_found.begin(), storage_keys_found.end(),
  1571. inserter(diff, diff.begin()));
  1572. EXPECT_TRUE(diff.empty());
  1573. }
  1574. TEST_P(ObfuscatedFileUtilTest, TestRevokeUsageCache) {
  1575. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1576. int64_t expected_quota = 0;
  1577. for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
  1578. SCOPED_TRACE(testing::Message() << "Creating kRegularTestCase " << i);
  1579. const FileSystemTestCaseRecord& test_case = kRegularFileSystemTestCases[i];
  1580. base::FilePath file_path(test_case.path);
  1581. expected_quota += ObfuscatedFileUtil::ComputeFilePathCost(file_path);
  1582. if (test_case.is_directory) {
  1583. bool exclusive = true;
  1584. bool recursive = false;
  1585. ASSERT_EQ(base::File::FILE_OK,
  1586. ofu()->CreateDirectory(context.get(), CreateURL(file_path),
  1587. exclusive, recursive));
  1588. } else {
  1589. bool created = false;
  1590. ASSERT_EQ(base::File::FILE_OK,
  1591. ofu()->EnsureFileExists(context.get(), CreateURL(file_path),
  1592. &created));
  1593. ASSERT_TRUE(created);
  1594. ASSERT_EQ(base::File::FILE_OK,
  1595. ofu()->Truncate(context.get(), CreateURL(file_path),
  1596. test_case.data_file_size));
  1597. expected_quota += test_case.data_file_size;
  1598. }
  1599. }
  1600. // Usually raw size in usage cache and the usage returned by QuotaUtil
  1601. // should be same.
  1602. EXPECT_EQ(expected_quota, SizeInUsageFile());
  1603. EXPECT_EQ(expected_quota, SizeByQuotaUtil());
  1604. RevokeUsageCache();
  1605. EXPECT_EQ(-1, SizeInUsageFile());
  1606. EXPECT_EQ(expected_quota, SizeByQuotaUtil());
  1607. // This should reconstruct the cache.
  1608. GetUsageFromQuotaManager();
  1609. EXPECT_EQ(expected_quota, SizeInUsageFile());
  1610. EXPECT_EQ(expected_quota, SizeByQuotaUtil());
  1611. EXPECT_EQ(expected_quota, usage());
  1612. }
  1613. TEST_P(ObfuscatedFileUtilTest, TestInconsistency) {
  1614. const FileSystemURL kPath1 = CreateURLFromUTF8("hoge");
  1615. const FileSystemURL kPath2 = CreateURLFromUTF8("fuga");
  1616. std::unique_ptr<FileSystemOperationContext> context;
  1617. base::File::Info file_info;
  1618. base::FilePath data_path;
  1619. bool created = false;
  1620. // Create a non-empty file.
  1621. context = NewContext(nullptr);
  1622. EXPECT_EQ(base::File::FILE_OK,
  1623. ofu()->EnsureFileExists(context.get(), kPath1, &created));
  1624. EXPECT_TRUE(created);
  1625. context = NewContext(nullptr);
  1626. EXPECT_EQ(base::File::FILE_OK, ofu()->Truncate(context.get(), kPath1, 10));
  1627. context = NewContext(nullptr);
  1628. EXPECT_EQ(base::File::FILE_OK,
  1629. ofu()->GetFileInfo(context.get(), kPath1, &file_info, &data_path));
  1630. EXPECT_EQ(10, file_info.size);
  1631. // Destroy database to make inconsistency between database and filesystem.
  1632. (is_non_default_bucket())
  1633. ? ofu()->DestroyDirectoryDatabaseForBucket(custom_bucket_, type())
  1634. : ofu()->DestroyDirectoryDatabaseForStorageKey(storage_key(), type());
  1635. // Try to get file info of broken file.
  1636. EXPECT_FALSE(PathExists(kPath1));
  1637. context = NewContext(nullptr);
  1638. EXPECT_EQ(base::File::FILE_OK,
  1639. ofu()->EnsureFileExists(context.get(), kPath1, &created));
  1640. EXPECT_TRUE(created);
  1641. context = NewContext(nullptr);
  1642. EXPECT_EQ(base::File::FILE_OK,
  1643. ofu()->GetFileInfo(context.get(), kPath1, &file_info, &data_path));
  1644. EXPECT_EQ(0, file_info.size);
  1645. // Make another broken file to `kPath2`.
  1646. context = NewContext(nullptr);
  1647. EXPECT_EQ(base::File::FILE_OK,
  1648. ofu()->EnsureFileExists(context.get(), kPath2, &created));
  1649. EXPECT_TRUE(created);
  1650. // Destroy again.
  1651. (is_non_default_bucket())
  1652. ? ofu()->DestroyDirectoryDatabaseForBucket(custom_bucket_, type())
  1653. : ofu()->DestroyDirectoryDatabaseForStorageKey(storage_key(), type());
  1654. // Repair broken `kPath1`.
  1655. context = NewContext(nullptr);
  1656. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  1657. ofu()->Touch(context.get(), kPath1, base::Time::Now(),
  1658. base::Time::Now()));
  1659. EXPECT_EQ(base::File::FILE_OK,
  1660. ofu()->EnsureFileExists(context.get(), kPath1, &created));
  1661. EXPECT_TRUE(created);
  1662. // Copy from sound `kPath1` to broken `kPath2`.
  1663. context = NewContext(nullptr);
  1664. EXPECT_EQ(base::File::FILE_OK,
  1665. ofu()->CopyOrMoveFile(context.get(), kPath1, kPath2,
  1666. FileSystemOperation::CopyOrMoveOptionSet(),
  1667. true /* copy */));
  1668. (is_non_default_bucket())
  1669. ? ofu()->DestroyDirectoryDatabaseForBucket(custom_bucket_, type())
  1670. : ofu()->DestroyDirectoryDatabaseForStorageKey(storage_key(), type());
  1671. context = NewContext(nullptr);
  1672. created = false;
  1673. EXPECT_EQ(base::File::FILE_OK,
  1674. ofu()->EnsureFileExists(context.get(), kPath1, &created));
  1675. EXPECT_TRUE(created);
  1676. EXPECT_EQ(0, GetPathSize(kPath1));
  1677. }
  1678. TEST_P(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) {
  1679. const FileSystemURL kPath[] = {CreateURLFromUTF8("foo"),
  1680. CreateURLFromUTF8("bar"),
  1681. CreateURLFromUTF8("baz")};
  1682. const FileSystemURL empty_path = CreateURL(base::FilePath());
  1683. std::unique_ptr<FileSystemOperationContext> context;
  1684. for (const auto& path : kPath) {
  1685. bool created = false;
  1686. context = NewContext(nullptr);
  1687. EXPECT_EQ(base::File::FILE_OK,
  1688. ofu()->EnsureFileExists(context.get(), path, &created));
  1689. EXPECT_TRUE(created);
  1690. }
  1691. std::vector<filesystem::mojom::DirectoryEntry> entries;
  1692. EXPECT_EQ(base::File::FILE_OK,
  1693. AsyncFileTestHelper::ReadDirectory(file_system_context(),
  1694. empty_path, &entries));
  1695. EXPECT_EQ(3u, entries.size());
  1696. EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), kPath[0]));
  1697. entries.clear();
  1698. EXPECT_EQ(base::File::FILE_OK,
  1699. AsyncFileTestHelper::ReadDirectory(file_system_context(),
  1700. empty_path, &entries));
  1701. EXPECT_EQ(std::size(kPath) - 1, entries.size());
  1702. }
  1703. TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
  1704. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1705. const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
  1706. // Create working directory.
  1707. EXPECT_EQ(base::File::FILE_OK,
  1708. ofu()->CreateDirectory(context.get(), dir_url, false, false));
  1709. // EnsureFileExists, create case.
  1710. FileSystemURL url(FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_file"));
  1711. bool created = false;
  1712. ClearTimestamp(dir_url);
  1713. context = NewContext(nullptr);
  1714. EXPECT_EQ(base::File::FILE_OK,
  1715. ofu()->EnsureFileExists(context.get(), url, &created));
  1716. EXPECT_TRUE(created);
  1717. EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
  1718. // non create case.
  1719. created = true;
  1720. ClearTimestamp(dir_url);
  1721. context = NewContext(nullptr);
  1722. EXPECT_EQ(base::File::FILE_OK,
  1723. ofu()->EnsureFileExists(context.get(), url, &created));
  1724. EXPECT_FALSE(created);
  1725. EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
  1726. // fail case.
  1727. url = FileSystemURLAppendUTF8(dir_url, "EnsureFileExists_dir");
  1728. context = NewContext(nullptr);
  1729. EXPECT_EQ(base::File::FILE_OK,
  1730. ofu()->CreateDirectory(context.get(), url, false, false));
  1731. ClearTimestamp(dir_url);
  1732. context = NewContext(nullptr);
  1733. EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE,
  1734. ofu()->EnsureFileExists(context.get(), url, &created));
  1735. EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
  1736. // CreateOrOpen, create case.
  1737. url = FileSystemURLAppendUTF8(dir_url, "CreateOrOpen_file");
  1738. ClearTimestamp(dir_url);
  1739. context = NewContext(nullptr);
  1740. created = false;
  1741. EXPECT_EQ(base::File::FILE_OK,
  1742. ofu()->EnsureFileExists(context.get(), url, &created));
  1743. EXPECT_TRUE(created);
  1744. EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
  1745. // open case.
  1746. ClearTimestamp(dir_url);
  1747. context = NewContext(nullptr);
  1748. EXPECT_EQ(base::File::FILE_OK,
  1749. ofu()->EnsureFileExists(context.get(), url, &created));
  1750. EXPECT_FALSE(created);
  1751. EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
  1752. // fail case
  1753. ClearTimestamp(dir_url);
  1754. context = NewContext(nullptr);
  1755. EXPECT_EQ(base::File::FILE_OK,
  1756. ofu()->EnsureFileExists(context.get(), url, &created));
  1757. EXPECT_FALSE(created);
  1758. EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
  1759. // CreateDirectory, create case.
  1760. // Creating CreateDirectory_dir and CreateDirectory_dir/subdir.
  1761. url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
  1762. FileSystemURL subdir_url(FileSystemURLAppendUTF8(url, "subdir"));
  1763. ClearTimestamp(dir_url);
  1764. context = NewContext(nullptr);
  1765. EXPECT_EQ(base::File::FILE_OK,
  1766. ofu()->CreateDirectory(context.get(), subdir_url,
  1767. true /* exclusive */, true /* recursive */));
  1768. EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
  1769. // create subdir case.
  1770. // Creating CreateDirectory_dir/subdir2.
  1771. subdir_url = FileSystemURLAppendUTF8(url, "subdir2");
  1772. ClearTimestamp(dir_url);
  1773. ClearTimestamp(url);
  1774. context = NewContext(nullptr);
  1775. EXPECT_EQ(base::File::FILE_OK,
  1776. ofu()->CreateDirectory(context.get(), subdir_url,
  1777. true /* exclusive */, true /* recursive */));
  1778. EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
  1779. EXPECT_NE(base::Time(), GetModifiedTime(url));
  1780. // fail case.
  1781. url = FileSystemURLAppendUTF8(dir_url, "CreateDirectory_dir");
  1782. ClearTimestamp(dir_url);
  1783. context = NewContext(nullptr);
  1784. EXPECT_EQ(base::File::FILE_ERROR_EXISTS,
  1785. ofu()->CreateDirectory(context.get(), url, true /* exclusive */,
  1786. true /* recursive */));
  1787. EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
  1788. // CopyInForeignFile, create case.
  1789. url = FileSystemURLAppendUTF8(dir_url, "CopyInForeignFile_file");
  1790. base::ScopedTempDir foreign_source_dir;
  1791. ASSERT_TRUE(foreign_source_dir.CreateUniqueTempDir());
  1792. base::FilePath foreign_src_file_path =
  1793. foreign_source_dir.GetPath().AppendASCII("file_name");
  1794. EXPECT_EQ(base::File::FILE_OK,
  1795. NativeFileUtil::EnsureFileExists(foreign_src_file_path, &created));
  1796. EXPECT_TRUE(created);
  1797. ClearTimestamp(dir_url);
  1798. context = NewContext(nullptr);
  1799. EXPECT_EQ(
  1800. base::File::FILE_OK,
  1801. ofu()->CopyInForeignFile(context.get(), foreign_src_file_path, url));
  1802. EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
  1803. }
  1804. TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForDeletion) {
  1805. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1806. const FileSystemURL dir_url = CreateURLFromUTF8("foo_dir");
  1807. // Create working directory.
  1808. EXPECT_EQ(base::File::FILE_OK,
  1809. ofu()->CreateDirectory(context.get(), dir_url, false, false));
  1810. // DeleteFile, delete case.
  1811. FileSystemURL url = FileSystemURLAppendUTF8(dir_url, "DeleteFile_file");
  1812. bool created = false;
  1813. context = NewContext(nullptr);
  1814. EXPECT_EQ(base::File::FILE_OK,
  1815. ofu()->EnsureFileExists(context.get(), url, &created));
  1816. EXPECT_TRUE(created);
  1817. ClearTimestamp(dir_url);
  1818. context = NewContext(nullptr);
  1819. EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), url));
  1820. EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
  1821. // fail case.
  1822. ClearTimestamp(dir_url);
  1823. context = NewContext(nullptr);
  1824. EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
  1825. ofu()->DeleteFile(context.get(), url));
  1826. EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
  1827. // DeleteDirectory, fail case.
  1828. url = FileSystemURLAppendUTF8(dir_url, "DeleteDirectory_dir");
  1829. FileSystemURL file_path(FileSystemURLAppendUTF8(url, "pakeratta"));
  1830. context = NewContext(nullptr);
  1831. EXPECT_EQ(base::File::FILE_OK,
  1832. ofu()->CreateDirectory(context.get(), url, true, true));
  1833. created = false;
  1834. context = NewContext(nullptr);
  1835. EXPECT_EQ(base::File::FILE_OK,
  1836. ofu()->EnsureFileExists(context.get(), file_path, &created));
  1837. EXPECT_TRUE(created);
  1838. ClearTimestamp(dir_url);
  1839. context = NewContext(nullptr);
  1840. EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
  1841. ofu()->DeleteDirectory(context.get(), url));
  1842. EXPECT_EQ(base::Time(), GetModifiedTime(dir_url));
  1843. // delete case.
  1844. context = NewContext(nullptr);
  1845. EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteFile(context.get(), file_path));
  1846. ClearTimestamp(dir_url);
  1847. context = NewContext(nullptr);
  1848. EXPECT_EQ(base::File::FILE_OK, ofu()->DeleteDirectory(context.get(), url));
  1849. EXPECT_NE(base::Time(), GetModifiedTime(dir_url));
  1850. }
  1851. TEST_P(ObfuscatedFileUtilTest, TestDirectoryTimestampForCopyAndMove) {
  1852. TestDirectoryTimestampHelper(CreateURLFromUTF8("copy overwrite"), true, true);
  1853. TestDirectoryTimestampHelper(CreateURLFromUTF8("copy non-overwrite"), true,
  1854. false);
  1855. TestDirectoryTimestampHelper(CreateURLFromUTF8("move overwrite"), false,
  1856. true);
  1857. TestDirectoryTimestampHelper(CreateURLFromUTF8("move non-overwrite"), false,
  1858. false);
  1859. }
  1860. TEST_P(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) {
  1861. FileSystemURL dir = CreateURLFromUTF8("foo");
  1862. FileSystemURL url1 = FileSystemURLAppendUTF8(dir, "bar");
  1863. FileSystemURL url2 = FileSystemURLAppendUTF8(dir, "baz");
  1864. std::unique_ptr<FileSystemOperationContext> context = NewContext(nullptr);
  1865. EXPECT_EQ(base::File::FILE_OK,
  1866. ofu()->CreateDirectory(context.get(), dir, false, false));
  1867. bool created = false;
  1868. context = NewContext(nullptr);
  1869. EXPECT_EQ(base::File::FILE_OK,
  1870. ofu()->EnsureFileExists(context.get(), url1, &created));
  1871. EXPECT_TRUE(created);
  1872. context = NewContext(nullptr);
  1873. EXPECT_EQ(base::File::FILE_OK,
  1874. ofu()->CreateDirectory(context.get(), url2, false, false));
  1875. base::FilePath file_path;
  1876. context = NewContext(nullptr);
  1877. EXPECT_EQ(base::File::FILE_OK,
  1878. ofu()->GetLocalFilePath(context.get(), url1, &file_path));
  1879. EXPECT_FALSE(file_path.empty());
  1880. context = NewContext(nullptr);
  1881. EXPECT_EQ(base::File::FILE_OK,
  1882. ofu()->Touch(context.get(), url1,
  1883. base::Time::Now() + base::Hours(1), base::Time()));
  1884. context = NewContext(nullptr);
  1885. std::unique_ptr<FileSystemFileUtil::AbstractFileEnumerator> file_enum =
  1886. ofu()->CreateFileEnumerator(context.get(), dir, false);
  1887. int count = 0;
  1888. base::FilePath file_path_each;
  1889. while (!(file_path_each = file_enum->Next()).empty()) {
  1890. context = NewContext(nullptr);
  1891. base::File::Info file_info;
  1892. FileSystemURL new_url = FileSystemURL::CreateForTest(
  1893. dir.storage_key(), dir.mount_type(), file_path_each);
  1894. if (dir.bucket().has_value())
  1895. new_url.SetBucket(dir.bucket().value());
  1896. EXPECT_EQ(base::File::FILE_OK, ofu()->GetFileInfo(context.get(), new_url,
  1897. &file_info, &file_path));
  1898. EXPECT_EQ(file_info.is_directory, file_enum->IsDirectory());
  1899. EXPECT_EQ(file_info.last_modified, file_enum->LastModifiedTime());
  1900. EXPECT_EQ(file_info.size, file_enum->Size());
  1901. ++count;
  1902. }
  1903. EXPECT_EQ(2, count);
  1904. }
  1905. TEST_P(ObfuscatedFileUtilTest, TestQuotaOnCopyFile) {
  1906. FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
  1907. FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
  1908. FileSystemURL to_file1(CreateURLFromUTF8("tofile1"));
  1909. FileSystemURL to_file2(CreateURLFromUTF8("tofile2"));
  1910. bool created;
  1911. int64_t expected_total_file_size = 0;
  1912. ASSERT_EQ(base::File::FILE_OK,
  1913. ofu()->EnsureFileExists(
  1914. AllowUsageIncrease(PathCost(from_file))->context(), from_file,
  1915. &created));
  1916. ASSERT_TRUE(created);
  1917. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  1918. ASSERT_EQ(base::File::FILE_OK,
  1919. ofu()->EnsureFileExists(
  1920. AllowUsageIncrease(PathCost(obstacle_file))->context(),
  1921. obstacle_file, &created));
  1922. ASSERT_TRUE(created);
  1923. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  1924. int64_t from_file_size = 1020;
  1925. expected_total_file_size += from_file_size;
  1926. ASSERT_EQ(base::File::FILE_OK,
  1927. ofu()->Truncate(AllowUsageIncrease(from_file_size)->context(),
  1928. from_file, from_file_size));
  1929. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  1930. int64_t obstacle_file_size = 1;
  1931. expected_total_file_size += obstacle_file_size;
  1932. ASSERT_EQ(base::File::FILE_OK,
  1933. ofu()->Truncate(AllowUsageIncrease(obstacle_file_size)->context(),
  1934. obstacle_file, obstacle_file_size));
  1935. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  1936. int64_t to_file1_size = from_file_size;
  1937. expected_total_file_size += to_file1_size;
  1938. ASSERT_EQ(
  1939. base::File::FILE_OK,
  1940. ofu()->CopyOrMoveFile(
  1941. AllowUsageIncrease(PathCost(to_file1) + to_file1_size)->context(),
  1942. from_file, to_file1, FileSystemOperation::CopyOrMoveOptionSet(),
  1943. true /* copy */));
  1944. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  1945. ASSERT_EQ(
  1946. base::File::FILE_ERROR_NO_SPACE,
  1947. ofu()->CopyOrMoveFile(
  1948. DisallowUsageIncrease(PathCost(to_file2) + from_file_size)->context(),
  1949. from_file, to_file2, FileSystemOperation::CopyOrMoveOptionSet(),
  1950. true /* copy */));
  1951. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  1952. int64_t old_obstacle_file_size = obstacle_file_size;
  1953. obstacle_file_size = from_file_size;
  1954. expected_total_file_size += obstacle_file_size - old_obstacle_file_size;
  1955. ASSERT_EQ(base::File::FILE_OK,
  1956. ofu()->CopyOrMoveFile(
  1957. AllowUsageIncrease(obstacle_file_size - old_obstacle_file_size)
  1958. ->context(),
  1959. from_file, obstacle_file,
  1960. FileSystemOperation::CopyOrMoveOptionSet(), true /* copy */));
  1961. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  1962. int64_t old_from_file_size = from_file_size;
  1963. from_file_size = old_from_file_size - 1;
  1964. expected_total_file_size += from_file_size - old_from_file_size;
  1965. ASSERT_EQ(
  1966. base::File::FILE_OK,
  1967. ofu()->Truncate(
  1968. AllowUsageIncrease(from_file_size - old_from_file_size)->context(),
  1969. from_file, from_file_size));
  1970. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  1971. // quota exceeded
  1972. {
  1973. old_obstacle_file_size = obstacle_file_size;
  1974. obstacle_file_size = from_file_size;
  1975. expected_total_file_size += obstacle_file_size - old_obstacle_file_size;
  1976. std::unique_ptr<UsageVerifyHelper> helper =
  1977. AllowUsageIncrease(obstacle_file_size - old_obstacle_file_size);
  1978. helper->context()->set_allowed_bytes_growth(
  1979. helper->context()->allowed_bytes_growth() - 1);
  1980. ASSERT_EQ(base::File::FILE_OK,
  1981. ofu()->CopyOrMoveFile(helper->context(), from_file, obstacle_file,
  1982. FileSystemOperation::CopyOrMoveOptionSet(),
  1983. true /* copy */));
  1984. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  1985. }
  1986. }
  1987. TEST_P(ObfuscatedFileUtilTest, TestQuotaOnMoveFile) {
  1988. FileSystemURL from_file(CreateURLFromUTF8("fromfile"));
  1989. FileSystemURL obstacle_file(CreateURLFromUTF8("obstaclefile"));
  1990. FileSystemURL to_file(CreateURLFromUTF8("tofile"));
  1991. bool created;
  1992. int64_t expected_total_file_size = 0;
  1993. ASSERT_EQ(base::File::FILE_OK,
  1994. ofu()->EnsureFileExists(
  1995. AllowUsageIncrease(PathCost(from_file))->context(), from_file,
  1996. &created));
  1997. ASSERT_TRUE(created);
  1998. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  1999. int64_t from_file_size = 1020;
  2000. expected_total_file_size += from_file_size;
  2001. ASSERT_EQ(base::File::FILE_OK,
  2002. ofu()->Truncate(AllowUsageIncrease(from_file_size)->context(),
  2003. from_file, from_file_size));
  2004. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  2005. from_file_size = 0;
  2006. ASSERT_EQ(base::File::FILE_OK,
  2007. ofu()->CopyOrMoveFile(
  2008. AllowUsageIncrease(-PathCost(from_file) + PathCost(to_file))
  2009. ->context(),
  2010. from_file, to_file, FileSystemOperation::CopyOrMoveOptionSet(),
  2011. false /* move */));
  2012. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  2013. ASSERT_EQ(base::File::FILE_OK,
  2014. ofu()->EnsureFileExists(
  2015. AllowUsageIncrease(PathCost(from_file))->context(), from_file,
  2016. &created));
  2017. ASSERT_TRUE(created);
  2018. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  2019. ASSERT_EQ(base::File::FILE_OK,
  2020. ofu()->EnsureFileExists(
  2021. AllowUsageIncrease(PathCost(obstacle_file))->context(),
  2022. obstacle_file, &created));
  2023. ASSERT_TRUE(created);
  2024. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  2025. from_file_size = 1020;
  2026. expected_total_file_size += from_file_size;
  2027. ASSERT_EQ(base::File::FILE_OK,
  2028. ofu()->Truncate(AllowUsageIncrease(from_file_size)->context(),
  2029. from_file, from_file_size));
  2030. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  2031. int64_t obstacle_file_size = 1;
  2032. expected_total_file_size += obstacle_file_size;
  2033. ASSERT_EQ(base::File::FILE_OK,
  2034. ofu()->Truncate(AllowUsageIncrease(1)->context(), obstacle_file,
  2035. obstacle_file_size));
  2036. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  2037. int64_t old_obstacle_file_size = obstacle_file_size;
  2038. obstacle_file_size = from_file_size;
  2039. from_file_size = 0;
  2040. expected_total_file_size -= old_obstacle_file_size;
  2041. ASSERT_EQ(
  2042. base::File::FILE_OK,
  2043. ofu()->CopyOrMoveFile(
  2044. AllowUsageIncrease(-old_obstacle_file_size - PathCost(from_file))
  2045. ->context(),
  2046. from_file, obstacle_file, FileSystemOperation::CopyOrMoveOptionSet(),
  2047. false /* move */));
  2048. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  2049. ASSERT_EQ(base::File::FILE_OK,
  2050. ofu()->EnsureFileExists(
  2051. AllowUsageIncrease(PathCost(from_file))->context(), from_file,
  2052. &created));
  2053. ASSERT_TRUE(created);
  2054. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  2055. from_file_size = 10;
  2056. expected_total_file_size += from_file_size;
  2057. ASSERT_EQ(base::File::FILE_OK,
  2058. ofu()->Truncate(AllowUsageIncrease(from_file_size)->context(),
  2059. from_file, from_file_size));
  2060. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  2061. // quota exceeded even after operation
  2062. old_obstacle_file_size = obstacle_file_size;
  2063. obstacle_file_size = from_file_size;
  2064. from_file_size = 0;
  2065. expected_total_file_size -= old_obstacle_file_size;
  2066. std::unique_ptr<FileSystemOperationContext> context =
  2067. LimitedContext(-old_obstacle_file_size - PathCost(from_file) - 1);
  2068. ASSERT_EQ(base::File::FILE_OK,
  2069. ofu()->CopyOrMoveFile(context.get(), from_file, obstacle_file,
  2070. FileSystemOperation::CopyOrMoveOptionSet(),
  2071. false /* move */));
  2072. ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
  2073. context.reset();
  2074. }
  2075. TEST_P(ObfuscatedFileUtilTest, TestQuotaOnRemove) {
  2076. FileSystemURL dir(CreateURLFromUTF8("dir"));
  2077. FileSystemURL file(CreateURLFromUTF8("file"));
  2078. FileSystemURL dfile1(CreateURLFromUTF8("dir/dfile1"));
  2079. FileSystemURL dfile2(CreateURLFromUTF8("dir/dfile2"));
  2080. bool created;
  2081. ASSERT_EQ(base::File::FILE_OK,
  2082. ofu()->EnsureFileExists(
  2083. AllowUsageIncrease(PathCost(file))->context(), file, &created));
  2084. ASSERT_TRUE(created);
  2085. ASSERT_EQ(0, ComputeTotalFileSize());
  2086. ASSERT_EQ(base::File::FILE_OK,
  2087. ofu()->CreateDirectory(AllowUsageIncrease(PathCost(dir))->context(),
  2088. dir, false, false));
  2089. ASSERT_EQ(0, ComputeTotalFileSize());
  2090. ASSERT_EQ(
  2091. base::File::FILE_OK,
  2092. ofu()->EnsureFileExists(AllowUsageIncrease(PathCost(dfile1))->context(),
  2093. dfile1, &created));
  2094. ASSERT_TRUE(created);
  2095. ASSERT_EQ(0, ComputeTotalFileSize());
  2096. ASSERT_EQ(
  2097. base::File::FILE_OK,
  2098. ofu()->EnsureFileExists(AllowUsageIncrease(PathCost(dfile2))->context(),
  2099. dfile2, &created));
  2100. ASSERT_TRUE(created);
  2101. ASSERT_EQ(0, ComputeTotalFileSize());
  2102. ASSERT_EQ(base::File::FILE_OK,
  2103. ofu()->Truncate(AllowUsageIncrease(340)->context(), file, 340));
  2104. ASSERT_EQ(340, ComputeTotalFileSize());
  2105. ASSERT_EQ(base::File::FILE_OK,
  2106. ofu()->Truncate(AllowUsageIncrease(1020)->context(), dfile1, 1020));
  2107. ASSERT_EQ(1360, ComputeTotalFileSize());
  2108. ASSERT_EQ(base::File::FILE_OK,
  2109. ofu()->Truncate(AllowUsageIncrease(120)->context(), dfile2, 120));
  2110. ASSERT_EQ(1480, ComputeTotalFileSize());
  2111. ASSERT_EQ(base::File::FILE_OK,
  2112. ofu()->DeleteFile(
  2113. AllowUsageIncrease(-PathCost(file) - 340)->context(), file));
  2114. ASSERT_EQ(1140, ComputeTotalFileSize());
  2115. ASSERT_EQ(base::File::FILE_OK,
  2116. AsyncFileTestHelper::Remove(file_system_context(), dir,
  2117. true /* recursive */));
  2118. ASSERT_EQ(0, ComputeTotalFileSize());
  2119. }
  2120. TEST_P(ObfuscatedFileUtilTest, TestQuotaOnOpen) {
  2121. FileSystemURL url(CreateURLFromUTF8("file"));
  2122. bool created;
  2123. // Creating a file.
  2124. ASSERT_EQ(base::File::FILE_OK,
  2125. ofu()->EnsureFileExists(
  2126. AllowUsageIncrease(PathCost(url))->context(), url, &created));
  2127. ASSERT_TRUE(created);
  2128. ASSERT_EQ(0, ComputeTotalFileSize());
  2129. // Opening it, which shouldn't change the usage.
  2130. ASSERT_EQ(
  2131. base::File::FILE_OK,
  2132. ofu()->EnsureFileExists(AllowUsageIncrease(0)->context(), url, &created));
  2133. ASSERT_EQ(0, ComputeTotalFileSize());
  2134. const int length = 33;
  2135. ASSERT_EQ(
  2136. base::File::FILE_OK,
  2137. ofu()->Truncate(AllowUsageIncrease(length)->context(), url, length));
  2138. ASSERT_EQ(length, ComputeTotalFileSize());
  2139. // TODO(https://crbug.com/936722): After CreateOrOpen is modified to return
  2140. // file error instead of file, the in-memory test can proceed through the next
  2141. // steps.
  2142. if (is_incognito())
  2143. return;
  2144. // Opening it with CREATE_ALWAYS flag, which should truncate the file size.
  2145. base::File file = ofu()->CreateOrOpen(
  2146. AllowUsageIncrease(-length)->context(), url,
  2147. base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
  2148. ASSERT_TRUE(file.IsValid());
  2149. ASSERT_EQ(0, ComputeTotalFileSize());
  2150. file.Close();
  2151. // Extending the file again.
  2152. ASSERT_EQ(
  2153. base::File::FILE_OK,
  2154. ofu()->Truncate(AllowUsageIncrease(length)->context(), url, length));
  2155. ASSERT_EQ(length, ComputeTotalFileSize());
  2156. // Opening it with TRUNCATED flag, which should truncate the file size.
  2157. file = ofu()->CreateOrOpen(
  2158. AllowUsageIncrease(-length)->context(), url,
  2159. base::File::FLAG_OPEN_TRUNCATED | base::File::FLAG_WRITE);
  2160. ASSERT_TRUE(file.IsValid());
  2161. ASSERT_EQ(0, ComputeTotalFileSize());
  2162. file.Close();
  2163. }
  2164. TEST_P(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase) {
  2165. MaybeDropDatabasesAliveCaseTestBody();
  2166. }
  2167. TEST_P(ObfuscatedFileUtilTest, MaybeDropDatabasesAlreadyDeletedCase) {
  2168. MaybeDropDatabasesAlreadyDeletedCaseTestBody();
  2169. }
  2170. TEST_P(ObfuscatedFileUtilTest, DestroyDirectoryDatabase_Isolated) {
  2171. DestroyDirectoryDatabase_IsolatedTestBody();
  2172. }
  2173. TEST_P(ObfuscatedFileUtilTest, GetDirectoryDatabase_Isolated) {
  2174. GetDirectoryDatabase_IsolatedTestBody();
  2175. }
  2176. TEST_P(ObfuscatedFileUtilTest, OpenPathInNonDirectory) {
  2177. FileSystemURL url(CreateURLFromUTF8("file"));
  2178. FileSystemURL path_in_file(CreateURLFromUTF8("file/file"));
  2179. bool created;
  2180. ASSERT_EQ(base::File::FILE_OK,
  2181. ofu()->EnsureFileExists(UnlimitedContext().get(), url, &created));
  2182. ASSERT_TRUE(created);
  2183. ASSERT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY,
  2184. ofu()->EnsureFileExists(UnlimitedContext().get(), path_in_file,
  2185. &created));
  2186. ASSERT_EQ(
  2187. base::File::FILE_ERROR_NOT_A_DIRECTORY,
  2188. ofu()->CreateDirectory(UnlimitedContext().get(), path_in_file,
  2189. false /* exclusive */, false /* recursive */));
  2190. }
  2191. TEST_P(ObfuscatedFileUtilTest, CreateDirectory_NotADirectoryInRecursive) {
  2192. FileSystemURL file(CreateURLFromUTF8("file"));
  2193. FileSystemURL path_in_file(CreateURLFromUTF8("file/child"));
  2194. FileSystemURL path_in_file_in_file(
  2195. CreateURLFromUTF8("file/child/grandchild"));
  2196. bool created;
  2197. ASSERT_EQ(base::File::FILE_OK,
  2198. ofu()->EnsureFileExists(UnlimitedContext().get(), file, &created));
  2199. ASSERT_TRUE(created);
  2200. ASSERT_EQ(
  2201. base::File::FILE_ERROR_NOT_A_DIRECTORY,
  2202. ofu()->CreateDirectory(UnlimitedContext().get(), path_in_file,
  2203. false /* exclusive */, true /* recursive */));
  2204. ASSERT_EQ(
  2205. base::File::FILE_ERROR_NOT_A_DIRECTORY,
  2206. ofu()->CreateDirectory(UnlimitedContext().get(), path_in_file_in_file,
  2207. false /* exclusive */, true /* recursive */));
  2208. }
  2209. TEST_P(ObfuscatedFileUtilTest, DeleteDirectoryForBucketAndType) {
  2210. // Create directories.
  2211. std::unique_ptr<SandboxFileSystemTestHelper> fs1 =
  2212. NewFileSystem(default_bucket_, kFileSystemTypeTemporary);
  2213. std::unique_ptr<SandboxFileSystemTestHelper> fs2 =
  2214. NewFileSystem(default_bucket_, kFileSystemTypePersistent);
  2215. std::unique_ptr<SandboxFileSystemTestHelper> fs3 =
  2216. NewFileSystem(custom_bucket_, kFileSystemTypeTemporary);
  2217. std::unique_ptr<SandboxFileSystemTestHelper> fs4 =
  2218. NewFileSystem(custom_bucket_, kFileSystemTypePersistent);
  2219. // Make sure directories for default_bucket_ exist.
  2220. ASSERT_FALSE(ofu()
  2221. ->GetDirectoryForBucketAndType(default_bucket_,
  2222. kFileSystemTypeTemporary,
  2223. /*create=*/false)
  2224. .is_error());
  2225. ASSERT_FALSE(ofu()
  2226. ->GetDirectoryForBucketAndType(default_bucket_,
  2227. kFileSystemTypePersistent,
  2228. /*create=*/false)
  2229. .is_error());
  2230. // Make sure directories for custom_bucket_ exist.
  2231. ASSERT_FALSE(ofu()
  2232. ->GetDirectoryForBucketAndType(custom_bucket_,
  2233. kFileSystemTypeTemporary,
  2234. /*create=*/false)
  2235. .is_error());
  2236. ASSERT_FALSE(ofu()
  2237. ->GetDirectoryForBucketAndType(custom_bucket_,
  2238. kFileSystemTypePersistent,
  2239. /*create=*/false)
  2240. .is_error());
  2241. // Delete a directory for default_bucket_'s persistent filesystem.
  2242. ASSERT_TRUE(ofu()->DeleteDirectoryForBucketAndType(
  2243. default_bucket_, kFileSystemTypePersistent));
  2244. // The directory for default_bucket_'s temporary filesystem should not be
  2245. // removed.
  2246. ASSERT_FALSE(ofu()
  2247. ->GetDirectoryForBucketAndType(default_bucket_,
  2248. kFileSystemTypeTemporary,
  2249. /*create=*/false)
  2250. .is_error());
  2251. // The directory for default_bucket_'s persistent filesystem should be
  2252. // removed.
  2253. ASSERT_EQ(ofu()
  2254. ->GetDirectoryForBucketAndType(default_bucket_,
  2255. kFileSystemTypePersistent,
  2256. /*create=*/false)
  2257. .error(),
  2258. base::File::FILE_ERROR_NOT_FOUND);
  2259. // The directories for custom_bucket_ should not be removed.
  2260. ASSERT_FALSE(ofu()
  2261. ->GetDirectoryForBucketAndType(custom_bucket_,
  2262. kFileSystemTypeTemporary,
  2263. /*create=*/false)
  2264. .is_error());
  2265. ASSERT_FALSE(ofu()
  2266. ->GetDirectoryForBucketAndType(custom_bucket_,
  2267. kFileSystemTypePersistent,
  2268. /*create=*/false)
  2269. .is_error());
  2270. // Deleting directories which don't exist is not an error.
  2271. ASSERT_TRUE(ofu()->DeleteDirectoryForBucketAndType(
  2272. alternate_custom_bucket_, kFileSystemTypePersistent));
  2273. }
  2274. TEST_P(ObfuscatedFileUtilTest, DeleteDirectoryForStorageKeyAndType) {
  2275. const blink::StorageKey storage_key1 =
  2276. blink::StorageKey::CreateFromStringForTesting(
  2277. "http://www.example.com:12");
  2278. const blink::StorageKey storage_key2 =
  2279. blink::StorageKey::CreateFromStringForTesting(
  2280. "http://www.example.com:1234");
  2281. const blink::StorageKey storage_key3 =
  2282. blink::StorageKey::CreateFromStringForTesting("http://nope.example.com");
  2283. // Create origin directories.
  2284. std::unique_ptr<SandboxFileSystemTestHelper> fs1 =
  2285. NewFileSystem(storage_key1, kFileSystemTypeTemporary);
  2286. std::unique_ptr<SandboxFileSystemTestHelper> fs2 =
  2287. NewFileSystem(storage_key1, kFileSystemTypePersistent);
  2288. std::unique_ptr<SandboxFileSystemTestHelper> fs3 =
  2289. NewFileSystem(storage_key2, kFileSystemTypeTemporary);
  2290. std::unique_ptr<SandboxFileSystemTestHelper> fs4 =
  2291. NewFileSystem(storage_key2, kFileSystemTypePersistent);
  2292. // Make sure directories for storage_key1 exist.
  2293. ASSERT_FALSE(ofu()
  2294. ->GetDirectoryForStorageKeyAndType(storage_key1,
  2295. kFileSystemTypeTemporary,
  2296. /*create=*/false)
  2297. .is_error());
  2298. ASSERT_FALSE(ofu()
  2299. ->GetDirectoryForStorageKeyAndType(storage_key1,
  2300. kFileSystemTypePersistent,
  2301. /*create=*/false)
  2302. .is_error());
  2303. // Make sure directories for storage_key2 exist.
  2304. ASSERT_FALSE(ofu()
  2305. ->GetDirectoryForStorageKeyAndType(storage_key2,
  2306. kFileSystemTypeTemporary,
  2307. /*create=*/false)
  2308. .is_error());
  2309. ASSERT_FALSE(ofu()
  2310. ->GetDirectoryForStorageKeyAndType(storage_key2,
  2311. kFileSystemTypePersistent,
  2312. /*create=*/false)
  2313. .is_error());
  2314. // Delete a directory for storage_key1's persistent filesystem.
  2315. ASSERT_TRUE(ofu()->DeleteDirectoryForStorageKeyAndType(
  2316. storage_key1, kFileSystemTypePersistent));
  2317. // The directory for storage_key1's temporary filesystem should not be
  2318. // removed.
  2319. ASSERT_FALSE(ofu()
  2320. ->GetDirectoryForStorageKeyAndType(storage_key1,
  2321. kFileSystemTypeTemporary,
  2322. /*create=*/false)
  2323. .is_error());
  2324. // The directory for storage_key1's persistent filesystem should be removed.
  2325. ASSERT_EQ(ofu()
  2326. ->GetDirectoryForStorageKeyAndType(storage_key1,
  2327. kFileSystemTypePersistent,
  2328. /*create=*/false)
  2329. .error(),
  2330. base::File::FILE_ERROR_NOT_FOUND);
  2331. // The directories for storage_key2 should not be removed.
  2332. ASSERT_FALSE(ofu()
  2333. ->GetDirectoryForStorageKeyAndType(storage_key2,
  2334. kFileSystemTypeTemporary,
  2335. /*create=*/false)
  2336. .is_error());
  2337. ASSERT_FALSE(ofu()
  2338. ->GetDirectoryForStorageKeyAndType(storage_key2,
  2339. kFileSystemTypePersistent,
  2340. /*create=*/false)
  2341. .is_error());
  2342. // Make sure storage_key3's directories don't exist.
  2343. ASSERT_EQ(ofu()
  2344. ->GetDirectoryForStorageKeyAndType(storage_key3,
  2345. kFileSystemTypeTemporary,
  2346. /*create=*/false)
  2347. .error(),
  2348. base::File::FILE_ERROR_NOT_FOUND);
  2349. ASSERT_EQ(ofu()
  2350. ->GetDirectoryForStorageKeyAndType(storage_key3,
  2351. kFileSystemTypePersistent,
  2352. /*create=*/false)
  2353. .error(),
  2354. base::File::FILE_ERROR_NOT_FOUND);
  2355. // Deleting directories which don't exist is not an error.
  2356. ASSERT_TRUE(ofu()->DeleteDirectoryForStorageKeyAndType(
  2357. storage_key3, kFileSystemTypeTemporary));
  2358. ASSERT_TRUE(ofu()->DeleteDirectoryForStorageKeyAndType(
  2359. storage_key3, kFileSystemTypePersistent));
  2360. }
  2361. TEST_P(ObfuscatedFileUtilTest, DeleteDirectoryForBucketAndType_DeleteAll) {
  2362. // Create origin directories.
  2363. std::unique_ptr<SandboxFileSystemTestHelper> fs1 =
  2364. NewFileSystem(default_bucket_, kFileSystemTypeTemporary);
  2365. std::unique_ptr<SandboxFileSystemTestHelper> fs2 =
  2366. NewFileSystem(default_bucket_, kFileSystemTypePersistent);
  2367. std::unique_ptr<SandboxFileSystemTestHelper> fs3 =
  2368. NewFileSystem(custom_bucket_, kFileSystemTypeTemporary);
  2369. std::unique_ptr<SandboxFileSystemTestHelper> fs4 =
  2370. NewFileSystem(custom_bucket_, kFileSystemTypePersistent);
  2371. // Make sure directories for default_bucket_ exist.
  2372. ASSERT_FALSE(ofu()
  2373. ->GetDirectoryForBucketAndType(default_bucket_,
  2374. kFileSystemTypeTemporary,
  2375. /*create=*/false)
  2376. .is_error());
  2377. ASSERT_FALSE(ofu()
  2378. ->GetDirectoryForBucketAndType(default_bucket_,
  2379. kFileSystemTypePersistent,
  2380. /*create=*/false)
  2381. .is_error());
  2382. // Make sure directories for custom_bucket_ exist.
  2383. ASSERT_FALSE(ofu()
  2384. ->GetDirectoryForBucketAndType(custom_bucket_,
  2385. kFileSystemTypeTemporary,
  2386. /*create=*/false)
  2387. .is_error());
  2388. ASSERT_FALSE(ofu()
  2389. ->GetDirectoryForBucketAndType(custom_bucket_,
  2390. kFileSystemTypePersistent,
  2391. /*create=*/false)
  2392. .is_error());
  2393. // Delete all directories for default_bucket_.
  2394. ofu()->DeleteDirectoryForBucketAndType(default_bucket_, absl::nullopt);
  2395. // The directories for default_bucket_ should be removed.
  2396. ASSERT_EQ(ofu()
  2397. ->GetDirectoryForBucketAndType(default_bucket_,
  2398. kFileSystemTypeTemporary,
  2399. /*create=*/false)
  2400. .error(),
  2401. base::File::FILE_ERROR_NOT_FOUND);
  2402. ASSERT_EQ(ofu()
  2403. ->GetDirectoryForBucketAndType(default_bucket_,
  2404. kFileSystemTypePersistent,
  2405. /*create=*/false)
  2406. .error(),
  2407. base::File::FILE_ERROR_NOT_FOUND);
  2408. // The directories for custom_bucket_ should not be removed.
  2409. ASSERT_FALSE(ofu()
  2410. ->GetDirectoryForBucketAndType(custom_bucket_,
  2411. kFileSystemTypeTemporary,
  2412. /*create=*/false)
  2413. .is_error());
  2414. ASSERT_FALSE(ofu()
  2415. ->GetDirectoryForBucketAndType(custom_bucket_,
  2416. kFileSystemTypePersistent,
  2417. /*create=*/false)
  2418. .is_error());
  2419. }
  2420. TEST_P(ObfuscatedFileUtilTest, DeleteDirectoryForStorageKeyAndType_DeleteAll) {
  2421. const blink::StorageKey storage_key1 =
  2422. blink::StorageKey::CreateFromStringForTesting(
  2423. "http://www.example.com:12");
  2424. const blink::StorageKey storage_key2 =
  2425. blink::StorageKey::CreateFromStringForTesting(
  2426. "http://www.example.com:1234");
  2427. // Create origin directories.
  2428. std::unique_ptr<SandboxFileSystemTestHelper> fs1 =
  2429. NewFileSystem(storage_key1, kFileSystemTypeTemporary);
  2430. std::unique_ptr<SandboxFileSystemTestHelper> fs2 =
  2431. NewFileSystem(storage_key1, kFileSystemTypePersistent);
  2432. std::unique_ptr<SandboxFileSystemTestHelper> fs3 =
  2433. NewFileSystem(storage_key2, kFileSystemTypeTemporary);
  2434. std::unique_ptr<SandboxFileSystemTestHelper> fs4 =
  2435. NewFileSystem(storage_key2, kFileSystemTypePersistent);
  2436. // Make sure directories for storage_key1 exist.
  2437. ASSERT_FALSE(ofu()
  2438. ->GetDirectoryForStorageKeyAndType(storage_key1,
  2439. kFileSystemTypeTemporary,
  2440. /*create=*/false)
  2441. .is_error());
  2442. ASSERT_FALSE(ofu()
  2443. ->GetDirectoryForStorageKeyAndType(storage_key1,
  2444. kFileSystemTypePersistent,
  2445. /*create=*/false)
  2446. .is_error());
  2447. // Make sure directories for storage_key2 exist.
  2448. ASSERT_FALSE(ofu()
  2449. ->GetDirectoryForStorageKeyAndType(storage_key2,
  2450. kFileSystemTypeTemporary,
  2451. /*create=*/false)
  2452. .is_error());
  2453. ASSERT_FALSE(ofu()
  2454. ->GetDirectoryForStorageKeyAndType(storage_key2,
  2455. kFileSystemTypePersistent,
  2456. /*create=*/false)
  2457. .is_error());
  2458. // Delete all directories for storage_key1.
  2459. ofu()->DeleteDirectoryForStorageKeyAndType(storage_key1, absl::nullopt);
  2460. // The directories for storage_key1 should be removed.
  2461. ASSERT_EQ(ofu()
  2462. ->GetDirectoryForStorageKeyAndType(storage_key1,
  2463. kFileSystemTypeTemporary,
  2464. /*create=*/false)
  2465. .error(),
  2466. base::File::FILE_ERROR_NOT_FOUND);
  2467. ASSERT_EQ(ofu()
  2468. ->GetDirectoryForStorageKeyAndType(storage_key1,
  2469. kFileSystemTypePersistent,
  2470. /*create=*/false)
  2471. .error(),
  2472. base::File::FILE_ERROR_NOT_FOUND);
  2473. // The directories for storage_key2 should not be removed.
  2474. ASSERT_FALSE(ofu()
  2475. ->GetDirectoryForStorageKeyAndType(storage_key2,
  2476. kFileSystemTypeTemporary,
  2477. /*create=*/false)
  2478. .is_error());
  2479. ASSERT_FALSE(ofu()
  2480. ->GetDirectoryForStorageKeyAndType(storage_key2,
  2481. kFileSystemTypePersistent,
  2482. /*create=*/false)
  2483. .is_error());
  2484. }
  2485. } // namespace storage