OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h" | 5 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_util.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
11 #include "net/base/escape.h" | 11 #include "net/base/escape.h" |
12 #include "storage/browser/fileapi/file_system_url.h" | 12 #include "storage/browser/fileapi/file_system_url.h" |
13 #include "url/gurl.h" | 13 #include "url/gurl.h" |
14 | 14 |
15 namespace arc { | 15 namespace arc { |
16 | 16 |
| 17 // This is based on net/base/escape.cc: net::(anonymous namespace)::Escape. |
| 18 // TODO(nya): Consider consolidating this function with EscapeFileSystemId() in |
| 19 // chrome/browser/chromeos/file_system_provider/mount_path_util.cc. |
| 20 // This version differs from the other one in the point that dots are not always |
| 21 // escaped because authorities often contain harmless dots. |
| 22 std::string EscapePathComponent(const std::string& name) { |
| 23 std::string escaped; |
| 24 // Escape dots only when they forms a special file name. |
| 25 if (name == "." || name == "..") { |
| 26 base::ReplaceChars(name, ".", "%2E", &escaped); |
| 27 return escaped; |
| 28 } |
| 29 // Escape % and / only. |
| 30 for (size_t i = 0; i < name.size(); ++i) { |
| 31 const char c = name[i]; |
| 32 if (c == '%' || c == '/') |
| 33 base::StringAppendF(&escaped, "%%%02X", c); |
| 34 else |
| 35 escaped.push_back(c); |
| 36 } |
| 37 return escaped; |
| 38 } |
| 39 |
| 40 std::string UnescapePathComponent(const std::string& escaped) { |
| 41 return net::UnescapeURLComponent( |
| 42 escaped, net::UnescapeRule::PATH_SEPARATORS | |
| 43 net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS); |
| 44 } |
| 45 |
17 const char kDocumentsProviderMountPointName[] = "arc-documents-provider"; | 46 const char kDocumentsProviderMountPointName[] = "arc-documents-provider"; |
18 const base::FilePath::CharType kDocumentsProviderMountPointPath[] = | 47 const base::FilePath::CharType kDocumentsProviderMountPointPath[] = |
19 "/special/arc-documents-provider"; | 48 "/special/arc-documents-provider"; |
20 const char kAndroidDirectoryMimeType[] = "vnd.android.document/directory"; | 49 const char kAndroidDirectoryMimeType[] = "vnd.android.document/directory"; |
21 | 50 |
| 51 base::FilePath GetDocumentsProviderMountPath( |
| 52 const std::string& authority, |
| 53 const std::string& root_document_id) { |
| 54 return base::FilePath(kDocumentsProviderMountPointPath) |
| 55 .Append(EscapePathComponent(authority)) |
| 56 .Append(EscapePathComponent(root_document_id)); |
| 57 } |
| 58 |
22 bool ParseDocumentsProviderUrl(const storage::FileSystemURL& url, | 59 bool ParseDocumentsProviderUrl(const storage::FileSystemURL& url, |
23 std::string* authority, | 60 std::string* authority, |
24 std::string* root_document_id, | 61 std::string* root_document_id, |
25 base::FilePath* path) { | 62 base::FilePath* path) { |
26 if (url.type() != storage::kFileSystemTypeArcDocumentsProvider) | 63 if (url.type() != storage::kFileSystemTypeArcDocumentsProvider) |
27 return false; | 64 return false; |
28 base::FilePath url_path_stripped = url.path().StripTrailingSeparators(); | 65 base::FilePath url_path_stripped = url.path().StripTrailingSeparators(); |
29 | 66 |
30 if (!base::FilePath(kDocumentsProviderMountPointPath) | 67 if (!base::FilePath(kDocumentsProviderMountPointPath) |
31 .IsParent(url_path_stripped)) { | 68 .IsParent(url_path_stripped)) { |
32 return false; | 69 return false; |
33 } | 70 } |
34 | 71 |
35 // Filesystem URL format for documents provider is: | 72 // Filesystem URL format for documents provider is: |
36 // /special/arc-documents-provider/<authority>/<root_doc_id>/<relative_path> | 73 // /special/arc-documents-provider/<authority>/<root_doc_id>/<relative_path> |
37 std::vector<base::FilePath::StringType> components; | 74 std::vector<base::FilePath::StringType> components; |
38 url_path_stripped.GetComponents(&components); | 75 url_path_stripped.GetComponents(&components); |
39 if (components.size() < 5) | 76 if (components.size() < 5) |
40 return false; | 77 return false; |
41 | 78 |
42 *authority = components[3]; | 79 *authority = UnescapePathComponent(components[3]); |
43 *root_document_id = components[4]; | 80 *root_document_id = UnescapePathComponent(components[4]); |
44 | 81 |
45 base::FilePath root_path = base::FilePath(kDocumentsProviderMountPointPath) | 82 base::FilePath root_path = |
46 .Append(*authority) | 83 GetDocumentsProviderMountPath(*authority, *root_document_id); |
47 .Append(*root_document_id); | |
48 // Special case: AppendRelativePath() fails for identical paths. | 84 // Special case: AppendRelativePath() fails for identical paths. |
49 if (url_path_stripped == root_path) { | 85 if (url_path_stripped == root_path) { |
50 path->clear(); | 86 path->clear(); |
51 } else { | 87 } else { |
52 bool success = root_path.AppendRelativePath(url_path_stripped, path); | 88 bool success = root_path.AppendRelativePath(url_path_stripped, path); |
53 DCHECK(success); | 89 DCHECK(success); |
54 } | 90 } |
55 return true; | 91 return true; |
56 } | 92 } |
57 | 93 |
58 GURL BuildDocumentUrl(const std::string& authority, | 94 GURL BuildDocumentUrl(const std::string& authority, |
59 const std::string& document_id) { | 95 const std::string& document_id) { |
60 return GURL(base::StringPrintf( | 96 return GURL(base::StringPrintf( |
61 "content://%s/document/%s", | 97 "content://%s/document/%s", |
62 net::EscapeQueryParamValue(authority, false /* use_plus */).c_str(), | 98 net::EscapeQueryParamValue(authority, false /* use_plus */).c_str(), |
63 net::EscapeQueryParamValue(document_id, false /* use_plus */).c_str())); | 99 net::EscapeQueryParamValue(document_id, false /* use_plus */).c_str())); |
64 } | 100 } |
65 | 101 |
66 } // namespace arc | 102 } // namespace arc |
OLD | NEW |