Bug 366324 - Make SVG favicons work reliably. r=mak
authorJustin Dolske <dolske@mozilla.com>
Fri, 12 Jun 2015 12:02:48 -0700
changeset 248758 ed791601d8e74102ec99b578e3d67c7600a66f67
parent 248757 cec6df0d52238e0c6e42ffdd3c056b54f27aa944
child 248759 67fceb70fc6de648ee12d24fa430f8f47da640f6
push id61049
push userphilringnalda@gmail.com
push dateSun, 14 Jun 2015 02:53:25 +0000
treeherdermozilla-inbound@c223b8844264 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak
bugs366324
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 366324 - Make SVG favicons work reliably. r=mak
toolkit/components/places/AsyncFaviconHelpers.cpp
toolkit/components/places/tests/head_common.js
toolkit/components/places/tests/unit/test_svg_favicon.js
toolkit/components/places/tests/unit/xpcshell.ini
--- a/toolkit/components/places/AsyncFaviconHelpers.cpp
+++ b/toolkit/components/places/AsyncFaviconHelpers.cpp
@@ -630,34 +630,42 @@ AsyncFetchAndSetIconFromNetwork::OnStopR
     nsCOMPtr<nsIURI> iconURI;
     rv = NS_NewURI(getter_AddRefs(iconURI), mIcon.spec);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = favicons->AddFailedFavicon(iconURI);
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
   }
 
-  NS_SniffContent(NS_DATA_SNIFFER_CATEGORY, aRequest,
-                  TO_INTBUFFER(mIcon.data), mIcon.data.Length(),
-                  mIcon.mimeType);
+  nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
+  // aRequest should always QI to nsIChannel.
+  // See AsyncFetchAndSetIconFromNetwork::Run()
+  MOZ_ASSERT(channel);
+
+  nsAutoCString contentType;
+  channel->GetContentType(contentType);
+  // Bug 366324 - can't sniff SVG yet, so rely on server-specified type
+  if (contentType.EqualsLiteral("image/svg+xml")) {
+    mIcon.mimeType.AssignLiteral("image/svg+xml");
+  } else {
+    NS_SniffContent(NS_DATA_SNIFFER_CATEGORY, aRequest,
+                    TO_INTBUFFER(mIcon.data), mIcon.data.Length(),
+                    mIcon.mimeType);
+  }
 
   // If the icon does not have a valid MIME type, add it to the failed cache.
   if (mIcon.mimeType.IsEmpty()) {
     nsCOMPtr<nsIURI> iconURI;
     rv = NS_NewURI(getter_AddRefs(iconURI), mIcon.spec);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = favicons->AddFailedFavicon(iconURI);
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
   }
 
-  nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
-  // aRequest should always QI to nsIChannel.
-  // See AsyncFetchAndSetIconFromNetwork::Run()
-  MOZ_ASSERT(channel);
   mIcon.expiration = GetExpirationTimeFromChannel(channel);
 
   // Telemetry probes to measure the favicon file sizes for each different file type.
   // This allow us to measure common file sizes while also observing each type popularity.
   if (mIcon.mimeType.EqualsLiteral("image/png")) {
     mozilla::Telemetry::Accumulate(mozilla::Telemetry::PLACES_FAVICON_PNG_SIZES, mIcon.data.Length());
   }
   else if (mIcon.mimeType.EqualsLiteral("image/x-icon") ||
--- a/toolkit/components/places/tests/head_common.js
+++ b/toolkit/components/places/tests/head_common.js
@@ -52,16 +52,26 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 // This imports various other objects in addition to PlacesUtils.
 Cu.import("resource://gre/modules/PlacesUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "SMALLPNG_DATA_URI", function() {
   return NetUtil.newURI(
          "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAA" +
          "AAAA6fptVAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==");
 });
+XPCOMUtils.defineLazyGetter(this, "SMALLSVG_DATA_URI", function() {
+  return NetUtil.newURI(
+         "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy5" +
+         "3My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiBmaWxs" +
+         "PSIjNDI0ZTVhIj4NCiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iN" +
+         "DQiIHN0cm9rZT0iIzQyNGU1YSIgc3Ryb2tlLXdpZHRoPSIxMSIgZmlsbD" +
+         "0ibm9uZSIvPg0KICA8Y2lyY2xlIGN4PSI1MCIgY3k9IjI0LjYiIHI9IjY" +
+         "uNCIvPg0KICA8cmVjdCB4PSI0NSIgeT0iMzkuOSIgd2lkdGg9IjEwLjEi" +
+         "IGhlaWdodD0iNDEuOCIvPg0KPC9zdmc%2BDQo%3D");
+});
 
 let gTestDir = do_get_cwd();
 
 // Initialize profile.
 let gProfD = do_get_profile();
 
 // Remove any old database.
 clearDB();
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/unit/test_svg_favicon.js
@@ -0,0 +1,30 @@
+const PAGEURI = NetUtil.newURI("http://deliciousbacon.com/");
+
+add_task(function* () {
+  // First, add a history entry or else Places can't save a favicon.
+  yield PlacesTestUtils.addVisits({
+    uri: PAGEURI,
+    transition: TRANSITION_LINK,
+    visitDate: Date.now() * 1000
+  });
+
+  yield new Promise(resolve => {
+    function onSetComplete(aURI, aDataLen, aData, aMimeType) {
+      equal(aURI.spec, SMALLSVG_DATA_URI.spec, "setFavicon aURI check");
+      equal(aDataLen, 263, "setFavicon aDataLen check");
+      equal(aMimeType, "image/svg+xml", "setFavicon aMimeType check");
+      resolve();
+    }
+
+    PlacesUtils.favicons.setAndFetchFaviconForPage(PAGEURI, SMALLSVG_DATA_URI,
+                                                   false,
+                                                   PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
+                                                   onSetComplete);
+  });
+
+  let data = yield PlacesUtils.promiseFaviconData(PAGEURI.spec);
+  equal(data.uri.spec, SMALLSVG_DATA_URI.spec, "getFavicon aURI check");
+  equal(data.dataLen, 263, "getFavicon aDataLen check");
+  equal(data.mimeType, "image/svg+xml", "getFavicon aMimeType check");
+});
+
--- a/toolkit/components/places/tests/unit/xpcshell.ini
+++ b/toolkit/components/places/tests/unit/xpcshell.ini
@@ -133,16 +133,17 @@ skip-if = os == "android"
 [test_preventive_maintenance_runTasks.js]
 [test_promiseBookmarksTree.js]
 [test_removeVisitsByTimeframe.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
 [test_resolveNullBookmarkTitles.js]
 [test_result_sort.js]
 [test_sql_guid_functions.js]
+[test_svg_favicon.js]
 [test_tag_autocomplete_search.js]
 [test_tagging.js]
 [test_telemetry.js]
 [test_update_frecency_after_delete.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
 [test_utils_backups_create.js]
 [test_utils_getURLsForContainerNode.js]