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
5 #include "webkit/common/database/database_identifier.h"
6
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/string_util.h"
9 #include "url/url_canon.h"
10
11 namespace webkit_database {
12
13 // static
GetIdentifierFromOrigin(const GURL & origin)14 std::string GetIdentifierFromOrigin(const GURL& origin) {
15 return DatabaseIdentifier::CreateFromOrigin(origin).ToString();
16 }
17
18 // static
GetOriginFromIdentifier(const std::string & identifier)19 GURL GetOriginFromIdentifier(const std::string& identifier) {
20 return DatabaseIdentifier::Parse(identifier).ToOrigin();
21 }
22
SchemeIsUnique(const std::string & scheme)23 static bool SchemeIsUnique(const std::string& scheme) {
24 return scheme == "about" || scheme == "data" || scheme == "javascript";
25 }
26
27 // static
UniqueFileIdentifier()28 const DatabaseIdentifier DatabaseIdentifier::UniqueFileIdentifier() {
29 return DatabaseIdentifier("", "", 0, true, true);
30 }
31
32 // static
CreateFromOrigin(const GURL & origin)33 DatabaseIdentifier DatabaseIdentifier::CreateFromOrigin(const GURL& origin) {
34 if (!origin.is_valid() || origin.is_empty() ||
35 !origin.IsStandard() || SchemeIsUnique(origin.scheme()))
36 return DatabaseIdentifier();
37
38 if (origin.SchemeIsFile())
39 return UniqueFileIdentifier();
40
41 int port = origin.IntPort();
42 if (port == url_parse::PORT_INVALID)
43 return DatabaseIdentifier();
44
45 // We encode the default port for the specified scheme as 0. GURL
46 // canonicalizes this as an unspecified port.
47 if (port == url_parse::PORT_UNSPECIFIED)
48 port = 0;
49
50 return DatabaseIdentifier(origin.scheme(),
51 origin.host(),
52 port,
53 false /* unique */,
54 false /* file */);
55 }
56
57 // static
Parse(const std::string & identifier)58 DatabaseIdentifier DatabaseIdentifier::Parse(const std::string& identifier) {
59 if (!IsStringASCII(identifier))
60 return DatabaseIdentifier();
61
62 size_t first_underscore = identifier.find_first_of('_');
63 if (first_underscore == std::string::npos || first_underscore == 0)
64 return DatabaseIdentifier();
65
66 size_t last_underscore = identifier.find_last_of('_');
67 if (last_underscore == std::string::npos ||
68 last_underscore == first_underscore ||
69 last_underscore == identifier.length() - 1)
70 return DatabaseIdentifier();
71
72 std::string scheme(identifier.data(), first_underscore);
73 if (scheme == "file")
74 return UniqueFileIdentifier();
75
76 // This magical set of schemes is always treated as unique.
77 if (SchemeIsUnique(scheme))
78 return DatabaseIdentifier();
79
80 base::StringPiece port_str(identifier.begin() + last_underscore + 1,
81 identifier.end());
82 int port = 0;
83 if (!base::StringToInt(port_str, &port) || port < 0 || port >= 1 << 16)
84 return DatabaseIdentifier();
85
86 std::string hostname(identifier.data() + first_underscore + 1,
87 last_underscore - first_underscore - 1);
88 GURL url(scheme + "://" + hostname + "/");
89
90 if (!url.IsStandard())
91 hostname = "";
92
93 // If a url doesn't parse cleanly or doesn't round trip, reject it.
94 if (!url.is_valid() || url.scheme() != scheme || url.host() != hostname)
95 return DatabaseIdentifier();
96
97 return DatabaseIdentifier(scheme, hostname, port, false /* unique */, false);
98 }
99
DatabaseIdentifier()100 DatabaseIdentifier::DatabaseIdentifier()
101 : port_(0),
102 is_unique_(true),
103 is_file_(false) {
104 }
105
DatabaseIdentifier(const std::string & scheme,const std::string & hostname,int port,bool is_unique,bool is_file)106 DatabaseIdentifier::DatabaseIdentifier(const std::string& scheme,
107 const std::string& hostname,
108 int port,
109 bool is_unique,
110 bool is_file)
111 : scheme_(scheme),
112 hostname_(StringToLowerASCII(hostname)),
113 port_(port),
114 is_unique_(is_unique),
115 is_file_(is_file) {
116 }
117
~DatabaseIdentifier()118 DatabaseIdentifier::~DatabaseIdentifier() {}
119
ToString() const120 std::string DatabaseIdentifier::ToString() const {
121 if (is_file_)
122 return "file__0";
123 if (is_unique_)
124 return "__0";
125 return scheme_ + "_" + hostname_ + "_" + base::IntToString(port_);
126 }
127
ToOrigin() const128 GURL DatabaseIdentifier::ToOrigin() const {
129 if (is_file_)
130 return GURL("file:///");
131 if (is_unique_)
132 return GURL();
133 if (port_ == 0)
134 return GURL(scheme_ + "://" + hostname_);
135 return GURL(scheme_ + "://" + hostname_ + ":" + base::IntToString(port_));
136 }
137
138 } // namespace webkit_database
139