Bug 1379148: Part 1 - Allow blocking only non-script-created parsers. r?hsivonen draft
authorKris Maglione <maglione.k@gmail.com>
Wed, 20 Sep 2017 16:12:27 -0700
changeset 667975 2a50130368191a8e772301ab89130de05a4f7132
parent 667974 75a56a06d08b363a1b39a2fbebb881853f6d93d0
child 667976 63245f7d9a5dc93028d782a77640103eeb050bd2
push id80907
push usermaglione.k@gmail.com
push dateThu, 21 Sep 2017 00:03:55 +0000
reviewershsivonen
bugs1379148
milestone57.0a1
Bug 1379148: Part 1 - Allow blocking only non-script-created parsers. r?hsivonen MozReview-Commit-ID: 8cGxywiUzWj
dom/base/nsDocument.cpp
dom/base/nsIDocument.h
dom/webidl/Document.webidl
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -10888,21 +10888,22 @@ nsIDocument::ObsoleteSheet(const nsAStri
 }
 
 class UnblockParsingPromiseHandler final : public PromiseNativeHandler
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(UnblockParsingPromiseHandler)
 
-  explicit UnblockParsingPromiseHandler(nsIDocument* aDocument, Promise* aPromise)
+  explicit UnblockParsingPromiseHandler(nsIDocument* aDocument, Promise* aPromise,
+                                        const BlockParsingOptions& aOptions)
     : mPromise(aPromise)
   {
     nsCOMPtr<nsIParser> parser = aDocument->CreatorParserOrNull();
-    if (parser) {
+    if (parser && (aOptions.mBlockScriptCreated || !parser->IsScriptCreated())) {
       parser->BlockParser();
       mParser = do_GetWeakReference(parser);
       mDocument = aDocument;
     }
   }
 
   void
   ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
@@ -10955,24 +10956,25 @@ NS_IMPL_CYCLE_COLLECTION(UnblockParsingP
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(UnblockParsingPromiseHandler)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(UnblockParsingPromiseHandler)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(UnblockParsingPromiseHandler)
 
 already_AddRefed<Promise>
-nsIDocument::BlockParsing(Promise& aPromise, ErrorResult& aRv)
+nsIDocument::BlockParsing(Promise& aPromise, const BlockParsingOptions& aOptions, ErrorResult& aRv)
 {
   RefPtr<Promise> resultPromise = Promise::Create(aPromise.GetParentObject(), aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  RefPtr<PromiseNativeHandler> promiseHandler = new UnblockParsingPromiseHandler(this, resultPromise);
+  RefPtr<PromiseNativeHandler> promiseHandler = new UnblockParsingPromiseHandler(this, resultPromise,
+                                                                                 aOptions);
   aPromise.AppendNativeHandler(promiseHandler);
 
   return resultPromise.forget();
 }
 
 already_AddRefed<nsIURI>
 nsIDocument::GetMozDocumentURIIfNotForErrorPages()
 {
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2947,16 +2947,17 @@ public:
     return mStyleSheetChangeEventsEnabled;
   }
 
   void ObsoleteSheet(nsIURI *aSheetURI, mozilla::ErrorResult& rv);
 
   void ObsoleteSheet(const nsAString& aSheetURI, mozilla::ErrorResult& rv);
 
   already_AddRefed<mozilla::dom::Promise> BlockParsing(mozilla::dom::Promise& aPromise,
+                                                       const mozilla::dom::BlockParsingOptions& aOptions,
                                                        mozilla::ErrorResult& aRv);
 
   already_AddRefed<nsIURI> GetMozDocumentURIIfNotForErrorPages();
 
   // ParentNode
   nsIHTMLCollection* Children();
   uint32_t ChildElementCount();
 
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -380,23 +380,32 @@ partial interface Document {
   [ChromeOnly] readonly attribute nsIDocShell? docShell;
 
   [ChromeOnly] readonly attribute DOMString contentLanguage;
 
   [ChromeOnly] readonly attribute nsILoadGroup? documentLoadGroup;
 
   // Blocks the initial document parser until the given promise is settled.
   [ChromeOnly, Throws]
-  Promise<any> blockParsing(Promise<any> promise);
+  Promise<any> blockParsing(Promise<any> promise,
+                            optional BlockParsingOptions options);
 
   // like documentURI, except that for error pages, it returns the URI we were
   // trying to load when we hit an error, rather than the error page's own URI.
   [ChromeOnly] readonly attribute URI? mozDocumentURIIfNotForErrorPages;
 };
 
+dictionary BlockParsingOptions {
+  /**
+   * If true, blocks script-created parsers (created via document.open()) in
+   * addition to network-created parsers.
+   */
+  boolean blockScriptCreated = true;
+};
+
 // Extension to give chrome JS the ability to determine when a document was
 // created to satisfy an iframe with srcdoc attribute.
 partial interface Document {
   [ChromeOnly] readonly attribute boolean isSrcdocDocument;
 };
 
 
 // Extension to give chrome JS the ability to get the underlying