Use SecurityOriginData more consistently in Service Worker code
[WebKit-https.git] / Source / WebCore / page / SecurityOriginData.cpp
1 /*
2  * Copyright (C) 2011, 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "SecurityOriginData.h"
28
29 #include "Document.h"
30 #include "FileSystem.h"
31 #include "Frame.h"
32 #include "SecurityOrigin.h"
33 #include <wtf/text/CString.h>
34 #include <wtf/text/StringBuilder.h>
35 #include <wtf/text/StringConcatenateNumbers.h>
36
37 using namespace WebCore;
38
39 namespace WebCore {
40
41 String SecurityOriginData::toString() const
42 {
43     if (protocol == "file")
44         return ASCIILiteral("file://");
45
46     if (!port)
47         return makeString(protocol, "://", host);
48     return makeString(protocol, "://", host, ':', static_cast<uint32_t>(*port));
49 }
50
51 SecurityOriginData SecurityOriginData::fromFrame(Frame* frame)
52 {
53     if (!frame)
54         return SecurityOriginData { };
55     
56     auto* document = frame->document();
57     if (!document)
58         return SecurityOriginData { };
59
60     return document->securityOrigin().data();
61 }
62
63 Ref<SecurityOrigin> SecurityOriginData::securityOrigin() const
64 {
65     return SecurityOrigin::create(protocol.isolatedCopy(), host.isolatedCopy(), port);
66 }
67
68 static const char separatorCharacter = '_';
69
70 String SecurityOriginData::databaseIdentifier() const
71 {
72     // Historically, we've used the following (somewhat non-sensical) string
73     // for the databaseIdentifier of local files. We used to compute this
74     // string because of a bug in how we handled the scheme for file URLs.
75     // Now that we've fixed that bug, we still need to produce this string
76     // to avoid breaking existing persistent state.
77     if (equalIgnoringASCIICase(protocol, "file"))
78         return ASCIILiteral("file__0");
79     
80     StringBuilder stringBuilder;
81     stringBuilder.append(protocol);
82     stringBuilder.append(separatorCharacter);
83     stringBuilder.append(FileSystem::encodeForFileName(host));
84     stringBuilder.append(separatorCharacter);
85     stringBuilder.appendNumber(port.value_or(0));
86     
87     return stringBuilder.toString();
88 }
89
90 std::optional<SecurityOriginData> SecurityOriginData::fromDatabaseIdentifier(const String& databaseIdentifier)
91 {
92     // Make sure there's a first separator
93     size_t separator1 = databaseIdentifier.find(separatorCharacter);
94     if (separator1 == notFound)
95         return std::nullopt;
96     
97     // Make sure there's a second separator
98     size_t separator2 = databaseIdentifier.reverseFind(separatorCharacter);
99     if (separator2 == notFound)
100         return std::nullopt;
101     
102     // Ensure there were at least 2 separator characters. Some hostnames on intranets have
103     // underscores in them, so we'll assume that any additional underscores are part of the host.
104     if (separator1 == separator2)
105         return std::nullopt;
106     
107     // Make sure the port section is a valid port number or doesn't exist
108     bool portOkay;
109     int port = databaseIdentifier.right(databaseIdentifier.length() - separator2 - 1).toInt(&portOkay);
110     bool portAbsent = (separator2 == databaseIdentifier.length() - 1);
111     if (!(portOkay || portAbsent))
112         return std::nullopt;
113     
114     if (port < 0 || port > std::numeric_limits<uint16_t>::max())
115         return std::nullopt;
116     
117     return SecurityOriginData {databaseIdentifier.substring(0, separator1), databaseIdentifier.substring(separator1 + 1, separator2 - separator1 - 1), static_cast<uint16_t>(port)};
118 }
119
120 SecurityOriginData SecurityOriginData::isolatedCopy() const
121 {
122     SecurityOriginData result;
123
124     result.protocol = protocol.isolatedCopy();
125     result.host = host.isolatedCopy();
126     result.port = port;
127
128     return result;
129 }
130
131 bool operator==(const SecurityOriginData& a, const SecurityOriginData& b)
132 {
133     if (&a == &b)
134         return true;
135
136     return a.protocol == b.protocol
137         && a.host == b.host
138         && a.port == b.port;
139 }
140
141 } // namespace WebCore