toolkit/components/places/nsAnnoProtocolHandler.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 //* -*- Mode: C++; tab-width: 8; 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/. */
     6 /**
     7  * Implementation of moz-anno: URLs for accessing favicons.  The urls are sent
     8  * to the favicon service.  If the favicon service doesn't have the
     9  * data, a stream containing the default favicon will be returned.
    10  *
    11  * The reference to annotations ("moz-anno") is a leftover from previous
    12  * iterations of this component. As of now the moz-anno protocol is independent
    13  * of annotations.
    14  */
    16 #include "nsAnnoProtocolHandler.h"
    17 #include "nsFaviconService.h"
    18 #include "nsIChannel.h"
    19 #include "nsIInputStreamChannel.h"
    20 #include "nsILoadGroup.h"
    21 #include "nsIStandardURL.h"
    22 #include "nsIStringStream.h"
    23 #include "nsISupportsUtils.h"
    24 #include "nsIURI.h"
    25 #include "nsNetUtil.h"
    26 #include "nsServiceManagerUtils.h"
    27 #include "nsStringStream.h"
    28 #include "mozilla/storage.h"
    29 #include "nsIPipe.h"
    30 #include "Helpers.h"
    32 using namespace mozilla;
    33 using namespace mozilla::places;
    35 ////////////////////////////////////////////////////////////////////////////////
    36 //// Global Functions
    38 /**
    39  * Creates a channel to obtain the default favicon.
    40  */
    41 static
    42 nsresult
    43 GetDefaultIcon(nsIChannel **aChannel)
    44 {
    45   nsCOMPtr<nsIURI> defaultIconURI;
    46   nsresult rv = NS_NewURI(getter_AddRefs(defaultIconURI),
    47                           NS_LITERAL_CSTRING(FAVICON_DEFAULT_URL));
    48   NS_ENSURE_SUCCESS(rv, rv);
    49   return NS_NewChannel(aChannel, defaultIconURI);
    50 }
    52 ////////////////////////////////////////////////////////////////////////////////
    53 //// faviconAsyncLoader
    55 namespace {
    57 /**
    58  * An instance of this class is passed to the favicon service as the callback
    59  * for getting favicon data from the database.  We'll get this data back in
    60  * HandleResult, and on HandleCompletion, we'll close our output stream which
    61  * will close the original channel for the favicon request.
    62  *
    63  * However, if an error occurs at any point, we do not set mReturnDefaultIcon to
    64  * false, so we will open up another channel to get the default favicon, and
    65  * pass that along to our output stream in HandleCompletion.  If anything
    66  * happens at that point, the world must be against us, so we return nothing.
    67  */
    68 class faviconAsyncLoader : public AsyncStatementCallback
    69                          , public nsIRequestObserver
    70 {
    71 public:
    72   NS_DECL_ISUPPORTS_INHERITED
    74   faviconAsyncLoader(nsIChannel *aChannel, nsIOutputStream *aOutputStream) :
    75       mChannel(aChannel)
    76     , mOutputStream(aOutputStream)
    77     , mReturnDefaultIcon(true)
    78   {
    79     NS_ASSERTION(aChannel,
    80                  "Not providing a channel will result in crashes!");
    81     NS_ASSERTION(aOutputStream,
    82                  "Not providing an output stream will result in crashes!");
    83   }
    85   //////////////////////////////////////////////////////////////////////////////
    86   //// mozIStorageStatementCallback
    88   NS_IMETHOD HandleResult(mozIStorageResultSet *aResultSet)
    89   {
    90     // We will only get one row back in total, so we do not need to loop.
    91     nsCOMPtr<mozIStorageRow> row;
    92     nsresult rv = aResultSet->GetNextRow(getter_AddRefs(row));
    93     NS_ENSURE_SUCCESS(rv, rv);
    95     // We do not allow favicons without a MIME type, so we'll return the default
    96     // icon.
    97     nsAutoCString mimeType;
    98     (void)row->GetUTF8String(1, mimeType);
    99     NS_ENSURE_FALSE(mimeType.IsEmpty(), NS_OK);
   101     // Set our mimeType now that we know it.
   102     rv = mChannel->SetContentType(mimeType);
   103     NS_ENSURE_SUCCESS(rv, rv);
   105     // Obtain the binary blob that contains our favicon data.
   106     uint8_t *favicon;
   107     uint32_t size = 0;
   108     rv = row->GetBlob(0, &size, &favicon);
   109     NS_ENSURE_SUCCESS(rv, rv);
   111     uint32_t totalWritten = 0;
   112     do {
   113       uint32_t bytesWritten;
   114       rv = mOutputStream->Write(
   115         &(reinterpret_cast<const char *>(favicon)[totalWritten]),
   116         size - totalWritten,
   117         &bytesWritten
   118       );
   119       if (NS_FAILED(rv) || !bytesWritten)
   120         break;
   121       totalWritten += bytesWritten;
   122     } while (size != totalWritten);
   123     NS_ASSERTION(NS_FAILED(rv) || size == totalWritten,
   124                  "Failed to write all of our data out to the stream!");
   126     // Free our favicon array.
   127     NS_Free(favicon);
   129     // Handle an error to write if it occurred, but only after we've freed our
   130     // favicon.
   131     NS_ENSURE_SUCCESS(rv, rv);
   133     // At this point, we should have written out all of our data to our stream.
   134     // HandleCompletion will close the output stream, so we are done here.
   135     mReturnDefaultIcon = false;
   136     return NS_OK;
   137   }
   139   NS_IMETHOD HandleCompletion(uint16_t aReason)
   140   {
   141     if (!mReturnDefaultIcon)
   142       return mOutputStream->Close();
   144     // We need to return our default icon, so we'll open up a new channel to get
   145     // that data, and push it to our output stream.  If at any point we get an
   146     // error, we can't do anything, so we'll just close our output stream.
   147     nsCOMPtr<nsIStreamListener> listener;
   148     nsresult rv = NS_NewSimpleStreamListener(getter_AddRefs(listener),
   149                                              mOutputStream, this);
   150     NS_ENSURE_SUCCESS(rv, mOutputStream->Close());
   152     nsCOMPtr<nsIChannel> newChannel;
   153     rv = GetDefaultIcon(getter_AddRefs(newChannel));
   154     NS_ENSURE_SUCCESS(rv, mOutputStream->Close());
   156     rv = newChannel->AsyncOpen(listener, nullptr);
   157     NS_ENSURE_SUCCESS(rv, mOutputStream->Close());
   159     return NS_OK;
   160   }
   162   //////////////////////////////////////////////////////////////////////////////
   163   //// nsIRequestObserver
   165   NS_IMETHOD OnStartRequest(nsIRequest *, nsISupports *)
   166   {
   167     return NS_OK;
   168   }
   170   NS_IMETHOD OnStopRequest(nsIRequest *, nsISupports *, nsresult aStatusCode)
   171   {
   172     // We always need to close our output stream, regardless of the status code.
   173     (void)mOutputStream->Close();
   175     // But, we'll warn about it not being successful if it wasn't.
   176     NS_WARN_IF_FALSE(NS_SUCCEEDED(aStatusCode),
   177                      "Got an error when trying to load our default favicon!");
   179     return NS_OK;
   180   }
   182 private:
   183   nsCOMPtr<nsIChannel> mChannel;
   184   nsCOMPtr<nsIOutputStream> mOutputStream;
   185   bool mReturnDefaultIcon;
   186 };
   188 NS_IMPL_ISUPPORTS_INHERITED(
   189   faviconAsyncLoader,
   190   AsyncStatementCallback,
   191   nsIRequestObserver
   192 )
   194 } // anonymous namespace
   196 ////////////////////////////////////////////////////////////////////////////////
   197 //// nsAnnoProtocolHandler
   199 NS_IMPL_ISUPPORTS(nsAnnoProtocolHandler, nsIProtocolHandler)
   201 // nsAnnoProtocolHandler::GetScheme
   203 NS_IMETHODIMP
   204 nsAnnoProtocolHandler::GetScheme(nsACString& aScheme)
   205 {
   206   aScheme.AssignLiteral("moz-anno");
   207   return NS_OK;
   208 }
   211 // nsAnnoProtocolHandler::GetDefaultPort
   212 //
   213 //    There is no default port for annotation URLs
   215 NS_IMETHODIMP
   216 nsAnnoProtocolHandler::GetDefaultPort(int32_t *aDefaultPort)
   217 {
   218   *aDefaultPort = -1;
   219   return NS_OK;
   220 }
   223 // nsAnnoProtocolHandler::GetProtocolFlags
   225 NS_IMETHODIMP
   226 nsAnnoProtocolHandler::GetProtocolFlags(uint32_t *aProtocolFlags)
   227 {
   228   *aProtocolFlags = (URI_NORELATIVE | URI_NOAUTH | URI_DANGEROUS_TO_LOAD |
   229                      URI_IS_LOCAL_RESOURCE);
   230   return NS_OK;
   231 }
   234 // nsAnnoProtocolHandler::NewURI
   236 NS_IMETHODIMP
   237 nsAnnoProtocolHandler::NewURI(const nsACString& aSpec,
   238                               const char *aOriginCharset,
   239                               nsIURI *aBaseURI, nsIURI **_retval)
   240 {
   241   nsCOMPtr <nsIURI> uri = do_CreateInstance(NS_SIMPLEURI_CONTRACTID);
   242   if (!uri)
   243     return NS_ERROR_OUT_OF_MEMORY;
   244   nsresult rv = uri->SetSpec(aSpec);
   245   NS_ENSURE_SUCCESS(rv, rv);
   247   *_retval = nullptr;
   248   uri.swap(*_retval);
   249   return NS_OK;
   250 }
   253 // nsAnnoProtocolHandler::NewChannel
   254 //
   256 NS_IMETHODIMP
   257 nsAnnoProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
   258 {
   259   NS_ENSURE_ARG_POINTER(aURI);
   261   // annotation info
   262   nsCOMPtr<nsIURI> annoURI;
   263   nsAutoCString annoName;
   264   nsresult rv = ParseAnnoURI(aURI, getter_AddRefs(annoURI), annoName);
   265   NS_ENSURE_SUCCESS(rv, rv);
   267   // Only favicon annotation are supported.
   268   if (!annoName.EqualsLiteral(FAVICON_ANNOTATION_NAME))
   269     return NS_ERROR_INVALID_ARG;
   271   return NewFaviconChannel(aURI, annoURI, _retval);
   272 }
   275 // nsAnnoProtocolHandler::AllowPort
   276 //
   277 //    Don't override any bans on bad ports.
   279 NS_IMETHODIMP
   280 nsAnnoProtocolHandler::AllowPort(int32_t port, const char *scheme,
   281                                  bool *_retval)
   282 {
   283   *_retval = false;
   284   return NS_OK;
   285 }
   288 // nsAnnoProtocolHandler::ParseAnnoURI
   289 //
   290 //    Splits an annotation URL into its URI and name parts
   292 nsresult
   293 nsAnnoProtocolHandler::ParseAnnoURI(nsIURI* aURI,
   294                                     nsIURI** aResultURI, nsCString& aName)
   295 {
   296   nsresult rv;
   297   nsAutoCString path;
   298   rv = aURI->GetPath(path);
   299   NS_ENSURE_SUCCESS(rv, rv);
   301   int32_t firstColon = path.FindChar(':');
   302   if (firstColon <= 0)
   303     return NS_ERROR_MALFORMED_URI;
   305   rv = NS_NewURI(aResultURI, Substring(path, firstColon + 1));
   306   NS_ENSURE_SUCCESS(rv, rv);
   308   aName = Substring(path, 0, firstColon);
   309   return NS_OK;
   310 }
   312 nsresult
   313 nsAnnoProtocolHandler::NewFaviconChannel(nsIURI *aURI, nsIURI *aAnnotationURI,
   314                                          nsIChannel **_channel)
   315 {
   316   // Create our pipe.  This will give us our input stream and output stream
   317   // that will be written to when we get data from the database.
   318   nsCOMPtr<nsIInputStream> inputStream;
   319   nsCOMPtr<nsIOutputStream> outputStream;
   320   nsresult rv = NS_NewPipe(getter_AddRefs(inputStream),
   321                            getter_AddRefs(outputStream),
   322                            MAX_FAVICON_SIZE, MAX_FAVICON_SIZE, true,
   323                            true);
   324   NS_ENSURE_SUCCESS(rv, GetDefaultIcon(_channel));
   326   // Create our channel.  We'll call SetContentType with the right type when
   327   // we know what it actually is.
   328   nsCOMPtr<nsIChannel> channel;
   329   rv = NS_NewInputStreamChannel(getter_AddRefs(channel), aURI, inputStream,
   330                                 EmptyCString());
   331   NS_ENSURE_SUCCESS(rv, GetDefaultIcon(_channel));
   333   // Now we go ahead and get our data asynchronously for the favicon.
   334   nsCOMPtr<mozIStorageStatementCallback> callback =
   335     new faviconAsyncLoader(channel, outputStream);
   336   NS_ENSURE_TRUE(callback, GetDefaultIcon(_channel));
   337   nsFaviconService* faviconService = nsFaviconService::GetFaviconService();
   338   NS_ENSURE_TRUE(faviconService, GetDefaultIcon(_channel));
   340   rv = faviconService->GetFaviconDataAsync(aAnnotationURI, callback);
   341   NS_ENSURE_SUCCESS(rv, GetDefaultIcon(_channel));
   343   channel.forget(_channel);
   344   return NS_OK;
   345 }

mercurial