nsResProtocolHandler.cpp (6483B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "mozilla/chrome/RegistryMessageUtils.h" 7 #include "mozilla/dom/ContentParent.h" 8 #include "mozilla/ClearOnShutdown.h" 9 10 #include "nsResProtocolHandler.h" 11 #include "nsNetCID.h" 12 #include "nsNetUtil.h" 13 #include "nsURLHelper.h" 14 #include "nsEscape.h" 15 16 #include "mozilla/Omnijar.h" 17 18 using mozilla::LogLevel; 19 using mozilla::dom::ContentParent; 20 21 #define kAPP "app" 22 #define kGRE "gre" 23 #define kAndroid "android" 24 25 mozilla::StaticRefPtr<nsResProtocolHandler> nsResProtocolHandler::sSingleton; 26 27 already_AddRefed<nsResProtocolHandler> nsResProtocolHandler::GetSingleton() { 28 if (!sSingleton) { 29 RefPtr<nsResProtocolHandler> handler = new nsResProtocolHandler(); 30 if (NS_WARN_IF(NS_FAILED(handler->Init()))) { 31 return nullptr; 32 } 33 sSingleton = handler; 34 ClearOnShutdown(&sSingleton); 35 } 36 return do_AddRef(sSingleton); 37 } 38 39 nsresult nsResProtocolHandler::Init() { 40 nsresult rv; 41 rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::APP, mAppURI); 42 NS_ENSURE_SUCCESS(rv, rv); 43 rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::GRE, mGREURI); 44 NS_ENSURE_SUCCESS(rv, rv); 45 46 // mozilla::Omnijar::GetURIString always returns a string ending with /, 47 // and we want to remove it. 48 mGREURI.Truncate(mGREURI.Length() - 1); 49 if (mAppURI.Length()) { 50 mAppURI.Truncate(mAppURI.Length() - 1); 51 } else { 52 mAppURI = mGREURI; 53 } 54 55 #ifdef ANDROID 56 rv = GetApkURI(mApkURI); 57 #endif 58 59 // XXXbsmedberg Neil wants a resource://pchrome/ for the profile chrome dir... 60 // but once I finish multiple chrome registration I'm not sure that it is 61 // needed 62 63 // XXX dveditz: resource://pchrome/ defeats profile directory salting 64 // if web content can load it. Tread carefully. 65 66 return rv; 67 } 68 69 #ifdef ANDROID 70 nsresult nsResProtocolHandler::GetApkURI(nsACString& aResult) { 71 nsCString::const_iterator start, iter; 72 mGREURI.BeginReading(start); 73 mGREURI.EndReading(iter); 74 nsCString::const_iterator start_iter = start; 75 76 // This is like jar:jar:file://path/to/apk/base.apk!/path/to/omni.ja!/ 77 bool found = FindInReadable("!/"_ns, start_iter, iter); 78 NS_ENSURE_TRUE(found, NS_ERROR_UNEXPECTED); 79 80 // like jar:jar:file://path/to/apk/base.apk!/ 81 const nsDependentCSubstring& withoutPath = Substring(start, iter); 82 NS_ENSURE_TRUE(withoutPath.Length() >= 4, NS_ERROR_UNEXPECTED); 83 84 // Let's make sure we're removing what we expect to remove 85 NS_ENSURE_TRUE(Substring(withoutPath, 0, 4).EqualsLiteral("jar:"), 86 NS_ERROR_UNEXPECTED); 87 88 // like jar:file://path/to/apk/base.apk!/ 89 aResult = ToNewCString(Substring(withoutPath, 4)); 90 91 // Remove the trailing / 92 NS_ENSURE_TRUE(aResult.Length() >= 1, NS_ERROR_UNEXPECTED); 93 aResult.Truncate(aResult.Length() - 1); 94 return NS_OK; 95 } 96 #endif 97 98 //---------------------------------------------------------------------------- 99 // nsResProtocolHandler::nsISupports 100 //---------------------------------------------------------------------------- 101 102 NS_IMPL_QUERY_INTERFACE(nsResProtocolHandler, nsIResProtocolHandler, 103 nsISubstitutingProtocolHandler, nsIProtocolHandler, 104 nsISupportsWeakReference) 105 NS_IMPL_ADDREF_INHERITED(nsResProtocolHandler, SubstitutingProtocolHandler) 106 NS_IMPL_RELEASE_INHERITED(nsResProtocolHandler, SubstitutingProtocolHandler) 107 108 NS_IMETHODIMP 109 nsResProtocolHandler::AllowContentToAccess(nsIURI* aURI, bool* aResult) { 110 *aResult = false; 111 112 nsAutoCString host; 113 nsresult rv = aURI->GetAsciiHost(host); 114 NS_ENSURE_SUCCESS(rv, rv); 115 116 uint32_t flags; 117 rv = GetSubstitutionFlags(host, &flags); 118 NS_ENSURE_SUCCESS(rv, rv); 119 120 *aResult = flags & nsISubstitutingProtocolHandler::ALLOW_CONTENT_ACCESS; 121 return NS_OK; 122 } 123 124 uint32_t nsResProtocolHandler::GetJARFlags(const nsACString& aRoot) { 125 if (aRoot.Equals(kAndroid)) { 126 return nsISubstitutingProtocolHandler::RESOLVE_JAR_URI; 127 } 128 129 // 0 implies no content access. 130 return 0; 131 } 132 133 nsresult nsResProtocolHandler::GetSubstitutionInternal(const nsACString& aRoot, 134 nsIURI** aResult) { 135 nsAutoCString uri; 136 137 if (!ResolveSpecialCases(aRoot, "/"_ns, "/"_ns, uri)) { 138 return NS_ERROR_NOT_AVAILABLE; 139 } 140 141 return NS_NewURI(aResult, uri); 142 } 143 144 bool nsResProtocolHandler::ResolveSpecialCases(const nsACString& aHost, 145 const nsACString& aPath, 146 const nsACString& aPathname, 147 nsACString& aResult) { 148 if (aHost.EqualsLiteral("") || aHost.EqualsLiteral(kAPP)) { 149 aResult.Assign(mAppURI); 150 } else if (aHost.Equals(kGRE)) { 151 aResult.Assign(mGREURI); 152 #ifdef ANDROID 153 } else if (aHost.Equals(kAndroid)) { 154 aResult.Assign(mApkURI); 155 #endif 156 } else { 157 return false; 158 } 159 aResult.Append(aPath); 160 return true; 161 } 162 163 nsresult nsResProtocolHandler::SetSubstitution(const nsACString& aRoot, 164 nsIURI* aBaseURI) { 165 MOZ_ASSERT(!aRoot.EqualsLiteral("")); 166 MOZ_ASSERT(!aRoot.EqualsLiteral(kAPP)); 167 MOZ_ASSERT(!aRoot.EqualsLiteral(kGRE)); 168 MOZ_ASSERT(!aRoot.EqualsLiteral(kAndroid)); 169 return SubstitutingProtocolHandler::SetSubstitution(aRoot, aBaseURI); 170 } 171 172 nsresult nsResProtocolHandler::SetSubstitutionWithFlags(const nsACString& aRoot, 173 nsIURI* aBaseURI, 174 uint32_t aFlags) { 175 MOZ_ASSERT(!aRoot.EqualsLiteral("")); 176 MOZ_ASSERT(!aRoot.EqualsLiteral(kAPP)); 177 MOZ_ASSERT(!aRoot.EqualsLiteral(kGRE)); 178 MOZ_ASSERT(!aRoot.EqualsLiteral(kAndroid)); 179 return SubstitutingProtocolHandler::SetSubstitutionWithFlags(aRoot, aBaseURI, 180 aFlags); 181 } 182 183 nsresult nsResProtocolHandler::HasSubstitution(const nsACString& aRoot, 184 bool* aResult) { 185 if (aRoot.EqualsLiteral(kAPP) || aRoot.EqualsLiteral(kGRE) 186 #ifdef ANDROID 187 || aRoot.EqualsLiteral(kAndroid) 188 #endif 189 ) { 190 *aResult = true; 191 return NS_OK; 192 } 193 194 return mozilla::net::SubstitutingProtocolHandler::HasSubstitution(aRoot, 195 aResult); 196 }