Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim:set expandtab ts=2 sw=2 sts=2 cin: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #include "AppProtocolHandler.h" |
michael@0 | 8 | #include "nsBaseChannel.h" |
michael@0 | 9 | #include "nsJARChannel.h" |
michael@0 | 10 | #include "nsNetCID.h" |
michael@0 | 11 | #include "nsIAppsService.h" |
michael@0 | 12 | #include "nsCxPusher.h" |
michael@0 | 13 | #include "nsXULAppAPI.h" |
michael@0 | 14 | |
michael@0 | 15 | /** |
michael@0 | 16 | * This dummy channel implementation only provides enough functionality |
michael@0 | 17 | * to return a fake 404 error when the caller asks for an app:// URL |
michael@0 | 18 | * containing an unknown appId. |
michael@0 | 19 | */ |
michael@0 | 20 | class DummyChannel : public nsIJARChannel |
michael@0 | 21 | , nsRunnable |
michael@0 | 22 | { |
michael@0 | 23 | public: |
michael@0 | 24 | NS_DECL_ISUPPORTS |
michael@0 | 25 | NS_DECL_NSIREQUEST |
michael@0 | 26 | NS_DECL_NSICHANNEL |
michael@0 | 27 | NS_DECL_NSIJARCHANNEL |
michael@0 | 28 | |
michael@0 | 29 | DummyChannel(); |
michael@0 | 30 | |
michael@0 | 31 | NS_IMETHODIMP Run(); |
michael@0 | 32 | |
michael@0 | 33 | private: |
michael@0 | 34 | bool mPending; |
michael@0 | 35 | uint32_t mSuspendCount; |
michael@0 | 36 | nsCOMPtr<nsISupports> mListenerContext; |
michael@0 | 37 | nsCOMPtr<nsIStreamListener> mListener; |
michael@0 | 38 | nsCOMPtr<nsILoadGroup> mLoadGroup; |
michael@0 | 39 | nsLoadFlags mLoadFlags; |
michael@0 | 40 | }; |
michael@0 | 41 | |
michael@0 | 42 | NS_IMPL_ISUPPORTS(DummyChannel, nsIRequest, nsIChannel, nsIJARChannel) |
michael@0 | 43 | |
michael@0 | 44 | DummyChannel::DummyChannel() : mPending(false) |
michael@0 | 45 | , mSuspendCount(0) |
michael@0 | 46 | , mLoadFlags(LOAD_NORMAL) |
michael@0 | 47 | { |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | NS_IMETHODIMP DummyChannel::GetName(nsACString &result) |
michael@0 | 51 | { |
michael@0 | 52 | result = "dummy_app_channel"; |
michael@0 | 53 | return NS_OK; |
michael@0 | 54 | } |
michael@0 | 55 | |
michael@0 | 56 | NS_IMETHODIMP DummyChannel::GetStatus(nsresult *aStatus) |
michael@0 | 57 | { |
michael@0 | 58 | *aStatus = NS_ERROR_FILE_NOT_FOUND; |
michael@0 | 59 | return NS_OK; |
michael@0 | 60 | } |
michael@0 | 61 | |
michael@0 | 62 | NS_IMETHODIMP DummyChannel::IsPending(bool *aResult) |
michael@0 | 63 | { |
michael@0 | 64 | *aResult = mPending; |
michael@0 | 65 | return NS_OK; |
michael@0 | 66 | } |
michael@0 | 67 | |
michael@0 | 68 | NS_IMETHODIMP DummyChannel::Suspend() |
michael@0 | 69 | { |
michael@0 | 70 | mSuspendCount++; |
michael@0 | 71 | return NS_OK; |
michael@0 | 72 | } |
michael@0 | 73 | |
michael@0 | 74 | NS_IMETHODIMP DummyChannel::Resume() |
michael@0 | 75 | { |
michael@0 | 76 | if (mSuspendCount <= 0) { |
michael@0 | 77 | return NS_ERROR_UNEXPECTED; |
michael@0 | 78 | } |
michael@0 | 79 | |
michael@0 | 80 | if (--mSuspendCount == 0) { |
michael@0 | 81 | NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); |
michael@0 | 82 | } |
michael@0 | 83 | return NS_OK; |
michael@0 | 84 | } |
michael@0 | 85 | |
michael@0 | 86 | NS_IMETHODIMP DummyChannel::Open(nsIInputStream**) |
michael@0 | 87 | { |
michael@0 | 88 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 89 | } |
michael@0 | 90 | |
michael@0 | 91 | NS_IMETHODIMP DummyChannel::AsyncOpen(nsIStreamListener* aListener, nsISupports* aContext) |
michael@0 | 92 | { |
michael@0 | 93 | mListener = aListener; |
michael@0 | 94 | mListenerContext = aContext; |
michael@0 | 95 | mPending = true; |
michael@0 | 96 | |
michael@0 | 97 | if (mLoadGroup) { |
michael@0 | 98 | mLoadGroup->AddRequest(this, aContext); |
michael@0 | 99 | } |
michael@0 | 100 | |
michael@0 | 101 | if (mSuspendCount == 0) { |
michael@0 | 102 | NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL); |
michael@0 | 103 | } |
michael@0 | 104 | |
michael@0 | 105 | return NS_OK; |
michael@0 | 106 | } |
michael@0 | 107 | |
michael@0 | 108 | // nsIJarChannel, needed for XHR to turn NS_ERROR_FILE_NOT_FOUND into |
michael@0 | 109 | // a 404 error. |
michael@0 | 110 | NS_IMETHODIMP DummyChannel::GetIsUnsafe(bool *aResult) |
michael@0 | 111 | { |
michael@0 | 112 | *aResult = false; |
michael@0 | 113 | return NS_OK; |
michael@0 | 114 | } |
michael@0 | 115 | |
michael@0 | 116 | NS_IMETHODIMP DummyChannel::SetAppURI(nsIURI *aURI) |
michael@0 | 117 | { |
michael@0 | 118 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 119 | } |
michael@0 | 120 | |
michael@0 | 121 | NS_IMETHODIMP DummyChannel::Run() |
michael@0 | 122 | { |
michael@0 | 123 | nsresult rv = mListener->OnStartRequest(this, mListenerContext); |
michael@0 | 124 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 125 | mPending = false; |
michael@0 | 126 | rv = mListener->OnStopRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND); |
michael@0 | 127 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 128 | if (mLoadGroup) { |
michael@0 | 129 | mLoadGroup->RemoveRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND); |
michael@0 | 130 | } |
michael@0 | 131 | |
michael@0 | 132 | mListener = nullptr; |
michael@0 | 133 | mListenerContext = nullptr; |
michael@0 | 134 | rv = SetNotificationCallbacks(nullptr); |
michael@0 | 135 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 136 | |
michael@0 | 137 | return NS_OK; |
michael@0 | 138 | } |
michael@0 | 139 | |
michael@0 | 140 | NS_IMETHODIMP DummyChannel::Cancel(nsresult) |
michael@0 | 141 | { |
michael@0 | 142 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 143 | } |
michael@0 | 144 | |
michael@0 | 145 | NS_IMETHODIMP DummyChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup) |
michael@0 | 146 | { |
michael@0 | 147 | *aLoadGroup = mLoadGroup; |
michael@0 | 148 | NS_IF_ADDREF(*aLoadGroup); |
michael@0 | 149 | return NS_OK; |
michael@0 | 150 | } |
michael@0 | 151 | |
michael@0 | 152 | NS_IMETHODIMP DummyChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) |
michael@0 | 153 | { |
michael@0 | 154 | mLoadGroup = aLoadGroup; |
michael@0 | 155 | return NS_OK; |
michael@0 | 156 | } |
michael@0 | 157 | |
michael@0 | 158 | NS_IMETHODIMP DummyChannel::GetLoadFlags(nsLoadFlags *aLoadFlags) |
michael@0 | 159 | { |
michael@0 | 160 | *aLoadFlags = mLoadFlags; |
michael@0 | 161 | return NS_OK; |
michael@0 | 162 | } |
michael@0 | 163 | |
michael@0 | 164 | NS_IMETHODIMP DummyChannel::SetLoadFlags(nsLoadFlags aLoadFlags) |
michael@0 | 165 | { |
michael@0 | 166 | mLoadFlags = aLoadFlags; |
michael@0 | 167 | return NS_OK; |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | NS_IMETHODIMP DummyChannel::GetOriginalURI(nsIURI**) |
michael@0 | 171 | { |
michael@0 | 172 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 173 | } |
michael@0 | 174 | |
michael@0 | 175 | NS_IMETHODIMP DummyChannel::SetOriginalURI(nsIURI*) |
michael@0 | 176 | { |
michael@0 | 177 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 178 | } |
michael@0 | 179 | |
michael@0 | 180 | NS_IMETHODIMP DummyChannel::GetOwner(nsISupports**) |
michael@0 | 181 | { |
michael@0 | 182 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 183 | } |
michael@0 | 184 | |
michael@0 | 185 | NS_IMETHODIMP DummyChannel::SetOwner(nsISupports*) |
michael@0 | 186 | { |
michael@0 | 187 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 188 | } |
michael@0 | 189 | |
michael@0 | 190 | NS_IMETHODIMP DummyChannel::GetNotificationCallbacks(nsIInterfaceRequestor**) |
michael@0 | 191 | { |
michael@0 | 192 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 193 | } |
michael@0 | 194 | |
michael@0 | 195 | NS_IMETHODIMP DummyChannel::SetNotificationCallbacks(nsIInterfaceRequestor*) |
michael@0 | 196 | { |
michael@0 | 197 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 198 | } |
michael@0 | 199 | |
michael@0 | 200 | NS_IMETHODIMP DummyChannel::GetSecurityInfo(nsISupports**) |
michael@0 | 201 | { |
michael@0 | 202 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 203 | } |
michael@0 | 204 | |
michael@0 | 205 | NS_IMETHODIMP DummyChannel::GetContentType(nsACString&) |
michael@0 | 206 | { |
michael@0 | 207 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 208 | } |
michael@0 | 209 | |
michael@0 | 210 | NS_IMETHODIMP DummyChannel::SetContentType(const nsACString&) |
michael@0 | 211 | { |
michael@0 | 212 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 213 | } |
michael@0 | 214 | |
michael@0 | 215 | NS_IMETHODIMP DummyChannel::GetContentCharset(nsACString&) |
michael@0 | 216 | { |
michael@0 | 217 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 218 | } |
michael@0 | 219 | |
michael@0 | 220 | NS_IMETHODIMP DummyChannel::SetContentCharset(const nsACString&) |
michael@0 | 221 | { |
michael@0 | 222 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 223 | } |
michael@0 | 224 | |
michael@0 | 225 | NS_IMETHODIMP DummyChannel::GetContentLength(int64_t*) |
michael@0 | 226 | { |
michael@0 | 227 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | NS_IMETHODIMP DummyChannel::SetContentLength(int64_t) |
michael@0 | 231 | { |
michael@0 | 232 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 233 | } |
michael@0 | 234 | |
michael@0 | 235 | NS_IMETHODIMP DummyChannel::GetContentDisposition(uint32_t*) |
michael@0 | 236 | { |
michael@0 | 237 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 238 | } |
michael@0 | 239 | |
michael@0 | 240 | NS_IMETHODIMP DummyChannel::SetContentDisposition(uint32_t) |
michael@0 | 241 | { |
michael@0 | 242 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 243 | } |
michael@0 | 244 | |
michael@0 | 245 | NS_IMETHODIMP DummyChannel::GetURI(nsIURI**) |
michael@0 | 246 | { |
michael@0 | 247 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 248 | } |
michael@0 | 249 | |
michael@0 | 250 | NS_IMETHODIMP DummyChannel::GetContentDispositionFilename(nsAString&) |
michael@0 | 251 | { |
michael@0 | 252 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | NS_IMETHODIMP DummyChannel::SetContentDispositionFilename(nsAString const &) |
michael@0 | 256 | { |
michael@0 | 257 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 258 | } |
michael@0 | 259 | |
michael@0 | 260 | NS_IMETHODIMP DummyChannel::GetContentDispositionHeader(nsACString&) |
michael@0 | 261 | { |
michael@0 | 262 | return NS_ERROR_NOT_IMPLEMENTED; |
michael@0 | 263 | } |
michael@0 | 264 | |
michael@0 | 265 | /** |
michael@0 | 266 | * app:// protocol implementation. |
michael@0 | 267 | */ |
michael@0 | 268 | |
michael@0 | 269 | AppProtocolHandler::AppProtocolHandler() { |
michael@0 | 270 | } |
michael@0 | 271 | |
michael@0 | 272 | AppProtocolHandler::~AppProtocolHandler() { |
michael@0 | 273 | mAppInfoCache.Clear(); |
michael@0 | 274 | } |
michael@0 | 275 | |
michael@0 | 276 | NS_IMPL_ISUPPORTS(AppProtocolHandler, nsIProtocolHandler) |
michael@0 | 277 | |
michael@0 | 278 | /* static */ |
michael@0 | 279 | nsresult |
michael@0 | 280 | AppProtocolHandler::Create(nsISupports* aOuter, |
michael@0 | 281 | const nsIID& aIID, |
michael@0 | 282 | void* *aResult) |
michael@0 | 283 | { |
michael@0 | 284 | // Instantiate the service here since that intializes gJarHandler, which we |
michael@0 | 285 | // use indirectly (via our new JarChannel) in NewChannel. |
michael@0 | 286 | nsCOMPtr<nsIProtocolHandler> jarInitializer( |
michael@0 | 287 | do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "jar")); |
michael@0 | 288 | AppProtocolHandler* ph = new AppProtocolHandler(); |
michael@0 | 289 | if (ph == nullptr) { |
michael@0 | 290 | return NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 291 | } |
michael@0 | 292 | NS_ADDREF(ph); |
michael@0 | 293 | nsresult rv = ph->QueryInterface(aIID, aResult); |
michael@0 | 294 | NS_RELEASE(ph); |
michael@0 | 295 | return rv; |
michael@0 | 296 | } |
michael@0 | 297 | |
michael@0 | 298 | NS_IMETHODIMP |
michael@0 | 299 | AppProtocolHandler::GetScheme(nsACString &aResult) |
michael@0 | 300 | { |
michael@0 | 301 | aResult.AssignLiteral("app"); |
michael@0 | 302 | return NS_OK; |
michael@0 | 303 | } |
michael@0 | 304 | |
michael@0 | 305 | NS_IMETHODIMP |
michael@0 | 306 | AppProtocolHandler::GetDefaultPort(int32_t *aResult) |
michael@0 | 307 | { |
michael@0 | 308 | // No ports for the app protocol. |
michael@0 | 309 | *aResult = -1; |
michael@0 | 310 | return NS_OK; |
michael@0 | 311 | } |
michael@0 | 312 | |
michael@0 | 313 | NS_IMETHODIMP |
michael@0 | 314 | AppProtocolHandler::GetProtocolFlags(uint32_t *aResult) |
michael@0 | 315 | { |
michael@0 | 316 | *aResult = URI_NOAUTH | |
michael@0 | 317 | URI_DANGEROUS_TO_LOAD | |
michael@0 | 318 | URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM; |
michael@0 | 319 | return NS_OK; |
michael@0 | 320 | } |
michael@0 | 321 | |
michael@0 | 322 | NS_IMETHODIMP |
michael@0 | 323 | AppProtocolHandler::NewURI(const nsACString &aSpec, |
michael@0 | 324 | const char *aCharset, // ignore charset info |
michael@0 | 325 | nsIURI *aBaseURI, |
michael@0 | 326 | nsIURI **result) |
michael@0 | 327 | { |
michael@0 | 328 | nsresult rv; |
michael@0 | 329 | nsCOMPtr<nsIStandardURL> surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv)); |
michael@0 | 330 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 331 | |
michael@0 | 332 | rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI); |
michael@0 | 333 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 334 | |
michael@0 | 335 | nsCOMPtr<nsIURL> url(do_QueryInterface(surl, &rv)); |
michael@0 | 336 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 337 | |
michael@0 | 338 | url.forget(result); |
michael@0 | 339 | return NS_OK; |
michael@0 | 340 | } |
michael@0 | 341 | |
michael@0 | 342 | // We map app://ABCDEF/path/to/file.ext to |
michael@0 | 343 | // jar:file:///path/to/profile/webapps/ABCDEF/application.zip!/path/to/file.ext |
michael@0 | 344 | NS_IMETHODIMP |
michael@0 | 345 | AppProtocolHandler::NewChannel(nsIURI* aUri, nsIChannel* *aResult) |
michael@0 | 346 | { |
michael@0 | 347 | NS_ENSURE_ARG_POINTER(aUri); |
michael@0 | 348 | nsRefPtr<nsJARChannel> channel = new nsJARChannel(); |
michael@0 | 349 | |
michael@0 | 350 | nsAutoCString host; |
michael@0 | 351 | nsresult rv = aUri->GetHost(host); |
michael@0 | 352 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 353 | |
michael@0 | 354 | nsAutoCString fileSpec; |
michael@0 | 355 | nsCOMPtr<nsIURL> url = do_QueryInterface(aUri); |
michael@0 | 356 | rv = url->GetFilePath(fileSpec); |
michael@0 | 357 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 358 | |
michael@0 | 359 | mozilla::dom::AppInfo *appInfo; |
michael@0 | 360 | |
michael@0 | 361 | if (!mAppInfoCache.Get(host, &appInfo)) { |
michael@0 | 362 | nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID); |
michael@0 | 363 | if (!appsService) { |
michael@0 | 364 | return NS_ERROR_FAILURE; |
michael@0 | 365 | } |
michael@0 | 366 | |
michael@0 | 367 | mozilla::AutoSafeJSContext cx; |
michael@0 | 368 | JS::RootedValue jsInfo(cx); |
michael@0 | 369 | rv = appsService->GetAppInfo(NS_ConvertUTF8toUTF16(host), &jsInfo); |
michael@0 | 370 | if (NS_FAILED(rv) || !jsInfo.isObject()) { |
michael@0 | 371 | // Return a DummyChannel. |
michael@0 | 372 | printf_stderr("!! Creating a dummy channel for %s (no appInfo)\n", host.get()); |
michael@0 | 373 | NS_IF_ADDREF(*aResult = new DummyChannel()); |
michael@0 | 374 | return NS_OK; |
michael@0 | 375 | } |
michael@0 | 376 | |
michael@0 | 377 | appInfo = new mozilla::dom::AppInfo(); |
michael@0 | 378 | JSAutoCompartment ac(cx, &jsInfo.toObject()); |
michael@0 | 379 | if (!appInfo->Init(cx, jsInfo) || appInfo->mPath.IsEmpty()) { |
michael@0 | 380 | // Return a DummyChannel. |
michael@0 | 381 | printf_stderr("!! Creating a dummy channel for %s (invalid appInfo)\n", host.get()); |
michael@0 | 382 | NS_IF_ADDREF(*aResult = new DummyChannel()); |
michael@0 | 383 | return NS_OK; |
michael@0 | 384 | } |
michael@0 | 385 | mAppInfoCache.Put(host, appInfo); |
michael@0 | 386 | } |
michael@0 | 387 | |
michael@0 | 388 | bool noRemote = (appInfo->mIsCoreApp || |
michael@0 | 389 | XRE_GetProcessType() == GeckoProcessType_Default); |
michael@0 | 390 | |
michael@0 | 391 | // In-parent and CoreApps can directly access files, so use jar:file:// |
michael@0 | 392 | nsAutoCString jarSpec(noRemote ? "jar:file://" |
michael@0 | 393 | : "jar:remoteopenfile://"); |
michael@0 | 394 | jarSpec += NS_ConvertUTF16toUTF8(appInfo->mPath) + |
michael@0 | 395 | NS_LITERAL_CSTRING("/application.zip!") + |
michael@0 | 396 | fileSpec; |
michael@0 | 397 | |
michael@0 | 398 | nsCOMPtr<nsIURI> jarURI; |
michael@0 | 399 | rv = NS_NewURI(getter_AddRefs(jarURI), |
michael@0 | 400 | jarSpec, nullptr, nullptr); |
michael@0 | 401 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 402 | |
michael@0 | 403 | rv = channel->Init(jarURI); |
michael@0 | 404 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 405 | |
michael@0 | 406 | rv = channel->SetAppURI(aUri); |
michael@0 | 407 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 408 | |
michael@0 | 409 | rv = channel->SetOriginalURI(aUri); |
michael@0 | 410 | NS_ENSURE_SUCCESS(rv, rv); |
michael@0 | 411 | |
michael@0 | 412 | channel.forget(aResult); |
michael@0 | 413 | return NS_OK; |
michael@0 | 414 | } |
michael@0 | 415 | |
michael@0 | 416 | NS_IMETHODIMP |
michael@0 | 417 | AppProtocolHandler::AllowPort(int32_t aPort, const char *aScheme, bool *aRetval) |
michael@0 | 418 | { |
michael@0 | 419 | // No port allowed for this scheme. |
michael@0 | 420 | *aRetval = false; |
michael@0 | 421 | return NS_OK; |
michael@0 | 422 | } |
michael@0 | 423 |