1 // Copyright 2014 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 
5 #include "chrome/browser/chromeos/fileapi/external_file_url_util.h"
6 
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/test/base/testing_browser_process.h"
9 #include "chrome/test/base/testing_profile_manager.h"
10 #include "components/drive/file_system_core_util.h"
11 #include "content/public/common/url_constants.h"
12 #include "content/public/test/browser_task_environment.h"
13 #include "storage/browser/file_system/file_system_url.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 namespace chromeos {
17 
18 namespace {
19 
20 // Sets up ProfileManager for testing and marks the current thread as UI by
21 // BrowserTaskEnvironment. We need the thread since Profile objects must be
22 // touched from UI and hence has CHECK/DCHECKs for it.
23 class ExternalFileURLUtilTest : public testing::Test {
24  protected:
ExternalFileURLUtilTest()25   ExternalFileURLUtilTest()
26       : testing_profile_manager_(TestingBrowserProcess::GetGlobal()) {}
27 
SetUp()28   void SetUp() override { ASSERT_TRUE(testing_profile_manager_.SetUp()); }
29 
testing_profile_manager()30   TestingProfileManager& testing_profile_manager() {
31     return testing_profile_manager_;
32   }
33 
CreateExpectedURL(const base::FilePath & path)34   storage::FileSystemURL CreateExpectedURL(const base::FilePath& path) {
35     return storage::FileSystemURL::CreateForTest(
36         url::Origin::Create(GURL("chrome-extension://xxx")),
37         storage::kFileSystemTypeExternal,
38         base::FilePath("arc-documents-provider").Append(path), "",
39         storage::kFileSystemTypeArcDocumentsProvider, base::FilePath(), "",
40         storage::FileSystemMountOption());
41   }
42 
43  private:
44   content::BrowserTaskEnvironment task_environment_;
45   TestingProfileManager testing_profile_manager_;
46 };
47 
48 }  // namespace
49 
TEST_F(ExternalFileURLUtilTest,FilePathToExternalFileURL)50 TEST_F(ExternalFileURLUtilTest, FilePathToExternalFileURL) {
51   storage::FileSystemURL url;
52 
53   // Path with alphabets and numbers.
54   url = CreateExpectedURL(base::FilePath("foo/bar012.txt"));
55   EXPECT_EQ(url.virtual_path(),
56             ExternalFileURLToVirtualPath(FileSystemURLToExternalFileURL(url)));
57 
58   // Path with symbols.
59   url = CreateExpectedURL(base::FilePath(" !\"#$%&'()*+,-.:;<=>?@[\\]^_`{|}~"));
60   EXPECT_EQ(url.virtual_path(),
61             ExternalFileURLToVirtualPath(FileSystemURLToExternalFileURL(url)));
62 
63   // Path with '%'.
64   url = CreateExpectedURL(base::FilePath("%19%20%21.txt"));
65   EXPECT_EQ(url.virtual_path(),
66             ExternalFileURLToVirtualPath(FileSystemURLToExternalFileURL(url)));
67 
68   // Path with multi byte characters.
69   base::string16 utf16_string;
70   utf16_string.push_back(0x307b);  // HIRAGANA_LETTER_HO
71   utf16_string.push_back(0x3052);  // HIRAGANA_LETTER_GE
72   url = CreateExpectedURL(
73       base::FilePath::FromUTF8Unsafe(base::UTF16ToUTF8(utf16_string) + ".txt"));
74   EXPECT_EQ(url.virtual_path().AsUTF8Unsafe(),
75             ExternalFileURLToVirtualPath(FileSystemURLToExternalFileURL(url))
76                 .AsUTF8Unsafe());
77 }
78 
79 // Tests that given virtual path is encoded to an expected externalfile: URL
80 // and then the original path is reconstructed from it.
ExpectVirtualPathRoundtrip(const base::FilePath::StringType & virtual_path_string,std::string expected_url)81 void ExpectVirtualPathRoundtrip(
82     const base::FilePath::StringType& virtual_path_string,
83     std::string expected_url) {
84   base::FilePath virtual_path(virtual_path_string);
85   GURL result = VirtualPathToExternalFileURL(virtual_path);
86   EXPECT_TRUE(result.is_valid());
87   EXPECT_EQ(content::kExternalFileScheme, result.scheme());
88   EXPECT_EQ(expected_url, result.path());
89   EXPECT_EQ(virtual_path.value(), ExternalFileURLToVirtualPath(result).value());
90 }
91 
TEST_F(ExternalFileURLUtilTest,VirtualPathToExternalFileURL)92 TEST_F(ExternalFileURLUtilTest, VirtualPathToExternalFileURL) {
93   ExpectVirtualPathRoundtrip(FILE_PATH_LITERAL("foo/bar012.txt"),
94                              "foo/bar012.txt");
95 
96   // Path containing precent character, which is also used for URL encoding.
97   ExpectVirtualPathRoundtrip(FILE_PATH_LITERAL("foo/bar012%41%.txt"),
98                              "foo/bar012%2541%25.txt");
99 
100   // Path containing some ASCII characters that are escaped by URL enconding.
101   ExpectVirtualPathRoundtrip(FILE_PATH_LITERAL("foo/bar \"#<>?`{}.txt"),
102                              "foo/bar%20%22%23%3C%3E%3F%60%7B%7D.txt");
103 
104   // (U+3000) IDEOGRAPHIC SPACE and (U+1F512) LOCK are examples of characters
105   // potentially used for URL spoofing. Those are blacklisted from unescaping
106   // when a URL is displayed, but this should not prevent it from being
107   // unescaped when converting a URL to a virtual file path. See
108   // crbug.com/585422 for detail.
109   ExpectVirtualPathRoundtrip(FILE_PATH_LITERAL("foo/bar/space\u3000lock��.zip"),
110                              "foo/bar/space%E3%80%80lock%F0%9F%94%92.zip");
111 }
112 
113 }  // namespace chromeos
114