• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::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::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 (!base::IsStringASCII(identifier))
60     return DatabaseIdentifier();
61   if (identifier.find("..") != std::string::npos)
62     return DatabaseIdentifier();
63   char forbidden[] = {'\\', '/', ':' ,'\0'};
64   if (identifier.find_first_of(forbidden, 0, arraysize(forbidden)) !=
65           std::string::npos) {
66     return DatabaseIdentifier();
67   }
68 
69   size_t first_underscore = identifier.find_first_of('_');
70   if (first_underscore == std::string::npos || first_underscore == 0)
71     return DatabaseIdentifier();
72 
73   size_t last_underscore = identifier.find_last_of('_');
74   if (last_underscore == std::string::npos ||
75       last_underscore == first_underscore ||
76       last_underscore == identifier.length() - 1)
77     return DatabaseIdentifier();
78 
79   std::string scheme(identifier.data(), first_underscore);
80   if (scheme == "file")
81     return UniqueFileIdentifier();
82 
83   // This magical set of schemes is always treated as unique.
84   if (SchemeIsUnique(scheme))
85     return DatabaseIdentifier();
86 
87   base::StringPiece port_str(identifier.begin() + last_underscore + 1,
88                              identifier.end());
89   int port = 0;
90   if (!base::StringToInt(port_str, &port) || port < 0 || port >= 1 << 16)
91     return DatabaseIdentifier();
92 
93   std::string hostname(identifier.data() + first_underscore + 1,
94                        last_underscore - first_underscore - 1);
95   GURL url(scheme + "://" + hostname + "/");
96 
97   if (!url.IsStandard())
98     hostname = "";
99 
100   // If a url doesn't parse cleanly or doesn't round trip, reject it.
101   if (!url.is_valid() || url.scheme() != scheme || url.host() != hostname)
102     return DatabaseIdentifier();
103 
104   return DatabaseIdentifier(scheme, hostname, port, false /* unique */, false);
105 }
106 
DatabaseIdentifier()107 DatabaseIdentifier::DatabaseIdentifier()
108     : port_(0),
109       is_unique_(true),
110       is_file_(false) {
111 }
112 
DatabaseIdentifier(const std::string & scheme,const std::string & hostname,int port,bool is_unique,bool is_file)113 DatabaseIdentifier::DatabaseIdentifier(const std::string& scheme,
114                                        const std::string& hostname,
115                                        int port,
116                                        bool is_unique,
117                                        bool is_file)
118     : scheme_(scheme),
119       hostname_(StringToLowerASCII(hostname)),
120       port_(port),
121       is_unique_(is_unique),
122       is_file_(is_file) {
123 }
124 
~DatabaseIdentifier()125 DatabaseIdentifier::~DatabaseIdentifier() {}
126 
ToString() const127 std::string DatabaseIdentifier::ToString() const {
128   if (is_file_)
129     return "file__0";
130   if (is_unique_)
131     return "__0";
132   return scheme_ + "_" + hostname_ + "_" + base::IntToString(port_);
133 }
134 
ToOrigin() const135 GURL DatabaseIdentifier::ToOrigin() const {
136   if (is_file_)
137     return GURL("file:///");
138   if (is_unique_)
139     return GURL();
140   if (port_ == 0)
141     return GURL(scheme_ + "://" + hostname_);
142   return GURL(scheme_ + "://" + hostname_ + ":" + base::IntToString(port_));
143 }
144 
145 }  // namespace webkit_database
146