Bug 1381434 - off-main-thread loading web font draft
authorShih-Chiang Chien <schien@mozilla.com>
Fri, 29 Sep 2017 10:10:13 +0800
changeset 673174 2b09d2506f04e5e14e2fd77825444720896b6a9e
parent 673165 44643fce30b43a8981535c335aaccb45006e456b
child 734023 760b2a0218e1a63fbabe60cc7dddc2bd93cbc454
push id82485
push userbmo:schien@mozilla.com
push dateMon, 02 Oct 2017 02:14:54 +0000
bugs1381434
milestone58.0a1
Bug 1381434 - off-main-thread loading web font MozReview-Commit-ID: 8PQdxK5K55
layout/style/FontFaceSet.cpp
layout/style/nsFontFaceLoader.cpp
layout/style/nsFontFaceLoader.h
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -678,17 +678,17 @@ FontFaceSet::StartLoad(gfxUserFontEntry*
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
   nsCOMPtr<nsISupportsPriority> priorityChannel(do_QueryInterface(channel));
   if (priorityChannel) {
     priorityChannel->AdjustPriority(nsISupportsPriority::PRIORITY_HIGH);
   }
 
-  rv = NS_NewStreamLoader(getter_AddRefs(streamLoader), fontLoader);
+  rv = NS_NewStreamLoader(getter_AddRefs(streamLoader), fontLoader, fontLoader);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mozilla::net::PredictorLearn(aFontFaceSrc->mURI->get(),
                                mDocument->GetDocumentURI(),
                                nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE,
                                loadGroup);
 
   rv = channel->AsyncOpen2(streamLoader);
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -11,23 +11,26 @@
 
 #include "nsFontFaceLoader.h"
 
 #include "nsError.h"
 #include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StylePrefs.h"
 #include "mozilla/Telemetry.h"
+#include "mozilla/Unused.h"
 #include "FontFaceSet.h"
 #include "nsPresContext.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIHttpChannel.h"
 #include "nsIContentPolicy.h"
+#include "nsIThreadRetargetableRequest.h"
 #include "nsContentPolicyUtils.h"
+#include "nsNetCID.h"
 
 #include "mozilla/gfx/2D.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define LOG(args) MOZ_LOG(gfxUserFontSet::GetUserFontsLog(), mozilla::LogLevel::Debug, args)
 #define LOG_ENABLED() MOZ_LOG_TEST(gfxUserFontSet::GetUserFontsLog(), \
@@ -190,25 +193,30 @@ nsFontFaceLoader::LoadTimerCallback(nsIT
         ctx->UserFontSetUpdated(ufe);
         LOG(("userfonts (%p) timeout reflow for pres context %p display %d\n",
              loader, ctx, fontDisplay));
       }
     }
   }
 }
 
-NS_IMPL_ISUPPORTS(nsFontFaceLoader, nsIStreamLoaderObserver)
+NS_IMPL_ISUPPORTS(nsFontFaceLoader,
+                  nsIStreamLoaderObserver,
+                  nsIRequestObserver)
 
+// nsIStreamLoaderObserver
 NS_IMETHODIMP
 nsFontFaceLoader::OnStreamComplete(nsIStreamLoader* aLoader,
                                    nsISupports* aContext,
                                    nsresult aStatus,
                                    uint32_t aStringLen,
                                    const uint8_t* aString)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
   if (!mFontFaceSet) {
     // We've been canceled
     return aStatus;
   }
 
   mFontFaceSet->RemoveLoader(this);
 
   TimeStamp doneTime = TimeStamp::Now();
@@ -286,16 +294,41 @@ nsFontFaceLoader::OnStreamComplete(nsISt
   if (mLoadTimer) {
     mLoadTimer->Cancel();
     mLoadTimer = nullptr;
   }
 
   return NS_SUCCESS_ADOPTED_DATA;
 }
 
+// nsIRequestObserver
+NS_IMETHODIMP
+nsFontFaceLoader::OnStartRequest(nsIRequest* aRequest,
+                                 nsISupports* aContext)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIThreadRetargetableRequest> req = do_QueryInterface(aRequest);
+  if (req) {
+    nsCOMPtr<nsIEventTarget> sts =
+      do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+    Unused << NS_WARN_IF(NS_FAILED(req->RetargetDeliveryTo(sts)));
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFontFaceLoader::OnStopRequest(nsIRequest* aRequest,
+                                nsISupports* aContext,
+                                nsresult aStatusCode)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  return NS_OK;
+}
+
 void
 nsFontFaceLoader::Cancel()
 {
   mUserFontEntry->mFontDataLoadingState = gfxUserFontEntry::NOT_LOADING;
   mUserFontEntry->mLoader = nullptr;
   mFontFaceSet = nullptr;
   if (mLoadTimer) {
     mLoadTimer->Cancel();
--- a/layout/style/nsFontFaceLoader.h
+++ b/layout/style/nsFontFaceLoader.h
@@ -9,32 +9,35 @@
 #ifndef nsFontFaceLoader_h_
 #define nsFontFaceLoader_h_
 
 #include "mozilla/Attributes.h"
 #include "mozilla/TimeStamp.h"
 #include "nsCOMPtr.h"
 #include "nsIStreamLoader.h"
 #include "nsIChannel.h"
+#include "nsIRequestObserver.h"
 #include "gfxUserFontSet.h"
 #include "nsHashKeys.h"
 #include "nsTHashtable.h"
 #include "nsCSSRules.h"
 
 class nsIPrincipal;
 
 class nsFontFaceLoader : public nsIStreamLoaderObserver
+                       , public nsIRequestObserver
 {
 public:
   nsFontFaceLoader(gfxUserFontEntry* aFontToLoad, nsIURI* aFontURI,
                    mozilla::dom::FontFaceSet* aFontFaceSet,
                    nsIChannel* aChannel);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISTREAMLOADEROBSERVER
+  NS_DECL_NSIREQUESTOBSERVER
 
   // initiate the load
   nsresult Init();
   // cancel the load and remove its reference to mFontFaceSet
   void Cancel();
 
   void DropChannel() { mChannel = nullptr; }