1 // Copyright 2006, Google Inc.
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "gears/base/common/security_model.h"
30 #include "gears/base/common/string_utils.h"
31 #include "gears/localserver/common/http_constants.h"
33 // TODO(mpcomplete): implement these.
34 #if BROWSER_NPAPI && defined(WIN32)
42 #include <gecko_sdk/include/nsIURI.h>
43 #include "gears/base/common/common.h"
44 #include "gears/base/firefox/dom_utils.h"
46 #include "gears/base/safari/browser_utils.h"
47 #include "gears/base/safari/scoped_cf.h"
48 #include "gears/base/safari/string_utils.h"
52 const char16
* kUnknownDomain
= STRING16(L
"_null_.localdomain");
53 const char* kUnknownDomainAscii
= "_null_.localdomain";
55 //------------------------------------------------------------------------------
57 //------------------------------------------------------------------------------
58 bool SecurityOrigin::Init(const char16
*full_url
, const char16
*scheme
,
59 const char16
*host
, int port
) {
60 assert(full_url
&& scheme
&& host
); // file URLs pass 0 for 'port'
61 if (!full_url
[0] || !scheme
[0] || !host
[0])
69 port_string_
= IntegerToString16(port_
);
74 url_
+= STRING16(L
"://");
76 if (!IsDefaultPort(scheme_
, port_
)) {
77 url_
+= STRING16(L
":");
86 //------------------------------------------------------------------------------
88 //------------------------------------------------------------------------------
89 bool SecurityOrigin::InitFromUrl(const char16
*full_url
) {
93 URL_COMPONENTSW components
= {0};
94 components
.dwStructSize
= sizeof(URL_COMPONENTSW
);
95 components
.dwHostNameLength
= 1;
96 components
.dwSchemeLength
= 1;
97 if (!InternetCrackUrlW(full_url
, 0, 0, &components
)) {
101 // Expcilitly disallow urls with embedded username:passwords. These
102 // are disabled by default in IE such that InternetCrackUrl fails.
103 // To have consistent behavior, do the same for all browsers.
104 if (components
.lpszUserName
&& components
.dwUserNameLength
) {
107 switch (components
.nScheme
) {
108 case INTERNET_SCHEME_HTTP
:
109 case INTERNET_SCHEME_HTTPS
: {
110 if (!components
.lpszScheme
|| !components
.lpszHostName
) {
113 std::string16
scheme(components
.lpszScheme
, components
.dwSchemeLength
);
114 std::string16
host(components
.lpszHostName
, components
.dwHostNameLength
);
115 return Init(full_url
, scheme
.c_str(), host
.c_str(), components
.nPort
);
117 case INTERNET_SCHEME_FILE
:
118 return Init(full_url
, HttpConstants::kFileScheme
, kUnknownDomain
, 0);
124 nsCOMPtr
<nsIURI
> url_obj
;
125 if (!DOMUtils::NewAbsoluteURI(full_url
, getter_AddRefs(url_obj
)))
128 // Expcilitly disallow urls with embedded username:passwords. These
129 // are disabled by default in IE such that InternetCrackUrl fails.
130 // To have consistent behavior, do the same for all browsers.
132 url_obj
->GetUsername(user_name
);
133 if (user_name
.Length() > 0)
136 enum SchemeType
{ kSchemeTypeHttp
, kSchemeTypeHttps
, kSchemeTypeFile
};
138 SchemeType scheme_type
;
139 const char16
*scheme
;
140 const char *schemeAscii
;
143 { kSchemeTypeHttp
, HttpConstants::kHttpScheme
,
144 HttpConstants::kHttpSchemeAscii
, HttpConstants::kHttpDefaultPort
},
145 { kSchemeTypeHttps
, HttpConstants::kHttpsScheme
,
146 HttpConstants::kHttpsSchemeAscii
, HttpConstants::kHttpsDefaultPort
},
147 { kSchemeTypeFile
, HttpConstants::kFileScheme
,
148 HttpConstants::kFileSchemeAscii
, HttpConstants::kFileDefaultPort
}
151 PRBool match
= PR_FALSE
;
153 for (; i
< ARRAYSIZE(kSchemes
); ++i
) {
154 nr
= url_obj
->SchemeIs(kSchemes
[i
].schemeAscii
, &match
);
155 if (NS_FAILED(nr
)) { return false; }
159 if (!match
) { return false; }
160 switch (kSchemes
[i
].scheme_type
) {
161 case kSchemeTypeHttp
:
162 case kSchemeTypeHttps
: {
164 nr
= url_obj
->GetHost(utf8
); // or GetAsciiHost to convert using IDNA spec
165 if (NS_FAILED(nr
)) { return false; }
166 std::string16
host(NS_ConvertUTF8toUTF16(utf8
).get());
168 nr
= url_obj
->GetPort(&port
);
169 if (NS_FAILED(nr
)) { return false; }
171 // -1 implies the default port for the scheme
172 port
= kSchemes
[i
].default_port
;
174 return Init(full_url
, kSchemes
[i
].scheme
, host
.c_str(), port
);
176 case kSchemeTypeFile
:
177 return Init(full_url
, HttpConstants::kFileScheme
, kUnknownDomain
, 0);
183 scoped_CFString
url_str(CFStringCreateWithString16(full_url
));
184 scoped_CFURL
url(CFURLCreateWithString(kCFAllocatorDefault
,
185 url_str
.get(), NULL
));
189 // Expcilitly disallow urls with embedded username:passwords.
190 // To have consistent behavior, do the same for all browsers.
191 // CFURLCopyUserName() will return NULL if there is no user name.
192 scoped_CFString
user_name(CFURLCopyUserName(url
.get()));
196 scoped_CFString
scheme_str(CFURLCopyScheme(url
.get()));
197 if (!scheme_str
.get())
200 std::string16 scheme
;
201 CFStringRefToString16(scheme_str
.get(), &scheme
);
204 if (scheme
== HttpConstants::kHttpScheme
||
205 scheme
== HttpConstants::kHttpsScheme
) {
206 scoped_CFString
host_str(CFURLCopyHostName(url
.get()));
208 CFStringRefToString16(host_str
.get(), &host
);
210 // CF's implementation is that if no port is specified, it returns -1
211 // The expectation is that http defaults to 80 and https defaults to 443.
212 int port
= CFURLGetPortNumber(url
.get());
215 if (scheme
== HttpConstants::kHttpsScheme
)
216 port
= HttpConstants::kHttpsDefaultPort
;
218 port
= HttpConstants::kHttpDefaultPort
;
221 return Init(full_url
, scheme
.c_str(), host
.c_str(), port
);
222 } else if (scheme
== HttpConstants::kFileScheme
) {
223 return Init(full_url
, HttpConstants::kFileScheme
, kUnknownDomain
, 0);