nsChromeProtocolHandler.cpp (5178B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=4 sw=2 sts=2 et cin: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* 8 9 A protocol handler for ``chrome:'' 10 11 */ 12 13 #include "nsChromeProtocolHandler.h" 14 #include "nsChromeRegistry.h" 15 #include "nsCOMPtr.h" 16 #include "nsContentUtils.h" 17 #include "nsThreadUtils.h" 18 #include "nsIChannel.h" 19 #include "nsIChromeRegistry.h" 20 #include "nsIFile.h" 21 #include "nsIFileChannel.h" 22 #include "nsIStandardURL.h" 23 #include "nsNetUtil.h" 24 #include "nsNetCID.h" 25 #include "nsIURL.h" 26 #include "nsString.h" 27 #include "nsStandardURL.h" 28 29 //////////////////////////////////////////////////////////////////////////////// 30 31 NS_IMPL_ISUPPORTS(nsChromeProtocolHandler, nsIProtocolHandler, 32 nsISupportsWeakReference) 33 34 //////////////////////////////////////////////////////////////////////////////// 35 // nsIProtocolHandler methods: 36 37 NS_IMETHODIMP 38 nsChromeProtocolHandler::GetScheme(nsACString& result) { 39 result.AssignLiteral("chrome"); 40 return NS_OK; 41 } 42 43 NS_IMETHODIMP 44 nsChromeProtocolHandler::AllowPort(int32_t port, const char* scheme, 45 bool* _retval) { 46 // don't override anything. 47 *_retval = false; 48 return NS_OK; 49 } 50 51 /* static */ nsresult nsChromeProtocolHandler::CreateNewURI( 52 const nsACString& aSpec, const char* aCharset, nsIURI* aBaseURI, 53 nsIURI** result) { 54 // Chrome: URLs (currently) have no additional structure beyond that provided 55 // by standard URLs, so there is no "outer" given to CreateInstance 56 nsresult rv; 57 nsCOMPtr<nsIURI> surl; 58 rv = 59 NS_MutateURI(new mozilla::net::nsStandardURL::Mutator()) 60 .Apply(&nsIStandardURLMutator::Init, nsIStandardURL::URLTYPE_STANDARD, 61 -1, aSpec, aCharset, aBaseURI, nullptr) 62 63 .Finalize(surl); 64 if (NS_FAILED(rv)) { 65 return rv; 66 } 67 68 // Canonify the "chrome:" URL; e.g., so that we collapse 69 // "chrome://navigator/content/" and "chrome://navigator/content" 70 // and "chrome://navigator/content/navigator.xul". 71 72 rv = nsChromeRegistry::Canonify(surl); 73 (void)NS_WARN_IF(NS_FAILED(rv)); 74 75 surl.forget(result); 76 return NS_OK; 77 } 78 79 NS_IMETHODIMP 80 nsChromeProtocolHandler::NewChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo, 81 nsIChannel** aResult) { 82 nsresult rv; 83 84 NS_ENSURE_ARG_POINTER(aURI); 85 NS_ENSURE_ARG_POINTER(aLoadInfo); 86 87 MOZ_ASSERT(aResult, "Null out param"); 88 89 nsCOMPtr<nsIURI> debugURL = aURI; 90 rv = nsChromeRegistry::Canonify(debugURL); 91 NS_ENSURE_SUCCESS(rv, rv); 92 93 nsCOMPtr<nsIChannel> result; 94 95 if (!nsChromeRegistry::gChromeRegistry) { 96 // We don't actually want this ref, we just want the service to 97 // initialize if it hasn't already. 98 nsCOMPtr<nsIChromeRegistry> reg = mozilla::services::GetChromeRegistry(); 99 NS_ENSURE_TRUE(nsChromeRegistry::gChromeRegistry, NS_ERROR_FAILURE); 100 } 101 102 nsCOMPtr<nsIURI> resolvedURI; 103 rv = nsChromeRegistry::gChromeRegistry->ConvertChromeURL( 104 aURI, getter_AddRefs(resolvedURI)); 105 if (NS_FAILED(rv)) { 106 #ifdef DEBUG 107 printf("Couldn't convert chrome URL: %s\n", aURI->GetSpecOrDefault().get()); 108 #endif 109 return rv; 110 } 111 112 // We don't want to allow the inner protocol handler modify the result 113 // principal URI since we want either |aURI| or anything pre-set by upper 114 // layers to prevail. 115 nsCOMPtr<nsIURI> savedResultPrincipalURI; 116 rv = 117 aLoadInfo->GetResultPrincipalURI(getter_AddRefs(savedResultPrincipalURI)); 118 NS_ENSURE_SUCCESS(rv, rv); 119 120 rv = NS_NewChannelInternal(getter_AddRefs(result), resolvedURI, aLoadInfo); 121 NS_ENSURE_SUCCESS(rv, rv); 122 123 #ifdef DEBUG 124 nsCOMPtr<nsIFileChannel> fileChan(do_QueryInterface(result)); 125 if (fileChan) { 126 nsCOMPtr<nsIFile> file; 127 fileChan->GetFile(getter_AddRefs(file)); 128 129 bool exists = false; 130 file->Exists(&exists); 131 if (!exists) { 132 printf("Chrome file doesn't exist: %s\n", 133 file->HumanReadablePath().get()); 134 } 135 } 136 #endif 137 138 // Make sure that the channel remembers where it was 139 // originally loaded from. 140 rv = aLoadInfo->SetResultPrincipalURI(savedResultPrincipalURI); 141 NS_ENSURE_SUCCESS(rv, rv); 142 rv = result->SetOriginalURI(aURI); 143 if (NS_FAILED(rv)) return rv; 144 145 // Use a system principal for /content and /skin files. 146 // See bug 1855225 for discussion about whether to extend it more generally 147 // to other chrome:// URIs. 148 nsAutoCString path; 149 aURI->GetPathQueryRef(path); 150 if (StringBeginsWith(path, "/content/"_ns) || 151 StringBeginsWith(path, "/skin/"_ns)) { 152 result->SetOwner(nsContentUtils::GetSystemPrincipal()); 153 } 154 155 // XXX Removed dependency-tracking code from here, because we're not 156 // tracking them anyways (with fastload we checked only in DEBUG 157 // and with startupcache not at all), but this is where we would start 158 // if we need to re-add. 159 // See bug 531886, bug 533038. 160 result->SetContentCharset("UTF-8"_ns); 161 162 result.forget(aResult); 163 return NS_OK; 164 } 165 166 ////////////////////////////////////////////////////////////////////////////////