Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim: set sw=2 ts=8 et tw=80 : */ |
michael@0 | 3 | |
michael@0 | 4 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 7 | |
michael@0 | 8 | #include "necko-config.h" |
michael@0 | 9 | #include "nsHttp.h" |
michael@0 | 10 | #include "mozilla/net/NeckoParent.h" |
michael@0 | 11 | #include "mozilla/net/HttpChannelParent.h" |
michael@0 | 12 | #include "mozilla/net/CookieServiceParent.h" |
michael@0 | 13 | #include "mozilla/net/WyciwygChannelParent.h" |
michael@0 | 14 | #include "mozilla/net/FTPChannelParent.h" |
michael@0 | 15 | #include "mozilla/net/WebSocketChannelParent.h" |
michael@0 | 16 | #ifdef NECKO_PROTOCOL_rtsp |
michael@0 | 17 | #include "mozilla/net/RtspControllerParent.h" |
michael@0 | 18 | #include "mozilla/net/RtspChannelParent.h" |
michael@0 | 19 | #endif |
michael@0 | 20 | #include "mozilla/net/DNSRequestParent.h" |
michael@0 | 21 | #include "mozilla/net/RemoteOpenFileParent.h" |
michael@0 | 22 | #include "mozilla/net/ChannelDiverterParent.h" |
michael@0 | 23 | #include "mozilla/dom/ContentParent.h" |
michael@0 | 24 | #include "mozilla/dom/TabParent.h" |
michael@0 | 25 | #include "mozilla/dom/network/TCPSocketParent.h" |
michael@0 | 26 | #include "mozilla/dom/network/TCPServerSocketParent.h" |
michael@0 | 27 | #include "mozilla/dom/network/UDPSocketParent.h" |
michael@0 | 28 | #include "mozilla/ipc/URIUtils.h" |
michael@0 | 29 | #include "mozilla/LoadContext.h" |
michael@0 | 30 | #include "mozilla/AppProcessChecker.h" |
michael@0 | 31 | #include "nsPrintfCString.h" |
michael@0 | 32 | #include "nsHTMLDNSPrefetch.h" |
michael@0 | 33 | #include "nsIAppsService.h" |
michael@0 | 34 | #include "nsIUDPSocketFilter.h" |
michael@0 | 35 | #include "nsEscape.h" |
michael@0 | 36 | #include "RemoteOpenFileParent.h" |
michael@0 | 37 | #include "SerializedLoadContext.h" |
michael@0 | 38 | |
michael@0 | 39 | using mozilla::dom::ContentParent; |
michael@0 | 40 | using mozilla::dom::TabParent; |
michael@0 | 41 | using mozilla::net::PTCPSocketParent; |
michael@0 | 42 | using mozilla::dom::TCPSocketParent; |
michael@0 | 43 | using mozilla::net::PTCPServerSocketParent; |
michael@0 | 44 | using mozilla::dom::TCPServerSocketParent; |
michael@0 | 45 | using mozilla::net::PUDPSocketParent; |
michael@0 | 46 | using mozilla::dom::UDPSocketParent; |
michael@0 | 47 | using IPC::SerializedLoadContext; |
michael@0 | 48 | |
michael@0 | 49 | namespace mozilla { |
michael@0 | 50 | namespace net { |
michael@0 | 51 | |
michael@0 | 52 | // C++ file contents |
michael@0 | 53 | NeckoParent::NeckoParent() |
michael@0 | 54 | { |
michael@0 | 55 | // Init HTTP protocol handler now since we need atomTable up and running very |
michael@0 | 56 | // early (IPDL argument handling for PHttpChannel constructor needs it) so |
michael@0 | 57 | // normal init (during 1st Http channel request) isn't early enough. |
michael@0 | 58 | nsCOMPtr<nsIProtocolHandler> proto = |
michael@0 | 59 | do_GetService("@mozilla.org/network/protocol;1?name=http"); |
michael@0 | 60 | |
michael@0 | 61 | if (UsingNeckoIPCSecurity()) { |
michael@0 | 62 | // cache values for core/packaged apps basepaths |
michael@0 | 63 | nsAutoString corePath, webPath; |
michael@0 | 64 | nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID); |
michael@0 | 65 | if (appsService) { |
michael@0 | 66 | appsService->GetCoreAppsBasePath(corePath); |
michael@0 | 67 | appsService->GetWebAppsBasePath(webPath); |
michael@0 | 68 | } |
michael@0 | 69 | // corePath may be empty: we don't use it for all build types |
michael@0 | 70 | MOZ_ASSERT(!webPath.IsEmpty()); |
michael@0 | 71 | |
michael@0 | 72 | LossyCopyUTF16toASCII(corePath, mCoreAppsBasePath); |
michael@0 | 73 | LossyCopyUTF16toASCII(webPath, mWebAppsBasePath); |
michael@0 | 74 | } |
michael@0 | 75 | } |
michael@0 | 76 | |
michael@0 | 77 | NeckoParent::~NeckoParent() |
michael@0 | 78 | { |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | static PBOverrideStatus |
michael@0 | 82 | PBOverrideStatusFromLoadContext(const SerializedLoadContext& aSerialized) |
michael@0 | 83 | { |
michael@0 | 84 | if (!aSerialized.IsNotNull() && aSerialized.IsPrivateBitValid()) { |
michael@0 | 85 | return aSerialized.mUsePrivateBrowsing ? |
michael@0 | 86 | kPBOverride_Private : |
michael@0 | 87 | kPBOverride_NotPrivate; |
michael@0 | 88 | } |
michael@0 | 89 | return kPBOverride_Unset; |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | const char* |
michael@0 | 93 | NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized, |
michael@0 | 94 | PContentParent* aContent, |
michael@0 | 95 | uint32_t* aAppId, |
michael@0 | 96 | bool* aInBrowserElement) |
michael@0 | 97 | { |
michael@0 | 98 | *aAppId = NECKO_UNKNOWN_APP_ID; |
michael@0 | 99 | *aInBrowserElement = false; |
michael@0 | 100 | |
michael@0 | 101 | if (UsingNeckoIPCSecurity()) { |
michael@0 | 102 | if (!aSerialized.IsNotNull()) { |
michael@0 | 103 | return "SerializedLoadContext from child is null"; |
michael@0 | 104 | } |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | const InfallibleTArray<PBrowserParent*>& browsers = aContent->ManagedPBrowserParent(); |
michael@0 | 108 | for (uint32_t i = 0; i < browsers.Length(); i++) { |
michael@0 | 109 | nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(browsers[i]); |
michael@0 | 110 | uint32_t appId = tabParent->OwnOrContainingAppId(); |
michael@0 | 111 | bool inBrowserElement = aSerialized.IsNotNull() ? aSerialized.mIsInBrowserElement |
michael@0 | 112 | : tabParent->IsBrowserElement(); |
michael@0 | 113 | |
michael@0 | 114 | if (appId == NECKO_UNKNOWN_APP_ID) { |
michael@0 | 115 | continue; |
michael@0 | 116 | } |
michael@0 | 117 | // We may get appID=NO_APP if child frame is neither a browser nor an app |
michael@0 | 118 | if (appId == NECKO_NO_APP_ID) { |
michael@0 | 119 | if (tabParent->HasOwnApp()) { |
michael@0 | 120 | continue; |
michael@0 | 121 | } |
michael@0 | 122 | if (UsingNeckoIPCSecurity() && tabParent->IsBrowserElement()) { |
michael@0 | 123 | // <iframe mozbrowser> which doesn't have an <iframe mozapp> above it. |
michael@0 | 124 | // This is not supported now, and we'll need to do a code audit to make |
michael@0 | 125 | // sure we can handle it (i.e don't short-circuit using separate |
michael@0 | 126 | // namespace if just appID==0) |
michael@0 | 127 | continue; |
michael@0 | 128 | } |
michael@0 | 129 | } |
michael@0 | 130 | *aAppId = appId; |
michael@0 | 131 | *aInBrowserElement = inBrowserElement; |
michael@0 | 132 | return nullptr; |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | if (browsers.Length() != 0) { |
michael@0 | 136 | return "App does not have permission"; |
michael@0 | 137 | } |
michael@0 | 138 | |
michael@0 | 139 | if (!UsingNeckoIPCSecurity()) { |
michael@0 | 140 | // We are running xpcshell tests |
michael@0 | 141 | if (aSerialized.IsNotNull()) { |
michael@0 | 142 | *aAppId = aSerialized.mAppId; |
michael@0 | 143 | *aInBrowserElement = aSerialized.mIsInBrowserElement; |
michael@0 | 144 | } else { |
michael@0 | 145 | *aAppId = NECKO_NO_APP_ID; |
michael@0 | 146 | } |
michael@0 | 147 | return nullptr; |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | return "ContentParent does not have any PBrowsers"; |
michael@0 | 151 | } |
michael@0 | 152 | |
michael@0 | 153 | const char * |
michael@0 | 154 | NeckoParent::CreateChannelLoadContext(PBrowserParent* aBrowser, |
michael@0 | 155 | PContentParent* aContent, |
michael@0 | 156 | const SerializedLoadContext& aSerialized, |
michael@0 | 157 | nsCOMPtr<nsILoadContext> &aResult) |
michael@0 | 158 | { |
michael@0 | 159 | uint32_t appId = NECKO_UNKNOWN_APP_ID; |
michael@0 | 160 | bool inBrowser = false; |
michael@0 | 161 | dom::Element* topFrameElement = nullptr; |
michael@0 | 162 | const char* error = GetValidatedAppInfo(aSerialized, aContent, &appId, &inBrowser); |
michael@0 | 163 | if (error) { |
michael@0 | 164 | return error; |
michael@0 | 165 | } |
michael@0 | 166 | |
michael@0 | 167 | if (aBrowser) { |
michael@0 | 168 | nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(aBrowser); |
michael@0 | 169 | topFrameElement = tabParent->GetOwnerElement(); |
michael@0 | 170 | } |
michael@0 | 171 | |
michael@0 | 172 | // if !UsingNeckoIPCSecurity(), we may not have a LoadContext to set. This is |
michael@0 | 173 | // the common case for most xpcshell tests. |
michael@0 | 174 | if (aSerialized.IsNotNull()) { |
michael@0 | 175 | aResult = new LoadContext(aSerialized, topFrameElement, appId, inBrowser); |
michael@0 | 176 | } |
michael@0 | 177 | |
michael@0 | 178 | return nullptr; |
michael@0 | 179 | } |
michael@0 | 180 | |
michael@0 | 181 | PHttpChannelParent* |
michael@0 | 182 | NeckoParent::AllocPHttpChannelParent(PBrowserParent* aBrowser, |
michael@0 | 183 | const SerializedLoadContext& aSerialized, |
michael@0 | 184 | const HttpChannelCreationArgs& aOpenArgs) |
michael@0 | 185 | { |
michael@0 | 186 | nsCOMPtr<nsILoadContext> loadContext; |
michael@0 | 187 | const char *error = CreateChannelLoadContext(aBrowser, Manager(), |
michael@0 | 188 | aSerialized, loadContext); |
michael@0 | 189 | if (error) { |
michael@0 | 190 | printf_stderr("NeckoParent::AllocPHttpChannelParent: " |
michael@0 | 191 | "FATAL error: %s: KILLING CHILD PROCESS\n", |
michael@0 | 192 | error); |
michael@0 | 193 | return nullptr; |
michael@0 | 194 | } |
michael@0 | 195 | PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(aSerialized); |
michael@0 | 196 | HttpChannelParent *p = new HttpChannelParent(aBrowser, loadContext, overrideStatus); |
michael@0 | 197 | p->AddRef(); |
michael@0 | 198 | return p; |
michael@0 | 199 | } |
michael@0 | 200 | |
michael@0 | 201 | bool |
michael@0 | 202 | NeckoParent::DeallocPHttpChannelParent(PHttpChannelParent* channel) |
michael@0 | 203 | { |
michael@0 | 204 | HttpChannelParent *p = static_cast<HttpChannelParent *>(channel); |
michael@0 | 205 | p->Release(); |
michael@0 | 206 | return true; |
michael@0 | 207 | } |
michael@0 | 208 | |
michael@0 | 209 | bool |
michael@0 | 210 | NeckoParent::RecvPHttpChannelConstructor( |
michael@0 | 211 | PHttpChannelParent* aActor, |
michael@0 | 212 | PBrowserParent* aBrowser, |
michael@0 | 213 | const SerializedLoadContext& aSerialized, |
michael@0 | 214 | const HttpChannelCreationArgs& aOpenArgs) |
michael@0 | 215 | { |
michael@0 | 216 | HttpChannelParent* p = static_cast<HttpChannelParent*>(aActor); |
michael@0 | 217 | return p->Init(aOpenArgs); |
michael@0 | 218 | } |
michael@0 | 219 | |
michael@0 | 220 | PFTPChannelParent* |
michael@0 | 221 | NeckoParent::AllocPFTPChannelParent(PBrowserParent* aBrowser, |
michael@0 | 222 | const SerializedLoadContext& aSerialized, |
michael@0 | 223 | const FTPChannelCreationArgs& aOpenArgs) |
michael@0 | 224 | { |
michael@0 | 225 | nsCOMPtr<nsILoadContext> loadContext; |
michael@0 | 226 | const char *error = CreateChannelLoadContext(aBrowser, Manager(), |
michael@0 | 227 | aSerialized, loadContext); |
michael@0 | 228 | if (error) { |
michael@0 | 229 | printf_stderr("NeckoParent::AllocPFTPChannelParent: " |
michael@0 | 230 | "FATAL error: %s: KILLING CHILD PROCESS\n", |
michael@0 | 231 | error); |
michael@0 | 232 | return nullptr; |
michael@0 | 233 | } |
michael@0 | 234 | PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(aSerialized); |
michael@0 | 235 | FTPChannelParent *p = new FTPChannelParent(loadContext, overrideStatus); |
michael@0 | 236 | p->AddRef(); |
michael@0 | 237 | return p; |
michael@0 | 238 | } |
michael@0 | 239 | |
michael@0 | 240 | bool |
michael@0 | 241 | NeckoParent::DeallocPFTPChannelParent(PFTPChannelParent* channel) |
michael@0 | 242 | { |
michael@0 | 243 | FTPChannelParent *p = static_cast<FTPChannelParent *>(channel); |
michael@0 | 244 | p->Release(); |
michael@0 | 245 | return true; |
michael@0 | 246 | } |
michael@0 | 247 | |
michael@0 | 248 | bool |
michael@0 | 249 | NeckoParent::RecvPFTPChannelConstructor( |
michael@0 | 250 | PFTPChannelParent* aActor, |
michael@0 | 251 | PBrowserParent* aBrowser, |
michael@0 | 252 | const SerializedLoadContext& aSerialized, |
michael@0 | 253 | const FTPChannelCreationArgs& aOpenArgs) |
michael@0 | 254 | { |
michael@0 | 255 | FTPChannelParent* p = static_cast<FTPChannelParent*>(aActor); |
michael@0 | 256 | return p->Init(aOpenArgs); |
michael@0 | 257 | } |
michael@0 | 258 | |
michael@0 | 259 | PCookieServiceParent* |
michael@0 | 260 | NeckoParent::AllocPCookieServiceParent() |
michael@0 | 261 | { |
michael@0 | 262 | return new CookieServiceParent(); |
michael@0 | 263 | } |
michael@0 | 264 | |
michael@0 | 265 | bool |
michael@0 | 266 | NeckoParent::DeallocPCookieServiceParent(PCookieServiceParent* cs) |
michael@0 | 267 | { |
michael@0 | 268 | delete cs; |
michael@0 | 269 | return true; |
michael@0 | 270 | } |
michael@0 | 271 | |
michael@0 | 272 | PWyciwygChannelParent* |
michael@0 | 273 | NeckoParent::AllocPWyciwygChannelParent() |
michael@0 | 274 | { |
michael@0 | 275 | WyciwygChannelParent *p = new WyciwygChannelParent(); |
michael@0 | 276 | p->AddRef(); |
michael@0 | 277 | return p; |
michael@0 | 278 | } |
michael@0 | 279 | |
michael@0 | 280 | bool |
michael@0 | 281 | NeckoParent::DeallocPWyciwygChannelParent(PWyciwygChannelParent* channel) |
michael@0 | 282 | { |
michael@0 | 283 | WyciwygChannelParent *p = static_cast<WyciwygChannelParent *>(channel); |
michael@0 | 284 | p->Release(); |
michael@0 | 285 | return true; |
michael@0 | 286 | } |
michael@0 | 287 | |
michael@0 | 288 | PWebSocketParent* |
michael@0 | 289 | NeckoParent::AllocPWebSocketParent(PBrowserParent* browser, |
michael@0 | 290 | const SerializedLoadContext& serialized) |
michael@0 | 291 | { |
michael@0 | 292 | nsCOMPtr<nsILoadContext> loadContext; |
michael@0 | 293 | const char *error = CreateChannelLoadContext(browser, Manager(), |
michael@0 | 294 | serialized, loadContext); |
michael@0 | 295 | if (error) { |
michael@0 | 296 | printf_stderr("NeckoParent::AllocPWebSocketParent: " |
michael@0 | 297 | "FATAL error: %s: KILLING CHILD PROCESS\n", |
michael@0 | 298 | error); |
michael@0 | 299 | return nullptr; |
michael@0 | 300 | } |
michael@0 | 301 | |
michael@0 | 302 | TabParent* tabParent = static_cast<TabParent*>(browser); |
michael@0 | 303 | PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(serialized); |
michael@0 | 304 | WebSocketChannelParent* p = new WebSocketChannelParent(tabParent, loadContext, |
michael@0 | 305 | overrideStatus); |
michael@0 | 306 | p->AddRef(); |
michael@0 | 307 | return p; |
michael@0 | 308 | } |
michael@0 | 309 | |
michael@0 | 310 | bool |
michael@0 | 311 | NeckoParent::DeallocPWebSocketParent(PWebSocketParent* actor) |
michael@0 | 312 | { |
michael@0 | 313 | WebSocketChannelParent* p = static_cast<WebSocketChannelParent*>(actor); |
michael@0 | 314 | p->Release(); |
michael@0 | 315 | return true; |
michael@0 | 316 | } |
michael@0 | 317 | |
michael@0 | 318 | PRtspControllerParent* |
michael@0 | 319 | NeckoParent::AllocPRtspControllerParent() |
michael@0 | 320 | { |
michael@0 | 321 | #ifdef NECKO_PROTOCOL_rtsp |
michael@0 | 322 | RtspControllerParent* p = new RtspControllerParent(); |
michael@0 | 323 | p->AddRef(); |
michael@0 | 324 | return p; |
michael@0 | 325 | #else |
michael@0 | 326 | return nullptr; |
michael@0 | 327 | #endif |
michael@0 | 328 | } |
michael@0 | 329 | |
michael@0 | 330 | bool |
michael@0 | 331 | NeckoParent::DeallocPRtspControllerParent(PRtspControllerParent* actor) |
michael@0 | 332 | { |
michael@0 | 333 | #ifdef NECKO_PROTOCOL_rtsp |
michael@0 | 334 | RtspControllerParent* p = static_cast<RtspControllerParent*>(actor); |
michael@0 | 335 | p->Release(); |
michael@0 | 336 | #endif |
michael@0 | 337 | return true; |
michael@0 | 338 | } |
michael@0 | 339 | |
michael@0 | 340 | PRtspChannelParent* |
michael@0 | 341 | NeckoParent::AllocPRtspChannelParent(const RtspChannelConnectArgs& aArgs) |
michael@0 | 342 | { |
michael@0 | 343 | #ifdef NECKO_PROTOCOL_rtsp |
michael@0 | 344 | nsCOMPtr<nsIURI> uri = DeserializeURI(aArgs.uri()); |
michael@0 | 345 | RtspChannelParent *p = new RtspChannelParent(uri); |
michael@0 | 346 | p->AddRef(); |
michael@0 | 347 | return p; |
michael@0 | 348 | #else |
michael@0 | 349 | return nullptr; |
michael@0 | 350 | #endif |
michael@0 | 351 | } |
michael@0 | 352 | |
michael@0 | 353 | bool |
michael@0 | 354 | NeckoParent::RecvPRtspChannelConstructor( |
michael@0 | 355 | PRtspChannelParent* aActor, |
michael@0 | 356 | const RtspChannelConnectArgs& aConnectArgs) |
michael@0 | 357 | { |
michael@0 | 358 | #ifdef NECKO_PROTOCOL_rtsp |
michael@0 | 359 | RtspChannelParent* p = static_cast<RtspChannelParent*>(aActor); |
michael@0 | 360 | return p->Init(aConnectArgs); |
michael@0 | 361 | #else |
michael@0 | 362 | return nullptr; |
michael@0 | 363 | #endif |
michael@0 | 364 | } |
michael@0 | 365 | |
michael@0 | 366 | bool |
michael@0 | 367 | NeckoParent::DeallocPRtspChannelParent(PRtspChannelParent* actor) |
michael@0 | 368 | { |
michael@0 | 369 | #ifdef NECKO_PROTOCOL_rtsp |
michael@0 | 370 | RtspChannelParent* p = static_cast<RtspChannelParent*>(actor); |
michael@0 | 371 | p->Release(); |
michael@0 | 372 | #endif |
michael@0 | 373 | return true; |
michael@0 | 374 | } |
michael@0 | 375 | |
michael@0 | 376 | PTCPSocketParent* |
michael@0 | 377 | NeckoParent::AllocPTCPSocketParent() |
michael@0 | 378 | { |
michael@0 | 379 | TCPSocketParent* p = new TCPSocketParent(); |
michael@0 | 380 | p->AddIPDLReference(); |
michael@0 | 381 | return p; |
michael@0 | 382 | } |
michael@0 | 383 | |
michael@0 | 384 | bool |
michael@0 | 385 | NeckoParent::DeallocPTCPSocketParent(PTCPSocketParent* actor) |
michael@0 | 386 | { |
michael@0 | 387 | TCPSocketParent* p = static_cast<TCPSocketParent*>(actor); |
michael@0 | 388 | p->ReleaseIPDLReference(); |
michael@0 | 389 | return true; |
michael@0 | 390 | } |
michael@0 | 391 | |
michael@0 | 392 | PTCPServerSocketParent* |
michael@0 | 393 | NeckoParent::AllocPTCPServerSocketParent(const uint16_t& aLocalPort, |
michael@0 | 394 | const uint16_t& aBacklog, |
michael@0 | 395 | const nsString& aBinaryType) |
michael@0 | 396 | { |
michael@0 | 397 | TCPServerSocketParent* p = new TCPServerSocketParent(); |
michael@0 | 398 | p->AddIPDLReference(); |
michael@0 | 399 | return p; |
michael@0 | 400 | } |
michael@0 | 401 | |
michael@0 | 402 | bool |
michael@0 | 403 | NeckoParent::RecvPTCPServerSocketConstructor(PTCPServerSocketParent* aActor, |
michael@0 | 404 | const uint16_t& aLocalPort, |
michael@0 | 405 | const uint16_t& aBacklog, |
michael@0 | 406 | const nsString& aBinaryType) |
michael@0 | 407 | { |
michael@0 | 408 | return static_cast<TCPServerSocketParent*>(aActor)-> |
michael@0 | 409 | Init(this, aLocalPort, aBacklog, aBinaryType); |
michael@0 | 410 | } |
michael@0 | 411 | |
michael@0 | 412 | bool |
michael@0 | 413 | NeckoParent::DeallocPTCPServerSocketParent(PTCPServerSocketParent* actor) |
michael@0 | 414 | { |
michael@0 | 415 | TCPServerSocketParent* p = static_cast<TCPServerSocketParent*>(actor); |
michael@0 | 416 | p->ReleaseIPDLReference(); |
michael@0 | 417 | return true; |
michael@0 | 418 | } |
michael@0 | 419 | |
michael@0 | 420 | PUDPSocketParent* |
michael@0 | 421 | NeckoParent::AllocPUDPSocketParent(const nsCString& aHost, |
michael@0 | 422 | const uint16_t& aPort, |
michael@0 | 423 | const nsCString& aFilter) |
michael@0 | 424 | { |
michael@0 | 425 | UDPSocketParent* p = nullptr; |
michael@0 | 426 | |
michael@0 | 427 | // Only allow socket if it specifies a valid packet filter. |
michael@0 | 428 | nsAutoCString contractId(NS_NETWORK_UDP_SOCKET_FILTER_HANDLER_PREFIX); |
michael@0 | 429 | contractId.Append(aFilter); |
michael@0 | 430 | |
michael@0 | 431 | if (!aFilter.IsEmpty()) { |
michael@0 | 432 | nsCOMPtr<nsIUDPSocketFilterHandler> filterHandler = |
michael@0 | 433 | do_GetService(contractId.get()); |
michael@0 | 434 | if (filterHandler) { |
michael@0 | 435 | nsCOMPtr<nsIUDPSocketFilter> filter; |
michael@0 | 436 | nsresult rv = filterHandler->NewFilter(getter_AddRefs(filter)); |
michael@0 | 437 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 438 | p = new UDPSocketParent(filter); |
michael@0 | 439 | } else { |
michael@0 | 440 | printf_stderr("Cannot create filter that content specified. " |
michael@0 | 441 | "filter name: %s, error code: %d.", aFilter.get(), rv); |
michael@0 | 442 | } |
michael@0 | 443 | } else { |
michael@0 | 444 | printf_stderr("Content doesn't have a valid filter. " |
michael@0 | 445 | "filter name: %s.", aFilter.get()); |
michael@0 | 446 | } |
michael@0 | 447 | } |
michael@0 | 448 | |
michael@0 | 449 | NS_IF_ADDREF(p); |
michael@0 | 450 | return p; |
michael@0 | 451 | } |
michael@0 | 452 | |
michael@0 | 453 | bool |
michael@0 | 454 | NeckoParent::RecvPUDPSocketConstructor(PUDPSocketParent* aActor, |
michael@0 | 455 | const nsCString& aHost, |
michael@0 | 456 | const uint16_t& aPort, |
michael@0 | 457 | const nsCString& aFilter) |
michael@0 | 458 | { |
michael@0 | 459 | return static_cast<UDPSocketParent*>(aActor)->Init(aHost, aPort); |
michael@0 | 460 | } |
michael@0 | 461 | |
michael@0 | 462 | bool |
michael@0 | 463 | NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor) |
michael@0 | 464 | { |
michael@0 | 465 | UDPSocketParent* p = static_cast<UDPSocketParent*>(actor); |
michael@0 | 466 | p->Release(); |
michael@0 | 467 | return true; |
michael@0 | 468 | } |
michael@0 | 469 | |
michael@0 | 470 | PDNSRequestParent* |
michael@0 | 471 | NeckoParent::AllocPDNSRequestParent(const nsCString& aHost, |
michael@0 | 472 | const uint32_t& aFlags) |
michael@0 | 473 | { |
michael@0 | 474 | DNSRequestParent *p = new DNSRequestParent(); |
michael@0 | 475 | p->AddRef(); |
michael@0 | 476 | return p; |
michael@0 | 477 | } |
michael@0 | 478 | |
michael@0 | 479 | bool |
michael@0 | 480 | NeckoParent::RecvPDNSRequestConstructor(PDNSRequestParent* aActor, |
michael@0 | 481 | const nsCString& aHost, |
michael@0 | 482 | const uint32_t& aFlags) |
michael@0 | 483 | { |
michael@0 | 484 | static_cast<DNSRequestParent*>(aActor)->DoAsyncResolve(aHost, aFlags); |
michael@0 | 485 | return true; |
michael@0 | 486 | } |
michael@0 | 487 | |
michael@0 | 488 | bool |
michael@0 | 489 | NeckoParent::DeallocPDNSRequestParent(PDNSRequestParent* aParent) |
michael@0 | 490 | { |
michael@0 | 491 | DNSRequestParent *p = static_cast<DNSRequestParent*>(aParent); |
michael@0 | 492 | p->Release(); |
michael@0 | 493 | return true; |
michael@0 | 494 | } |
michael@0 | 495 | |
michael@0 | 496 | PRemoteOpenFileParent* |
michael@0 | 497 | NeckoParent::AllocPRemoteOpenFileParent(const URIParams& aURI, |
michael@0 | 498 | const OptionalURIParams& aAppURI) |
michael@0 | 499 | { |
michael@0 | 500 | nsCOMPtr<nsIURI> uri = DeserializeURI(aURI); |
michael@0 | 501 | nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(uri); |
michael@0 | 502 | if (!fileURL) { |
michael@0 | 503 | return nullptr; |
michael@0 | 504 | } |
michael@0 | 505 | |
michael@0 | 506 | // security checks |
michael@0 | 507 | if (UsingNeckoIPCSecurity()) { |
michael@0 | 508 | nsCOMPtr<nsIAppsService> appsService = |
michael@0 | 509 | do_GetService(APPS_SERVICE_CONTRACTID); |
michael@0 | 510 | if (!appsService) { |
michael@0 | 511 | return nullptr; |
michael@0 | 512 | } |
michael@0 | 513 | bool haveValidBrowser = false; |
michael@0 | 514 | bool hasManage = false; |
michael@0 | 515 | nsCOMPtr<mozIApplication> mozApp; |
michael@0 | 516 | for (uint32_t i = 0; i < Manager()->ManagedPBrowserParent().Length(); i++) { |
michael@0 | 517 | nsRefPtr<TabParent> tabParent = |
michael@0 | 518 | static_cast<TabParent*>(Manager()->ManagedPBrowserParent()[i]); |
michael@0 | 519 | uint32_t appId = tabParent->OwnOrContainingAppId(); |
michael@0 | 520 | nsresult rv = appsService->GetAppByLocalId(appId, getter_AddRefs(mozApp)); |
michael@0 | 521 | if (NS_FAILED(rv) || !mozApp) { |
michael@0 | 522 | continue; |
michael@0 | 523 | } |
michael@0 | 524 | hasManage = false; |
michael@0 | 525 | rv = mozApp->HasPermission("webapps-manage", &hasManage); |
michael@0 | 526 | if (NS_FAILED(rv)) { |
michael@0 | 527 | continue; |
michael@0 | 528 | } |
michael@0 | 529 | haveValidBrowser = true; |
michael@0 | 530 | break; |
michael@0 | 531 | } |
michael@0 | 532 | |
michael@0 | 533 | if (!haveValidBrowser) { |
michael@0 | 534 | return nullptr; |
michael@0 | 535 | } |
michael@0 | 536 | |
michael@0 | 537 | nsAutoCString requestedPath; |
michael@0 | 538 | fileURL->GetPath(requestedPath); |
michael@0 | 539 | NS_UnescapeURL(requestedPath); |
michael@0 | 540 | |
michael@0 | 541 | // Check if we load the whitelisted app uri for the neterror page. |
michael@0 | 542 | bool netErrorWhiteList = false; |
michael@0 | 543 | |
michael@0 | 544 | nsCOMPtr<nsIURI> appUri = DeserializeURI(aAppURI); |
michael@0 | 545 | if (appUri) { |
michael@0 | 546 | nsAdoptingString netErrorURI; |
michael@0 | 547 | netErrorURI = Preferences::GetString("b2g.neterror.url"); |
michael@0 | 548 | if (netErrorURI) { |
michael@0 | 549 | nsAutoCString spec; |
michael@0 | 550 | appUri->GetSpec(spec); |
michael@0 | 551 | netErrorWhiteList = spec.Equals(NS_ConvertUTF16toUTF8(netErrorURI).get()); |
michael@0 | 552 | } |
michael@0 | 553 | } |
michael@0 | 554 | |
michael@0 | 555 | if (hasManage || netErrorWhiteList) { |
michael@0 | 556 | // webapps-manage permission means allow reading any application.zip file |
michael@0 | 557 | // in either the regular webapps directory, or the core apps directory (if |
michael@0 | 558 | // we're using one). |
michael@0 | 559 | NS_NAMED_LITERAL_CSTRING(appzip, "/application.zip"); |
michael@0 | 560 | nsAutoCString pathEnd; |
michael@0 | 561 | requestedPath.Right(pathEnd, appzip.Length()); |
michael@0 | 562 | if (!pathEnd.Equals(appzip)) { |
michael@0 | 563 | return nullptr; |
michael@0 | 564 | } |
michael@0 | 565 | nsAutoCString pathStart; |
michael@0 | 566 | requestedPath.Left(pathStart, mWebAppsBasePath.Length()); |
michael@0 | 567 | if (!pathStart.Equals(mWebAppsBasePath)) { |
michael@0 | 568 | if (mCoreAppsBasePath.IsEmpty()) { |
michael@0 | 569 | return nullptr; |
michael@0 | 570 | } |
michael@0 | 571 | requestedPath.Left(pathStart, mCoreAppsBasePath.Length()); |
michael@0 | 572 | if (!pathStart.Equals(mCoreAppsBasePath)) { |
michael@0 | 573 | return nullptr; |
michael@0 | 574 | } |
michael@0 | 575 | } |
michael@0 | 576 | // Finally: make sure there are no "../" in URI. |
michael@0 | 577 | // Note: not checking for symlinks (would cause I/O for each path |
michael@0 | 578 | // component). So it's up to us to avoid creating symlinks that could |
michael@0 | 579 | // provide attack vectors. |
michael@0 | 580 | if (PL_strnstr(requestedPath.BeginReading(), "/../", |
michael@0 | 581 | requestedPath.Length())) { |
michael@0 | 582 | printf_stderr("NeckoParent::AllocPRemoteOpenFile: " |
michael@0 | 583 | "FATAL error: requested file URI '%s' contains '/../' " |
michael@0 | 584 | "KILLING CHILD PROCESS\n", requestedPath.get()); |
michael@0 | 585 | return nullptr; |
michael@0 | 586 | } |
michael@0 | 587 | } else { |
michael@0 | 588 | // regular packaged apps can only access their own application.zip file |
michael@0 | 589 | nsAutoString basePath; |
michael@0 | 590 | nsresult rv = mozApp->GetBasePath(basePath); |
michael@0 | 591 | if (NS_FAILED(rv)) { |
michael@0 | 592 | return nullptr; |
michael@0 | 593 | } |
michael@0 | 594 | nsAutoString uuid; |
michael@0 | 595 | rv = mozApp->GetId(uuid); |
michael@0 | 596 | if (NS_FAILED(rv)) { |
michael@0 | 597 | return nullptr; |
michael@0 | 598 | } |
michael@0 | 599 | nsPrintfCString mustMatch("%s/%s/application.zip", |
michael@0 | 600 | NS_LossyConvertUTF16toASCII(basePath).get(), |
michael@0 | 601 | NS_LossyConvertUTF16toASCII(uuid).get()); |
michael@0 | 602 | if (!requestedPath.Equals(mustMatch)) { |
michael@0 | 603 | printf_stderr("NeckoParent::AllocPRemoteOpenFile: " |
michael@0 | 604 | "FATAL error: app without webapps-manage permission is " |
michael@0 | 605 | "requesting file '%s' but is only allowed to open its " |
michael@0 | 606 | "own application.zip at %s: KILLING CHILD PROCESS\n", |
michael@0 | 607 | requestedPath.get(), mustMatch.get()); |
michael@0 | 608 | return nullptr; |
michael@0 | 609 | } |
michael@0 | 610 | } |
michael@0 | 611 | } |
michael@0 | 612 | |
michael@0 | 613 | RemoteOpenFileParent* parent = new RemoteOpenFileParent(fileURL); |
michael@0 | 614 | return parent; |
michael@0 | 615 | } |
michael@0 | 616 | |
michael@0 | 617 | bool |
michael@0 | 618 | NeckoParent::RecvPRemoteOpenFileConstructor(PRemoteOpenFileParent* aActor, |
michael@0 | 619 | const URIParams& aFileURI, |
michael@0 | 620 | const OptionalURIParams& aAppURI) |
michael@0 | 621 | { |
michael@0 | 622 | return static_cast<RemoteOpenFileParent*>(aActor)->OpenSendCloseDelete(); |
michael@0 | 623 | } |
michael@0 | 624 | |
michael@0 | 625 | bool |
michael@0 | 626 | NeckoParent::DeallocPRemoteOpenFileParent(PRemoteOpenFileParent* actor) |
michael@0 | 627 | { |
michael@0 | 628 | delete actor; |
michael@0 | 629 | return true; |
michael@0 | 630 | } |
michael@0 | 631 | |
michael@0 | 632 | bool |
michael@0 | 633 | NeckoParent::RecvHTMLDNSPrefetch(const nsString& hostname, |
michael@0 | 634 | const uint16_t& flags) |
michael@0 | 635 | { |
michael@0 | 636 | nsHTMLDNSPrefetch::Prefetch(hostname, flags); |
michael@0 | 637 | return true; |
michael@0 | 638 | } |
michael@0 | 639 | |
michael@0 | 640 | bool |
michael@0 | 641 | NeckoParent::RecvCancelHTMLDNSPrefetch(const nsString& hostname, |
michael@0 | 642 | const uint16_t& flags, |
michael@0 | 643 | const nsresult& reason) |
michael@0 | 644 | { |
michael@0 | 645 | nsHTMLDNSPrefetch::CancelPrefetch(hostname, flags, reason); |
michael@0 | 646 | return true; |
michael@0 | 647 | } |
michael@0 | 648 | |
michael@0 | 649 | PChannelDiverterParent* |
michael@0 | 650 | NeckoParent::AllocPChannelDiverterParent(const ChannelDiverterArgs& channel) |
michael@0 | 651 | { |
michael@0 | 652 | return new ChannelDiverterParent(); |
michael@0 | 653 | } |
michael@0 | 654 | |
michael@0 | 655 | bool |
michael@0 | 656 | NeckoParent::RecvPChannelDiverterConstructor(PChannelDiverterParent* actor, |
michael@0 | 657 | const ChannelDiverterArgs& channel) |
michael@0 | 658 | { |
michael@0 | 659 | auto parent = static_cast<ChannelDiverterParent*>(actor); |
michael@0 | 660 | parent->Init(channel); |
michael@0 | 661 | return true; |
michael@0 | 662 | } |
michael@0 | 663 | |
michael@0 | 664 | bool |
michael@0 | 665 | NeckoParent::DeallocPChannelDiverterParent(PChannelDiverterParent* parent) |
michael@0 | 666 | { |
michael@0 | 667 | delete static_cast<ChannelDiverterParent*>(parent); |
michael@0 | 668 | return true; |
michael@0 | 669 | } |
michael@0 | 670 | |
michael@0 | 671 | void |
michael@0 | 672 | NeckoParent::CloneManagees(ProtocolBase* aSource, |
michael@0 | 673 | mozilla::ipc::ProtocolCloneContext* aCtx) |
michael@0 | 674 | { |
michael@0 | 675 | aCtx->SetNeckoParent(this); // For cloning protocols managed by this. |
michael@0 | 676 | PNeckoParent::CloneManagees(aSource, aCtx); |
michael@0 | 677 | } |
michael@0 | 678 | |
michael@0 | 679 | mozilla::ipc::IProtocol* |
michael@0 | 680 | NeckoParent::CloneProtocol(Channel* aChannel, |
michael@0 | 681 | mozilla::ipc::ProtocolCloneContext* aCtx) |
michael@0 | 682 | { |
michael@0 | 683 | ContentParent* contentParent = aCtx->GetContentParent(); |
michael@0 | 684 | nsAutoPtr<PNeckoParent> actor(contentParent->AllocPNeckoParent()); |
michael@0 | 685 | if (!actor || !contentParent->RecvPNeckoConstructor(actor)) { |
michael@0 | 686 | return nullptr; |
michael@0 | 687 | } |
michael@0 | 688 | return actor.forget(); |
michael@0 | 689 | } |
michael@0 | 690 | |
michael@0 | 691 | }} // mozilla::net |