Browse Source

rip out more npapi

Frank-Rainer Grahl 2 years ago
parent
commit
263b3e5f3a

+ 604 - 0
mozilla-release/patches/1352567-1-58a1.patch

@@ -0,0 +1,604 @@
+# HG changeset patch
+# User Benjamin Smedberg <benjamin@smedbergs.us>
+# Date 1506973148 25200
+# Node ID 989ab34fd26da1673f0c1c03e5f555ecfdba6976
+# Parent  2f0af848b329345a397fd9c91f3f1982a4f47fbd
+Bug 1352567 - Remove tests for plugin stream behavior except NP_NORMAL, r=jimm
+
+MozReview-Commit-ID: 8ne3cKV1bxc
+
+diff --git a/dom/plugins/test/mochitest/mochitest.ini b/dom/plugins/test/mochitest/mochitest.ini
+--- a/dom/plugins/test/mochitest/mochitest.ini
++++ b/dom/plugins/test/mochitest/mochitest.ini
+@@ -36,9 +36,8 @@ skip-if = true # Bug 1267432
+ [test_positioning.html]
+ skip-if = true # disabled due to oddness, perhaps scrolling of the mochitest window?
+ [test_queryContentsScaleFactor.html]
+ skip-if = (toolkit != "cocoa") || (os != "win")
+ [test_queryContentsScaleFactorWindowed.html]
+ skip-if = (toolkit != "cocoa") || (os != "win")
+ [test_refresh_navigator_plugins.html]
+ skip-if = e10s # Bug 1090576
+-[test_twostreams.html]
+diff --git a/dom/plugins/test/mochitest/test_twostreams.html b/dom/plugins/test/mochitest/test_twostreams.html
+deleted file mode 100644
+--- a/dom/plugins/test/mochitest/test_twostreams.html
++++ /dev/null
+@@ -1,54 +0,0 @@
+-<html>
+-<head>
+-  <title>Dual NPAPI NP_ASFILEONLY NPStream Test</title>
+-  <script type="text/javascript" 
+-          src="/tests/SimpleTest/SimpleTest.js"></script>
+-  <script type="text/javascript" src="plugin-utils.js"></script>
+-  <link rel="stylesheet" type="text/css" 
+-        href="/tests/SimpleTest/test.css" />
+-</head>
+-<body>
+-  <p id="display"></p>
+-
+-  <script type="text/javascript">
+-  SimpleTest.expectAssertions(0, 2);
+-
+-  SimpleTest.waitForExplicitFinish();
+-  setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+-
+-  var framesToLoad = 2;
+-  function frameLoaded(id) {
+-    var frame = document.getElementById('testframe' + id);
+-    // We have to use SpecialPowers because nptest.cpp prepends
+-    // data: whichs makes the frame cross origin with the including page.
+-    var wrappedDoc = SpecialPowers.wrap(frame).contentDocument;
+-
+-    if (!wrappedDoc.body.innerHTML.length)
+-      return;
+-
+-    --framesToLoad;
+-    if (0 == framesToLoad) {
+-      var frame1 = document.getElementById('testframe1');
+-      var frame2 = document.getElementById('testframe2');
+-      var wrappedDocFrame1 = SpecialPowers.wrap(frame1).contentDocument;
+-      var wrappedDocFrame2 = SpecialPowers.wrap(frame2).contentDocument;
+-
+-      is(wrappedDocFrame1.body.innerHTML, wrappedDocFrame2.body.innerHTML,
+-         "Frame contents should match");
+-      SimpleTest.finish();
+-    }
+-  }
+-  </script>
+-
+-  <iframe id="testframe1" name="testframe1" onload="frameLoaded(1)"></iframe>
+-  <iframe id="testframe2" name="testframe2" onload="frameLoaded(2)"></iframe>
+-
+-  <embed src="loremipsum_nocache.txt" streammode="asfileonly"
+-         frame="testframe1"
+-         id="embedtest" style="width: 400px; height: 100px;"
+-         type="application/x-test"></embed>
+-  <embed src="loremipsum_nocache.txt" streammode="asfileonly"
+-	 frame="testframe2"
+-	 id="embedtest2" style="width: 400px; height: 100px;"
+-	 type="application/x-test"></embed>
+-
+diff --git a/dom/plugins/test/testplugin/README b/dom/plugins/test/testplugin/README
+--- a/dom/plugins/test/testplugin/README
++++ b/dom/plugins/test/testplugin/README
+@@ -297,20 +297,16 @@ is specified) send the data from that st
+ stream, whereupon it will be displayed in the specified frame.  If some
+ error occurs during stream processing, an error message will appear in the
+ frame instead of the stream data. If no "frame" attribute is present, a 
+ stream can still be received by the plugin, but the plugin will do nothing
+ with it.
+ 
+ The attributes which control stream tests are:
+ 
+-"streammode": one of "normal", "asfile", "asfileonly", "seek". Sets the
+-  stream mode to the specified mode in any call to NPP_NewStream.
+-  Defaults to "asfileonly".
+-
+ "streamchunksize": the number of bytes the plugin reports it can accept
+   in calls to NPP_WriteReady.  Defaults to 1,024.
+ 
+ "src": a url.  If specified, the browser will call NPP_NewStream for
+   this url as soon as the plugin is initialized.
+ 
+ "geturl": a url.  If specified, the plugin will request this url
+   from the browser when the plugin is initialized, via a call to
+@@ -328,25 +324,16 @@ The attributes which control stream test
+   element which instantiated the plugin. For any of the preceding three
+   attributes, a stream is received by the plugin via calls to NPP_NewStream,
+   NPP_WriteReady, NPP_Write, and NPP_DestroyStream.  When NPP_DestroyStream
+   is called (or NPP_UrlNotify, in the case of "geturlnotify"), and a 
+   "frame" attribute is present, the data from the stream is converted into a
+   data: url, and sent back to the browser in another stream via a call to
+   NPN_GetURL, whereupon it should be displayed in the specified frame.
+ 
+-"range": one or more byte ranges, in the format "offset,length;offset,length".
+-  Only valid when "streammode" = "seek".  When "range" is present, the plugin
+-  will request the specified byte ranges from the stream via a call to
+-  NPN_RequestRead, which it makes after the browser makes its final call to
+-  NPP_Write.  The plugin verifies that the browser makes additional calls
+-  to NPP_Write according to the requested byte ranges, and that the data
+-  received is correct.  Any errors will appear in the test "frame", if
+-  specified.
+-
+ "posturl": a url.  After the plugin receives a stream, and NPP_DestroyStream
+   is called, if "posturl" is specified, the plugin will post the contents
+   of the stream to the specified url via NPN_PostURL.  See "postmode" for
+   additional details.
+ 
+ "postmode": either "frame" or "stream".  If "frame", and a "frame" attribute
+   is present, the plugin will pass the frame name to calls to NPN_PostURL,
+   so that the HTTP response from that operation will be displayed in the
+@@ -363,20 +350,16 @@ The attributes which control stream test
+ "functiontofail": one of "npp_newstream", "npp_write", "npp_destroystream".
+   When specified, the given function will return an error code (-1 for
+   NPP_Write, or else the value of the "failurecode" attribute) the first time
+   it is called by the browser.
+ 
+ "failurecode": one of the NPError constants.  Used to specify the error
+   that will be returned by the "functiontofail".
+ 
+-If the plugin is instantiated as a full-page plugin, the following defaults
+-are used:
+-  streammode="seek" frame="testframe" range="100,100"
+-
+ * streamTest(url, doPost, postData, writeCallback, notifyCallback, redirectCallback, allowRedirects, postFile = false)
+ This will test how NPN_GetURLNotify and NPN_PostURLNotify behave when they are
+ called with arbitrary (malformed) URLs. The function will return `true` if
+ NPN_[Get/Post]URLNotify succeeds, and `false` if it fails.
+ @url url to request
+ @param doPost whether to call NPN_PostURLNotify
+ @param postData null, or a string to send a postdata
+ @writeCallback will be called when data is received for the stream
+diff --git a/dom/plugins/test/testplugin/nptest.cpp b/dom/plugins/test/testplugin/nptest.cpp
+--- a/dom/plugins/test/testplugin/nptest.cpp
++++ b/dom/plugins/test/testplugin/nptest.cpp
+@@ -421,49 +421,23 @@ static void clearIdentifiers()
+   memset(sPluginMethodIdentifiers, 0,
+       MOZ_ARRAY_LENGTH(sPluginMethodIdentifiers) * sizeof(NPIdentifier));
+   memset(sPluginPropertyIdentifiers, 0,
+       MOZ_ARRAY_LENGTH(sPluginPropertyIdentifiers) * sizeof(NPIdentifier));
+ 
+   sIdentifiersInitialized = false;
+ }
+ 
+-static void addRange(InstanceData* instanceData, const char* range)
+-{
+-  /*
+-  increased rangestr size from 16 to 17, the 17byte is only for
+-  null terminated value, maybe for actual capacity it needs 16 bytes
+-  */
+-  char rangestr[17];
+-  memset(rangestr, 0, sizeof(rangestr));
+-  strncpy(rangestr, range, sizeof(rangestr) - sizeof(char));
+-  const char* str1 = strtok(rangestr, ",");
+-  const char* str2 = str1 ? strtok(nullptr, ",") : nullptr;
+-  if (str1 && str2) {
+-    TestRange* byterange = new TestRange;
+-    byterange->offset = atoi(str1);
+-    byterange->length = atoi(str2);
+-    byterange->waiting = true;
+-    byterange->next = instanceData->testrange;
+-    instanceData->testrange = byterange;
+-  }
+-}
+-
+ static void sendBufferToFrame(NPP instance)
+ {
+   InstanceData* instanceData = (InstanceData*)(instance->pdata);
+   string outbuf;
+   if (!instanceData->npnNewStream) outbuf = "data:text/html,";
+   const char* buf = reinterpret_cast<char *>(instanceData->streamBuf);
+   int32_t bufsize = instanceData->streamBufSize;
+-  if (instanceData->streamMode == NP_ASFILE ||
+-      instanceData->streamMode == NP_ASFILEONLY) {
+-    buf = reinterpret_cast<char *>(instanceData->fileBuf);
+-    bufsize = instanceData->fileBufSize;
+-  }
+   if (instanceData->err.str().length() > 0) {
+     outbuf.append(instanceData->err.str());
+   }
+   else if (bufsize > 0) {
+     outbuf.append(buf);
+   }
+   else {
+     outbuf.append("Error: no data in buffer");
+@@ -667,17 +641,16 @@ static bool fillPluginFunctionTable(NPPl
+   if (pFuncs->size < (offsetof(NPPluginFuncs, getsiteswithdata) + sizeof(void*)))
+     return false;
+ 
+   pFuncs->newp = NPP_New;
+   pFuncs->destroy = NPP_Destroy;
+   pFuncs->setwindow = NPP_SetWindow;
+   pFuncs->newstream = NPP_NewStream;
+   pFuncs->destroystream = NPP_DestroyStream;
+-  pFuncs->asfile = NPP_StreamAsFile;
+   pFuncs->writeready = NPP_WriteReady;
+   pFuncs->write = NPP_Write;
+   pFuncs->print = NPP_Print;
+   pFuncs->event = NPP_HandleEvent;
+   pFuncs->urlnotify = NPP_URLNotify;
+   pFuncs->getvalue = NPP_GetValue;
+   pFuncs->setvalue = NPP_SetValue;
+   pFuncs->urlredirectnotify = NPP_URLRedirectNotify;
+@@ -773,30 +746,26 @@ NPP_New(NPMIMEType pluginType, NPP insta
+   if (!browserSupportsWindowless && !pluginSupportsWindowMode()) {
+     printf("Windowless mode not supported by the browser, windowed mode not supported by the plugin!\n");
+     return NPERR_GENERIC_ERROR;
+   }
+ 
+   // set up our our instance data
+   InstanceData* instanceData = new InstanceData;
+   instanceData->npp = instance;
+-  instanceData->streamMode = NP_ASFILEONLY;
+   instanceData->testFunction = FUNCTION_NONE;
+   instanceData->functionToFail = FUNCTION_NONE;
+   instanceData->failureCode = 0;
+   instanceData->callOnDestroy = nullptr;
+   instanceData->streamChunkSize = 1024;
+   instanceData->streamBuf = nullptr;
+   instanceData->streamBufSize = 0;
+-  instanceData->fileBuf = nullptr;
+-  instanceData->fileBufSize = 0;
+   instanceData->throwOnNextInvoke = false;
+   instanceData->runScriptOnPaint = false;
+   instanceData->dontTouchElement = false;
+-  instanceData->testrange = nullptr;
+   instanceData->hasWidget = false;
+   instanceData->npnNewStream = false;
+   instanceData->invalidateDuringPaint = false;
+   instanceData->slowPaint = false;
+   instanceData->playingAudio = false;
+   instanceData->audioMuted = false;
+   instanceData->writeCount = 0;
+   instanceData->writeReadyCount = 0;
+@@ -851,31 +820,16 @@ NPP_New(NPMIMEType pluginType, NPP insta
+     }
+     else if (strcmp(argn[i], "asyncmodel") == 0) {
+       if (strcmp(argv[i], "bitmap") == 0) {
+         requestAsyncDrawing = AD_BITMAP;
+       } else if (strcmp(argv[i], "dxgi") == 0) {
+         requestAsyncDrawing = AD_DXGI;
+       }
+     }
+-    if (strcmp(argn[i], "streammode") == 0) {
+-      if (strcmp(argv[i], "normal") == 0) {
+-        instanceData->streamMode = NP_NORMAL;
+-      }
+-      else if ((strcmp(argv[i], "asfile") == 0) &&
+-                strlen(argv[i]) == strlen("asfile")) {
+-        instanceData->streamMode = NP_ASFILE;
+-      }
+-      else if (strcmp(argv[i], "asfileonly") == 0) {
+-        instanceData->streamMode = NP_ASFILEONLY;
+-      }
+-      else if (strcmp(argv[i], "seek") == 0) {
+-        instanceData->streamMode = NP_SEEK;
+-      }
+-    }
+     if (strcmp(argn[i], "streamchunksize") == 0) {
+       instanceData->streamChunkSize = atoi(argv[i]);
+     }
+     if (strcmp(argn[i], "failurecode") == 0) {
+       instanceData->failureCode = atoi(argv[i]);
+     }
+     if (strcmp(argn[i], "functiontofail") == 0) {
+       instanceData->functionToFail = getFuncFromString(argv[i]);
+@@ -898,30 +852,16 @@ NPP_New(NPMIMEType pluginType, NPP insta
+       }
+       else if (strcmp(argv[i], "stream") == 0) {
+         instanceData->postMode = POSTMODE_STREAM;
+       }
+     }
+     if (strcmp(argn[i], "frame") == 0) {
+       instanceData->frame = argv[i];
+     }
+-    if (strcmp(argn[i], "range") == 0) {
+-      string range = argv[i];
+-      size_t semicolon = range.find(';');
+-      while (semicolon != string::npos) {
+-        addRange(instanceData, range.substr(0, semicolon).c_str());
+-        if (semicolon == range.length()) {
+-          range = "";
+-          break;
+-        }
+-        range = range.substr(semicolon + 1);
+-        semicolon = range.find(';');
+-      }
+-      if (range.length()) addRange(instanceData, range.c_str());
+-    }
+     if (strcmp(argn[i], "newstream") == 0 &&
+         strcmp(argv[i], "true") == 0) {
+       instanceData->npnNewStream = true;
+     }
+     if (strcmp(argn[i], "newcrash") == 0) {
+       IntentionalCrash();
+     }
+     if (strcmp(argn[i], "paintscript") == 0) {
+@@ -956,25 +896,16 @@ NPP_New(NPMIMEType pluginType, NPP insta
+       if (alreadyHasSalign) {
+         // If salign came before this parameter, error out now.
+         return NPERR_GENERIC_ERROR;
+       }
+     }
+     if (strcmp(argn[i], "salign") == 0) {
+       alreadyHasSalign = true;
+     }
+-
+-    // We don't support NP_FULL any more, but name="plugin" is an indication
+-    // that we're a full-page plugin. We use default seek parameters for
+-    // test_fullpage.html
+-    if (strcmp(argn[i], "name") == 0 && strcmp(argv[i], "plugin") == 0) {
+-      instanceData->streamMode = NP_SEEK;
+-      instanceData->frame = "testframe";
+-      addRange(instanceData, "100,100");
+-    }
+   }
+ 
+   if (!browserSupportsWindowless || !pluginSupportsWindowlessMode()) {
+     requestWindow = true;
+   } else if (!pluginSupportsWindowMode()) {
+     requestWindow = false;
+   }
+   if (requestWindow) {
+@@ -1091,27 +1022,16 @@ NPP_Destroy(NPP instance, NPSavedData** 
+     NPN_InvokeDefault(instance, instanceData->callOnDestroy, nullptr, 0, &result);
+     NPN_ReleaseVariantValue(&result);
+     NPN_ReleaseObject(instanceData->callOnDestroy);
+   }
+ 
+   if (instanceData->streamBuf) {
+     free(instanceData->streamBuf);
+   }
+-  if (instanceData->fileBuf) {
+-    free(instanceData->fileBuf);
+-  }
+-
+-  TestRange* currentrange = instanceData->testrange;
+-  TestRange* nextrange;
+-  while (currentrange != nullptr) {
+-    nextrange = reinterpret_cast<TestRange*>(currentrange->next);
+-    delete currentrange;
+-    currentrange = nextrange;
+-  }
+ 
+   if (instanceData->frontBuffer) {
+     NPN_SetCurrentAsyncSurface(instance, nullptr, nullptr);
+     NPN_FinalizeAsyncSurface(instance, instanceData->frontBuffer);
+     NPN_MemFree(instanceData->frontBuffer);
+   }
+   if (instanceData->backBuffer) {
+     NPN_FinalizeAsyncSurface(instance, instanceData->backBuffer);
+@@ -1216,17 +1136,17 @@ NPP_NewStream(NPP instance, NPMIMEType t
+   }
+ 
+   if (stream->notifyData &&
+       static_cast<URLNotifyData*>(stream->notifyData) != &kNotifyData) {
+     // stream from streamTest
+     *stype = NP_NORMAL;
+   }
+   else {
+-    *stype = instanceData->streamMode;
++    *stype = NP_NORMAL;
+ 
+     if (instanceData->streamBufSize) {
+       free(instanceData->streamBuf);
+       instanceData->streamBufSize = 0;
+       if (instanceData->testFunction == FUNCTION_NPP_POSTURL &&
+           instanceData->postMode == POSTMODE_STREAM) {
+         instanceData->testFunction = FUNCTION_NPP_GETURL;
+       }
+@@ -1264,36 +1184,16 @@ NPP_DestroyStream(NPP instance, NPStream
+     return instanceData->failureCode;
+   }
+ 
+   URLNotifyData* nd = static_cast<URLNotifyData*>(stream->notifyData);
+   if (nd && nd != &kNotifyData) {
+     return NPERR_NO_ERROR;
+   }
+ 
+-  if (instanceData->streamMode == NP_ASFILE &&
+-      instanceData->functionToFail == FUNCTION_NONE) {
+-    if (!instanceData->streamBuf) {
+-      instanceData->err <<
+-        "Error: no data written with NPP_Write";
+-      return NPERR_GENERIC_ERROR;
+-    }
+-
+-    if (!instanceData->fileBuf) {
+-      instanceData->err <<
+-        "Error: no data written with NPP_StreamAsFile";
+-      return NPERR_GENERIC_ERROR;
+-    }
+-
+-    if (strcmp(reinterpret_cast<char *>(instanceData->fileBuf),
+-               reinterpret_cast<char *>(instanceData->streamBuf))) {
+-      instanceData->err <<
+-        "Error: data passed to NPP_Write and NPP_StreamAsFile differed";
+-    }
+-  }
+   if (instanceData->frame.length() > 0 &&
+       instanceData->testFunction != FUNCTION_NPP_GETURLNOTIFY &&
+       instanceData->testFunction != FUNCTION_NPP_POSTURL) {
+     sendBufferToFrame(instance);
+   }
+   if (instanceData->testFunction == FUNCTION_NPP_POSTURL) {
+     NPError err = NPN_PostURL(instance, instanceData->testUrl.c_str(),
+       instanceData->postMode == POSTMODE_FRAME ? instanceData->frame.c_str() : nullptr,
+@@ -1365,50 +1265,26 @@ NPP_Write(NPP instance, NPStream* stream
+ 
+   if (nd && nd != &kNotifyData) {
+     uint32_t newsize = nd->size + len;
+     nd->data = (char*) realloc(nd->data, newsize);
+     memcpy(nd->data + nd->size, buffer, len);
+     nd->size = newsize;
+     return len;
+   }
+-  if (instanceData->streamMode == NP_SEEK &&
+-      stream->end != 0 &&
+-      stream->end == ((uint32_t)instanceData->streamBufSize + len)) {
+-    // If the complete stream has been written, and we're doing a seek test,
+-    // then call NPN_RequestRead.
+-    // prevent recursion
+-    instanceData->streamMode = NP_NORMAL;
+-
+-    if (instanceData->testrange != nullptr) {
+-      NPError err = NPN_RequestRead(stream, instanceData->testrange);
+-      if (err != NPERR_NO_ERROR) {
+-        instanceData->err << "NPN_RequestRead returned error %d" << err;
+-      }
+-      printf("called NPN_RequestRead, return %d\n", err);
+-    }
+-  }
+ 
+   char* streamBuf = reinterpret_cast<char *>(instanceData->streamBuf);
+   if (offset + len <= instanceData->streamBufSize) {
+     if (memcmp(buffer, streamBuf + offset, len)) {
+       instanceData->err <<
+-          "Error: data written from NPN_RequestRead doesn't match";
++          "Error: data written doesn't match";
+     }
+     else {
+       printf("data matches!\n");
+     }
+-    TestRange* range = instanceData->testrange;
+-    while(range != nullptr) {
+-      if (offset == range->offset &&
+-        (uint32_t)len == range->length) {
+-        range->waiting = false;
+-      }
+-      range = reinterpret_cast<TestRange*>(range->next);
+-    }
+   }
+   else {
+     if (instanceData->streamBufSize == 0) {
+       instanceData->streamBuf = malloc(len + 1);
+       streamBuf = reinterpret_cast<char *>(instanceData->streamBuf);
+     }
+     else {
+       instanceData->streamBuf =
+@@ -1419,53 +1295,16 @@ NPP_Write(NPP instance, NPStream* stream
+     memcpy(streamBuf + instanceData->streamBufSize, buffer, len);
+     instanceData->streamBufSize = instanceData->streamBufSize + len;
+     streamBuf[instanceData->streamBufSize] = '\0';
+   }
+   return len;
+ }
+ 
+ void
+-NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
+-{
+-  size_t size;
+-
+-  InstanceData* instanceData = (InstanceData*)(instance->pdata);
+-
+-  if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM ||
+-      instanceData->functionToFail == FUNCTION_NPP_WRITE) {
+-    instanceData->err << "NPP_StreamAsFile called";
+-  }
+-
+-  if (!fname)
+-    return;
+-
+-  FILE *file = fopen(fname, "rb");
+-  if (file) {
+-    fseek(file, 0, SEEK_END);
+-    size = ftell(file);
+-    instanceData->fileBuf = malloc((int32_t)size + 1);
+-    char* buf = reinterpret_cast<char *>(instanceData->fileBuf);
+-    fseek(file, 0, SEEK_SET);
+-    size_t sizeRead = fread(instanceData->fileBuf, 1, size, file);
+-    if (sizeRead != size) {
+-      printf("Unable to read data from file\n");
+-      instanceData->err << "Unable to read data from file " << fname;
+-    }
+-    fclose(file);
+-    buf[size] = '\0';
+-    instanceData->fileBufSize = (int32_t)size;
+-  }
+-  else {
+-    printf("Unable to open file\n");
+-    instanceData->err << "Unable to open file " << fname;
+-  }
+-}
+-
+-void
+ NPP_Print(NPP instance, NPPrint* platformPrint)
+ {
+ }
+ 
+ int16_t
+ NPP_HandleEvent(NPP instance, void* event)
+ {
+   InstanceData* instanceData = (InstanceData*)(instance->pdata);
+@@ -1819,22 +1658,16 @@ NPN_GetURLNotify(NPP instance, const cha
+ 
+ NPError
+ NPN_GetURL(NPP instance, const char* url, const char* target)
+ {
+   return sBrowserFuncs->geturl(instance, url, target);
+ }
+ 
+ NPError
+-NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
+-{
+-  return sBrowserFuncs->requestread(stream, rangeList);
+-}
+-
+-NPError
+ NPN_PostURLNotify(NPP instance, const char* url,
+                   const char* target, uint32_t len,
+                   const char* buf, NPBool file, void* notifyData)
+ {
+   return sBrowserFuncs->posturlnotify(instance, url, target, len, buf, file, notifyData);
+ }
+ 
+ NPError
+diff --git a/dom/plugins/test/testplugin/nptest.h b/dom/plugins/test/testplugin/nptest.h
+--- a/dom/plugins/test/testplugin/nptest.h
++++ b/dom/plugins/test/testplugin/nptest.h
+@@ -86,20 +86,16 @@ typedef enum {
+ typedef struct TestNPObject : NPObject {
+   NPP npp;
+   DrawMode drawMode;
+   uint32_t drawColor; // 0xAARRGGBB
+ } TestNPObject;
+ 
+ typedef struct _PlatformData PlatformData;
+ 
+-typedef struct TestRange : NPByteRange {
+-  bool waiting;
+-} TestRange;
+-
+ typedef struct InstanceData {
+   NPP npp;
+   NPWindow window;
+   TestNPObject* scriptableObject;
+   PlatformData* platformData;
+   int32_t instanceCountWatchGeneration;
+   bool lastReportedPrivateModeState;
+   bool hasWidget;
+@@ -125,23 +121,19 @@ typedef struct InstanceData {
+   TestFunction functionToFail;
+   NPError failureCode;
+   NPObject* callOnDestroy;
+   PostMode postMode;
+   std::string testUrl;
+   std::string frame;
+   std::string timerTestScriptCallback;
+   std::ostringstream err;
+-  uint16_t streamMode;
+   int32_t streamChunkSize;
+   int32_t streamBufSize;
+-  int32_t fileBufSize;
+-  TestRange* testrange;
+   void* streamBuf;
+-  void* fileBuf;
+   bool crashOnDestroy;
+   bool cleanupWidget;
+   ActivationState topLevelWindowActivationState;
+   int32_t topLevelWindowActivationEventCount;
+   ActivationState focusState;
+   int32_t focusEventCount;
+   int32_t eventModel;
+   bool closeStream;

+ 511 - 0
mozilla-release/patches/1352567-2-58a1.patch

@@ -0,0 +1,511 @@
+# HG changeset patch
+# User Benjamin Smedberg <benjamin@smedbergs.us>
+# Date 1506973755 25200
+# Node ID 0dfd227a6a20a7eec7c41b84381e63e8718fd861
+# Parent  7e90129c43f6a51377117551c2a8a01740cc96bd
+Bug 1352567 - Remove plugin IPC code to support stream types other than NP_NORMAL (seekable and/or file streams), r=jimm
+
+MozReview-Commit-ID: FWl2gcpKy6D
+
+diff --git a/dom/plugins/ipc/BrowserStreamChild.cpp b/dom/plugins/ipc/BrowserStreamChild.cpp
+--- a/dom/plugins/ipc/BrowserStreamChild.cpp
++++ b/dom/plugins/ipc/BrowserStreamChild.cpp
+@@ -17,17 +17,16 @@ BrowserStreamChild::BrowserStreamChild(P
+                                        const uint32_t& length,
+                                        const uint32_t& lastmodified,
+                                        StreamNotifyChild* notifyData,
+                                        const nsCString& headers)
+   : mInstance(instance)
+   , mStreamStatus(kStreamOpen)
+   , mDestroyPending(NOT_DESTROYED)
+   , mNotifyPending(false)
+-  , mStreamAsFilePending(false)
+   , mInstanceDying(false)
+   , mState(CONSTRUCTING)
+   , mURL(url)
+   , mHeaders(headers)
+   , mStreamNotify(notifyData)
+   , mDeliveryTracker(this)
+ {
+   PLUGIN_LOG_DEBUG(("%s (%s, %i, %i, %p, %s)", FULLFUNCTION,
+@@ -55,16 +54,25 @@ BrowserStreamChild::StreamConstructed(
+             uint16_t* stype)
+ {
+   NPError rv = NPERR_NO_ERROR;
+ 
+   *stype = NP_NORMAL;
+   rv = mInstance->mPluginIface->newstream(
+     &mInstance->mData, const_cast<char*>(NullableStringGet(mimeType)),
+     &mStream, seekable, stype);
++
++  // NP_NORMAL is the only permissible stream type
++  if (*stype != NP_NORMAL) {
++    rv = NPERR_INVALID_PARAM;
++    // The plugin thinks the stream is alive, so we kill it explicitly
++    (void) mInstance->mPluginIface
++      ->destroystream(&mInstance->mData, &mStream, NPRES_NETWORK_ERR);
++  }
++
+   if (rv != NPERR_NO_ERROR) {
+     mState = DELETING;
+     if (mStreamNotify) {
+       mStreamNotify->SetAssociatedStream(nullptr);
+       mStreamNotify = nullptr;
+     }
+   }
+   else {
+@@ -104,36 +112,16 @@ BrowserStreamChild::RecvWrite(const int3
+   newdata->curpos = 0;
+ 
+   EnsureDeliveryPending();
+ 
+   return IPC_OK();
+ }
+ 
+ mozilla::ipc::IPCResult
+-BrowserStreamChild::RecvNPP_StreamAsFile(const nsCString& fname)
+-{
+-  PLUGIN_LOG_DEBUG(("%s (fname=%s)", FULLFUNCTION, fname.get()));
+-
+-  AssertPluginThread();
+-
+-  if (ALIVE != mState)
+-    MOZ_CRASH("Unexpected state: received file after NPP_DestroyStream?");
+-
+-  if (kStreamOpen != mStreamStatus)
+-    return IPC_OK();
+-
+-  mStreamAsFilePending = true;
+-  mStreamAsFileName = fname;
+-  EnsureDeliveryPending();
+-
+-  return IPC_OK();
+-}
+-
+-mozilla::ipc::IPCResult
+ BrowserStreamChild::RecvNPP_DestroyStream(const NPReason& reason)
+ {
+   PLUGIN_LOG_DEBUG_METHOD;
+ 
+   if (ALIVE != mState)
+     MOZ_CRASH("Unexpected state: recevied NPP_DestroyStream twice?");
+ 
+   mState = DYING;
+@@ -151,37 +139,16 @@ BrowserStreamChild::Recv__delete__()
+   AssertPluginThread();
+ 
+   if (DELETING != mState)
+     MOZ_CRASH("Bad state, not DELETING");
+ 
+   return IPC_OK();
+ }
+ 
+-NPError
+-BrowserStreamChild::NPN_RequestRead(NPByteRange* aRangeList)
+-{
+-  PLUGIN_LOG_DEBUG_FUNCTION;
+-
+-  AssertPluginThread();
+-
+-  if (ALIVE != mState || kStreamOpen != mStreamStatus)
+-    return NPERR_GENERIC_ERROR;
+-
+-  IPCByteRanges ranges;
+-  for (; aRangeList; aRangeList = aRangeList->next) {
+-    IPCByteRange br = {aRangeList->offset, aRangeList->length};
+-    ranges.AppendElement(br);
+-  }
+-
+-  NPError result;
+-  CallNPN_RequestRead(ranges, &result);
+-  return result;
+-}
+-
+ void
+ BrowserStreamChild::EnsureDeliveryPending()
+ {
+   MessageLoop::current()->PostTask(
+     mDeliveryTracker.NewRunnableMethod(&BrowserStreamChild::Deliver));
+ }
+ 
+ void
+@@ -194,30 +161,16 @@ BrowserStreamChild::Deliver()
+     }
+   }
+   ClearSuspendedTimer();
+ 
+   NS_ASSERTION(kStreamOpen != mStreamStatus || 0 == mPendingData.Length(),
+                "Exit out of the data-delivery loop with pending data");
+   mPendingData.Clear();
+ 
+-  // NPP_StreamAsFile() is documented (at MDN) to be called "when the stream
+-  // is complete" -- i.e. after all calls to NPP_WriteReady() and NPP_Write()
+-  // have finished.  We make these calls asynchronously (from
+-  // DeliverPendingData()).  So we need to make sure all the "pending data"
+-  // has been "delivered" before calling NPP_StreamAsFile() (also
+-  // asynchronously).  Doing this resolves bug 687610, bug 670036 and possibly
+-  // also other bugs.
+-  if (mStreamAsFilePending) {
+-    if (mStreamStatus == kStreamOpen)
+-      mInstance->mPluginIface->asfile(&mInstance->mData, &mStream,
+-                                      mStreamAsFileName.get());
+-    mStreamAsFilePending = false;
+-  }
+-
+   if (DESTROY_PENDING == mDestroyPending) {
+     mDestroyPending = DESTROYED;
+     if (mState != DYING)
+       MOZ_CRASH("mDestroyPending but state not DYING");
+ 
+     NS_ASSERTION(NPRES_DONE != mStreamStatus, "Success status set too early!");
+     if (kStreamOpen == mStreamStatus)
+       mStreamStatus = NPRES_DONE;
+diff --git a/dom/plugins/ipc/BrowserStreamChild.h b/dom/plugins/ipc/BrowserStreamChild.h
+--- a/dom/plugins/ipc/BrowserStreamChild.h
++++ b/dom/plugins/ipc/BrowserStreamChild.h
+@@ -33,33 +33,30 @@ public:
+   NPError StreamConstructed(
+             const nsCString& mimeType,
+             const bool& seekable,
+             uint16_t* stype);
+ 
+   virtual mozilla::ipc::IPCResult RecvWrite(const int32_t& offset,
+                                             const uint32_t& newsize,
+                                             const Buffer& data) override;
+-  virtual mozilla::ipc::IPCResult RecvNPP_StreamAsFile(const nsCString& fname) override;
+   virtual mozilla::ipc::IPCResult RecvNPP_DestroyStream(const NPReason& reason) override;
+   virtual mozilla::ipc::IPCResult Recv__delete__() override;
+ 
+   void EnsureCorrectInstance(PluginInstanceChild* i)
+   {
+     if (i != mInstance)
+       MOZ_CRASH("Incorrect stream instance");
+   }
+   void EnsureCorrectStream(NPStream* s)
+   {
+     if (s != &mStream)
+       MOZ_CRASH("Incorrect stream data");
+   }
+ 
+-  NPError NPN_RequestRead(NPByteRange* aRangeList);
+-
+   void NotifyPending() {
+     NS_ASSERTION(!mNotifyPending, "Pending twice?");
+     mNotifyPending = true;
+     EnsureDeliveryPending();
+   }
+ 
+   /**
+    * During instance destruction, artificially cancel all outstanding streams.
+@@ -125,18 +122,16 @@ private:
+    * all data has been delivered.
+    */
+   enum {
+     NOT_DESTROYED, // NPP_DestroyStream not yet received
+     DESTROY_PENDING, // NPP_DestroyStream received, not yet delivered
+     DESTROYED // NPP_DestroyStream delivered, NPP_URLNotify may still be pending
+   } mDestroyPending;
+   bool mNotifyPending;
+-  bool mStreamAsFilePending;
+-  nsCString mStreamAsFileName;
+ 
+   // When NPP_Destroy is called for our instance (manager), this flag is set
+   // cancels the stream and avoids sending StreamDestroyed.
+   bool mInstanceDying;
+ 
+   enum {
+     CONSTRUCTING,
+     ALIVE,
+diff --git a/dom/plugins/ipc/BrowserStreamParent.cpp b/dom/plugins/ipc/BrowserStreamParent.cpp
+--- a/dom/plugins/ipc/BrowserStreamParent.cpp
++++ b/dom/plugins/ipc/BrowserStreamParent.cpp
+@@ -38,58 +38,16 @@ BrowserStreamParent::~BrowserStreamParen
+ }
+ 
+ void
+ BrowserStreamParent::ActorDestroy(ActorDestroyReason aWhy)
+ {
+   // Implement me! Bug 1005159
+ }
+ 
+-mozilla::ipc::IPCResult
+-BrowserStreamParent::AnswerNPN_RequestRead(const IPCByteRanges& ranges,
+-                                           NPError* result)
+-{
+-  PLUGIN_LOG_DEBUG_FUNCTION;
+-
+-  switch (mState) {
+-  case INITIALIZING:
+-    NS_ERROR("Requesting a read before initialization has completed");
+-    *result = NPERR_GENERIC_ERROR;
+-    return IPC_FAIL_NO_REASON(this);
+-
+-  case ALIVE:
+-    break;
+-
+-  case DYING:
+-    *result = NPERR_GENERIC_ERROR;
+-    return IPC_OK();
+-
+-  default:
+-    NS_ERROR("Unexpected state");
+-    return IPC_FAIL_NO_REASON(this);
+-  }
+-
+-  if (!mStream)
+-    return IPC_FAIL_NO_REASON(this);
+-
+-  if (ranges.Length() > INT32_MAX)
+-    return IPC_FAIL_NO_REASON(this);
+-
+-  UniquePtr<NPByteRange[]> rp(new NPByteRange[ranges.Length()]);
+-  for (uint32_t i = 0; i < ranges.Length(); ++i) {
+-    rp[i].offset = ranges[i].offset;
+-    rp[i].length = ranges[i].length;
+-    rp[i].next = &rp[i + 1];
+-  }
+-  rp[ranges.Length() - 1].next = nullptr;
+-
+-  *result = mNPP->mNPNIface->requestread(mStream, rp.get());
+-  return IPC_OK();
+-}
+-
+ void
+ BrowserStreamParent::NPP_DestroyStream(NPReason reason)
+ {
+   NS_ASSERTION(ALIVE == mState || INITIALIZING == mState,
+                "NPP_DestroyStream called twice?");
+   bool stillInitializing = INITIALIZING == mState;
+   if (stillInitializing) {
+     mState = DEFERRING_DESTROY;
+@@ -140,29 +98,10 @@ BrowserStreamParent::Write(int32_t offse
+     len = kSendDataChunk;
+ 
+   return SendWrite(offset,
+                    mStream->end,
+                    nsCString(static_cast<char*>(buffer), len)) ?
+     len : -1;
+ }
+ 
+-void
+-BrowserStreamParent::StreamAsFile(const char* fname)
+-{
+-  PLUGIN_LOG_DEBUG_FUNCTION;
+-
+-  NS_ASSERTION(ALIVE == mState,
+-               "Calling streamasfile after NPP_DestroyStream?");
+-
+-  // Make sure our stream survives until the plugin process tells us we've
+-  // been destroyed (until RecvStreamDestroyed() is called).  Since we retain
+-  // mStreamPeer at most once, we won't get in trouble if StreamAsFile() is
+-  // called more than once.
+-  if (!mStreamPeer) {
+-    nsNPAPIPlugin::RetainStream(mStream, getter_AddRefs(mStreamPeer));
+-  }
+-
+-  Unused << SendNPP_StreamAsFile(nsCString(fname));
+-}
+-
+ } // namespace plugins
+ } // namespace mozilla
+diff --git a/dom/plugins/ipc/BrowserStreamParent.h b/dom/plugins/ipc/BrowserStreamParent.h
+--- a/dom/plugins/ipc/BrowserStreamParent.h
++++ b/dom/plugins/ipc/BrowserStreamParent.h
+@@ -25,24 +25,20 @@ public:
+   BrowserStreamParent(PluginInstanceParent* npp,
+                       NPStream* stream);
+   virtual ~BrowserStreamParent();
+ 
+   virtual bool IsBrowserStream() override { return true; }
+ 
+   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+ 
+-  virtual mozilla::ipc::IPCResult AnswerNPN_RequestRead(const IPCByteRanges& ranges,
+-                                                        NPError* result) override;
+-
+   virtual mozilla::ipc::IPCResult RecvStreamDestroyed() override;
+ 
+   int32_t WriteReady();
+   int32_t Write(int32_t offset, int32_t len, void* buffer);
+-  void StreamAsFile(const char* fname);
+ 
+   void NPP_DestroyStream(NPReason reason);
+ 
+   void SetAlive()
+   {
+     if (mState == INITIALIZING) {
+       mState = ALIVE;
+     }
+diff --git a/dom/plugins/ipc/PBrowserStream.ipdl b/dom/plugins/ipc/PBrowserStream.ipdl
+--- a/dom/plugins/ipc/PBrowserStream.ipdl
++++ b/dom/plugins/ipc/PBrowserStream.ipdl
+@@ -21,47 +21,22 @@ namespace plugins {
+ 
+ intr protocol PBrowserStream
+ {
+   manager PPluginInstance;
+ 
+ child:
+   async Write(int32_t offset, uint32_t newlength,
+               Buffer data);
+-  async NPP_StreamAsFile(nsCString fname);
+ 
+   /**
+    * NPP_DestroyStream may race with other messages: the child acknowledges
+    * the message with StreamDestroyed before this actor is deleted.
+    */
+   async NPP_DestroyStream(NPReason reason);
+   async __delete__();
+ 
+ parent:
+-  intr NPN_RequestRead(IPCByteRanges ranges)
+-    returns (NPError result);
+   async StreamDestroyed();
+-
+-/*
+-  TODO: turn on state machine.
+-
+-  // need configurable start state: if the constructor
+-  // returns an error in result, start state should
+-  // be DELETING.
+-start state ALIVE:
+-  send Write goto ALIVE;
+-  call NPP_StreamAsFile goto ALIVE;
+-  send NPP_DestroyStream goto ALIVE;
+-  answer NPN_RequestRead goto ALIVE;
+-  recv NPN_DestroyStream goto DYING;
+-
+-state DYING:
+-  answer NPN_RequestRead goto DYING;
+-  recv NPN_DestroyStream goto DYING;
+-  recv StreamDestroyed goto DELETING;
+-
+-state DELETING:
+-  send __delete__;
+-*/
+ };
+ 
+ } // namespace plugins
+ } // namespace mozilla
+diff --git a/dom/plugins/ipc/PluginModuleChild.cpp b/dom/plugins/ipc/PluginModuleChild.cpp
+--- a/dom/plugins/ipc/PluginModuleChild.cpp
++++ b/dom/plugins/ipc/PluginModuleChild.cpp
+@@ -1035,23 +1035,17 @@ InstCast(NPP aNPP)
+ namespace mozilla {
+ namespace plugins {
+ namespace child {
+ 
+ NPError
+ _requestread(NPStream* aStream,
+              NPByteRange* aRangeList)
+ {
+-    PLUGIN_LOG_DEBUG_FUNCTION;
+-    ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
+-
+-    BrowserStreamChild* bs =
+-        static_cast<BrowserStreamChild*>(static_cast<AStream*>(aStream->ndata));
+-    bs->EnsureCorrectStream(aStream);
+-    return bs->NPN_RequestRead(aRangeList);
++    return NPERR_STREAM_NOT_SEEKABLE;
+ }
+ 
+ NPError
+ _geturlnotify(NPP aNPP,
+               const char* aRelativeURL,
+               const char* aTarget,
+               void* aNotifyData)
+ {
+diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp
+--- a/dom/plugins/ipc/PluginModuleParent.cpp
++++ b/dom/plugins/ipc/PluginModuleParent.cpp
+@@ -1662,17 +1662,16 @@ PluginModuleParent::SetPluginFuncs(NPPlu
+     aFuncs->newp = nullptr;
+     aFuncs->clearsitedata = nullptr;
+     aFuncs->getsiteswithdata = nullptr;
+ 
+     aFuncs->destroy = NPP_Destroy;
+     aFuncs->setwindow = NPP_SetWindow;
+     aFuncs->newstream = NPP_NewStream;
+     aFuncs->destroystream = NPP_DestroyStream;
+-    aFuncs->asfile = NPP_StreamAsFile;
+     aFuncs->writeready = NPP_WriteReady;
+     aFuncs->write = NPP_Write;
+     aFuncs->print = NPP_Print;
+     aFuncs->event = NPP_HandleEvent;
+     aFuncs->urlnotify = NPP_URLNotify;
+     aFuncs->getvalue = NPP_GetValue;
+     aFuncs->setvalue = NPP_SetValue;
+     aFuncs->gotfocus = nullptr;
+@@ -1758,28 +1757,16 @@ PluginModuleParent::NPP_Write(NPP instan
+     BrowserStreamParent* s = StreamCast(instance, stream);
+     if (!s)
+         return -1;
+ 
+     return s->Write(offset, len, buffer);
+ }
+ 
+ void
+-PluginModuleParent::NPP_StreamAsFile(NPP instance,
+-                                     NPStream* stream,
+-                                     const char* fname)
+-{
+-    BrowserStreamParent* s = StreamCast(instance, stream);
+-    if (!s)
+-        return;
+-
+-    s->StreamAsFile(fname);
+-}
+-
+-void
+ PluginModuleParent::NPP_Print(NPP instance, NPPrint* platformPrint)
+ {
+ 
+     PluginInstanceParent* pip = PluginInstanceParent::Cast(instance);
+     return pip ? pip->NPP_Print(platformPrint) : (void)0;
+ }
+ 
+ int16_t
+diff --git a/dom/plugins/ipc/PluginModuleParent.h b/dom/plugins/ipc/PluginModuleParent.h
+--- a/dom/plugins/ipc/PluginModuleParent.h
++++ b/dom/plugins/ipc/PluginModuleParent.h
+@@ -215,18 +215,16 @@ protected:
+     static NPError NPP_SetWindow(NPP instance, NPWindow* window);
+     static NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream,
+                                  NPBool seekable, uint16_t* stype);
+     static NPError NPP_DestroyStream(NPP instance,
+                                      NPStream* stream, NPReason reason);
+     static int32_t NPP_WriteReady(NPP instance, NPStream* stream);
+     static int32_t NPP_Write(NPP instance, NPStream* stream,
+                              int32_t offset, int32_t len, void* buffer);
+-    static void NPP_StreamAsFile(NPP instance,
+-                                 NPStream* stream, const char* fname);
+     static void NPP_Print(NPP instance, NPPrint* platformPrint);
+     static int16_t NPP_HandleEvent(NPP instance, void* event);
+     static void NPP_URLNotify(NPP instance, const char* url,
+                               NPReason reason, void* notifyData);
+     static NPError NPP_GetValue(NPP instance,
+                                 NPPVariable variable, void *ret_value);
+     static NPError NPP_SetValue(NPP instance, NPNVariable variable,
+                                 void *value);
+diff --git a/ipc/ipdl/sync-messages.ini b/ipc/ipdl/sync-messages.ini
+--- a/ipc/ipdl/sync-messages.ini
++++ b/ipc/ipdl/sync-messages.ini
+@@ -913,18 +913,16 @@ description =
+ [PGMPVideoDecoder::NeedShmem]
+ description =
+ [PGMPVideoEncoder::NeedShmem]
+ description =
+ [PVideoDecoderManager::PVideoDecoder]
+ description =
+ [PVideoDecoderManager::Readback]
+ description =
+-[PBrowserStream::NPN_RequestRead]
+-description =
+ [PBackgroundStorage::Preload]
+ description =
+ [PRemoteSpellcheckEngine::Check]
+ description =
+ [PRemoteSpellcheckEngine::CheckAndSuggest]
+ description =
+ [PRemoteSpellcheckEngine::SetDictionary]
+ description =

+ 1369 - 0
mozilla-release/patches/1352567-3-58a1.patch

@@ -0,0 +1,1369 @@
+# HG changeset patch
+# User Benjamin Smedberg <benjamin@smedbergs.us>
+# Date 1506973895 25200
+# Node ID 3eca597f346fda5899c7da9237b1b35327b312d0
+# Parent  0b77cf4789d4d197b0040056696dcfaefb103b51
+Bug 1352567 - Remove NPAPI seekable and file streams from the dom/plugins/base code, r=jimm
+
+MozReview-Commit-ID: 4qxEFjTKMVZ
+
+diff --git a/dom/plugins/base/nsNPAPIPlugin.cpp b/dom/plugins/base/nsNPAPIPlugin.cpp
+--- a/dom/plugins/base/nsNPAPIPlugin.cpp
++++ b/dom/plugins/base/nsNPAPIPlugin.cpp
+@@ -1705,56 +1705,17 @@ NPError
+     default:
+       return NPERR_GENERIC_ERROR;
+   }
+ }
+ 
+ NPError
+ _requestread(NPStream *pstream, NPByteRange *rangeList)
+ {
+-  if (!NS_IsMainThread()) {
+-    NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_requestread called from the wrong thread\n"));
+-    return NPERR_INVALID_PARAM;
+-  }
+-  NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_RequestRead: stream=%p\n",
+-                                     (void*)pstream));
+-
+-#ifdef PLUGIN_LOGGING
+-  for(NPByteRange * range = rangeList; range != nullptr; range = range->next)
+-    MOZ_LOG(nsPluginLogging::gNPNLog,PLUGIN_LOG_NOISY,
+-    ("%i-%i", range->offset, range->offset + range->length - 1));
+-
+-  MOZ_LOG(nsPluginLogging::gNPNLog,PLUGIN_LOG_NOISY, ("\n\n"));
+-  PR_LogFlush();
+-#endif
+-
+-  if (!pstream || !rangeList || !pstream->ndata)
+-    return NPERR_INVALID_PARAM;
+-
+-  nsNPAPIStreamWrapper* streamWrapper = static_cast<nsNPAPIStreamWrapper*>(pstream->ndata);
+-  nsNPAPIPluginStreamListener* streamlistener = streamWrapper->GetStreamListener();
+-  if (!streamlistener) {
+-    return NPERR_GENERIC_ERROR;
+-  }
+-
+-  int32_t streamtype = NP_NORMAL;
+-
+-  streamlistener->GetStreamType(&streamtype);
+-
+-  if (streamtype != NP_SEEK)
+-    return NPERR_STREAM_NOT_SEEKABLE;
+-
+-  if (!streamlistener->mStreamListenerPeer)
+-    return NPERR_GENERIC_ERROR;
+-
+-  nsresult rv = streamlistener->mStreamListenerPeer->RequestRead((NPByteRange *)rangeList);
+-  if (NS_FAILED(rv))
+-    return NPERR_GENERIC_ERROR;
+-
+-  return NPERR_NO_ERROR;
++  return NPERR_STREAM_NOT_SEEKABLE;
+ }
+ 
+ // Deprecated, only stubbed out
+ void* /* OJI type: JRIEnv* */
+ _getJavaEnv()
+ {
+   NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_GetJavaEnv\n"));
+   return nullptr;
+diff --git a/dom/plugins/base/nsNPAPIPluginStreamListener.cpp b/dom/plugins/base/nsNPAPIPluginStreamListener.cpp
+--- a/dom/plugins/base/nsNPAPIPluginStreamListener.cpp
++++ b/dom/plugins/base/nsNPAPIPluginStreamListener.cpp
+@@ -41,17 +41,16 @@ NS_IMPL_ISUPPORTS(nsNPAPIPluginStreamLis
+ nsNPAPIPluginStreamListener::nsNPAPIPluginStreamListener(nsNPAPIPluginInstance* inst,
+                                                          void* notifyData,
+                                                          const char* aURL)
+   : mStreamBuffer(nullptr)
+   , mNotifyURL(aURL ? PL_strdup(aURL) : nullptr)
+   , mInst(inst)
+   , mStreamBufferSize(0)
+   , mStreamBufferByteCount(0)
+-  , mStreamType(NP_NORMAL)
+   , mStreamState(eStreamStopped)
+   , mStreamCleanedUp(false)
+   , mCallNotify(notifyData ? true : false)
+   , mIsSuspended(false)
+   , mIsPluginInitJSStream(mInst->mInPluginInitCall &&
+                           aURL && strncmp(aURL, "javascript:",
+                                           sizeof("javascript:") - 1) == 0)
+   , mRedirectDenied(false)
+@@ -110,21 +109,16 @@ nsNPAPIPluginStreamListener::CleanUpStre
+   StopDataPump();
+ 
+   // Release any outstanding redirect callback.
+   if (mHTTPRedirectCallback) {
+     mHTTPRedirectCallback->OnRedirectVerifyCallback(NS_ERROR_FAILURE);
+     mHTTPRedirectCallback = nullptr;
+   }
+ 
+-  // Seekable streams have an extra addref when they are created which must
+-  // be matched here.
+-  if (NP_SEEK == mStreamType && mStreamState == eStreamTypeSet)
+-    NS_RELEASE_THIS();
+-
+   if (mStreamListenerPeer) {
+     mStreamListenerPeer->CancelRequests(NS_BINDING_ABORTED);
+     mStreamListenerPeer = nullptr;
+   }
+ 
+   if (!mInst || !mInst->CanFireNotifications())
+     return rv;
+ 
+@@ -207,98 +201,53 @@ nsNPAPIPluginStreamListener::OnStartBind
+   NPPluginFuncs* pluginFunctions = plugin->PluginFuncs();
+ 
+   if (!pluginFunctions->newstream)
+     return NS_ERROR_FAILURE;
+ 
+   NPP npp;
+   mInst->GetNPP(&npp);
+ 
+-  bool seekable;
+   char* contentType;
+   uint16_t streamType = NP_NORMAL;
+   NPError error;
+ 
+   streamPeer->GetURL(&mNPStreamWrapper->mNPStream.url);
+   streamPeer->GetLength((uint32_t*)&(mNPStreamWrapper->mNPStream.end));
+   streamPeer->GetLastModified((uint32_t*)&(mNPStreamWrapper->mNPStream.lastmodified));
+-  streamPeer->IsSeekable(&seekable);
+   streamPeer->GetContentType(&contentType);
+ 
+   if (!mResponseHeaders.IsEmpty()) {
+     mResponseHeaderBuf = PL_strdup(mResponseHeaders.get());
+     mNPStreamWrapper->mNPStream.headers = mResponseHeaderBuf;
+   }
+ 
+   mStreamListenerPeer = streamPeer;
+ 
+   NPPAutoPusher nppPusher(npp);
+ 
+-  NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->newstream)(npp, (char*)contentType, &mNPStreamWrapper->mNPStream, seekable, &streamType), mInst,
++  NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->newstream)(npp, (char*)contentType, &mNPStreamWrapper->mNPStream, false, &streamType), mInst,
+                           NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
+ 
+   NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
+                  ("NPP NewStream called: this=%p, npp=%p, mime=%s, seek=%d, type=%d, return=%d, url=%s\n",
+-                  this, npp, (char *)contentType, seekable, streamType, error, mNPStreamWrapper->mNPStream.url));
++                  this, npp, (char *)contentType, false, streamType, error, mNPStreamWrapper->mNPStream.url));
+ 
+   if (error != NPERR_NO_ERROR)
+     return NS_ERROR_FAILURE;
+ 
+   mStreamState = eNewStreamCalled;
+ 
+-  if (!SetStreamType(streamType, false)) {
++  if (streamType != NP_NORMAL) {
+     return NS_ERROR_FAILURE;
+   }
+ 
+   return NS_OK;
+ }
+ 
+-bool
+-nsNPAPIPluginStreamListener::SetStreamType(uint16_t aType, bool aNeedsResume)
+-{
+-  switch(aType)
+-  {
+-    case NP_NORMAL:
+-      mStreamType = NP_NORMAL;
+-      break;
+-    case NP_ASFILEONLY:
+-      mStreamType = NP_ASFILEONLY;
+-      break;
+-    case NP_ASFILE:
+-      mStreamType = NP_ASFILE;
+-      break;
+-    case NP_SEEK:
+-      mStreamType = NP_SEEK;
+-      // Seekable streams should continue to exist even after OnStopRequest
+-      // is fired, so we AddRef ourself an extra time and Release when the
+-      // plugin calls NPN_DestroyStream (CleanUpStream). If the plugin never
+-      // calls NPN_DestroyStream the stream will be destroyed before the plugin
+-      // instance is destroyed.
+-      NS_ADDREF_THIS();
+-      break;
+-    case nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN:
+-      MOZ_ASSERT(!aNeedsResume);
+-      mStreamType = nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN;
+-      SuspendRequest();
+-      mStreamStopMode = eDoDeferredStop;
+-      // In this case we do not want to execute anything else in this function.
+-      return true;
+-    default:
+-      return false;
+-  }
+-  mStreamState = eStreamTypeSet;
+-  if (aNeedsResume) {
+-    if (mStreamListenerPeer) {
+-      mStreamListenerPeer->OnStreamTypeSet(mStreamType);
+-    }
+-    ResumeRequest();
+-  }
+-  return true;
+-}
+-
+ void
+ nsNPAPIPluginStreamListener::SuspendRequest()
+ {
+   NS_ASSERTION(!mIsSuspended,
+                "Suspending a request that's already suspended!");
+ 
+   nsresult rv = StartDataPump();
+   if (NS_FAILED(rv))
+@@ -704,35 +653,17 @@ nsNPAPIPluginStreamListener::OnStopBindi
+ 
+   NPReason reason = NS_FAILED(status) ? NPRES_NETWORK_ERR : NPRES_DONE;
+   if (mRedirectDenied || status == NS_BINDING_ABORTED) {
+     reason = NPRES_USER_BREAK;
+   }
+ 
+   // The following code can result in the deletion of 'this'. Don't
+   // assume we are alive after this!
+-  //
+-  // Delay cleanup if the stream is of type NP_SEEK and status isn't
+-  // NS_BINDING_ABORTED (meaning the plugin hasn't called NPN_DestroyStream).
+-  // This is because even though we're done delivering data the plugin may
+-  // want to seek. Eventually either the plugin will call NPN_DestroyStream
+-  // or we'll perform cleanup when the instance goes away. See bug 91140.
+-  if (mStreamType != NP_SEEK ||
+-      (NP_SEEK == mStreamType && NS_BINDING_ABORTED == status)) {
+-    return CleanUpStream(reason);
+-  }
+-
+-  return NS_OK;
+-}
+-
+-nsresult
+-nsNPAPIPluginStreamListener::GetStreamType(int32_t *result)
+-{
+-  *result = mStreamType;
+-  return NS_OK;
++  return CleanUpStream(reason);
+ }
+ 
+ bool
+ nsNPAPIPluginStreamListener::MaybeRunStopBinding()
+ {
+   if (mIsSuspended || mStreamStopMode != eStopPending) {
+     return false;
+   }
+diff --git a/dom/plugins/base/nsNPAPIPluginStreamListener.h b/dom/plugins/base/nsNPAPIPluginStreamListener.h
+--- a/dom/plugins/base/nsNPAPIPluginStreamListener.h
++++ b/dom/plugins/base/nsNPAPIPluginStreamListener.h
+@@ -60,18 +60,16 @@ public:
+   nsresult OnStartBinding(nsPluginStreamListenerPeer* streamPeer);
+   nsresult OnDataAvailable(nsPluginStreamListenerPeer* streamPeer,
+                            nsIInputStream* input,
+                            uint32_t length);
+   nsresult OnFileAvailable(nsPluginStreamListenerPeer* streamPeer,
+                            const char* fileName);
+   nsresult OnStopBinding(nsPluginStreamListenerPeer* streamPeer,
+                          nsresult status);
+-  nsresult GetStreamType(int32_t *result);
+-  bool SetStreamType(uint16_t aType, bool aNeedsResume = true);
+ 
+   bool IsStarted();
+   nsresult CleanUpStream(NPReason reason);
+   void CallURLNotify(NPReason reason);
+   void SetCallNotify(bool aCallNotify) { mCallNotify = aCallNotify; }
+   void SuspendRequest();
+   void ResumeRequest();
+   nsresult StartDataPump();
+@@ -107,17 +105,16 @@ protected:
+   bool MaybeRunStopBinding();
+ 
+   char* mStreamBuffer;
+   char* mNotifyURL;
+   RefPtr<nsNPAPIPluginInstance> mInst;
+   nsNPAPIStreamWrapper *mNPStreamWrapper;
+   uint32_t mStreamBufferSize;
+   int32_t mStreamBufferByteCount;
+-  int32_t mStreamType;
+   StreamState mStreamState;
+   bool mStreamCleanedUp;
+   bool mCallNotify;
+   bool mIsSuspended;
+   bool mIsPluginInitJSStream;
+   bool mRedirectDenied;
+   nsCString mResponseHeaders;
+   char* mResponseHeaderBuf;
+diff --git a/dom/plugins/base/nsPluginStreamListenerPeer.cpp b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
++++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+@@ -15,297 +15,65 @@
+ #include "nsMimeTypes.h"
+ #include "nsISupportsPrimitives.h"
+ #include "nsNetCID.h"
+ #include "nsPluginInstanceOwner.h"
+ #include "nsPluginLogging.h"
+ #include "nsIURI.h"
+ #include "nsIURL.h"
+ #include "nsPluginHost.h"
+-#include "nsIByteRangeRequest.h"
+ #include "nsIMultiPartChannel.h"
+ #include "nsIInputStreamTee.h"
+ #include "nsPrintfCString.h"
+ #include "nsIScriptGlobalObject.h"
+ #include "nsIDocument.h"
+ #include "nsIWebNavigation.h"
+ #include "nsContentUtils.h"
+ #include "nsNetUtil.h"
+ #include "nsPluginNativeWindow.h"
+ #include "GeckoProfiler.h"
+ #include "nsPluginInstanceOwner.h"
+ #include "nsDataHashtable.h"
+ #include "NullPrincipal.h"
+ 
+-#define BYTERANGE_REQUEST_CONTEXT 0x01020304
+-
+-// nsPluginByteRangeStreamListener
+-
+-class nsPluginByteRangeStreamListener
+-  : public nsIStreamListener
+-  , public nsIInterfaceRequestor
+-{
+-public:
+-  explicit nsPluginByteRangeStreamListener(nsIWeakReference* aWeakPtr);
+-
+-  NS_DECL_ISUPPORTS
+-  NS_DECL_NSIREQUESTOBSERVER
+-  NS_DECL_NSISTREAMLISTENER
+-  NS_DECL_NSIINTERFACEREQUESTOR
+-
+-private:
+-  virtual ~nsPluginByteRangeStreamListener();
+-
+-  nsCOMPtr<nsIStreamListener> mStreamConverter;
+-  nsWeakPtr mWeakPtrPluginStreamListenerPeer;
+-  bool mRemoveByteRangeRequest;
+-};
+-
+-NS_IMPL_ISUPPORTS(nsPluginByteRangeStreamListener,
+-                  nsIRequestObserver,
+-                  nsIStreamListener,
+-                  nsIInterfaceRequestor)
+-
+-nsPluginByteRangeStreamListener::nsPluginByteRangeStreamListener(nsIWeakReference* aWeakPtr)
+-{
+-  mWeakPtrPluginStreamListenerPeer = aWeakPtr;
+-  mRemoveByteRangeRequest = false;
+-}
+-
+-nsPluginByteRangeStreamListener::~nsPluginByteRangeStreamListener()
+-{
+-  mStreamConverter = nullptr;
+-  mWeakPtrPluginStreamListenerPeer = nullptr;
+-}
+-
+-/**
+- * Unwrap any byte-range requests so that we can check whether the base channel
+- * is being tracked properly.
+- */
+-static nsCOMPtr<nsIRequest>
+-GetBaseRequest(nsIRequest* r)
+-{
+-  nsCOMPtr<nsIMultiPartChannel> mp = do_QueryInterface(r);
+-  if (!mp)
+-    return r;
+-
+-  nsCOMPtr<nsIChannel> base;
+-  mp->GetBaseChannel(getter_AddRefs(base));
+-  return already_AddRefed<nsIRequest>(base.forget());
+-}
+-
+-NS_IMETHODIMP
+-nsPluginByteRangeStreamListener::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
+-{
+-  nsresult rv;
+-
+-  nsCOMPtr<nsIStreamListener> finalStreamListener = do_QueryReferent(mWeakPtrPluginStreamListenerPeer);
+-  if (!finalStreamListener)
+-    return NS_ERROR_FAILURE;
+-
+-  nsPluginStreamListenerPeer *pslp =
+-    static_cast<nsPluginStreamListenerPeer*>(finalStreamListener.get());
+-
+-#ifdef DEBUG
+-  nsCOMPtr<nsIRequest> baseRequest = GetBaseRequest(request);
+-#endif
+-  NS_ASSERTION(pslp->mRequests.IndexOfObject(baseRequest) != -1,
+-               "Untracked byte-range request?");
+-
+-  nsCOMPtr<nsIStreamConverterService> serv = do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
+-  if (NS_SUCCEEDED(rv)) {
+-    rv = serv->AsyncConvertData(MULTIPART_BYTERANGES,
+-                                "*/*",
+-                                finalStreamListener,
+-                                nullptr,
+-                                getter_AddRefs(mStreamConverter));
+-    if (NS_SUCCEEDED(rv)) {
+-      rv = mStreamConverter->OnStartRequest(request, ctxt);
+-      if (NS_SUCCEEDED(rv))
+-        return rv;
+-    }
+-  }
+-  mStreamConverter = nullptr;
+-
+-  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
+-  if (!httpChannel) {
+-    return NS_ERROR_FAILURE;
+-  }
+-
+-  uint32_t responseCode = 0;
+-  rv = httpChannel->GetResponseStatus(&responseCode);
+-  if (NS_FAILED(rv)) {
+-    return NS_ERROR_FAILURE;
+-  }
+-
+-  if (responseCode != 200) {
+-    uint32_t wantsAllNetworkStreams = 0;
+-    rv = pslp->GetPluginInstance()->GetValueFromPlugin(NPPVpluginWantsAllNetworkStreams,
+-                                                       &wantsAllNetworkStreams);
+-    // If the call returned an error code make sure we still use our default value.
+-    if (NS_FAILED(rv)) {
+-      wantsAllNetworkStreams = 0;
+-    }
+-
+-    if (!wantsAllNetworkStreams){
+-      return NS_ERROR_FAILURE;
+-    }
+-  }
+-
+-  // if server cannot continue with byte range (206 status) and sending us whole object (200 status)
+-  // reset this seekable stream & try serve it to plugin instance as a file
+-  mStreamConverter = finalStreamListener;
+-  mRemoveByteRangeRequest = true;
+-
+-  rv = pslp->ServeStreamAsFile(request, ctxt);
+-  return rv;
+-}
+-
+-NS_IMETHODIMP
+-nsPluginByteRangeStreamListener::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
+-                                               nsresult status)
+-{
+-  if (!mStreamConverter)
+-    return NS_ERROR_FAILURE;
+-
+-  nsCOMPtr<nsIStreamListener> finalStreamListener = do_QueryReferent(mWeakPtrPluginStreamListenerPeer);
+-  if (!finalStreamListener)
+-    return NS_ERROR_FAILURE;
+-
+-  nsPluginStreamListenerPeer *pslp =
+-    static_cast<nsPluginStreamListenerPeer*>(finalStreamListener.get());
+-  bool found = pslp->mRequests.RemoveObject(request);
+-  if (!found) {
+-    NS_ERROR("OnStopRequest received for untracked byte-range request!");
+-  }
+-
+-  if (mRemoveByteRangeRequest) {
+-    // remove byte range request from container
+-    nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(ctxt);
+-    if (container) {
+-      uint32_t byteRangeRequest = 0;
+-      container->GetData(&byteRangeRequest);
+-      if (byteRangeRequest == BYTERANGE_REQUEST_CONTEXT) {
+-        // to allow properly finish nsPluginStreamListenerPeer->OnStopRequest()
+-        // set it to something that is not the byte range request.
+-        container->SetData(0);
+-      }
+-    } else {
+-      NS_WARNING("Bad state of nsPluginByteRangeStreamListener");
+-    }
+-  }
+-
+-  return mStreamConverter->OnStopRequest(request, ctxt, status);
+-}
+-
+-// CachedFileHolder
+-
+-CachedFileHolder::CachedFileHolder(nsIFile* cacheFile)
+-: mFile(cacheFile)
+-{
+-  NS_ASSERTION(mFile, "Empty CachedFileHolder");
+-}
+-
+-CachedFileHolder::~CachedFileHolder()
+-{
+-  mFile->Remove(false);
+-}
+-
+-void
+-CachedFileHolder::AddRef()
+-{
+-  ++mRefCnt;
+-  NS_LOG_ADDREF(this, mRefCnt, "CachedFileHolder", sizeof(*this));
+-}
+-
+-void
+-CachedFileHolder::Release()
+-{
+-  --mRefCnt;
+-  NS_LOG_RELEASE(this, mRefCnt, "CachedFileHolder");
+-  if (0 == mRefCnt)
+-    delete this;
+-}
+-
+-
+-NS_IMETHODIMP
+-nsPluginByteRangeStreamListener::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
+-                                                 nsIInputStream *inStr,
+-                                                 uint64_t sourceOffset,
+-                                                 uint32_t count)
+-{
+-  if (!mStreamConverter)
+-    return NS_ERROR_FAILURE;
+-
+-  nsCOMPtr<nsIStreamListener> finalStreamListener = do_QueryReferent(mWeakPtrPluginStreamListenerPeer);
+-  if (!finalStreamListener)
+-    return NS_ERROR_FAILURE;
+-
+-  return mStreamConverter->OnDataAvailable(request, ctxt, inStr, sourceOffset, count);
+-}
+-
+-NS_IMETHODIMP
+-nsPluginByteRangeStreamListener::GetInterface(const nsIID& aIID, void** result)
+-{
+-  // Forward interface requests to our parent
+-  nsCOMPtr<nsIInterfaceRequestor> finalStreamListener = do_QueryReferent(mWeakPtrPluginStreamListenerPeer);
+-  if (!finalStreamListener)
+-    return NS_ERROR_FAILURE;
+-
+-  return finalStreamListener->GetInterface(aIID, result);
+-}
+-
+ // nsPluginStreamListenerPeer
+ 
+ NS_IMPL_ISUPPORTS(nsPluginStreamListenerPeer,
+                   nsIStreamListener,
+                   nsIRequestObserver,
+                   nsIHttpHeaderVisitor,
+                   nsISupportsWeakReference,
+                   nsIInterfaceRequestor,
+                   nsIChannelEventSink)
+ 
+ nsPluginStreamListenerPeer::nsPluginStreamListenerPeer()
+ {
+   mStreamType = NP_NORMAL;
+   mStartBinding = false;
+-  mAbort = false;
+   mRequestFailed = false;
+ 
+   mPendingRequests = 0;
+   mHaveFiredOnStartRequest = false;
+-  mDataForwardToRequest = nullptr;
+ 
+   mUseLocalCache = false;
+-  mSeekable = false;
+   mModified = 0;
+   mStreamOffset = 0;
+   mStreamComplete = 0;
+ }
+ 
+ nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer()
+ {
+ #ifdef PLUGIN_LOGGING
+   MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL,
+          ("nsPluginStreamListenerPeer::dtor this=%p, url=%s\n",this, mURLSpec.get()));
+ #endif
+ 
+   if (mPStreamListener) {
+     mPStreamListener->SetStreamListenerPeer(nullptr);
+   }
+-
+-  // close FD of mFileCacheOutputStream if it's still open
+-  // or we won't be able to remove the cache file
+-  if (mFileCacheOutputStream)
+-    mFileCacheOutputStream = nullptr;
+-
+-  delete mDataForwardToRequest;
+-
+-  if (mPluginInstance)
+-    mPluginInstance->FileCachedStreamListeners()->RemoveElement(this);
+ }
+ 
+ // Called as a result of GetURL and PostURL, or by the host in the case of the
+ // initial plugin stream.
+ nsresult nsPluginStreamListenerPeer::Initialize(nsIURI *aURL,
+                                                 nsNPAPIPluginInstance *aInstance,
+                                                 nsNPAPIPluginStreamListener* aListener)
+ {
+@@ -333,110 +101,27 @@ nsresult nsPluginStreamListenerPeer::Ini
+   // SetUpStreamListener
+   if (aListener) {
+     mPStreamListener = aListener;
+     mPStreamListener->SetStreamListenerPeer(this);
+   }
+ 
+   mPendingRequests = 1;
+ 
+-  mDataForwardToRequest = new nsDataHashtable<nsUint32HashKey, uint32_t>();
+-
+   return NS_OK;
+ }
+ 
+-// SetupPluginCacheFile is called if we have to save the stream to disk.
+-//
+-// These files will be deleted when the host is destroyed.
+-//
+-// TODO? What if we fill up the the dest dir?
+-nsresult
+-nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel)
+-{
+-  nsresult rv = NS_OK;
+-
+-  bool useExistingCacheFile = false;
+-  RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
+-
+-  // Look for an existing cache file for the URI.
+-  nsTArray< RefPtr<nsNPAPIPluginInstance> > *instances = pluginHost->InstanceArray();
+-  for (uint32_t i = 0; i < instances->Length(); i++) {
+-    // most recent streams are at the end of list
+-    nsTArray<nsPluginStreamListenerPeer*> *streamListeners = instances->ElementAt(i)->FileCachedStreamListeners();
+-    for (int32_t i = streamListeners->Length() - 1; i >= 0; --i) {
+-      nsPluginStreamListenerPeer *lp = streamListeners->ElementAt(i);
+-      if (lp && lp->mLocalCachedFileHolder) {
+-        useExistingCacheFile = lp->UseExistingPluginCacheFile(this);
+-        if (useExistingCacheFile) {
+-          mLocalCachedFileHolder = lp->mLocalCachedFileHolder;
+-          break;
+-        }
+-      }
+-      if (useExistingCacheFile)
+-        break;
+-    }
+-  }
+-
+-  // Create a new cache file if one could not be found.
+-  if (!useExistingCacheFile) {
+-    nsCOMPtr<nsIFile> pluginTmp;
+-    rv = nsPluginHost::GetPluginTempDir(getter_AddRefs(pluginTmp));
+-    if (NS_FAILED(rv)) {
+-      return rv;
+-    }
+-
+-    // Get the filename from the channel
+-    nsCOMPtr<nsIURI> uri;
+-    rv = channel->GetURI(getter_AddRefs(uri));
+-    if (NS_FAILED(rv)) return rv;
+-
+-    nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
+-    if (!url)
+-      return NS_ERROR_FAILURE;
+-
+-    nsAutoCString filename;
+-    url->GetFileName(filename);
+-    if (NS_FAILED(rv))
+-      return rv;
+-
+-    // Create a file to save our stream into. Should we scramble the name?
+-    filename.InsertLiteral("plugin-", 0);
+-    rv = pluginTmp->AppendNative(filename);
+-    if (NS_FAILED(rv))
+-      return rv;
+-
+-    // Yes, make it unique.
+-    rv = pluginTmp->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
+-    if (NS_FAILED(rv))
+-      return rv;
+-
+-    // create a file output stream to write to...
+-    rv = NS_NewLocalFileOutputStream(getter_AddRefs(mFileCacheOutputStream), pluginTmp, -1, 00600);
+-    if (NS_FAILED(rv))
+-      return rv;
+-
+-    // save the file.
+-    mLocalCachedFileHolder = new CachedFileHolder(pluginTmp);
+-  }
+-
+-  // add this listenerPeer to list of stream peers for this instance
+-  mPluginInstance->FileCachedStreamListeners()->AppendElement(this);
+-
+-  return rv;
+-}
+-
+ NS_IMETHODIMP
+ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
+                                            nsISupports* aContext)
+ {
+   nsresult rv = NS_OK;
+   AUTO_PROFILER_LABEL("nsPluginStreamListenerPeer::OnStartRequest", OTHER);
+ 
+-  nsCOMPtr<nsIRequest> baseRequest = GetBaseRequest(request);
+-  if (mRequests.IndexOfObject(baseRequest) == -1) {
++  if (mRequests.IndexOfObject(request) == -1) {
+     NS_ASSERTION(mRequests.Count() == 0,
+                  "Only our initial stream should be unknown!");
+     TrackRequest(request);
+   }
+ 
+   if (mHaveFiredOnStartRequest) {
+     return NS_OK;
+   }
+@@ -593,23 +278,16 @@ nsresult
+ nsPluginStreamListenerPeer::GetContentType(char** result)
+ {
+   *result = const_cast<char*>(mContentType.get());
+   return NS_OK;
+ }
+ 
+ 
+ nsresult
+-nsPluginStreamListenerPeer::IsSeekable(bool* result)
+-{
+-  *result = mSeekable;
+-  return NS_OK;
+-}
+-
+-nsresult
+ nsPluginStreamListenerPeer::GetLength(uint32_t* result)
+ {
+   *result = mLength;
+   return NS_OK;
+ }
+ 
+ nsresult
+ nsPluginStreamListenerPeer::GetLastModified(uint32_t* result)
+@@ -620,51 +298,16 @@ nsPluginStreamListenerPeer::GetLastModif
+ 
+ nsresult
+ nsPluginStreamListenerPeer::GetURL(const char** result)
+ {
+   *result = mURLSpec.get();
+   return NS_OK;
+ }
+ 
+-void
+-nsPluginStreamListenerPeer::MakeByteRangeString(NPByteRange* aRangeList, nsACString &rangeRequest,
+-                                                int32_t *numRequests)
+-{
+-  rangeRequest.Truncate();
+-  *numRequests  = 0;
+-  //the string should look like this: bytes=500-700,601-999
+-  if (!aRangeList)
+-    return;
+-
+-  int32_t requestCnt = 0;
+-  nsAutoCString string("bytes=");
+-
+-  for (NPByteRange * range = aRangeList; range != nullptr; range = range->next) {
+-    // XXX zero length?
+-    if (!range->length)
+-      continue;
+-
+-    // XXX needs to be fixed for negative offsets
+-    string.AppendInt(range->offset);
+-    string.Append('-');
+-    string.AppendInt(range->offset + range->length - 1);
+-    if (range->next)
+-      string.Append(',');
+-
+-    requestCnt++;
+-  }
+-
+-  // get rid of possible trailing comma
+-  string.Trim(",", false);
+-
+-  rangeRequest = string;
+-  *numRequests  = requestCnt;
+-}
+-
+ // XXX: Converting the channel within nsPluginStreamListenerPeer
+ // to use asyncOpen2() and do not want to touch the fragile logic
+ // of byte range requests. Hence we just introduce this lightweight
+ // wrapper to proxy the context.
+ class PluginContextProxy final : public nsIStreamListener
+ {
+ public:
+   NS_DECL_ISUPPORTS
+@@ -713,275 +356,66 @@ private:
+   ~PluginContextProxy() {}
+   nsCOMPtr<nsIStreamListener> mListener;
+   nsCOMPtr<nsISupports> mContext;
+ };
+ 
+ NS_IMPL_ISUPPORTS(PluginContextProxy, nsIStreamListener)
+ 
+ nsresult
+-nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
+-{
+-  nsAutoCString rangeString;
+-  int32_t numRequests;
+-
+-  MakeByteRangeString(rangeList, rangeString, &numRequests);
+-
+-  if (numRequests == 0)
+-    return NS_ERROR_FAILURE;
+-
+-  nsresult rv = NS_OK;
+-
+-  RefPtr<nsPluginInstanceOwner> owner = mPluginInstance->GetOwner();
+-  nsCOMPtr<nsIDOMElement> element;
+-  nsCOMPtr<nsIDocument> doc;
+-  if (owner) {
+-    rv = owner->GetDOMElement(getter_AddRefs(element));
+-    NS_ENSURE_SUCCESS(rv, rv);
+-    rv = owner->GetDocument(getter_AddRefs(doc));
+-    NS_ENSURE_SUCCESS(rv, rv);
+-  }
+-
+-  nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryReferent(mWeakPtrChannelCallbacks);
+-  nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakPtrChannelLoadGroup);
+-
+-  nsCOMPtr<nsIChannel> channel;
+-  nsCOMPtr<nsINode> requestingNode(do_QueryInterface(element));
+-  if (requestingNode) {
+-    rv = NS_NewChannel(getter_AddRefs(channel),
+-                       mURL,
+-                       requestingNode,
+-                       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
+-                       nsIContentPolicy::TYPE_OTHER,
+-                       loadGroup,
+-                       callbacks,
+-                       nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
+-  }
+-  else {
+-    // In this else branch we really don't know where the load is coming
+-    // from. Let's fall back to using the SystemPrincipal for such Plugins.
+-    rv = NS_NewChannel(getter_AddRefs(channel),
+-                       mURL,
+-                       nsContentUtils::GetSystemPrincipal(),
+-                       nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
+-                       nsIContentPolicy::TYPE_OTHER,
+-                       loadGroup,
+-                       callbacks,
+-                       nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
+-  }
+-
+-  if (NS_FAILED(rv))
+-    return rv;
+-
+-  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
+-  if (!httpChannel)
+-    return NS_ERROR_FAILURE;
+-
+-  rv = httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, false);
+-  MOZ_ASSERT(NS_SUCCEEDED(rv));
+-
+-  mAbort = true; // instruct old stream listener to cancel
+-  // the request on the next ODA.
+-
+-  nsCOMPtr<nsIStreamListener> converter;
+-
+-  if (numRequests == 1) {
+-    converter = this;
+-    // set current stream offset equal to the first offset in the range list
+-    // it will work for single byte range request
+-    // for multy range we'll reset it in ODA
+-    SetStreamOffset(rangeList->offset);
+-  } else {
+-    nsWeakPtr weakpeer =
+-    do_GetWeakReference(static_cast<nsISupportsWeakReference*>(this));
+-    converter = new nsPluginByteRangeStreamListener(weakpeer);
+-  }
+-
+-  mPendingRequests += numRequests;
+-
+-  nsCOMPtr<nsISupportsPRUint32> container = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
+-  NS_ENSURE_SUCCESS(rv, rv);
+-  rv = container->SetData(BYTERANGE_REQUEST_CONTEXT);
+-  NS_ENSURE_SUCCESS(rv, rv);
+-
+-  RefPtr<PluginContextProxy> pluginContextProxy =
+-    new PluginContextProxy(converter, container);
+-  rv = channel->AsyncOpen2(pluginContextProxy);
+-  NS_ENSURE_SUCCESS(rv, rv);
+-  TrackRequest(channel);
+-  return NS_OK;
+-}
+-
+-nsresult
+ nsPluginStreamListenerPeer::GetStreamOffset(int32_t* result)
+ {
+   *result = mStreamOffset;
+   return NS_OK;
+ }
+ 
+ nsresult
+ nsPluginStreamListenerPeer::SetStreamOffset(int32_t value)
+ {
+   mStreamOffset = value;
+   return NS_OK;
+ }
+ 
+-nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request,
+-                                                       nsISupports* aContext)
+-{
+-  if (!mPluginInstance)
+-    return NS_ERROR_FAILURE;
+-
+-  // mPluginInstance->Stop calls mPStreamListener->CleanUpStream(), so stream will be properly clean up
+-  mPluginInstance->Stop();
+-  mPluginInstance->Start();
+-  RefPtr<nsPluginInstanceOwner> owner = mPluginInstance->GetOwner();
+-  if (owner) {
+-    NPWindow* window = nullptr;
+-    owner->GetWindow(window);
+-    owner->CallSetWindow();
+-  }
+-
+-  mSeekable = false;
+-  mPStreamListener->OnStartBinding(this);
+-  mStreamOffset = 0;
+-
+-  // force the plugin to use stream as file
+-  mStreamType = NP_ASFILE;
+-
+-  nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
+-  if (channel) {
+-    SetupPluginCacheFile(channel);
+-  }
+-
+-  // unset mPendingRequests
+-  mPendingRequests = 0;
+-
+-  return NS_OK;
+-}
+-
+-bool
+-nsPluginStreamListenerPeer::UseExistingPluginCacheFile(nsPluginStreamListenerPeer* psi)
+-{
+-  NS_ENSURE_TRUE(psi, false);
+-
+-  if (psi->mLength == mLength &&
+-      psi->mModified == mModified &&
+-      mStreamComplete &&
+-      mURLSpec.Equals(psi->mURLSpec))
+-  {
+-    return true;
+-  }
+-  return false;
+-}
+-
+ NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request,
+                                                           nsISupports* aContext,
+                                                           nsIInputStream *aIStream,
+                                                           uint64_t sourceOffset,
+                                                           uint32_t aLength)
+ {
+-  nsCOMPtr<nsIRequest> baseRequest = GetBaseRequest(request);
+-  if (mRequests.IndexOfObject(baseRequest) == -1) {
++  if (mRequests.IndexOfObject(request) == -1) {
+     MOZ_ASSERT(false, "Received OnDataAvailable for untracked request.");
+     return NS_ERROR_UNEXPECTED;
+   }
+ 
+   if (mRequestFailed)
+     return NS_ERROR_FAILURE;
+ 
+-  if (mAbort) {
+-    uint32_t byteRangeRequest = 0;  // set it to something that is not the byte range request.
+-    nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(aContext);
+-    if (container)
+-      container->GetData(&byteRangeRequest);
+-
+-    if (byteRangeRequest != BYTERANGE_REQUEST_CONTEXT) {
+-      // this is not one of our range requests
+-      mAbort = false;
+-      return NS_BINDING_ABORTED;
+-    }
+-  }
+-
+   nsresult rv = NS_OK;
+ 
+   if (!mPStreamListener)
+     return NS_ERROR_FAILURE;
+ 
+   const char * url = nullptr;
+   GetURL(&url);
+ 
+   PLUGIN_LOG(PLUGIN_LOG_NOISY,
+              ("nsPluginStreamListenerPeer::OnDataAvailable this=%p request=%p, offset=%" PRIu64 ", length=%u, url=%s\n",
+               this, request, sourceOffset, aLength, url ? url : "no url set"));
+ 
+-  // if the plugin has requested an AsFileOnly stream, then don't
+-  // call OnDataAvailable
+-  if (mStreamType != NP_ASFILEONLY) {
+-    // get the absolute offset of the request, if one exists.
+-    nsCOMPtr<nsIByteRangeRequest> brr = do_QueryInterface(request);
+-    if (brr) {
+-      if (!mDataForwardToRequest)
+-        return NS_ERROR_FAILURE;
+-
+-      int64_t absoluteOffset64 = 0;
+-      brr->GetStartRange(&absoluteOffset64);
+-
+-      // XXX handle 64-bit for real
+-      int32_t absoluteOffset = (int32_t)int64_t(absoluteOffset64);
+-
+-      // we need to track how much data we have forwarded to the
+-      // plugin.
+-
+-      // FIXME: http://bugzilla.mozilla.org/show_bug.cgi?id=240130
+-      //
+-      // Why couldn't this be tracked on the plugin info, and not in a
+-      // *hash table*?
+-      int32_t amtForwardToPlugin = mDataForwardToRequest->Get(absoluteOffset);
+-      mDataForwardToRequest->Put(absoluteOffset, (amtForwardToPlugin + aLength));
+-
+-      SetStreamOffset(absoluteOffset + amtForwardToPlugin);
+-    }
+-
+-    nsCOMPtr<nsIInputStream> stream = aIStream;
++  nsCOMPtr<nsIInputStream> stream = aIStream;
++  rv = mPStreamListener->OnDataAvailable(this,
++                                         stream,
++                                         aLength);
+ 
+-    // if we are caching the file ourselves to disk, we want to 'tee' off
+-    // the data as the plugin read from the stream.  We do this by the magic
+-    // of an input stream tee.
+-
+-    if (mFileCacheOutputStream) {
+-      rv = NS_NewInputStreamTee(getter_AddRefs(stream), aIStream, mFileCacheOutputStream);
+-      if (NS_FAILED(rv))
+-        return rv;
+-    }
+-
+-    rv =  mPStreamListener->OnDataAvailable(this,
+-                                            stream,
+-                                            aLength);
++  // if a plugin returns an error, the peer must kill the stream
++  //   else the stream and PluginStreamListener leak
++  if (NS_FAILED(rv)) {
++    request->Cancel(rv);
++  }
+ 
+-    // if a plugin returns an error, the peer must kill the stream
+-    //   else the stream and PluginStreamListener leak
+-    if (NS_FAILED(rv))
+-      request->Cancel(rv);
+-  }
+-  else
+-  {
+-    // if we don't read from the stream, OnStopRequest will never be called
+-    char* buffer = new char[aLength];
+-    uint32_t amountRead, amountWrote = 0;
+-    rv = aIStream->Read(buffer, aLength, &amountRead);
+-
+-    // if we are caching this to disk ourselves, lets write the bytes out.
+-    if (mFileCacheOutputStream) {
+-      while (amountWrote < amountRead && NS_SUCCEEDED(rv)) {
+-        rv = mFileCacheOutputStream->Write(buffer, amountRead, &amountWrote);
+-      }
+-    }
+-    delete [] buffer;
+-  }
+   return rv;
+ }
+ 
+ NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request,
+                                                         nsISupports* aContext,
+                                                         nsresult aStatus)
+ {
+   nsresult rv = NS_OK;
+@@ -993,53 +427,20 @@ NS_IMETHODIMP nsPluginStreamListenerPeer
+       NS_ERROR("Received OnStopRequest for untracked request.");
+     }
+   }
+ 
+   PLUGIN_LOG(PLUGIN_LOG_NOISY,
+              ("nsPluginStreamListenerPeer::OnStopRequest this=%p aStatus=%" PRIu32 " request=%p\n",
+               this, static_cast<uint32_t>(aStatus), request));
+ 
+-  // for ByteRangeRequest we're just updating the mDataForwardToRequest hash and return.
+-  nsCOMPtr<nsIByteRangeRequest> brr = do_QueryInterface(request);
+-  if (brr) {
+-    int64_t absoluteOffset64 = 0;
+-    brr->GetStartRange(&absoluteOffset64);
+-    // XXX support 64-bit offsets
+-    int32_t absoluteOffset = (int32_t)int64_t(absoluteOffset64);
+-
+-    // remove the request from our data forwarding count hash.
+-    mDataForwardToRequest->Remove(absoluteOffset);
+-
+-
+-    PLUGIN_LOG(PLUGIN_LOG_NOISY,
+-               ("                          ::OnStopRequest for ByteRangeRequest Started=%d\n",
+-                absoluteOffset));
+-  } else {
+-    // if this is not byte range request and
+-    // if we are writting the stream to disk ourselves,
+-    // close & tear it down here
+-    mFileCacheOutputStream = nullptr;
+-  }
+-
+   // if we still have pending stuff to do, lets not close the plugin socket.
+   if (--mPendingRequests > 0)
+     return NS_OK;
+ 
+-  // we keep our connections around...
+-  nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(aContext);
+-  if (container) {
+-    uint32_t byteRangeRequest = 0;  // something other than the byte range request.
+-    container->GetData(&byteRangeRequest);
+-    if (byteRangeRequest == BYTERANGE_REQUEST_CONTEXT) {
+-      // this is one of our range requests
+-      return NS_OK;
+-    }
+-  }
+-
+   if (!mPStreamListener)
+     return NS_ERROR_FAILURE;
+ 
+   nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
+   if (!channel)
+     return NS_ERROR_FAILURE;
+   // Set the content type to ensure we don't pass null to the plugin
+   nsAutoCString aContentType;
+@@ -1056,34 +457,16 @@ NS_IMETHODIMP nsPluginStreamListenerPeer
+ 
+   if (NS_FAILED(aStatus)) {
+     // on error status cleanup the stream
+     // and return w/o OnFileAvailable()
+     mPStreamListener->OnStopBinding(this, aStatus);
+     return NS_OK;
+   }
+ 
+-  // call OnFileAvailable if plugin requests stream type StreamType_AsFile or StreamType_AsFileOnly
+-  if (mStreamType >= NP_ASFILE) {
+-    nsCOMPtr<nsIFile> localFile;
+-    if (mLocalCachedFileHolder)
+-      localFile = mLocalCachedFileHolder->file();
+-    else {
+-      // see if it is a file channel.
+-      nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(request);
+-      if (fileChannel) {
+-        fileChannel->GetFile(getter_AddRefs(localFile));
+-      }
+-    }
+-
+-    if (localFile) {
+-      OnFileAvailable(localFile);
+-    }
+-  }
+-
+   if (mStartBinding) {
+     // On start binding has been called
+     mPStreamListener->OnStopBinding(this, aStatus);
+   } else {
+     // OnStartBinding hasn't been called, so complete the action.
+     mPStreamListener->OnStartBinding(this);
+     mPStreamListener->OnStopBinding(this, aStatus);
+   }
+@@ -1162,42 +545,16 @@ nsresult nsPluginStreamListenerPeer::Set
+                              statusText.get());
+       static_cast<nsIHTTPHeaderListener*>(mPStreamListener)->StatusLine(status.get());
+     }
+ 
+     // Also provide all HTTP response headers to our listener.
+     rv = httpChannel->VisitResponseHeaders(this);
+     MOZ_ASSERT(NS_SUCCEEDED(rv));
+ 
+-    mSeekable = false;
+-    // first we look for a content-encoding header. If we find one, we tell the
+-    // plugin that stream is not seekable, because the plugin always sees
+-    // uncompressed data, so it can't make meaningful range requests on a
+-    // compressed entity.  Also, we force the plugin to use
+-    // nsPluginStreamType_AsFile stream type and we have to save decompressed
+-    // file into local plugin cache, because necko cache contains original
+-    // compressed file.
+-    nsAutoCString contentEncoding;
+-    if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"),
+-                                                    contentEncoding))) {
+-      mUseLocalCache = true;
+-    } else {
+-      // set seekability (seekable if the stream has a known length and if the
+-      // http server accepts byte ranges).
+-      uint32_t length;
+-      GetLength(&length);
+-      if (length) {
+-        nsAutoCString range;
+-        if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("accept-ranges"), range)) &&
+-            range.Equals(NS_LITERAL_CSTRING("bytes"), nsCaseInsensitiveCStringComparator())) {
+-          mSeekable = true;
+-        }
+-      }
+-    }
+-
+     // we require a content len
+     // get Last-Modified header for plugin info
+     nsAutoCString lastModified;
+     if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("last-modified"), lastModified)) &&
+         !lastModified.IsEmpty()) {
+       PRTime time64;
+       PR_ParseTimeString(lastModified.get(), true, &time64);  //convert string time to integer time
+ 
+@@ -1212,66 +569,19 @@ nsresult nsPluginStreamListenerPeer::Set
+ 
+   rv = mPStreamListener->OnStartBinding(this);
+ 
+   mStartBinding = true;
+ 
+   if (NS_FAILED(rv))
+     return rv;
+ 
+-  int32_t streamType = NP_NORMAL;
+-  mPStreamListener->GetStreamType(&streamType);
+-
+-  if (streamType != STREAM_TYPE_UNKNOWN) {
+-    OnStreamTypeSet(streamType);
+-  }
+-
+   return NS_OK;
+ }
+ 
+-void
+-nsPluginStreamListenerPeer::OnStreamTypeSet(const int32_t aStreamType)
+-{
+-  MOZ_ASSERT(aStreamType != STREAM_TYPE_UNKNOWN);
+-  MOZ_ASSERT(mRequest);
+-  mStreamType = aStreamType;
+-  if (!mUseLocalCache && mStreamType >= NP_ASFILE) {
+-    // check it out if this is not a file channel.
+-    nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(mRequest);
+-    if (!fileChannel) {
+-      mUseLocalCache = true;
+-    }
+-  }
+-
+-  if (mUseLocalCache) {
+-    nsCOMPtr<nsIChannel> channel = do_QueryInterface(mRequest);
+-    SetupPluginCacheFile(channel);
+-  }
+-}
+-
+-nsresult
+-nsPluginStreamListenerPeer::OnFileAvailable(nsIFile* aFile)
+-{
+-  nsresult rv;
+-  if (!mPStreamListener)
+-    return NS_ERROR_FAILURE;
+-
+-  nsAutoCString path;
+-  rv = aFile->GetNativePath(path);
+-  if (NS_FAILED(rv)) return rv;
+-
+-  if (path.IsEmpty()) {
+-    NS_WARNING("empty path");
+-    return NS_OK;
+-  }
+-
+-  rv = mPStreamListener->OnFileAvailable(this, path.get());
+-  return rv;
+-}
+-
+ NS_IMETHODIMP
+ nsPluginStreamListenerPeer::VisitHeader(const nsACString &header, const nsACString &value)
+ {
+   return mPStreamListener->NewResponseHeader(PromiseFlatCString(header).get(),
+                                              PromiseFlatCString(value).get());
+ }
+ 
+ nsresult
+diff --git a/dom/plugins/base/nsPluginStreamListenerPeer.h b/dom/plugins/base/nsPluginStreamListenerPeer.h
+--- a/dom/plugins/base/nsPluginStreamListenerPeer.h
++++ b/dom/plugins/base/nsPluginStreamListenerPeer.h
+@@ -58,39 +58,27 @@ public:
+   NS_DECL_ISUPPORTS
+   NS_DECL_NSIPROGRESSEVENTSINK
+   NS_DECL_NSIREQUESTOBSERVER
+   NS_DECL_NSISTREAMLISTENER
+   NS_DECL_NSIHTTPHEADERVISITOR
+   NS_DECL_NSIINTERFACEREQUESTOR
+   NS_DECL_NSICHANNELEVENTSINK
+ 
+-  // Called by RequestRead
+-  void
+-  MakeByteRangeString(NPByteRange* aRangeList, nsACString &string, int32_t *numRequests);
+-
+-  bool UseExistingPluginCacheFile(nsPluginStreamListenerPeer* psi);
+-
+   // Called by GetURL and PostURL (via NewStream) or by the host in the case of
+   // the initial plugin stream.
+   nsresult Initialize(nsIURI *aURL,
+                       nsNPAPIPluginInstance *aInstance,
+                       nsNPAPIPluginStreamListener *aListener);
+ 
+-  nsresult OnFileAvailable(nsIFile* aFile);
+-
+-  nsresult ServeStreamAsFile(nsIRequest *request, nsISupports *ctxt);
+-
+   nsNPAPIPluginInstance *GetPluginInstance() { return mPluginInstance; }
+ 
+-  nsresult RequestRead(NPByteRange* rangeList);
+   nsresult GetLength(uint32_t* result);
+   nsresult GetURL(const char** result);
+   nsresult GetLastModified(uint32_t* result);
+-  nsresult IsSeekable(bool* result);
+   nsresult GetContentType(char** result);
+   nsresult GetStreamOffset(int32_t* result);
+   nsresult SetStreamOffset(int32_t value);
+ 
+   void TrackRequest(nsIRequest* request)
+   {
+     mRequests.AppendObject(request);
+   }
+@@ -123,26 +111,18 @@ public:
+   }
+ 
+   void ResumeRequests() {
+     nsCOMArray<nsIRequest> requestsCopy(mRequests);
+     for (int32_t i = 0; i < requestsCopy.Count(); ++i)
+       requestsCopy[i]->Resume();
+   }
+ 
+-  // Called by nsNPAPIPluginStreamListener
+-  void OnStreamTypeSet(const int32_t aStreamType);
+-
+-  enum {
+-    STREAM_TYPE_UNKNOWN = UINT16_MAX
+-  };
+-
+ private:
+   nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
+-  nsresult SetupPluginCacheFile(nsIChannel* channel);
+   nsresult GetInterfaceGlobal(const nsIID& aIID, void** result);
+ 
+   nsCOMPtr<nsIURI> mURL;
+   nsCString mURLSpec; // Have to keep this member because GetURL hands out char*
+   RefPtr<nsNPAPIPluginStreamListener> mPStreamListener;
+ 
+   // Set to true if we request failed (like with a HTTP response of 404)
+   bool                    mRequestFailed;
+@@ -154,32 +134,24 @@ private:
+    * been called.
+    */
+   bool              mStartBinding;
+   bool              mHaveFiredOnStartRequest;
+   // these get passed to the plugin stream listener
+   uint32_t                mLength;
+   int32_t                 mStreamType;
+ 
+-  // local cached file, we save the content into local cache if browser cache is not available,
+-  // or plugin asks stream as file and it expects file extension until bug 90558 got fixed
+-  RefPtr<CachedFileHolder> mLocalCachedFileHolder;
+-  nsCOMPtr<nsIOutputStream> mFileCacheOutputStream;
+-  nsDataHashtable<nsUint32HashKey, uint32_t>* mDataForwardToRequest;
+-
+   nsCString mContentType;
+   bool mUseLocalCache;
+   nsCOMPtr<nsIRequest> mRequest;
+-  bool mSeekable;
+   uint32_t mModified;
+   RefPtr<nsNPAPIPluginInstance> mPluginInstance;
+   int32_t mStreamOffset;
+   bool mStreamComplete;
+ 
+ public:
+-  bool                    mAbort;
+   int32_t                 mPendingRequests;
+   nsWeakPtr               mWeakPtrChannelCallbacks;
+   nsWeakPtr               mWeakPtrChannelLoadGroup;
+   nsCOMArray<nsIRequest> mRequests;
+ };
+ 
+ #endif // nsPluginStreamListenerPeer_h_

+ 1112 - 0
mozilla-release/patches/1352573-2-58a1.patch

@@ -0,0 +1,1112 @@
+# HG changeset patch
+# User Nicholas Nethercote <nnethercote@mozilla.com>
+# Date 1501762371 -36000
+# Node ID db05998a8a032109be3afe6066518cdf903c13e0
+# Parent  1a8bfc5486f81315def316a2892e118d350e0c58
+Bug 1352573 (part 2) - Remove NPN_PluginThreadAsyncCall() and related machinery. r=bsmedberg.
+* * *
+[mq]: rm-checkGCRace
+
+diff --git a/dom/plugins/base/nsNPAPIPlugin.cpp b/dom/plugins/base/nsNPAPIPlugin.cpp
+--- a/dom/plugins/base/nsNPAPIPlugin.cpp
++++ b/dom/plugins/base/nsNPAPIPlugin.cpp
+@@ -141,67 +141,49 @@ static NPNetscapeFuncs sBrowserFuncs = {
+   _removeproperty,
+   _hasproperty,
+   _hasmethod,
+   _releasevariantvalue,
+   _setexception,
+   _pushpopupsenabledstate,
+   _poppopupsenabledstate,
+   _enumerate,
+-  _pluginthreadasynccall,
++  nullptr, // pluginthreadasynccall, not used
+   _construct,
+   _getvalueforurl,
+   _setvalueforurl,
+   nullptr, //NPN GetAuthenticationInfo, not supported
+   _scheduletimer,
+   _unscheduletimer,
+   _popupcontextmenu,
+   _convertpoint,
+   nullptr, // handleevent, unimplemented
+   nullptr, // unfocusinstance, unimplemented
+   _urlredirectresponse,
+   _initasyncsurface,
+   _finalizeasyncsurface,
+   _setcurrentasyncsurface
+ };
+ 
+-static Mutex *sPluginThreadAsyncCallLock = nullptr;
+-static PRCList sPendingAsyncCalls = PR_INIT_STATIC_CLIST(&sPendingAsyncCalls);
+-
+ // POST/GET stream type
+ enum eNPPStreamTypeInternal {
+   eNPPStreamTypeInternal_Get,
+   eNPPStreamTypeInternal_Post
+ };
+ 
+ void NS_NotifyBeginPluginCall(NSPluginCallReentry aReentryState)
+ {
+   nsNPAPIPluginInstance::BeginPluginCall(aReentryState);
+ }
+ 
+ void NS_NotifyPluginCall(NSPluginCallReentry aReentryState)
+ {
+   nsNPAPIPluginInstance::EndPluginCall(aReentryState);
+ }
+ 
+-static void CheckClassInitialized()
+-{
+-  static bool initialized = false;
+-
+-  if (initialized)
+-    return;
+-
+-  if (!sPluginThreadAsyncCallLock)
+-    sPluginThreadAsyncCallLock = new Mutex("nsNPAPIPlugin.sPluginThreadAsyncCallLock");
+-
+-  initialized = true;
+-
+-  NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,("NPN callbacks initialized\n"));
+-}
+-
+ nsNPAPIPlugin::nsNPAPIPlugin()
+ {
+   memset((void*)&mPluginFuncs, 0, sizeof(mPluginFuncs));
+   mPluginFuncs.size = sizeof(mPluginFuncs);
+   mPluginFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
+ 
+   mLibrary = nullptr;
+ }
+@@ -251,18 +233,16 @@ nsNPAPIPlugin::CreatePlugin(nsPluginTag 
+ {
+   AUTO_PROFILER_LABEL("nsNPAPIPlugin::CreatePlugin", OTHER);
+   *aResult = nullptr;
+ 
+   if (!aPluginTag) {
+     return NS_ERROR_FAILURE;
+   }
+ 
+-  CheckClassInitialized();
+-
+   RefPtr<nsNPAPIPlugin> plugin = new nsNPAPIPlugin();
+ 
+   PluginLibrary* pluginLib = GetNewPluginLibrary(aPluginTag);
+   if (!pluginLib) {
+     return NS_ERROR_FAILURE;
+   }
+ 
+ #if defined(XP_MACOSX)
+@@ -435,47 +415,16 @@ MakeNewNPAPIStreamInternal(NPP npp, cons
+ #if defined(MOZ_MEMORY) && defined(XP_WIN)
+ extern "C" size_t malloc_usable_size(const void *ptr);
+ #endif
+ 
+ namespace {
+ 
+ static char *gNPPException;
+ 
+-class nsPluginThreadRunnable : public Runnable,
+-                               public PRCList
+-{
+-public:
+-  nsPluginThreadRunnable(NPP instance, PluginThreadCallback func,
+-                         void *userData);
+-  ~nsPluginThreadRunnable() override;
+-
+-  NS_IMETHOD Run() override;
+-
+-  bool IsForInstance(NPP instance)
+-  {
+-    return (mInstance == instance);
+-  }
+-
+-  void Invalidate()
+-  {
+-    mFunc = nullptr;
+-  }
+-
+-  bool IsValid()
+-  {
+-    return (mFunc != nullptr);
+-  }
+-
+-private:
+-  NPP mInstance;
+-  PluginThreadCallback mFunc;
+-  void *mUserData;
+-};
+-
+ static nsIDocument *
+ GetDocumentFromNPP(NPP npp)
+ {
+   NS_ENSURE_TRUE(npp, nullptr);
+ 
+   nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)npp->ndata;
+   NS_ENSURE_TRUE(inst, nullptr);
+ 
+@@ -531,128 +480,16 @@ NPPExceptionAutoHolder::NPPExceptionAuto
+ 
+ NPPExceptionAutoHolder::~NPPExceptionAutoHolder()
+ {
+   NS_ASSERTION(!gNPPException, "NPP exception not properly cleared!");
+ 
+   gNPPException = mOldException;
+ }
+ 
+-nsPluginThreadRunnable::nsPluginThreadRunnable(NPP instance,
+-                                               PluginThreadCallback func,
+-                                               void *userData)
+-  : Runnable("nsPluginThreadRunnable"),
+-    mInstance(instance),
+-    mFunc(func),
+-    mUserData(userData)
+-{
+-  if (!sPluginThreadAsyncCallLock) {
+-    // Failed to create lock, not much we can do here then...
+-    mFunc = nullptr;
+-
+-    return;
+-  }
+-
+-  PR_INIT_CLIST(this);
+-
+-  {
+-    MutexAutoLock lock(*sPluginThreadAsyncCallLock);
+-
+-    nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
+-    if (!inst || !inst->IsRunning()) {
+-      // The plugin was stopped, ignore this async call.
+-      mFunc = nullptr;
+-
+-      return;
+-    }
+-
+-    PR_APPEND_LINK(this, &sPendingAsyncCalls);
+-  }
+-}
+-
+-nsPluginThreadRunnable::~nsPluginThreadRunnable()
+-{
+-  if (!sPluginThreadAsyncCallLock) {
+-    return;
+-  }
+-
+-  {
+-    MutexAutoLock lock(*sPluginThreadAsyncCallLock);
+-
+-    PR_REMOVE_LINK(this);
+-  }
+-}
+-
+-NS_IMETHODIMP
+-nsPluginThreadRunnable::Run()
+-{
+-  if (mFunc) {
+-    PluginDestructionGuard guard(mInstance);
+-
+-    NS_TRY_SAFE_CALL_VOID(mFunc(mUserData), nullptr,
+-                          NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
+-  }
+-
+-  return NS_OK;
+-}
+-
+-void
+-OnPluginDestroy(NPP instance)
+-{
+-  if (!sPluginThreadAsyncCallLock) {
+-    return;
+-  }
+-
+-  {
+-    MutexAutoLock lock(*sPluginThreadAsyncCallLock);
+-
+-    if (PR_CLIST_IS_EMPTY(&sPendingAsyncCalls)) {
+-      return;
+-    }
+-
+-    nsPluginThreadRunnable *r =
+-      (nsPluginThreadRunnable *)PR_LIST_HEAD(&sPendingAsyncCalls);
+-
+-    do {
+-      if (r->IsForInstance(instance)) {
+-        r->Invalidate();
+-      }
+-
+-      r = (nsPluginThreadRunnable *)PR_NEXT_LINK(r);
+-    } while (r != &sPendingAsyncCalls);
+-  }
+-}
+-
+-void
+-OnShutdown()
+-{
+-  NS_ASSERTION(PR_CLIST_IS_EMPTY(&sPendingAsyncCalls),
+-               "Pending async plugin call list not cleaned up!");
+-
+-  if (sPluginThreadAsyncCallLock) {
+-    delete sPluginThreadAsyncCallLock;
+-
+-    sPluginThreadAsyncCallLock = nullptr;
+-  }
+-}
+-
+-AsyncCallbackAutoLock::AsyncCallbackAutoLock()
+-{
+-  if (sPluginThreadAsyncCallLock) {
+-    sPluginThreadAsyncCallLock->Lock();
+-  }
+-}
+-
+-AsyncCallbackAutoLock::~AsyncCallbackAutoLock()
+-{
+-  if (sPluginThreadAsyncCallLock) {
+-    sPluginThreadAsyncCallLock->Unlock();
+-  }
+-}
+-
+ NPP NPPStack::sCurrentNPP = nullptr;
+ 
+ const char *
+ PeekException()
+ {
+   return gNPPException;
+ }
+ 
+@@ -1987,32 +1824,16 @@ void
+   }
+   nsNPAPIPluginInstance *inst = npp ? (nsNPAPIPluginInstance *)npp->ndata : nullptr;
+   if (!inst)
+     return;
+ 
+   inst->PopPopupsEnabledState();
+ }
+ 
+-void
+-_pluginthreadasynccall(NPP instance, PluginThreadCallback func, void *userData)
+-{
+-  if (NS_IsMainThread()) {
+-    NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,("NPN_pluginthreadasynccall called from the main thread\n"));
+-  } else {
+-    NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,("NPN_pluginthreadasynccall called from a non main thread\n"));
+-  }
+-  RefPtr<nsPluginThreadRunnable> evt =
+-    new nsPluginThreadRunnable(instance, func, userData);
+-
+-  if (evt && evt->IsValid()) {
+-    NS_DispatchToMainThread(evt);
+-  }
+-}
+-
+ NPError
+ _getvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
+                 char **value, uint32_t *len)
+ {
+   if (!NS_IsMainThread()) {
+     NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getvalueforurl called from the wrong thread\n"));
+     return NPERR_GENERIC_ERROR;
+   }
+diff --git a/dom/plugins/base/nsNPAPIPlugin.h b/dom/plugins/base/nsNPAPIPlugin.h
+--- a/dom/plugins/base/nsNPAPIPlugin.h
++++ b/dom/plugins/base/nsNPAPIPlugin.h
+@@ -214,22 +214,16 @@ void
+ _setexception(NPObject* npobj, const NPUTF8 *message);
+ 
+ void
+ _pushpopupsenabledstate(NPP npp, NPBool enabled);
+ 
+ void
+ _poppopupsenabledstate(NPP npp);
+ 
+-typedef void(*PluginThreadCallback)(void *);
+-
+-void
+-_pluginthreadasynccall(NPP instance, PluginThreadCallback func,
+-                       void *userData);
+-
+ NPError
+ _getvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
+                 char **value, uint32_t *len);
+ 
+ NPError
+ _setvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
+                 const char *value, uint32_t len);
+ 
+@@ -322,32 +316,16 @@ void
+ } /* namespace mozilla */
+ 
+ const char *
+ PeekException();
+ 
+ void
+ PopException();
+ 
+-void
+-OnPluginDestroy(NPP instance);
+-
+-void
+-OnShutdown();
+-
+-/**
+- * within a lexical scope, locks and unlocks the mutex used to
+- * serialize modifications to plugin async callback state.
+- */
+-struct MOZ_STACK_CLASS AsyncCallbackAutoLock
+-{
+-  AsyncCallbackAutoLock();
+-  ~AsyncCallbackAutoLock();
+-};
+-
+ class NPPStack
+ {
+ public:
+   static NPP Peek()
+   {
+     return sCurrentNPP;
+   }
+ 
+diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp
+--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
++++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
+@@ -159,25 +159,18 @@ nsresult nsNPAPIPluginInstance::Stop()
+     UnscheduleTimer(mTimers[i - 1]->id);
+ 
+   // If there's code from this plugin instance on the stack, delay the
+   // destroy.
+   if (PluginDestructionGuard::DelayDestroy(this)) {
+     return NS_OK;
+   }
+ 
+-  // Make sure we lock while we're writing to mRunning after we've
+-  // started as other threads might be checking that inside a lock.
+-  {
+-    AsyncCallbackAutoLock lock;
+-    mRunning = DESTROYING;
+-    mStopTime = TimeStamp::Now();
+-  }
+-
+-  OnPluginDestroy(&mNPP);
++  mRunning = DESTROYING;
++  mStopTime = TimeStamp::Now();
+ 
+   // clean up open streams
+   while (mStreamListeners.Length() > 0) {
+     RefPtr<nsNPAPIPluginStreamListener> currentListener(mStreamListeners[0]);
+     currentListener->CleanUpStream(NPRES_USER_BREAK);
+     mStreamListeners.RemoveElement(currentListener);
+   }
+ 
+diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp
+--- a/dom/plugins/base/nsPluginHost.cpp
++++ b/dom/plugins/base/nsPluginHost.cpp
+@@ -3414,17 +3414,16 @@ void nsPluginHost::CreateWidget(nsPlugin
+   aOwner->CallSetWindow();
+ }
+ 
+ NS_IMETHODIMP nsPluginHost::Observe(nsISupports *aSubject,
+                                     const char *aTopic,
+                                     const char16_t *someData)
+ {
+   if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, aTopic)) {
+-    OnShutdown();
+     UnloadPlugins();
+     sInst->Release();
+   }
+   if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
+     mPluginsDisabled = Preferences::GetBool("plugin.disable", false);
+     // Unload or load plugins as needed
+     if (mPluginsDisabled) {
+       UnloadPlugins();
+diff --git a/dom/plugins/ipc/ChildAsyncCall.cpp b/dom/plugins/ipc/ChildAsyncCall.cpp
+deleted file mode 100644
+--- a/dom/plugins/ipc/ChildAsyncCall.cpp
++++ /dev/null
+@@ -1,54 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+- * vim: sw=2 ts=8 et :
+- */
+-/* This Source Code Form is subject to the terms of the Mozilla Public
+- * License, v. 2.0. If a copy of the MPL was not distributed with this
+- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+-
+-#include "ChildAsyncCall.h"
+-#include "PluginInstanceChild.h"
+-
+-namespace mozilla {
+-namespace plugins {
+-
+-ChildAsyncCall::ChildAsyncCall(PluginInstanceChild* instance,
+-                               PluginThreadCallback aFunc,
+-                               void* aUserData)
+-  : CancelableRunnable("plugins::ChildAsyncCall")
+-  , mInstance(instance)
+-  , mFunc(aFunc)
+-  , mData(aUserData)
+-{
+-}
+-
+-nsresult
+-ChildAsyncCall::Cancel()
+-{
+-  mInstance = nullptr;
+-  mFunc = nullptr;
+-  mData = nullptr;
+-  return NS_OK;
+-}
+-
+-void
+-ChildAsyncCall::RemoveFromAsyncList()
+-{
+-  if (mInstance) {
+-    MutexAutoLock lock(mInstance->mAsyncCallMutex);
+-    mInstance->mPendingAsyncCalls.RemoveElement(this);
+-  }
+-}
+-
+-NS_IMETHODIMP
+-ChildAsyncCall::Run()
+-{
+-  RemoveFromAsyncList();
+-
+-  if (mFunc)
+-    mFunc(mData);
+-
+-  return NS_OK;
+-}
+-
+-} // namespace plugins
+-} // namespace mozilla
+diff --git a/dom/plugins/ipc/ChildAsyncCall.h b/dom/plugins/ipc/ChildAsyncCall.h
+deleted file mode 100644
+--- a/dom/plugins/ipc/ChildAsyncCall.h
++++ /dev/null
+@@ -1,41 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+- * vim: sw=2 ts=8 et :
+- */
+-/* This Source Code Form is subject to the terms of the Mozilla Public
+- * License, v. 2.0. If a copy of the MPL was not distributed with this
+- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+-
+-#ifndef mozilla_plugins_ChildAsyncCall_h
+-#define mozilla_plugins_ChildAsyncCall_h
+-
+-#include "PluginMessageUtils.h"
+-#include "nsThreadUtils.h"
+-
+-namespace mozilla {
+-namespace plugins {
+-
+-typedef void (*PluginThreadCallback)(void*);
+-
+-class PluginInstanceChild;
+-
+-class ChildAsyncCall : public CancelableRunnable
+-{
+-public:
+-  ChildAsyncCall(PluginInstanceChild* instance,
+-                 PluginThreadCallback aFunc, void* aUserData);
+-
+-  NS_IMETHOD Run() override;
+-  nsresult Cancel() override;
+-
+-protected:
+-  PluginInstanceChild* mInstance;
+-  PluginThreadCallback mFunc;
+-  void* mData;
+-
+-  void RemoveFromAsyncList();
+-};
+-
+-} // namespace plugins
+-} // namespace mozilla
+-
+-#endif // mozilla_plugins_ChildAsyncCall_h
+diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginInstanceChild.cpp
+--- a/dom/plugins/ipc/PluginInstanceChild.cpp
++++ b/dom/plugins/ipc/PluginInstanceChild.cpp
+@@ -139,17 +139,16 @@ PluginInstanceChild::PluginInstanceChild
+     , mPluginWindowHWND(0)
+     , mPluginWndProc(0)
+     , mPluginParentHWND(0)
+     , mCachedWinlessPluginHWND(0)
+     , mWinlessPopupSurrogateHWND(0)
+     , mWinlessThrottleOldWndProc(0)
+     , mWinlessHiddenMsgHWND(0)
+ #endif // OS_WIN
+-    , mAsyncCallMutex("PluginInstanceChild::mAsyncCallMutex")
+ #if defined(MOZ_WIDGET_COCOA)
+ #if defined(__i386__)
+     , mEventModel(NPEventModelCarbon)
+ #endif
+     , mShColorSpace(nullptr)
+     , mShContext(nullptr)
+     , mCGLayer(nullptr)
+     , mCurrentEvent(nullptr)
+@@ -3820,35 +3819,16 @@ PluginInstanceChild::UnscheduleTimer(uin
+ {
+     if (0 == id)
+         return;
+ 
+     mTimers.RemoveElement(id, ChildTimer::IDComparator());
+ }
+ 
+ void
+-PluginInstanceChild::AsyncCall(PluginThreadCallback aFunc, void* aUserData)
+-{
+-    RefPtr<ChildAsyncCall> task = new ChildAsyncCall(this, aFunc, aUserData);
+-    PostChildAsyncCall(task.forget());
+-}
+-
+-void
+-PluginInstanceChild::PostChildAsyncCall(already_AddRefed<ChildAsyncCall> aTask)
+-{
+-    RefPtr<ChildAsyncCall> task = aTask;
+-
+-    {
+-        MutexAutoLock lock(mAsyncCallMutex);
+-        mPendingAsyncCalls.AppendElement(task);
+-    }
+-    ProcessChild::message_loop()->PostTask(task.forget());
+-}
+-
+-void
+ PluginInstanceChild::SwapSurfaces()
+ {
+     RefPtr<gfxASurface> tmpsurf = mCurrentSurface;
+ #ifdef XP_WIN
+     PPluginSurfaceChild* tmpactor = mCurrentSurfaceActor;
+ #endif
+ 
+     mCurrentSurface = mBackSurface;
+@@ -4057,23 +4037,16 @@ PluginInstanceChild::Destroy()
+     UnhookWinlessFlashThrottle();
+     DestroyPluginWindow();
+ 
+     for (uint32_t i = 0; i < mPendingFlashThrottleMsgs.Length(); ++i) {
+         mPendingFlashThrottleMsgs[i]->Cancel();
+     }
+     mPendingFlashThrottleMsgs.Clear();
+ #endif
+-
+-    // Pending async calls are discarded, not delivered. This matches the
+-    // in-process behavior.
+-    for (uint32_t i = 0; i < mPendingAsyncCalls.Length(); ++i)
+-        mPendingAsyncCalls[i]->Cancel();
+-
+-    mPendingAsyncCalls.Clear();
+ }
+ 
+ mozilla::ipc::IPCResult
+ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
+ {
+     PLUGIN_LOG_DEBUG_METHOD;
+     AssertPluginThread();
+     *aResult = NPERR_NO_ERROR;
+diff --git a/dom/plugins/ipc/PluginInstanceChild.h b/dom/plugins/ipc/PluginInstanceChild.h
+--- a/dom/plugins/ipc/PluginInstanceChild.h
++++ b/dom/plugins/ipc/PluginInstanceChild.h
+@@ -21,17 +21,16 @@
+ #include "mozilla/gfx/QuartzSupport.h"
+ #include "base/timer.h"
+ 
+ #endif
+ 
+ #include "npfunctions.h"
+ #include "nsAutoPtr.h"
+ #include "nsTArray.h"
+-#include "ChildAsyncCall.h"
+ #include "ChildTimer.h"
+ #include "nsRect.h"
+ #include "nsTHashtable.h"
+ #include "mozilla/PaintTracker.h"
+ #include "mozilla/gfx/Types.h"
+ 
+ #include <map>
+ 
+@@ -229,20 +228,16 @@ public:
+ 
+ #ifdef MOZ_WIDGET_COCOA
+     void Invalidate();
+ #endif // definied(MOZ_WIDGET_COCOA)
+ 
+     uint32_t ScheduleTimer(uint32_t interval, bool repeat, TimerFunc func);
+     void UnscheduleTimer(uint32_t id);
+ 
+-    void AsyncCall(PluginThreadCallback aFunc, void* aUserData);
+-    // This function is a more general version of AsyncCall
+-    void PostChildAsyncCall(already_AddRefed<ChildAsyncCall> aTask);
+-
+     int GetQuirks();
+ 
+     void NPN_URLRedirectResponse(void* notifyData, NPBool allow);
+ 
+ 
+     NPError NPN_InitAsyncSurface(NPSize *size, NPImageFormat format,
+                                  void *initData, NPAsyncSurface *surface);
+     NPError NPN_FinalizeAsyncSurface(NPAsyncSurface *surface);
+@@ -429,23 +424,19 @@ private:
+     int mNestedEventLevelDepth;
+     HWND mCachedWinlessPluginHWND;
+     HWND mWinlessPopupSurrogateHWND;
+     nsIntPoint mPluginSize;
+     WNDPROC mWinlessThrottleOldWndProc;
+     HWND mWinlessHiddenMsgHWND;
+ #endif
+ 
+-    friend class ChildAsyncCall;
+-
+ #if defined(OS_WIN)
+     nsTArray<FlashThrottleMsg*> mPendingFlashThrottleMsgs;
+ #endif
+-    Mutex mAsyncCallMutex;
+-    nsTArray<ChildAsyncCall*> mPendingAsyncCalls;
+     nsTArray<nsAutoPtr<ChildTimer> > mTimers;
+ 
+     /**
+      * During destruction we enumerate all remaining scriptable objects and
+      * invalidate/delete them. Enumeration can re-enter, so maintain a
+      * hash separate from PluginModuleChild.mObjectMap.
+      */
+     nsAutoPtr< nsTHashtable<DeletingObjectEntry> > mDeletingHash;
+diff --git a/dom/plugins/ipc/PluginModuleChild.cpp b/dom/plugins/ipc/PluginModuleChild.cpp
+--- a/dom/plugins/ipc/PluginModuleChild.cpp
++++ b/dom/plugins/ipc/PluginModuleChild.cpp
+@@ -916,20 +916,16 @@ static void
+ _setexception(NPObject* npobj, const NPUTF8 *message);
+ 
+ static void
+ _pushpopupsenabledstate(NPP aNPP, NPBool enabled);
+ 
+ static void
+ _poppopupsenabledstate(NPP aNPP);
+ 
+-static void
+-_pluginthreadasynccall(NPP instance, PluginThreadCallback func,
+-                       void *userData);
+-
+ static NPError
+ _getvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
+                 char **value, uint32_t *len);
+ 
+ static NPError
+ _setvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
+                 const char *value, uint32_t len);
+ 
+@@ -1007,17 +1003,17 @@ const NPNetscapeFuncs PluginModuleChild:
+     mozilla::plugins::child::_removeproperty,
+     mozilla::plugins::child::_hasproperty,
+     mozilla::plugins::child::_hasmethod,
+     mozilla::plugins::child::_releasevariantvalue,
+     mozilla::plugins::child::_setexception,
+     mozilla::plugins::child::_pushpopupsenabledstate,
+     mozilla::plugins::child::_poppopupsenabledstate,
+     mozilla::plugins::child::_enumerate,
+-    mozilla::plugins::child::_pluginthreadasynccall,
++    nullptr, // pluginthreadasynccall, not used
+     mozilla::plugins::child::_construct,
+     mozilla::plugins::child::_getvalueforurl,
+     mozilla::plugins::child::_setvalueforurl,
+     nullptr, //NPN GetAuthenticationInfo, not supported
+     mozilla::plugins::child::_scheduletimer,
+     mozilla::plugins::child::_unscheduletimer,
+     mozilla::plugins::child::_popupcontextmenu,
+     mozilla::plugins::child::_convertpoint,
+@@ -1540,28 +1536,16 @@ void
+ _poppopupsenabledstate(NPP aNPP)
+ {
+     PLUGIN_LOG_DEBUG_FUNCTION;
+     ENSURE_PLUGIN_THREAD_VOID();
+ 
+     InstCast(aNPP)->CallNPN_PopPopupsEnabledState();
+ }
+ 
+-void
+-_pluginthreadasynccall(NPP aNPP,
+-                       PluginThreadCallback aFunc,
+-                       void* aUserData)
+-{
+-    PLUGIN_LOG_DEBUG_FUNCTION;
+-    if (!aFunc)
+-        return;
+-
+-    InstCast(aNPP)->AsyncCall(aFunc, aUserData);
+-}
+-
+ NPError
+ _getvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
+                 char **value, uint32_t *len)
+ {
+     PLUGIN_LOG_DEBUG_FUNCTION;
+     AssertPluginThread();
+ 
+     if (!url)
+diff --git a/dom/plugins/ipc/moz.build b/dom/plugins/ipc/moz.build
+--- a/dom/plugins/ipc/moz.build
++++ b/dom/plugins/ipc/moz.build
+@@ -10,17 +10,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
+ EXPORTS.mozilla += [
+     'PluginLibrary.h',
+ ]
+ 
+ EXPORTS.mozilla.plugins += [
+     'AStream.h',
+     'BrowserStreamChild.h',
+     'BrowserStreamParent.h',
+-    'ChildAsyncCall.h',
+     'ChildTimer.h',
+     'NPEventOSX.h',
+     'NPEventUnix.h',
+     'NPEventWindows.h',
+     'PluginBridge.h',
+     'PluginInstanceChild.h',
+     'PluginInstanceParent.h',
+     'PluginMessageUtils.h',
+@@ -58,17 +57,16 @@ if CONFIG['OS_ARCH'] == 'WINNT':
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
+     EXPORTS.mozilla.plugins += [
+         'PluginInterposeOSX.h',
+     ]
+ 
+ UNIFIED_SOURCES += [
+     'BrowserStreamChild.cpp',
+     'BrowserStreamParent.cpp',
+-    'ChildAsyncCall.cpp',
+     'ChildTimer.cpp',
+     'PluginBackgroundDestroyer.cpp',
+     'PluginInstanceParent.cpp',
+     'PluginMessageUtils.cpp',
+     'PluginModuleParent.cpp',
+     'PluginProcessChild.cpp',
+     'PluginProcessParent.cpp',
+     'PluginQuirks.cpp',
+diff --git a/dom/plugins/test/testplugin/nptest.cpp b/dom/plugins/test/testplugin/nptest.cpp
+--- a/dom/plugins/test/testplugin/nptest.cpp
++++ b/dom/plugins/test/testplugin/nptest.cpp
+@@ -89,19 +89,16 @@ IntentionalCrash()
+ 
+ //
+ // static data
+ //
+ 
+ static NPNetscapeFuncs* sBrowserFuncs = nullptr;
+ static NPClass sNPClass;
+ 
+-void
+-asyncCallback(void* cookie);
+-
+ //
+ // identifiers
+ //
+ 
+ typedef bool (* ScriptableFunction)
+   (NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ 
+ static bool npnEvaluateTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+@@ -136,18 +133,16 @@ static bool streamTest(NPObject* npobj, 
+ static bool postFileToURLTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool setPluginWantsAllStreams(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool crashPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool crashOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool getObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool getJavaCodebase(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool checkObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool enableFPExceptions(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+-static bool asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+-static bool checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool stallPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool callOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool reinitWidget(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool crashPluginInNestedLoop(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool triggerXError(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+ static bool destroySharedGfxStuff(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
+@@ -210,18 +205,16 @@ static const NPUTF8* sPluginMethodIdenti
+   "postFileToURLTest",
+   "setPluginWantsAllStreams",
+   "crash",
+   "crashOnDestroy",
+   "getObjectValue",
+   "getJavaCodebase",
+   "checkObjectValue",
+   "enableFPExceptions",
+-  "asyncCallbackTest",
+-  "checkGCRace",
+   "hang",
+   "stall",
+   "getClipboardText",
+   "callOnDestroy",
+   "reinitWidget",
+   "crashInNestedLoop",
+   "triggerXError",
+   "destroySharedGfxStuff",
+@@ -285,18 +278,16 @@ static const ScriptableFunction sPluginM
+   postFileToURLTest,
+   setPluginWantsAllStreams,
+   crashPlugin,
+   crashOnDestroy,
+   getObjectValue,
+   getJavaCodebase,
+   checkObjectValue,
+   enableFPExceptions,
+-  asyncCallbackTest,
+-  checkGCRace,
+   hangPlugin,
+   stallPlugin,
+   getClipboardText,
+   callOnDestroy,
+   reinitWidget,
+   crashPluginInNestedLoop,
+   triggerXError,
+   destroySharedGfxStuff,
+@@ -1901,22 +1892,16 @@ NPN_SetValueForURL(NPP instance, NPNURLV
+ 
+ NPError
+ NPN_GetValueForURL(NPP instance, NPNURLVariable variable, const char *url, char **value, uint32_t *len)
+ {
+   return sBrowserFuncs->getvalueforurl(instance, variable, url, value, len);
+ }
+ 
+ void
+-NPN_PluginThreadAsyncCall(NPP plugin, void (*func)(void*), void* userdata)
+-{
+-  return sBrowserFuncs->pluginthreadasynccall(plugin, func, userdata);
+-}
+-
+-void
+ NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow)
+ {
+   return sBrowserFuncs->urlredirectresponse(instance, notifyData, allow);
+ }
+ 
+ NPError
+ NPN_InitAsyncSurface(NPP instance, NPSize *size, NPImageFormat format,
+                      void *initData, NPAsyncSurface *surface)
+@@ -3009,181 +2994,16 @@ timerTest(NPObject* npobj, const NPVaria
+   id->timerTestResult = true;
+   timerEvent event = timerEvents[currentTimerEventCount];
+ 
+   id->timerID[event.timerIdSchedule] = NPN_ScheduleTimer(npp, event.timerInterval, event.timerRepeat, timerCallback);
+ 
+   return id->timerID[event.timerIdSchedule] != 0;
+ }
+ 
+-#ifdef XP_WIN
+-void
+-ThreadProc(void* cookie)
+-#else
+-void*
+-ThreadProc(void* cookie)
+-#endif
+-{
+-  NPObject* npobj = (NPObject*)cookie;
+-  NPP npp = static_cast<TestNPObject*>(npobj)->npp;
+-  InstanceData* id = static_cast<InstanceData*>(npp->pdata);
+-  id->asyncTestPhase = 1;
+-  NPN_PluginThreadAsyncCall(npp, asyncCallback, (void*)npobj);
+-#ifndef XP_WIN
+-  return nullptr;
+-#endif
+-}
+-
+-void
+-asyncCallback(void* cookie)
+-{
+-  NPObject* npobj = (NPObject*)cookie;
+-  NPP npp = static_cast<TestNPObject*>(npobj)->npp;
+-  InstanceData* id = static_cast<InstanceData*>(npp->pdata);
+-
+-  switch (id->asyncTestPhase) {
+-    // async callback triggered from same thread
+-    case 0:
+-#ifdef XP_WIN
+-      if (_beginthread(ThreadProc, 0, (void*)npobj) == -1)
+-        id->asyncCallbackResult = false;
+-#else
+-      pthread_t tid;
+-      if (pthread_create(&tid, 0, ThreadProc, (void*)npobj))
+-        id->asyncCallbackResult = false;
+-#endif
+-      break;
+-
+-    // async callback triggered from different thread
+-    default:
+-      NPObject* windowObject;
+-      NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
+-      if (!windowObject)
+-        return;
+-      NPVariant arg, rval;
+-      BOOLEAN_TO_NPVARIANT(id->asyncCallbackResult, arg);
+-      NPN_Invoke(npp, windowObject, NPN_GetStringIdentifier(id->asyncTestScriptCallback.c_str()), &arg, 1, &rval);
+-      NPN_ReleaseVariantValue(&arg);
+-      NPN_ReleaseObject(windowObject);
+-      break;
+-  }
+-}
+-
+-static bool
+-asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
+-{
+-  NPP npp = static_cast<TestNPObject*>(npobj)->npp;
+-  InstanceData* id = static_cast<InstanceData*>(npp->pdata);
+-
+-  if (argCount < 1 || !NPVARIANT_IS_STRING(args[0]))
+-    return false;
+-  const NPString* argstr = &NPVARIANT_TO_STRING(args[0]);
+-  id->asyncTestScriptCallback = argstr->UTF8Characters;
+-
+-  id->asyncTestPhase = 0;
+-  id->asyncCallbackResult = true;
+-  NPN_PluginThreadAsyncCall(npp, asyncCallback, (void*)npobj);
+-
+-  return true;
+-}
+-
+-static bool
+-GCRaceInvoke(NPObject*, NPIdentifier, const NPVariant*, uint32_t, NPVariant*)
+-{
+-  return false;
+-}
+-
+-static bool
+-GCRaceInvokeDefault(NPObject* o, const NPVariant* args, uint32_t argCount,
+-		    NPVariant* result)
+-{
+-  if (1 != argCount || !NPVARIANT_IS_INT32(args[0]) ||
+-      35 != NPVARIANT_TO_INT32(args[0]))
+-    return false;
+-
+-  return true;
+-}
+-
+-static const NPClass kGCRaceClass = {
+-  NP_CLASS_STRUCT_VERSION,
+-  nullptr,
+-  nullptr,
+-  nullptr,
+-  nullptr,
+-  GCRaceInvoke,
+-  GCRaceInvokeDefault,
+-  nullptr,
+-  nullptr,
+-  nullptr,
+-  nullptr,
+-  nullptr,
+-  nullptr
+-};
+-
+-struct GCRaceData
+-{
+-  GCRaceData(NPP npp, NPObject* callback, NPObject* localFunc)
+-    : npp_(npp)
+-    , callback_(callback)
+-    , localFunc_(localFunc)
+-  {
+-    NPN_RetainObject(callback_);
+-    NPN_RetainObject(localFunc_);
+-  }
+-
+-  ~GCRaceData()
+-  {
+-    NPN_ReleaseObject(callback_);
+-    NPN_ReleaseObject(localFunc_);
+-  }
+-
+-  NPP npp_;
+-  NPObject* callback_;
+-  NPObject* localFunc_;
+-};
+-
+-static void
+-FinishGCRace(void* closure)
+-{
+-  GCRaceData* rd = static_cast<GCRaceData*>(closure);
+-
+-  XPSleep(5);
+-
+-  NPVariant arg;
+-  OBJECT_TO_NPVARIANT(rd->localFunc_, arg);
+-
+-  NPVariant result;
+-  bool ok = NPN_InvokeDefault(rd->npp_, rd->callback_, &arg, 1, &result);
+-  if (!ok)
+-    return;
+-
+-  NPN_ReleaseVariantValue(&result);
+-  delete rd;
+-}
+-
+-bool
+-checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount,
+-	    NPVariant* result)
+-{
+-  if (1 != argCount || !NPVARIANT_IS_OBJECT(args[0]))
+-    return false;
+-
+-  NPP npp = static_cast<TestNPObject*>(npobj)->npp;
+-
+-  NPObject* localFunc =
+-    NPN_CreateObject(npp, const_cast<NPClass*>(&kGCRaceClass));
+-
+-  GCRaceData* rd =
+-    new GCRaceData(npp, NPVARIANT_TO_OBJECT(args[0]), localFunc);
+-  NPN_PluginThreadAsyncCall(npp, FinishGCRace, rd);
+-
+-  OBJECT_TO_NPVARIANT(localFunc, *result);
+-  return true;
+-}
+-
+ bool
+ hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount,
+            NPVariant* result)
+ {
+   mozilla::NoteIntentionalCrash("plugin");
+ 
+   bool busyHang = false;
+   if ((argCount == 1) && NPVARIANT_IS_BOOLEAN(args[0])) {
+diff --git a/dom/plugins/test/testplugin/nptest.h b/dom/plugins/test/testplugin/nptest.h
+--- a/dom/plugins/test/testplugin/nptest.h
++++ b/dom/plugins/test/testplugin/nptest.h
+@@ -104,39 +104,36 @@ typedef struct InstanceData {
+   bool lastReportedPrivateModeState;
+   bool hasWidget;
+   bool npnNewStream;
+   bool throwOnNextInvoke;
+   bool runScriptOnPaint;
+   bool dontTouchElement;
+   uint32_t timerID[2];
+   bool timerTestResult;
+-  bool asyncCallbackResult;
+   bool invalidateDuringPaint;
+   bool slowPaint;
+   bool playingAudio;
+   bool audioMuted;
+   int32_t winX;
+   int32_t winY;
+   int32_t lastMouseX;
+   int32_t lastMouseY;
+   int32_t widthAtLastPaint;
+   int32_t paintCount;
+   int32_t writeCount;
+   int32_t writeReadyCount;
+-  int32_t asyncTestPhase;
+   TestFunction testFunction;
+   TestFunction functionToFail;
+   NPError failureCode;
+   NPObject* callOnDestroy;
+   PostMode postMode;
+   std::string testUrl;
+   std::string frame;
+   std::string timerTestScriptCallback;
+-  std::string asyncTestScriptCallback;
+   std::ostringstream err;
+   uint16_t streamMode;
+   int32_t streamChunkSize;
+   int32_t streamBufSize;
+   int32_t fileBufSize;
+   TestRange* testrange;
+   void* streamBuf;
+   void* fileBuf;

+ 93 - 0
mozilla-release/patches/1405312-58a1.patch

@@ -0,0 +1,93 @@
+# HG changeset patch
+# User Alex Gaynor <agaynor@mozilla.com>
+# Date 1507038788 14400
+# Node ID e8a4604faef277558f5862cb8424160251f40006
+# Parent  2192a8af145071f87771802521841da882ec5667
+Bug 1405312 - Remove dead code from nsPluginHost; r=jimm
+
+MozReview-Commit-ID: BsZIoTeZrNL
+
+diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp
+--- a/dom/plugins/base/nsPluginHost.cpp
++++ b/dom/plugins/base/nsPluginHost.cpp
+@@ -119,20 +119,16 @@ using mozilla::dom::FakePluginMimeEntry;
+   {                                                                  \
+     while (list_) {                                                  \
+       type_ temp = list_->mNext_;                                    \
+       list_->mNext_ = nullptr;                                       \
+       list_ = temp;                                                  \
+     }                                                                \
+   }
+ 
+-// this is the name of the directory which will be created
+-// to cache temporary files.
+-#define kPluginTmpDirName NS_LITERAL_CSTRING("plugtmp")
+-
+ static const char *kPrefWhitelist = "plugin.allowed_types";
+ static const char *kPrefLoadInParentPrefix = "plugin.load_in_parent_process.";
+ static const char *kPrefDisableFullPage = "plugin.disable_full_page_plugin_for_types";
+ 
+ // How long we wait before unloading an idle plugin process.
+ // Defaults to 30 seconds.
+ static const char *kPrefUnloadPluginTimeoutSecs = "dom.ipc.plugins.unloadTimeoutSecs";
+ static const uint32_t kDefaultPluginUnloadingTimeout = 30;
+@@ -665,37 +661,16 @@ void nsPluginHost::OnPluginInstanceDestr
+       aPluginTag->mUnloadTimer->InitWithCallback(this,
+                                                  1000 * unloadTimeout,
+                                                  nsITimer::TYPE_ONE_SHOT);
+     }
+   }
+ }
+ 
+ nsresult
+-nsPluginHost::GetPluginTempDir(nsIFile **aDir)
+-{
+-  if (!sPluginTempDir) {
+-    nsCOMPtr<nsIFile> tmpDir;
+-    nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR,
+-                                         getter_AddRefs(tmpDir));
+-    NS_ENSURE_SUCCESS(rv, rv);
+-
+-    rv = tmpDir->AppendNative(kPluginTmpDirName);
+-
+-    // make it unique, and mode == 0700, not world-readable
+-    rv = tmpDir->CreateUnique(nsIFile::DIRECTORY_TYPE, 0700);
+-    NS_ENSURE_SUCCESS(rv, rv);
+-
+-    tmpDir.swap(sPluginTempDir);
+-  }
+-
+-  return sPluginTempDir->Clone(aDir);
+-}
+-
+-nsresult
+ nsPluginHost::InstantiatePluginInstance(const nsACString& aMimeType, nsIURI* aURL,
+                                         nsObjectLoadingContent *aContent,
+                                         nsPluginInstanceOwner** aOwner)
+ {
+   NS_ENSURE_ARG_POINTER(aOwner);
+ 
+ #ifdef PLUGIN_LOGGING
+   nsAutoCString urlSpec;
+diff --git a/dom/plugins/base/nsPluginHost.h b/dom/plugins/base/nsPluginHost.h
+--- a/dom/plugins/base/nsPluginHost.h
++++ b/dom/plugins/base/nsPluginHost.h
+@@ -177,18 +177,16 @@ public:
+                     bool forceJSEnabled = false,
+                     uint32_t getHeadersLength = 0,
+                     const char* getHeaders = nullptr);
+ 
+   nsresult
+   AddHeadersToChannel(const char *aHeadersData, uint32_t aHeadersDataLen,
+                       nsIChannel *aGenericChannel);
+ 
+-  static nsresult GetPluginTempDir(nsIFile **aDir);
+-
+   // Helper that checks if a type is whitelisted in plugin.allowed_types.
+   // Always returns true if plugin.allowed_types is not set
+   static bool IsTypeWhitelisted(const char *aType);
+ 
+   // Helper that checks if a plugin of a given MIME type can be loaded by the
+   // parent process. It checks the plugin.load_in_parent_process.<mime> pref.
+   // Always returns false if plugin.load_in_parent_process.<mime> is not set.
+   static bool ShouldLoadTypeInParent(const nsACString& aMimeType);

+ 664 - 0
mozilla-release/patches/1413845-58a1.patch

@@ -0,0 +1,664 @@
+# HG changeset patch
+# User Marco Castelluccio <mcastelluccio@mozilla.com>
+# Date 1509617004 -3600
+# Node ID 899a407832c09e685748779d288637a24aaae2af
+# Parent  cff35191bcbcaf825746c8427ea31829c36b4627
+Bug 1413845 - Remove PluginPRLibrary as it is unused. r=jimm
+
+diff --git a/dom/plugins/base/PluginPRLibrary.cpp b/dom/plugins/base/PluginPRLibrary.cpp
+deleted file mode 100644
+--- a/dom/plugins/base/PluginPRLibrary.cpp
++++ /dev/null
+@@ -1,292 +0,0 @@
+-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+- * vim: sw=2 ts=8 et :
+- * This Source Code Form is subject to the terms of the Mozilla Public
+- * License, v. 2.0. If a copy of the MPL was not distributed with this
+- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+-
+-#include "mozilla/Assertions.h"
+-#include "mozilla/PluginPRLibrary.h"
+-#include "nsNPAPIPluginInstance.h"
+-
+-// Some plugins on Windows, notably Quake Live, implement NP_Initialize using
+-// cdecl instead of the documented stdcall. In order to work around this,
+-// we force the caller to use a frame pointer.
+-#if defined(XP_WIN) && defined(_M_IX86)
+-#include <malloc.h>
+-
+-// gNotOptimized exists so that the compiler will not optimize the alloca
+-// below.
+-static int gNotOptimized;
+-#define CALLING_CONVENTION_HACK void* foo MOZ_UNUSED_ATTRIBUTE = _alloca(gNotOptimized);
+-#else
+-#define CALLING_CONVENTION_HACK
+-#endif
+-
+-using namespace mozilla::layers;
+-
+-namespace mozilla {
+-#if defined(XP_UNIX) && !defined(XP_MACOSX)
+-nsresult
+-PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs,
+-                               NPPluginFuncs* pFuncs, NPError* error)
+-{
+-  if (mNP_Initialize) {
+-    *error = mNP_Initialize(bFuncs, pFuncs);
+-  } else {
+-    NP_InitializeFunc pfNP_Initialize = (NP_InitializeFunc)
+-      PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
+-    if (!pfNP_Initialize)
+-      return NS_ERROR_FAILURE;
+-    *error = pfNP_Initialize(bFuncs, pFuncs);
+-  }
+-
+-
+-  // Save pointers to functions that get called through PluginLibrary itself.
+-  mNPP_New = pFuncs->newp;
+-  mNPP_ClearSiteData = pFuncs->clearsitedata;
+-  mNPP_GetSitesWithData = pFuncs->getsiteswithdata;
+-  return NS_OK;
+-}
+-#else
+-nsresult
+-PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
+-{
+-  CALLING_CONVENTION_HACK
+-
+-  if (mNP_Initialize) {
+-    *error = mNP_Initialize(bFuncs);
+-  } else {
+-    NP_InitializeFunc pfNP_Initialize = (NP_InitializeFunc)
+-      PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
+-    if (!pfNP_Initialize)
+-      return NS_ERROR_FAILURE;
+-    *error = pfNP_Initialize(bFuncs);
+-  }
+-
+-  return NS_OK;
+-}
+-#endif
+-
+-nsresult
+-PluginPRLibrary::NP_Shutdown(NPError* error)
+-{
+-  CALLING_CONVENTION_HACK
+-
+-  if (mNP_Shutdown) {
+-    *error = mNP_Shutdown();
+-  } else {
+-    NP_ShutdownFunc pfNP_Shutdown = (NP_ShutdownFunc)
+-      PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
+-    if (!pfNP_Shutdown)
+-      return NS_ERROR_FAILURE;
+-    *error = pfNP_Shutdown();
+-  }
+-
+-  return NS_OK;
+-}
+-
+-nsresult
+-PluginPRLibrary::NP_GetMIMEDescription(const char** mimeDesc)
+-{
+-  CALLING_CONVENTION_HACK
+-
+-  if (mNP_GetMIMEDescription) {
+-    *mimeDesc = mNP_GetMIMEDescription();
+-  }
+-  else {
+-    NP_GetMIMEDescriptionFunc pfNP_GetMIMEDescription =
+-      (NP_GetMIMEDescriptionFunc)
+-      PR_FindFunctionSymbol(mLibrary, "NP_GetMIMEDescription");
+-    if (!pfNP_GetMIMEDescription) {
+-      *mimeDesc = "";
+-      return NS_ERROR_FAILURE;
+-    }
+-    *mimeDesc = pfNP_GetMIMEDescription();
+-  }
+-
+-  return NS_OK;
+-}
+-
+-nsresult
+-PluginPRLibrary::NP_GetValue(void *future, NPPVariable aVariable,
+-			     void *aValue, NPError* error)
+-{
+-#if defined(XP_UNIX) && !defined(XP_MACOSX)
+-  if (mNP_GetValue) {
+-    *error = mNP_GetValue(future, aVariable, aValue);
+-  } else {
+-    NP_GetValueFunc pfNP_GetValue = (NP_GetValueFunc)PR_FindFunctionSymbol(mLibrary, "NP_GetValue");
+-    if (!pfNP_GetValue)
+-      return NS_ERROR_FAILURE;
+-    *error = pfNP_GetValue(future, aVariable, aValue);
+-  }
+-  return NS_OK;
+-#else
+-  return NS_ERROR_NOT_IMPLEMENTED;
+-#endif
+-}
+-
+-#if defined(XP_WIN) || defined(XP_MACOSX)
+-nsresult
+-PluginPRLibrary::NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error)
+-{
+-  CALLING_CONVENTION_HACK
+-
+-  if (mNP_GetEntryPoints) {
+-    *error = mNP_GetEntryPoints(pFuncs);
+-  } else {
+-    NP_GetEntryPointsFunc pfNP_GetEntryPoints = (NP_GetEntryPointsFunc)
+-      PR_FindFunctionSymbol(mLibrary, "NP_GetEntryPoints");
+-    if (!pfNP_GetEntryPoints)
+-      return NS_ERROR_FAILURE;
+-    *error = pfNP_GetEntryPoints(pFuncs);
+-  }
+-
+-  // Save pointers to functions that get called through PluginLibrary itself.
+-  mNPP_New = pFuncs->newp;
+-  mNPP_ClearSiteData = pFuncs->clearsitedata;
+-  mNPP_GetSitesWithData = pFuncs->getsiteswithdata;
+-  return NS_OK;
+-}
+-#endif
+-
+-nsresult
+-PluginPRLibrary::NPP_New(NPMIMEType pluginType, NPP instance,
+-			 int16_t argc, char* argn[],
+-			 char* argv[], NPSavedData* saved,
+-			 NPError* error)
+-{
+-  if (!mNPP_New)
+-    return NS_ERROR_FAILURE;
+-
+-  *error = mNPP_New(pluginType, instance, NP_EMBED, argc, argn, argv, saved);
+-  return NS_OK;
+-}
+-
+-nsresult
+-PluginPRLibrary::NPP_ClearSiteData(const char* site, uint64_t flags,
+-                                   uint64_t maxAge, nsCOMPtr<nsIClearSiteDataCallback> callback)
+-{
+-  if (!mNPP_ClearSiteData) {
+-    return NS_ERROR_NOT_AVAILABLE;
+-  }
+-
+-  NPError result = mNPP_ClearSiteData(site, flags, maxAge);
+-
+-  nsresult rv;
+-  switch (result) {
+-  case NPERR_NO_ERROR:
+-    rv = NS_OK;
+-    break;
+-  case NPERR_TIME_RANGE_NOT_SUPPORTED:
+-    rv = NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED;
+-    break;
+-  case NPERR_MALFORMED_SITE:
+-    rv = NS_ERROR_INVALID_ARG;
+-    break;
+-  default:
+-    rv = NS_ERROR_FAILURE;
+-  }
+-  callback->Callback(rv);
+-  return NS_OK;
+-}
+-
+-nsresult
+-PluginPRLibrary::NPP_GetSitesWithData(nsCOMPtr<nsIGetSitesWithDataCallback> callback)
+-{
+-  if (!mNPP_GetSitesWithData) {
+-    return NS_ERROR_NOT_AVAILABLE;
+-  }
+-
+-  char** sites = mNPP_GetSitesWithData();
+-  if (!sites) {
+-    return NS_OK;
+-  }
+-  InfallibleTArray<nsCString> result;
+-  char** iterator = sites;
+-  while (*iterator) {
+-    result.AppendElement(*iterator);
+-    free(*iterator);
+-    ++iterator;
+-  }
+-  callback->SitesWithData(result);
+-  free(sites);
+-
+-  return NS_OK;
+-}
+-
+-nsresult
+-PluginPRLibrary::AsyncSetWindow(NPP instance, NPWindow* window)
+-{
+-  nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
+-  NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
+-  return NS_ERROR_NOT_IMPLEMENTED;
+-}
+-
+-nsresult
+-PluginPRLibrary::GetImageContainer(NPP instance, ImageContainer** aContainer)
+-{
+-  return NS_ERROR_NOT_IMPLEMENTED;
+-}
+-
+-#if defined(XP_MACOSX)
+-nsresult
+-PluginPRLibrary::IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing)
+-{
+-  nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
+-  NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
+-  *aDrawing = false;
+-  return NS_OK;
+-}
+-#endif
+-#if defined(XP_MACOSX) || defined(XP_WIN)
+-nsresult
+-PluginPRLibrary::ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor)
+-{
+-  nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
+-  NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
+-  return NS_OK;
+-}
+-#endif
+-
+-nsresult
+-PluginPRLibrary::GetImageSize(NPP instance, nsIntSize* aSize)
+-{
+-  return NS_ERROR_NOT_IMPLEMENTED;
+-}
+-
+-nsresult
+-PluginPRLibrary::SetBackgroundUnknown(NPP instance)
+-{
+-  nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
+-  NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
+-  NS_ERROR("Unexpected use of async APIs for in-process plugin.");
+-  return NS_ERROR_NOT_IMPLEMENTED;
+-}
+-
+-nsresult
+-PluginPRLibrary::BeginUpdateBackground(NPP instance, const nsIntRect&,
+-                                       DrawTarget** aDrawTarget)
+-{
+-  nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
+-  NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
+-  NS_ERROR("Unexpected use of async APIs for in-process plugin.");
+-  *aDrawTarget = nullptr;
+-  return NS_OK;
+-}
+-
+-nsresult
+-PluginPRLibrary::EndUpdateBackground(NPP instance, const nsIntRect&)
+-{
+-  MOZ_CRASH("This should never be called");
+-  return NS_ERROR_NOT_AVAILABLE;
+-}
+-
+-#if defined(XP_WIN)
+-nsresult
+-PluginPRLibrary::GetScrollCaptureContainer(NPP aInstance, ImageContainer** aContainer)
+-{
+-  return NS_ERROR_NOT_IMPLEMENTED;
+-}
+-#endif
+-} // namespace mozilla
+diff --git a/dom/plugins/base/PluginPRLibrary.h b/dom/plugins/base/PluginPRLibrary.h
+deleted file mode 100644
+--- a/dom/plugins/base/PluginPRLibrary.h
++++ /dev/null
+@@ -1,154 +0,0 @@
+-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+- * vim: sw=4 ts=4 et :
+- * This Source Code Form is subject to the terms of the Mozilla Public
+- * License, v. 2.0. If a copy of the MPL was not distributed with this
+- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+-
+-#ifndef PluginPRLibrary_h
+-#define PluginPRLibrary_h 1
+-
+-#include "mozilla/PluginLibrary.h"
+-#include "nsNPAPIPlugin.h"
+-#include "npfunctions.h"
+-
+-namespace mozilla {
+-
+-class PluginPRLibrary : public PluginLibrary
+-{
+-public:
+-    PluginPRLibrary(const char* aFilePath, PRLibrary* aLibrary) :
+-#if defined(XP_UNIX) && !defined(XP_MACOSX)
+-        mNP_Initialize(nullptr),
+-#else
+-        mNP_Initialize(nullptr),
+-#endif
+-        mNP_Shutdown(nullptr),
+-        mNP_GetMIMEDescription(nullptr),
+-#if defined(XP_UNIX) && !defined(XP_MACOSX)
+-        mNP_GetValue(nullptr),
+-#endif
+-#if defined(XP_WIN) || defined(XP_MACOSX)
+-        mNP_GetEntryPoints(nullptr),
+-#endif
+-        mNPP_New(nullptr),
+-        mNPP_ClearSiteData(nullptr),
+-        mNPP_GetSitesWithData(nullptr),
+-        mLibrary(aLibrary),
+-        mFilePath(aFilePath)
+-    {
+-        NS_ASSERTION(mLibrary, "need non-null lib");
+-        // addref here??
+-    }
+-
+-    virtual ~PluginPRLibrary()
+-    {
+-        // unref here??
+-    }
+-
+-    virtual void SetPlugin(nsNPAPIPlugin*) override { }
+-
+-    virtual bool HasRequiredFunctions() override {
+-        mNP_Initialize = (NP_InitializeFunc)
+-            PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
+-        if (!mNP_Initialize)
+-            return false;
+-
+-        mNP_Shutdown = (NP_ShutdownFunc)
+-            PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
+-        if (!mNP_Shutdown)
+-            return false;
+-
+-        mNP_GetMIMEDescription = (NP_GetMIMEDescriptionFunc)
+-            PR_FindFunctionSymbol(mLibrary, "NP_GetMIMEDescription");
+-#ifndef XP_MACOSX
+-        if (!mNP_GetMIMEDescription)
+-            return false;
+-#endif
+-
+-#if defined(XP_UNIX) && !defined(XP_MACOSX)
+-        mNP_GetValue = (NP_GetValueFunc)
+-            PR_FindFunctionSymbol(mLibrary, "NP_GetValue");
+-        if (!mNP_GetValue)
+-            return false;
+-#endif
+-
+-#if defined(XP_WIN) || defined(XP_MACOSX)
+-        mNP_GetEntryPoints = (NP_GetEntryPointsFunc)
+-            PR_FindFunctionSymbol(mLibrary, "NP_GetEntryPoints");
+-        if (!mNP_GetEntryPoints)
+-            return false;
+-#endif
+-        return true;
+-    }
+-
+-#if defined(XP_UNIX) && !defined(XP_MACOSX)
+-    virtual nsresult NP_Initialize(NPNetscapeFuncs* aNetscapeFuncs,
+-                                   NPPluginFuncs* aFuncs, NPError* aError) override;
+-#else
+-    virtual nsresult NP_Initialize(NPNetscapeFuncs* aNetscapeFuncs,
+-                                   NPError* aError) override;
+-#endif
+-
+-    virtual nsresult NP_Shutdown(NPError* aError) override;
+-    virtual nsresult NP_GetMIMEDescription(const char** aMimeDesc) override;
+-
+-    virtual nsresult NP_GetValue(void* aFuture, NPPVariable aVariable,
+-                                 void* aValue, NPError* aError) override;
+-
+-#if defined(XP_WIN) || defined(XP_MACOSX)
+-    virtual nsresult NP_GetEntryPoints(NPPluginFuncs* aFuncs, NPError* aError) override;
+-#endif
+-
+-    virtual nsresult NPP_New(NPMIMEType aPluginType, NPP aInstance,
+-                             int16_t aArgc, char* aArgn[],
+-                             char* aArgv[], NPSavedData* aSaved,
+-                             NPError* aError) override;
+-
+-    virtual nsresult NPP_ClearSiteData(const char* aSite, uint64_t aFlags,
+-                                       uint64_t aMaxAge, nsCOMPtr<nsIClearSiteDataCallback> callback) override;
+-    virtual nsresult NPP_GetSitesWithData(nsCOMPtr<nsIGetSitesWithDataCallback> callback) override;
+-
+-    virtual nsresult AsyncSetWindow(NPP aInstance, NPWindow* aWindow) override;
+-    virtual nsresult GetImageContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) override;
+-    virtual nsresult GetImageSize(NPP aInstance, nsIntSize* aSize) override;
+-    virtual bool IsOOP() override { return false; }
+-#if defined(XP_MACOSX)
+-    virtual nsresult IsRemoteDrawingCoreAnimation(NPP aInstance, bool* aDrawing) override;
+-#endif
+-#if defined(XP_MACOSX) || defined(XP_WIN)
+-    virtual nsresult ContentsScaleFactorChanged(NPP aInstance, double aContentsScaleFactor) override;
+-#endif
+-    virtual nsresult SetBackgroundUnknown(NPP instance) override;
+-    virtual nsresult BeginUpdateBackground(NPP instance, const nsIntRect&,
+-                                           DrawTarget** aDrawTarget) override;
+-    virtual nsresult EndUpdateBackground(NPP instance,
+-                                         const nsIntRect&) override;
+-    virtual void DidComposite(NPP aInstance) override { }
+-    virtual void GetLibraryPath(nsACString& aPath) { aPath.Assign(mFilePath); }
+-    virtual nsresult GetRunID(uint32_t* aRunID) override { return NS_ERROR_NOT_IMPLEMENTED; }
+-    virtual void SetHasLocalInstance() override { }
+-#if defined(XP_WIN)
+-    virtual nsresult GetScrollCaptureContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) override;
+-#endif
+-
+-private:
+-    NP_InitializeFunc mNP_Initialize;
+-    NP_ShutdownFunc mNP_Shutdown;
+-    NP_GetMIMEDescriptionFunc mNP_GetMIMEDescription;
+-#if defined(XP_UNIX) && !defined(XP_MACOSX)
+-    NP_GetValueFunc mNP_GetValue;
+-#endif
+-#if defined(XP_WIN) || defined(XP_MACOSX)
+-    NP_GetEntryPointsFunc mNP_GetEntryPoints;
+-#endif
+-    NPP_NewProcPtr mNPP_New;
+-    NPP_ClearSiteDataPtr mNPP_ClearSiteData;
+-    NPP_GetSitesWithDataPtr mNPP_GetSitesWithData;
+-    PRLibrary* mLibrary;
+-    nsCString mFilePath;
+-};
+-
+-
+-} // namespace mozilla
+-
+-#endif  // ifndef PluginPRLibrary_h
+diff --git a/dom/plugins/base/moz.build b/dom/plugins/base/moz.build
+--- a/dom/plugins/base/moz.build
++++ b/dom/plugins/base/moz.build
+@@ -28,29 +28,24 @@ EXPORTS += [
+     'nsPluginInstanceOwner.h',
+     'nsPluginLogging.h',
+     'nsPluginNativeWindow.h',
+     'nsPluginsCID.h',
+     'nsPluginsDir.h',
+     'nsPluginTags.h',
+ ]
+ 
+-EXPORTS.mozilla += [
+-    'PluginPRLibrary.h',
+-]
+-
+ UNIFIED_SOURCES += [
+     'nsJSNPRuntime.cpp',
+     'nsNPAPIPluginInstance.cpp',
+     'nsNPAPIPluginStreamListener.cpp',
+     'nsPluginInstanceOwner.cpp',
+     'nsPluginModule.cpp',
+     'nsPluginStreamListenerPeer.cpp',
+     'nsPluginTags.cpp',
+-    'PluginPRLibrary.cpp',
+ ]
+ 
+ SOURCES += [
+     'nsNPAPIPlugin.cpp', # Conflict with X11 headers
+     'nsPluginHost.cpp',  # Conflict with NS_NPAPIPLUGIN_CALLBACK
+ ]
+ 
+ if CONFIG['OS_ARCH'] == 'WINNT':
+diff --git a/dom/plugins/base/nsNPAPIPlugin.cpp b/dom/plugins/base/nsNPAPIPlugin.cpp
+--- a/dom/plugins/base/nsNPAPIPlugin.cpp
++++ b/dom/plugins/base/nsNPAPIPlugin.cpp
+@@ -69,19 +69,16 @@
+ 
+ #include "nsNetUtil.h"
+ #include "nsNetCID.h"
+ 
+ #include "mozilla/Mutex.h"
+ #include "mozilla/PluginLibrary.h"
+ using mozilla::PluginLibrary;
+ 
+-#include "mozilla/PluginPRLibrary.h"
+-using mozilla::PluginPRLibrary;
+-
+ #include "mozilla/plugins/PluginModuleParent.h"
+ using mozilla::plugins::PluginModuleChromeParent;
+ using mozilla::plugins::PluginModuleContentParent;
+ 
+ #ifdef MOZ_X11
+ #include "mozilla/X11Util.h"
+ #endif
+ 
+@@ -197,39 +194,30 @@ nsNPAPIPlugin::~nsNPAPIPlugin()
+ void
+ nsNPAPIPlugin::PluginCrashed(const nsAString& pluginDumpID,
+                              const nsAString& browserDumpID)
+ {
+   RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
+   host->PluginCrashed(this, pluginDumpID, browserDumpID);
+ }
+ 
+-bool
+-nsNPAPIPlugin::RunPluginOOP(const nsPluginTag *aPluginTag)
+-{
+-  return true;
+-}
+-
+ inline PluginLibrary*
+ GetNewPluginLibrary(nsPluginTag *aPluginTag)
+ {
+   AUTO_PROFILER_LABEL("GetNewPluginLibrary", OTHER);
+ 
+   if (!aPluginTag) {
+     return nullptr;
+   }
+ 
+   if (XRE_IsContentProcess()) {
+     return PluginModuleContentParent::LoadModule(aPluginTag->mId, aPluginTag);
+   }
+ 
+-  if (nsNPAPIPlugin::RunPluginOOP(aPluginTag)) {
+-    return PluginModuleChromeParent::LoadModule(aPluginTag->mFullPath.get(), aPluginTag->mId, aPluginTag);
+-  }
+-  return new PluginPRLibrary(aPluginTag->mFullPath.get(), aPluginTag->mLibrary);
++  return PluginModuleChromeParent::LoadModule(aPluginTag->mFullPath.get(), aPluginTag->mId, aPluginTag);
+ }
+ 
+ // Creates an nsNPAPIPlugin object. One nsNPAPIPlugin object exists per plugin (not instance).
+ nsresult
+ nsNPAPIPlugin::CreatePlugin(nsPluginTag *aPluginTag, nsNPAPIPlugin** aResult)
+ {
+   AUTO_PROFILER_LABEL("nsNPAPIPlugin::CreatePlugin", OTHER);
+   *aResult = nullptr;
+diff --git a/dom/plugins/base/nsNPAPIPlugin.h b/dom/plugins/base/nsNPAPIPlugin.h
+--- a/dom/plugins/base/nsNPAPIPlugin.h
++++ b/dom/plugins/base/nsNPAPIPlugin.h
+@@ -51,18 +51,16 @@ public:
+ 
+   // The IPC mechanism notifies the nsNPAPIPlugin if the plugin
+   // crashes and is no longer usable. pluginDumpID/browserDumpID are
+   // the IDs of respective minidumps that were written, or empty if no
+   // minidump was written.
+   void PluginCrashed(const nsAString& pluginDumpID,
+                      const nsAString& browserDumpID);
+ 
+-  static bool RunPluginOOP(const nsPluginTag *aPluginTag);
+-
+   nsresult Shutdown();
+ 
+   static nsresult RetainStream(NPStream *pstream, nsISupports **aRetainedPeer);
+ 
+ private:
+   ~nsNPAPIPlugin();
+ 
+   NPPluginFuncs mPluginFuncs;
+diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp
+--- a/dom/plugins/base/nsPluginHost.cpp
++++ b/dom/plugins/base/nsPluginHost.cpp
+@@ -1200,31 +1200,16 @@ nsPluginHost::FindNativePluginForExtensi
+   // Re-fetch the matching type because of how FindPreferredPlugin works...
+   preferredPlugin->HasExtension(aExtension, aMimeType);
+   return preferredPlugin;
+ }
+ 
+ static nsresult CreateNPAPIPlugin(nsPluginTag *aPluginTag,
+                                   nsNPAPIPlugin **aOutNPAPIPlugin)
+ {
+-  // If this is an in-process plugin we'll need to load it here if we haven't already.
+-  if (!nsNPAPIPlugin::RunPluginOOP(aPluginTag)) {
+-    if (aPluginTag->mFullPath.IsEmpty())
+-      return NS_ERROR_FAILURE;
+-    nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1");
+-    file->InitWithPath(NS_ConvertUTF8toUTF16(aPluginTag->mFullPath));
+-    nsPluginFile pluginFile(file);
+-    PRLibrary* pluginLibrary = nullptr;
+-
+-    if (NS_FAILED(pluginFile.LoadPlugin(&pluginLibrary)) || !pluginLibrary)
+-      return NS_ERROR_FAILURE;
+-
+-    aPluginTag->mLibrary = pluginLibrary;
+-  }
+-
+   nsresult rv;
+   rv = nsNPAPIPlugin::CreatePlugin(aPluginTag, aOutNPAPIPlugin);
+ 
+   return rv;
+ }
+ 
+ nsresult nsPluginHost::EnsurePluginLoaded(nsPluginTag* aPluginTag)
+ {
+@@ -2121,24 +2106,16 @@ nsresult nsPluginHost::ScanPluginsDirect
+     }
+ 
+     // do it if we still want it
+     if (!seenBefore) {
+       // We have a valid new plugin so report that plugins have changed.
+       *aPluginsChanged = true;
+     }
+ 
+-    // Avoid adding different versions of the same plugin if they are running
+-    // in-process, otherwise we risk undefined behaviour.
+-    if (!nsNPAPIPlugin::RunPluginOOP(pluginTag)) {
+-      if (HaveSamePlugin(pluginTag)) {
+-        continue;
+-      }
+-    }
+-
+     // Don't add the same plugin again if it hasn't changed
+     if (nsPluginTag* duplicate = FirstPluginWithPath(pluginTag->mFullPath)) {
+       if (pluginTag->mLastModifiedTime == duplicate->mLastModifiedTime) {
+         continue;
+       }
+     }
+ 
+     // If we're not creating a plugin list, simply looking for changes,
+diff --git a/dom/plugins/ipc/PluginModuleChild.cpp b/dom/plugins/ipc/PluginModuleChild.cpp
+--- a/dom/plugins/ipc/PluginModuleChild.cpp
++++ b/dom/plugins/ipc/PluginModuleChild.cpp
+@@ -294,18 +294,16 @@ PluginModuleChild::InitForChrome(const s
+     CommonInit();
+ 
+     if (!Open(aChannel, aParentPid, aIOLoop)) {
+         return false;
+     }
+ 
+     GetIPCChannel()->SetAbortOnError(true);
+ 
+-    // TODO: use PluginPRLibrary here
+-
+ #if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
+     mShutdownFunc =
+         (NP_PLUGINSHUTDOWN) PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
+ 
+     // create the new plugin handler
+ 
+     mInitializeFunc =
+         (NP_PLUGINUNIXINIT) PR_FindFunctionSymbol(mLibrary, "NP_Initialize");

+ 84 - 0
mozilla-release/patches/1528586-67a1.patch

@@ -0,0 +1,84 @@
+# HG changeset patch
+# User Masatoshi Kimura <VYV03354@nifty.ne.jp>
+# Date 1550374719 -32400
+# Node ID 211fcf7cb803afac968c00334fada58cb516bd2d
+# Parent  39a07a20d3a9801f2d33b3a35d91297a06587ba7
+Bug 1528586 - Remove PluginContextProxy. r=jimm
+
+diff --git a/dom/plugins/base/nsPluginStreamListenerPeer.cpp b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
++++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+@@ -298,73 +298,16 @@ nsPluginStreamListenerPeer::GetLastModif
+ 
+ nsresult
+ nsPluginStreamListenerPeer::GetURL(const char** result)
+ {
+   *result = mURLSpec.get();
+   return NS_OK;
+ }
+ 
+-// XXX: Converting the channel within nsPluginStreamListenerPeer
+-// to use asyncOpen2() and do not want to touch the fragile logic
+-// of byte range requests. Hence we just introduce this lightweight
+-// wrapper to proxy the context.
+-class PluginContextProxy final : public nsIStreamListener
+-{
+-public:
+-  NS_DECL_ISUPPORTS
+-
+-  PluginContextProxy(nsIStreamListener *aListener, nsISupports* aContext)
+-    : mListener(aListener)
+-    , mContext(aContext)
+-  {
+-    MOZ_ASSERT(aListener);
+-    MOZ_ASSERT(aContext);
+-  }
+-
+-  NS_IMETHOD
+-  OnDataAvailable(nsIRequest* aRequest,
+-                  nsISupports* aContext,
+-                  nsIInputStream *aIStream,
+-                  uint64_t aSourceOffset,
+-                  uint32_t aLength) override
+-  {
+-    // Proxy OnDataAvailable using the internal context
+-    return mListener->OnDataAvailable(aRequest,
+-                                      mContext,
+-                                      aIStream,
+-                                      aSourceOffset,
+-                                      aLength);
+-  }
+-
+-  NS_IMETHOD
+-  OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) override
+-  {
+-    // Proxy OnStartRequest using the internal context
+-    return mListener->OnStartRequest(aRequest, mContext);
+-  }
+-
+-  NS_IMETHOD
+-  OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
+-                nsresult aStatusCode) override
+-  {
+-    // Proxy OnStopRequest using the inernal context
+-    return mListener->OnStopRequest(aRequest,
+-                                    mContext,
+-                                    aStatusCode);
+-  }
+-
+-private:
+-  ~PluginContextProxy() {}
+-  nsCOMPtr<nsIStreamListener> mListener;
+-  nsCOMPtr<nsISupports> mContext;
+-};
+-
+-NS_IMPL_ISUPPORTS(PluginContextProxy, nsIStreamListener)
+-
+ nsresult
+ nsPluginStreamListenerPeer::GetStreamOffset(int32_t* result)
+ {
+   *result = mStreamOffset;
+   return NS_OK;
+ }
+ 
+ nsresult

+ 707 - 0
mozilla-release/patches/1545123-1-72a1.patch

@@ -0,0 +1,707 @@
+# HG changeset patch
+# User Gijs Kruitbosch <gijskruitbosch@gmail.com>
+# Date 1572734022 0
+#      Sat Nov 02 22:33:42 2019 +0000
+# Node ID 1facb4403c96f742879e63f418955a1ad93772b3
+# Parent  a07be193875d4fdb2ae5ba13ca9369ff4bfba2bb
+Bug 1545123 - simplify how we get directory information for plugins, r=handyman,mconley
+
+In this change we:
+- stop treating the nsPluginDirServiceProvider as a directory provider, as its
+  GetFile implementation was a no-op anyway - registering it didn't make any
+  difference.
+- stop treating it as a class entirely, because the PLID getters were already
+  static, so instantiating it also didn't do anything.
+- move IO from the plugin directory list provider and the Windows-only PLID
+  getters into nsPluginHost. This enables us to move it off of the main thread
+  later - the directory getting has to happen on the main thread, but we can
+  postpone further checks on the nsIFile instances.
+- in the process, stop doing exists() calls on files because we can fail more
+  lazily. This allows us to remove more allowlist entries from
+  browser_startup_mainthreadio, though the `isDirectory` calls will actually
+  still cause IO - they don't seem to create IO markers in the profiler.
+  We will move this IO away from the main thread in subsequent commits.
+
+Depends on D48328
+
+Differential Revision: https://phabricator.services.mozilla.com/D48329
+
+diff --git a/dom/plugins/base/nsPluginDirServiceProvider.cpp b/dom/plugins/base/nsPluginDirServiceProvider.cpp
+--- a/dom/plugins/base/nsPluginDirServiceProvider.cpp
++++ b/dom/plugins/base/nsPluginDirServiceProvider.cpp
+@@ -2,77 +2,31 @@
+ /* This Source Code Form is subject to the terms of the Mozilla Public
+  * License, v. 2.0. If a copy of the MPL was not distributed with this
+  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+ 
+ #include "nsPluginDirServiceProvider.h"
+ 
+ #include "nsCRT.h"
+ #include "nsIFile.h"
+-#include "nsDependentString.h"
+-#include "nsArrayEnumerator.h"
+-#include "mozilla/Preferences.h"
+ 
+ #include <windows.h>
+ #include "nsIWindowsRegKey.h"
+ 
+ using namespace mozilla;
+ 
+-//*****************************************************************************
+-// nsPluginDirServiceProvider::Constructor/Destructor
+-//*****************************************************************************
+-
+-nsPluginDirServiceProvider::nsPluginDirServiceProvider()
+-{
+-}
+-
+-nsPluginDirServiceProvider::~nsPluginDirServiceProvider()
+-{
++ nsresult GetPLIDDirectories(nsTArray<nsCOMPtr<nsIFile>>& aDirs) {
++  GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, aDirs);
++  GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
++                                aDirs);
++  return NS_OK;
+ }
+ 
+-//*****************************************************************************
+-// nsPluginDirServiceProvider::nsISupports
+-//*****************************************************************************
+-
+-NS_IMPL_ISUPPORTS(nsPluginDirServiceProvider,
+-                  nsIDirectoryServiceProvider)
+-
+-//*****************************************************************************
+-// nsPluginDirServiceProvider::nsIDirectoryServiceProvider
+-//*****************************************************************************
+-
+-NS_IMETHODIMP
+-nsPluginDirServiceProvider::GetFile(const char *charProp, bool *persistant,
+-                                    nsIFile **_retval)
+-{
+-  NS_ENSURE_ARG(charProp);
+-
+-  *_retval = nullptr;
+-  *persistant = false;
+-
+-  return NS_ERROR_FAILURE;
+-}
+-
+-nsresult
+-nsPluginDirServiceProvider::GetPLIDDirectories(nsISimpleEnumerator **aEnumerator)
+-{
+-  NS_ENSURE_ARG_POINTER(aEnumerator);
+-  *aEnumerator = nullptr;
+-
+-  nsCOMArray<nsIFile> dirs;
+-
+-  GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, dirs);
+-  GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, dirs);
+-
+-  return NS_NewArrayEnumerator(aEnumerator, dirs);
+-}
+-
+-nsresult
+-nsPluginDirServiceProvider::GetPLIDDirectoriesWithRootKey(uint32_t aKey, nsCOMArray<nsIFile> &aDirs)
+-{
++/* static */ nsresult GetPLIDDirectoriesWithRootKey(
++    uint32_t aKey, nsTArray<nsCOMPtr<nsIFile>>& aDirs) {
+   nsCOMPtr<nsIWindowsRegKey> regKey =
+     do_CreateInstance("@mozilla.org/windows-registry-key;1");
+   NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE);
+ 
+   nsresult rv = regKey->Open(aKey,
+                              NS_LITERAL_STRING("Software\\MozillaPlugins"),
+                              nsIWindowsRegKey::ACCESS_READ);
+   if (NS_FAILED(rv)) {
+@@ -88,48 +42,23 @@ nsPluginDirServiceProvider::GetPLIDDirec
+     if (NS_SUCCEEDED(rv)) {
+       nsCOMPtr<nsIWindowsRegKey> childKey;
+       rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE,
+                              getter_AddRefs(childKey));
+       if (NS_SUCCEEDED(rv) && childKey) {
+         nsAutoString path;
+         rv = childKey->ReadStringValue(NS_LITERAL_STRING("Path"), path);
+         if (NS_SUCCEEDED(rv)) {
++          // We deliberately do not do any further checks here on whether
++          // these are actually directories, whether they even exist, or
++          // whether they are duplicates. The pluginhost code will do them.
++          // This allows the whole process to avoid mainthread IO.
+           nsCOMPtr<nsIFile> localFile;
+-          if (NS_SUCCEEDED(NS_NewLocalFile(path, true,
+-                                           getter_AddRefs(localFile))) &&
+-              localFile) {
+-            // Some vendors use a path directly to the DLL so chop off
+-            // the filename
+-            bool isDir = false;
+-            if (NS_SUCCEEDED(localFile->IsDirectory(&isDir)) && !isDir) {
+-              nsCOMPtr<nsIFile> temp;
+-              localFile->GetParent(getter_AddRefs(temp));
+-              if (temp)
+-                localFile = temp;
+-            }
+-
+-            // Now we check to make sure it's actually on disk and
+-            // To see if we already have this directory in the array
+-            bool isFileThere = false;
+-            bool isDupEntry = false;
+-            if (NS_SUCCEEDED(localFile->Exists(&isFileThere)) && isFileThere) {
+-              int32_t c = aDirs.Count();
+-              for (int32_t i = 0; i < c; i++) {
+-                nsIFile *dup = static_cast<nsIFile*>(aDirs[i]);
+-                if (dup &&
+-                    NS_SUCCEEDED(dup->Equals(localFile, &isDupEntry)) &&
+-                    isDupEntry) {
+-                  break;
+-                }
+-              }
+-
+-              if (!isDupEntry) {
+-                aDirs.AppendObject(localFile);
+-              }
+-            }
++          rv = NS_NewLocalFile(path, true, getter_AddRefs(localFile));
++          if (NS_SUCCEEDED(rv) && localFile) {
++            aDirs.AppendElement(localFile);
+           }
+         }
+       }
+     }
+   }
+   return NS_OK;
+ }
+diff --git a/dom/plugins/base/nsPluginDirServiceProvider.h b/dom/plugins/base/nsPluginDirServiceProvider.h
+--- a/dom/plugins/base/nsPluginDirServiceProvider.h
++++ b/dom/plugins/base/nsPluginDirServiceProvider.h
+@@ -1,40 +1,19 @@
+ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+ /* This Source Code Form is subject to the terms of the Mozilla Public
+  * License, v. 2.0. If a copy of the MPL was not distributed with this
+  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+ 
+ #ifndef nsPluginDirServiceProvider_h_
+ #define nsPluginDirServiceProvider_h_
+ 
+-#include "nsIDirectoryService.h"
+-
+-#if defined (XP_WIN)
+-#include "nsCOMArray.h"
+-#endif
++#ifdef XP_WIN
++#  include "nsCOMPtr.h"
++#  include "nsTArray.h"
+ 
+-class nsISimpleEnumerator;
+-
+-//*****************************************************************************
+-// class nsPluginDirServiceProvider
+-//*****************************************************************************
++nsresult GetPLIDDirectories(nsTArray<nsCOMPtr<nsIFile>>& aDirs);
+ 
+-class nsPluginDirServiceProvider : public nsIDirectoryServiceProvider
+-{
+-public:
+-   nsPluginDirServiceProvider();
+-
+-   NS_DECL_THREADSAFE_ISUPPORTS
+-   NS_DECL_NSIDIRECTORYSERVICEPROVIDER
++static nsresult GetPLIDDirectoriesWithRootKey(
++    uint32_t aKey, nsTArray<nsCOMPtr<nsIFile>>& aDirs);
+ 
+-#ifdef XP_WIN
+-   static nsresult GetPLIDDirectories(nsISimpleEnumerator **aEnumerator);
+-private:
+-   static nsresult GetPLIDDirectoriesWithRootKey(uint32_t aKey,
+-     nsCOMArray<nsIFile> &aDirs);
+-#endif
+-
+-protected:
+-   virtual ~nsPluginDirServiceProvider();
+-};
+-
++#endif  // XP_WIN
+ #endif // nsPluginDirServiceProvider_h_
+diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp
+--- a/dom/plugins/base/nsPluginHost.cpp
++++ b/dom/plugins/base/nsPluginHost.cpp
+@@ -92,16 +92,18 @@
+ #include "nsContentPolicyUtils.h"
+ #include "mozilla/TimeStamp.h"
+ #include "mozilla/Telemetry.h"
+ #include "nsIImageLoadingContent.h"
+ #include "mozilla/Preferences.h"
+ #include "nsVersionComparator.h"
+ #include "NullPrincipal.h"
+ 
++#include "mozilla/ResultExtensions.h"
++
+ #if defined(XP_WIN)
+ #include "nsIWindowMediator.h"
+ #include "nsIBaseWindow.h"
+ #include "windows.h"
+ #include "winbase.h"
+ #endif
+ 
+ #include "npapi.h"
+@@ -130,18 +132,16 @@ static const char *kPrefDisableFullPage 
+ 
+ // How long we wait before unloading an idle plugin process.
+ // Defaults to 30 seconds.
+ static const char *kPrefUnloadPluginTimeoutSecs = "dom.ipc.plugins.unloadTimeoutSecs";
+ static const uint32_t kDefaultPluginUnloadingTimeout = 30;
+ 
+ static const char *kPluginRegistryVersion = "0.19";
+ 
+-static const char kDirectoryServiceContractID[] = "@mozilla.org/file/directory_service;1";
+-
+ #define kPluginRegistryFilename NS_LITERAL_CSTRING("pluginreg.dat")
+ 
+ LazyLogModule nsPluginLogging::gNPNLog(NPN_LOG_NAME);
+ LazyLogModule nsPluginLogging::gNPPLog(NPP_LOG_NAME);
+ LazyLogModule nsPluginLogging::gPluginLog(PLUGIN_LOG_NAME);
+ 
+ // #defines for plugin cache and prefs
+ #define NS_PREF_MAX_NUM_CACHED_INSTANCES "browser.plugins.max_num_cached_plugins"
+@@ -601,26 +601,16 @@ nsresult nsPluginHost::UnloadPlugins()
+   NS_ITERATIVE_UNREF_LIST(RefPtr<nsInvalidPluginTag>, mInvalidPlugins, mNext);
+ 
+   // Lets remove any of the temporary files that we created.
+   if (sPluginTempDir) {
+     sPluginTempDir->Remove(true);
+     NS_RELEASE(sPluginTempDir);
+   }
+ 
+-#ifdef XP_WIN
+-  if (mPrivateDirServiceProvider) {
+-    nsCOMPtr<nsIDirectoryService> dirService =
+-      do_GetService(kDirectoryServiceContractID);
+-    if (dirService)
+-      dirService->UnregisterProvider(mPrivateDirServiceProvider);
+-    mPrivateDirServiceProvider = nullptr;
+-  }
+-#endif /* XP_WIN */
+-
+   mPluginsLoaded = false;
+ 
+   return NS_OK;
+ }
+ 
+ void nsPluginHost::OnPluginInstanceDestroyed(nsPluginTag* aPluginTag)
+ {
+   bool hasInstance = false;
+@@ -2025,46 +2015,16 @@ nsresult nsPluginHost::ScanPluginsDirect
+     }
+ 
+     AddPluginTag(pluginTag);
+   }
+ 
+   return NS_OK;
+ }
+ 
+-nsresult nsPluginHost::ScanPluginsDirectoryList(nsISimpleEnumerator *dirEnum,
+-                                                bool aCreatePluginList,
+-                                                bool *aPluginsChanged)
+-{
+-  MOZ_ASSERT(XRE_IsParentProcess());
+-
+-    bool hasMore;
+-    while (NS_SUCCEEDED(dirEnum->HasMoreElements(&hasMore)) && hasMore) {
+-      nsCOMPtr<nsISupports> supports;
+-      nsresult rv = dirEnum->GetNext(getter_AddRefs(supports));
+-      if (NS_FAILED(rv))
+-        continue;
+-      nsCOMPtr<nsIFile> nextDir(do_QueryInterface(supports, &rv));
+-      if (NS_FAILED(rv))
+-        continue;
+-
+-      // don't pass aPluginsChanged directly to prevent it from been reset
+-      bool pluginschanged = false;
+-      ScanPluginsDirectory(nextDir, aCreatePluginList, &pluginschanged);
+-
+-      if (pluginschanged)
+-        *aPluginsChanged = true;
+-
+-      // if changes are detected and we are not creating the list, do not proceed
+-      if (!aCreatePluginList && *aPluginsChanged)
+-        break;
+-    }
+-    return NS_OK;
+-}
+-
+ void
+ nsPluginHost::IncrementChromeEpoch()
+ {
+   MOZ_ASSERT(XRE_IsParentProcess());
+   mPluginEpoch++;
+ }
+ 
+ uint32_t
+@@ -2241,97 +2201,74 @@ nsresult nsPluginHost::FindPlugins(bool 
+ {
+   Telemetry::AutoTimer<Telemetry::FIND_PLUGINS> telemetry;
+ 
+   NS_ENSURE_ARG_POINTER(aPluginsChanged);
+   MOZ_ASSERT(XRE_IsParentProcess());
+ 
+   *aPluginsChanged = false;
+ 
+-  nsresult rv;
+-
+-  // Read cached plugins info. If the profile isn't yet available then don't
+-  // scan for plugins
+-  if (ReadPluginInfo() == NS_ERROR_NOT_AVAILABLE)
+-    return NS_OK;
+-
+-#ifdef XP_WIN
+-  // Failure here is not a show-stopper so just warn.
+-  rv = EnsurePrivateDirServiceProvider();
+-  NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to register dir service provider.");
+-#endif /* XP_WIN */
+-
+-  nsCOMPtr<nsIProperties> dirService(do_GetService(kDirectoryServiceContractID, &rv));
+-  if (NS_FAILED(rv))
+-    return rv;
+-
+-  nsCOMPtr<nsISimpleEnumerator> dirList;
+-
+-  // Scan plugins directories;
+-  // don't pass aPluginsChanged directly, to prevent its
+-  // possible reset in subsequent ScanPluginsDirectory calls
+-  bool pluginschanged = false;
+-
+-  // Scan the app-defined list of plugin dirs.
+-  rv = dirService->Get(NS_APP_PLUGINS_DIR_LIST, NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(dirList));
+-  if (NS_SUCCEEDED(rv)) {
+-    ScanPluginsDirectoryList(dirList, aCreatePluginList, &pluginschanged);
+-
+-    if (pluginschanged)
+-      *aPluginsChanged = true;
+-
+-    // In tests, load plugins from the profile.
+-    if (xpc::IsInAutomation()) {
+-      nsCOMPtr<nsIFile> profDir;
+-      rv = dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
+-                           getter_AddRefs(profDir));
+-      if (NS_SUCCEEDED(rv)) {
+-        profDir->Append(NS_LITERAL_STRING("plugins"));
+-        ScanPluginsDirectory(profDir, aCreatePluginList, &pluginschanged);
+-        if (pluginschanged) {
+-          *aPluginsChanged = true;
+-        }
++  nsresult rv = EnsurePluginReg();
++  if (NS_FAILED(rv)) {
++    // If the profile isn't yet available then don't scan for plugins
++    return rv == NS_ERROR_NOT_AVAILABLE ? NS_OK : rv;
++  }
++
++  // Read cached plugins info.
++  ReadPluginInfo();
++
++  // Scan plugin directories:
++  nsTArray<nsCOMPtr<nsIFile>> pluginDirs;
++  MOZ_TRY(DeterminePluginDirs(pluginDirs));
++
++  for (nsIFile* pluginDir : pluginDirs) {
++    if (!pluginDir) {
++      continue;
++    }
++    // Ensure we have a directory; if this isn't a directory, try the parent.
++    // We do this because in some cases items in this list of supposed plugin
++    // directories can be individual plugin files instead of directories.
++    bool isDir = false;
++    nsCOMPtr<nsIFile> parent;
++    if (NS_FAILED(pluginDir->IsDirectory(&isDir)) || !isDir) {
++      pluginDir->GetParent(getter_AddRefs(parent));
++      pluginDir = parent;
++      if (!pluginDir) {
++        continue;
+       }
+     }
+ 
+-    // if we are just looking for possible changes,
+-    // no need to proceed if changes are detected
+-    if (!aCreatePluginList && *aPluginsChanged) {
+-      NS_ITERATIVE_UNREF_LIST(RefPtr<nsPluginTag>, mCachedPlugins, mNext);
+-      NS_ITERATIVE_UNREF_LIST(RefPtr<nsInvalidPluginTag>, mInvalidPlugins, mNext);
+-      return NS_OK;
++    // pluginDir not existing will be handled transparently in
++    // ScanPluginsDirectory
++
++    // don't pass aPluginsChanged directly, to prevent its
++    // possible reset in subsequent ScanPluginsDirectory calls
++    bool pluginschanged = false;
++    ScanPluginsDirectory(pluginDir, aCreatePluginList, &pluginschanged);
++
++    if (pluginschanged) {
++      *aPluginsChanged = true;
++      if (!aCreatePluginList) {
++        // We're just looking for changes, so we can stop looking.
++        break;
++      }
+     }
+   }
+ 
++  // if we are just looking for possible changes,
++  // no need to proceed if changes are detected
++  if (!aCreatePluginList && *aPluginsChanged) {
++    NS_ITERATIVE_UNREF_LIST(RefPtr<nsPluginTag>, mCachedPlugins, mNext);
++    NS_ITERATIVE_UNREF_LIST(RefPtr<nsInvalidPluginTag>, mInvalidPlugins, mNext);
++    return NS_OK;
++  }
++
+   mPluginsLoaded = true; // at this point 'some' plugins have been loaded,
+                             // the rest is optional
+ 
+-#ifdef XP_WIN
+-  bool bScanPLIDs = Preferences::GetBool("plugin.scan.plid.all", false);
+-
+-    // Now lets scan any PLID directories
+-  if (bScanPLIDs && mPrivateDirServiceProvider) {
+-    rv = mPrivateDirServiceProvider->GetPLIDDirectories(getter_AddRefs(dirList));
+-    if (NS_SUCCEEDED(rv)) {
+-      ScanPluginsDirectoryList(dirList, aCreatePluginList, &pluginschanged);
+-
+-      if (pluginschanged)
+-        *aPluginsChanged = true;
+-
+-      // if we are just looking for possible changes,
+-      // no need to proceed if changes are detected
+-      if (!aCreatePluginList && *aPluginsChanged) {
+-        NS_ITERATIVE_UNREF_LIST(RefPtr<nsPluginTag>, mCachedPlugins, mNext);
+-        NS_ITERATIVE_UNREF_LIST(RefPtr<nsInvalidPluginTag>, mInvalidPlugins, mNext);
+-        return NS_OK;
+-      }
+-    }
+-  }
+-#endif
+-
+   // We should also consider plugins to have changed if any plugins have been removed.
+   // We'll know if any were removed if they weren't taken out of the cached plugins list
+   // during our scan, thus we can assume something was removed if the cached plugins list
+   // contains anything.
+   if (!*aPluginsChanged && mCachedPlugins) {
+     *aPluginsChanged = true;
+   }
+ 
+@@ -2655,17 +2592,16 @@ nsPluginHost::WritePluginInfo()
+ }
+ 
+ nsresult nsPluginHost::EnsurePluginReg() {
+   if (mPluginRegFile) {
+     return NS_OK;
+   }
+ 
+   nsresult rv;
+-
+   nsCOMPtr<nsIProperties> directoryService(
+       do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
+   if (NS_FAILED(rv)) return rv;
+ 
+   directoryService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
+                         getter_AddRefs(mPluginRegFile));
+ 
+   if (!mPluginRegFile) {
+@@ -2678,16 +2614,65 @@ nsresult nsPluginHost::EnsurePluginReg()
+       return NS_ERROR_FAILURE;
+     }
+ 
+     return NS_ERROR_NOT_AVAILABLE;
+   }
+   return mPluginRegFile->AppendNative(kPluginRegistryFilename);
+ }
+ 
++nsresult nsPluginHost::DeterminePluginDirs(
++    nsTArray<nsCOMPtr<nsIFile>>& pluginDirs) {
++  nsresult rv;
++  nsCOMPtr<nsIProperties> dirService(
++      do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
++  if (NS_FAILED(rv)) {
++    return rv;
++  }
++
++  // Get the app-defined list of plugin dirs.
++  nsCOMPtr<nsISimpleEnumerator> dirEnum;
++  MOZ_TRY(dirService->Get(NS_APP_PLUGINS_DIR_LIST,
++                          NS_GET_IID(nsISimpleEnumerator),
++                          getter_AddRefs(dirEnum)));
++
++  bool hasMore = false;
++  while (NS_SUCCEEDED(dirEnum->HasMoreElements(&hasMore)) && hasMore) {
++    nsCOMPtr<nsISupports> supports;
++    nsresult rv = dirEnum->GetNext(getter_AddRefs(supports));
++    if (NS_SUCCEEDED(rv)) {
++      nsCOMPtr<nsIFile> nextDir(do_QueryInterface(supports, &rv));
++      if (NS_SUCCEEDED(rv)) {
++        pluginDirs.AppendElement(nextDir);
++      }
++    }
++  }
++
++  // In tests, load plugins from the profile.
++  if (xpc::IsInAutomation()) {
++    nsCOMPtr<nsIFile> profDir;
++    rv = dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
++                         getter_AddRefs(profDir));
++    if (NS_SUCCEEDED(rv)) {
++      profDir->Append(NS_LITERAL_STRING("plugins"));
++      pluginDirs.AppendElement(profDir);
++    }
++  }
++
++  // Get the directories from the windows registry. Note: these can
++  // be files instead of directories. We'll have to filter them later.
++#ifdef XP_WIN
++  bool bScanPLIDs = Preferences::GetBool("plugin.scan.plid.all", false);
++  if (bScanPLIDs) {
++    GetPLIDDirectories(pluginDirs);
++  }
++#endif /* XP_WIN */
++  return NS_OK;
++}
++
+ nsresult nsPluginHost::ReadPluginInfo() {
+   MOZ_ASSERT(XRE_IsParentProcess());
+ 
+   return ReadPluginInfoFromDisk();
+ }
+ 
+ nsresult nsPluginHost::ReadPluginInfoFromDisk() {
+   nsresult rv = EnsurePluginReg();
+@@ -2859,34 +2844,16 @@ nsPluginHost::RemoveCachedPluginsInfo(co
+       NS_ADDREF(*result);
+       break;
+     }
+     prev = tag;
+     tag = tag->mNext;
+   }
+ }
+ 
+-#ifdef XP_WIN
+-nsresult
+-nsPluginHost::EnsurePrivateDirServiceProvider()
+-{
+-  if (!mPrivateDirServiceProvider) {
+-    nsresult rv;
+-    mPrivateDirServiceProvider = new nsPluginDirServiceProvider();
+-    nsCOMPtr<nsIDirectoryService> dirService(do_GetService(kDirectoryServiceContractID, &rv));
+-    if (NS_FAILED(rv))
+-      return rv;
+-    rv = dirService->RegisterProvider(mPrivateDirServiceProvider);
+-    if (NS_FAILED(rv))
+-      return rv;
+-  }
+-  return NS_OK;
+-}
+-#endif /* XP_WIN */
+-
+ nsresult nsPluginHost::NewPluginURLStream(const nsString& aURL,
+                                           nsNPAPIPluginInstance *aInstance,
+                                           nsNPAPIPluginStreamListener* aListener,
+                                           nsIInputStream *aPostStream,
+                                           const char *aHeadersData,
+                                           uint32_t aHeadersDataLen)
+ {
+   nsCOMPtr<nsIURI> url;
+diff --git a/dom/plugins/base/nsPluginHost.h b/dom/plugins/base/nsPluginHost.h
+--- a/dom/plugins/base/nsPluginHost.h
++++ b/dom/plugins/base/nsPluginHost.h
+@@ -312,27 +312,24 @@ private:
+ 
+   void AddPluginTag(nsPluginTag* aPluginTag);
+ 
+   nsresult
+   ScanPluginsDirectory(nsIFile *pluginsDir,
+                        bool aCreatePluginList,
+                        bool *aPluginsChanged);
+ 
+-  nsresult
+-  ScanPluginsDirectoryList(nsISimpleEnumerator *dirEnum,
+-                           bool aCreatePluginList,
+-                           bool *aPluginsChanged);
+-
+   nsresult EnsurePluginLoaded(nsPluginTag* aPluginTag);
+ 
+   bool IsRunningPlugin(nsPluginTag * aPluginTag);
+ 
+   nsresult EnsurePluginReg();
+ 
++  nsresult DeterminePluginDirs(nsTArray<nsCOMPtr<nsIFile>>& pluginDirs);
++
+   // Read plugin info (either from prefs or disk)
+   nsresult ReadPluginInfo();
+ 
+   // Stores all plugins info into the plugin registry
+   nsresult WritePluginInfo();
+ 
+   // Loads all plugins info from the plugin registry
+   nsresult ReadPluginInfoFromDisk();
+@@ -346,18 +343,16 @@ private:
+   bool IsLiveTag(nsIPluginTag* tag);
+ 
+   // Checks our list of live tags for an equivalent tag.
+   nsPluginTag* HaveSamePlugin(const nsPluginTag * aPluginTag);
+ 
+   // Returns the first plugin at |path|
+   nsPluginTag* FirstPluginWithPath(const nsCString& path);
+ 
+-  nsresult EnsurePrivateDirServiceProvider();
+-
+   void OnPluginInstanceDestroyed(nsPluginTag* aPluginTag);
+ 
+   // To be used by the chrome process whenever the set of plugins changes.
+   void IncrementChromeEpoch();
+ 
+   // To be used by the chrome process; returns the current epoch.
+   uint32_t ChromeEpoch();
+ 
+@@ -386,18 +381,16 @@ private:
+ 
+   // Any instances in this array will have valid plugin objects via GetPlugin().
+   // When removing an instance it might not die - be sure to null out it's plugin.
+   nsTArray< RefPtr<nsNPAPIPluginInstance> > mInstances;
+ 
+   // An nsIFile for the pluginreg.dat file in the profile.
+   nsCOMPtr<nsIFile> mPluginRegFile;
+ #ifdef XP_WIN
+-  RefPtr<nsPluginDirServiceProvider> mPrivateDirServiceProvider;
+-
+   // In order to reload plugins when they change, we watch the registry via
+   // this object.
+   nsCOMPtr<nsIWindowsRegKey> mRegKeyHKLM;
+   nsCOMPtr<nsIWindowsRegKey> mRegKeyHKCU;
+ #endif
+ 
+   nsCOMPtr<nsIEffectiveTLDService> mTLDService;
+   nsCOMPtr<nsIIDNService> mIDNService;
+diff --git a/xpcom/io/nsAppFileLocationProvider.cpp.1545123.later b/xpcom/io/nsAppFileLocationProvider.cpp.1545123.later
+new file mode 100644
+--- /dev/null
++++ b/xpcom/io/nsAppFileLocationProvider.cpp.1545123.later
+@@ -0,0 +1,27 @@
++Don't think we want to put this in yet.
++
++--- nsAppFileLocationProvider.cpp
+++++ nsAppFileLocationProvider.cpp
++@@ -365,21 +365,17 @@ class nsAppDirectoryEnumerator : public 
++   const nsID& DefaultInterface() override { return NS_GET_IID(nsIFile); }
++ 
++   NS_IMETHOD HasMoreElements(bool* aResult) override {
++     while (!mNext && *mCurrentKey) {
++       bool dontCare;
++       nsCOMPtr<nsIFile> testFile;
++       (void)mProvider->GetFile(*mCurrentKey++, &dontCare,
++                                getter_AddRefs(testFile));
++-      // Don't return a file which does not exist.
++-      bool exists;
++-      if (testFile && NS_SUCCEEDED(testFile->Exists(&exists)) && exists) {
++-        mNext = testFile;
++-      }
+++      mNext = testFile;
++     }
++     *aResult = mNext != nullptr;
++     return NS_OK;
++   }
++ 
++   NS_IMETHOD GetNext(nsISupports** aResult) override {
++     if (NS_WARN_IF(!aResult)) {
++       return NS_ERROR_INVALID_ARG;

+ 744 - 0
mozilla-release/patches/1545123-1-SIMPLIFIED-72a1.patch

@@ -0,0 +1,744 @@
+# HG changeset patch
+# User Gijs Kruitbosch <gijskruitbosch@gmail.com>
+# Date 1572734008 0
+#      Sat Nov 02 22:33:28 2019 +0000
+# Node ID dc85aaeb9ee91f2df0a5c03106538138a9adbadb
+# Parent  866e74e7e3a4943f067fbe0dc6c81e4e44ad6181
+Bug 1545123 - store flash information in prefs instead of pluginreg, r=handyman
+
+Porting notes: Rip out flashOnly code and just assume it is true.
+               Remove dead code for now no longer valid code branches.
+
+By storing the plugin information in prefs when only flash is allowed, we can
+avoid reading pluginreg and doing a plugin scan on the mainthread on startup.
+
+As part of this, we're now keeping track of the 'is flash allowed' pref on the
+plugin host, and no longer write 'valid' plugin info into pluginreg if so.
+
+Also note that in this commit, we're changing `mPluginRegFile` to actually
+refer to the file, rather than the containing directory.
+
+Differential Revision: https://phabricator.services.mozilla.com/D48328
+
+diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp
+--- a/dom/plugins/base/nsPluginHost.cpp
++++ b/dom/plugins/base/nsPluginHost.cpp
+@@ -1847,37 +1847,17 @@ struct CompareFilesByTime
+   Equals(const nsCOMPtr<nsIFile>& a, const nsCOMPtr<nsIFile>& b) const
+   {
+     return GetPluginLastModifiedTime(a) == GetPluginLastModifiedTime(b);
+   }
+ };
+ 
+ } // namespace
+ 
+-static
+-bool
+-ShouldAddPlugin(const nsPluginInfo& info, bool flashOnly)
+-{
+-  if (!info.fName || flashOnly) {
+-    return false;
+-  }
+-  for (uint32_t i = 0; i < info.fVariantCount; ++i) {
+-    if (flashOnly) {
+-      continue;
+-    }
+-    if (info.fMimeTypeArray[i] &&
+-        (!strcmp(info.fMimeTypeArray[i], "application/x-test") ||
+-         !strcmp(info.fMimeTypeArray[i], "application/x-Second-Test"))) {
+-      return true;
+-    }
+-  }
+-#ifdef PLUGIN_LOGGING
+-  PLUGIN_LOG(PLUGIN_LOG_NORMAL,
+-             ("ShouldAddPlugin : Ignoring plugin library %s\n", aPluginTag->FileName().get()));
+-#endif // PLUGIN_LOGGING
++bool nsPluginHost::ShouldAddPlugin(const nsPluginInfo& info) {
+   return false;
+ }
+ 
+ void
+ nsPluginHost::AddPluginTag(nsPluginTag* aPluginTag)
+ {
+   aPluginTag->mNext = mPlugins;
+   mPlugins = aPluginTag;
+@@ -1909,18 +1889,16 @@ nsresult nsPluginHost::ScanPluginsDirect
+ 
+ #ifdef PLUGIN_LOGGING
+   nsAutoCString dirPath;
+   pluginsDir->GetNativePath(dirPath);
+   PLUGIN_LOG(PLUGIN_LOG_BASIC,
+   ("nsPluginHost::ScanPluginsDirectory dir=%s\n", dirPath.get()));
+ #endif
+ 
+-  bool flashOnly = Preferences::GetBool("plugin.load_flash_only", true);
+-
+   nsCOMPtr<nsISimpleEnumerator> iter;
+   rv = pluginsDir->GetDirectoryEntries(getter_AddRefs(iter));
+   if (NS_FAILED(rv))
+     return rv;
+ 
+   AutoTArray<nsCOMPtr<nsIFile>, 6> pluginFiles;
+ 
+   bool hasMore;
+@@ -2002,62 +1980,34 @@ nsresult nsPluginHost::ScanPluginsDirect
+     // if it is not found in cache info list or has been changed, create a new one
+     if (!pluginTag) {
+       nsPluginFile pluginFile(localfile);
+ 
+       // create a tag describing this plugin.
+       PRLibrary *library = nullptr;
+       nsPluginInfo info;
+       memset(&info, 0, sizeof(info));
+-      nsresult res;
+-      // Opening a block for the telemetry AutoTimer
+-      {
+-        Telemetry::AutoTimer<Telemetry::PLUGIN_LOAD_METADATA> telemetry;
+-        res = pluginFile.GetPluginInfo(info, &library);
+-      }
++
+       // if we don't have mime type don't proceed, this is not a plugin
+-      if (NS_FAILED(res) || !info.fMimeTypeArray ||
+-          (!ShouldAddPlugin(info, flashOnly))) {
+-        RefPtr<nsInvalidPluginTag> invalidTag = new nsInvalidPluginTag(filePath.get(),
+-                                                                         fileModTime);
+-        pluginFile.FreePluginInfo(info);
+-
+-        if (aCreatePluginList) {
+-          invalidTag->mSeen = true;
+-        }
+-        invalidTag->mNext = mInvalidPlugins;
+-        if (mInvalidPlugins) {
+-          mInvalidPlugins->mPrev = invalidTag;
+-        }
+-        mInvalidPlugins = invalidTag;
+-
+-        // Mark aPluginsChanged so pluginreg is rewritten
+-        *aPluginsChanged = true;
+-        continue;
++      RefPtr<nsInvalidPluginTag> invalidTag = new nsInvalidPluginTag(filePath.get(),
++                                                                       fileModTime);
++      pluginFile.FreePluginInfo(info);
++
++      if (aCreatePluginList) {
++        invalidTag->mSeen = true;
+       }
+-
+-      pluginTag = new nsPluginTag(&info, fileModTime);
+-      pluginFile.FreePluginInfo(info);
+-      pluginTag->mLibrary = library;
+-      uint32_t state;
+-      rv = pluginTag->GetBlocklistState(&state);
+-      NS_ENSURE_SUCCESS(rv, rv);
+-
+-      // If the blocklist says it is risky and we have never seen this
+-      // plugin before, then disable it.
+-      if (state == nsIBlocklistService::STATE_SOFTBLOCKED && !seenBefore) {
+-        pluginTag->SetEnabledState(nsIPluginTag::STATE_DISABLED);
++      invalidTag->mNext = mInvalidPlugins;
++      if (mInvalidPlugins) {
++        mInvalidPlugins->mPrev = invalidTag;
+       }
+-
+-      // Plugin unloading is tag-based. If we created a new tag and loaded
+-      // the library in the process then we want to attempt to unload it here.
+-      // Only do this if the pref is set for aggressive unloading.
+-      if (UnloadPluginsASAP()) {
+-        pluginTag->TryUnloadPlugin(false);
+-      }
++      mInvalidPlugins = invalidTag;
++
++      // Mark aPluginsChanged so pluginreg is rewritten
++      *aPluginsChanged = true;
++      continue;
+     }
+ 
+     // do it if we still want it
+     if (!seenBefore) {
+       // We have a valid new plugin so report that plugins have changed.
+       *aPluginsChanged = true;
+     }
+ 
+@@ -2287,25 +2237,20 @@ nsPluginHost::SetPluginsInContent(uint32
+ // if aCreatePluginList is false we will just scan for plugins
+ // and see if any changes have been made to the plugins.
+ // This is needed in ReloadPlugins to prevent possible recursive reloads
+ nsresult nsPluginHost::FindPlugins(bool aCreatePluginList, bool * aPluginsChanged)
+ {
+   Telemetry::AutoTimer<Telemetry::FIND_PLUGINS> telemetry;
+ 
+   NS_ENSURE_ARG_POINTER(aPluginsChanged);
++  MOZ_ASSERT(XRE_IsParentProcess());
+ 
+   *aPluginsChanged = false;
+ 
+-  // If plugins are found or change, the content process will be notified by the
+-  // parent process. Bail out early if this is called from the content process.
+-  if (XRE_IsContentProcess()) {
+-    return NS_OK;
+-  }
+-
+   nsresult rv;
+ 
+   // Read cached plugins info. If the profile isn't yet available then don't
+   // scan for plugins
+   if (ReadPluginInfo() == NS_ERROR_NOT_AVAILABLE)
+     return NS_OK;
+ 
+ #ifdef XP_WIN
+@@ -2622,125 +2567,67 @@ nsPluginHost::RegisterWithCategoryManage
+   }
+ }
+ 
+ nsresult
+ nsPluginHost::WritePluginInfo()
+ {
+   MOZ_ASSERT(XRE_IsParentProcess());
+ 
+-  nsresult rv = NS_OK;
+-  nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID,&rv));
++  nsresult rv = EnsurePluginReg();
+   if (NS_FAILED(rv))
+     return rv;
+ 
+-  directoryService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
+-                        getter_AddRefs(mPluginRegFile));
+-
+-  if (!mPluginRegFile)
+-    return NS_ERROR_FAILURE;
+-
+-  PRFileDesc* fd = nullptr;
+-
++  // Get the tmp file by getting the parent and then re-appending
++  // kPluginRegistryFilename followed by `.tmp`.
+   nsCOMPtr<nsIFile> pluginReg;
+ 
+-  rv = mPluginRegFile->Clone(getter_AddRefs(pluginReg));
++  rv = mPluginRegFile->GetParent(getter_AddRefs(pluginReg));
+   if (NS_FAILED(rv))
+     return rv;
+ 
+   nsAutoCString filename(kPluginRegistryFilename);
+   filename.AppendLiteral(".tmp");
+   rv = pluginReg->AppendNative(filename);
+   if (NS_FAILED(rv))
+     return rv;
+ 
++  PRFileDesc* fd = nullptr;
+   rv = pluginReg->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0600, &fd);
+   if (NS_FAILED(rv))
+     return rv;
+ 
+   nsCOMPtr<nsIXULRuntime> runtime = do_GetService("@mozilla.org/xre/runtime;1");
+   if (!runtime) {
+     return NS_ERROR_FAILURE;
+   }
+ 
+   nsAutoCString arch;
+   rv = runtime->GetXPCOMABI(arch);
+   if (NS_FAILED(rv)) {
+     return rv;
+   }
+ 
+-  bool flashOnly = Preferences::GetBool("plugin.load_flash_only", true);
+-
+   PR_fprintf(fd, "Generated File. Do not edit.\n");
+ 
+   PR_fprintf(fd, "\n[HEADER]\nVersion%c%s%c%c%c\nArch%c%s%c%c\n",
+              PLUGIN_REGISTRY_FIELD_DELIMITER,
+              kPluginRegistryVersion,
+-             flashOnly ? 't' : 'f',
++             't',
+              PLUGIN_REGISTRY_FIELD_DELIMITER,
+              PLUGIN_REGISTRY_END_OF_LINE_MARKER,
+              PLUGIN_REGISTRY_FIELD_DELIMITER,
+              arch.get(),
+              PLUGIN_REGISTRY_FIELD_DELIMITER,
+              PLUGIN_REGISTRY_END_OF_LINE_MARKER);
+ 
+   // Store all plugins in the mPlugins list - all plugins currently in use.
+   PR_fprintf(fd, "\n[PLUGINS]\n");
+ 
+-  for (nsPluginTag *tag = mPlugins; tag; tag = tag->mNext) {
+-    // store each plugin info into the registry
+-    // filename & fullpath are on separate line
+-    // because they can contain field delimiter char
+-    PR_fprintf(fd, "%s%c%c\n%s%c%c\n%s%c%c\n",
+-      (tag->FileName().get()),
+-      PLUGIN_REGISTRY_FIELD_DELIMITER,
+-      PLUGIN_REGISTRY_END_OF_LINE_MARKER,
+-      (tag->mFullPath.get()),
+-      PLUGIN_REGISTRY_FIELD_DELIMITER,
+-      PLUGIN_REGISTRY_END_OF_LINE_MARKER,
+-      (tag->Version().get()),
+-      PLUGIN_REGISTRY_FIELD_DELIMITER,
+-      PLUGIN_REGISTRY_END_OF_LINE_MARKER);
+-
+-    // lastModifiedTimeStamp|canUnload|tag->mFlags|fromExtension
+-    PR_fprintf(fd, "%lld%c%d%c%lu%c%d%c%c\n",
+-      tag->mLastModifiedTime,
+-      PLUGIN_REGISTRY_FIELD_DELIMITER,
+-      false, // did store whether or not to unload in-process plugins
+-      PLUGIN_REGISTRY_FIELD_DELIMITER,
+-      0, // legacy field for flags
+-      PLUGIN_REGISTRY_FIELD_DELIMITER,
+-      false,
+-      PLUGIN_REGISTRY_FIELD_DELIMITER,
+-      PLUGIN_REGISTRY_END_OF_LINE_MARKER);
+-
+-    //description, name & mtypecount are on separate line
+-    PR_fprintf(fd, "%s%c%c\n%s%c%c\n%d\n",
+-      (tag->Description().get()),
+-      PLUGIN_REGISTRY_FIELD_DELIMITER,
+-      PLUGIN_REGISTRY_END_OF_LINE_MARKER,
+-      (tag->Name().get()),
+-      PLUGIN_REGISTRY_FIELD_DELIMITER,
+-      PLUGIN_REGISTRY_END_OF_LINE_MARKER,
+-      tag->MimeTypes().Length());
+-
+-    // Add in each mimetype this plugin supports
+-    for (uint32_t i = 0; i < tag->MimeTypes().Length(); i++) {
+-      PR_fprintf(fd, "%d%c%s%c%s%c%s%c%c\n",
+-        i,PLUGIN_REGISTRY_FIELD_DELIMITER,
+-        (tag->MimeTypes()[i].get()),
+-        PLUGIN_REGISTRY_FIELD_DELIMITER,
+-        (tag->MimeDescriptions()[i].get()),
+-        PLUGIN_REGISTRY_FIELD_DELIMITER,
+-        (tag->Extensions()[i].get()),
+-        PLUGIN_REGISTRY_FIELD_DELIMITER,
+-        PLUGIN_REGISTRY_END_OF_LINE_MARKER);
+-    }
+-  }
+-
++  // Do not write plugin info.
+   PR_fprintf(fd, "\n[INVALID]\n");
+ 
+   RefPtr<nsInvalidPluginTag> invalidPlugins = mInvalidPlugins;
+   while (invalidPlugins) {
+     // fullPath
+     PR_fprintf(fd, "%s%c%c\n",
+       (!invalidPlugins->mFullPath.IsEmpty() ? invalidPlugins->mFullPath.get() : ""),
+       PLUGIN_REGISTRY_FIELD_DELIMITER,
+@@ -2758,63 +2645,69 @@ nsPluginHost::WritePluginInfo()
+   PRStatus prrc;
+   prrc = PR_Close(fd);
+   if (prrc != PR_SUCCESS) {
+     // we should obtain a refined value based on prrc;
+     rv = NS_ERROR_FAILURE;
+     MOZ_ASSERT(false, "PR_Close() failed.");
+     return rv;
+   }
+-  nsCOMPtr<nsIFile> parent;
+-  rv = pluginReg->GetParent(getter_AddRefs(parent));
+-  NS_ENSURE_SUCCESS(rv, rv);
+-  rv = pluginReg->MoveToNative(parent, kPluginRegistryFilename);
++  rv = pluginReg->MoveToNative(nullptr, kPluginRegistryFilename);
+   return rv;
+ }
+ 
+-nsresult
+-nsPluginHost::ReadPluginInfo()
+-{
+-  MOZ_ASSERT(XRE_IsParentProcess());
+-
+-  const long PLUGIN_REG_MIMETYPES_ARRAY_SIZE = 12;
+-  const long PLUGIN_REG_MAX_MIMETYPES = 1000;
++nsresult nsPluginHost::EnsurePluginReg() {
++  if (mPluginRegFile) {
++    return NS_OK;
++  }
+ 
+   nsresult rv;
+ 
+-  nsCOMPtr<nsIProperties> directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID,&rv));
+-  if (NS_FAILED(rv))
+-    return rv;
++  nsCOMPtr<nsIProperties> directoryService(
++      do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
++  if (NS_FAILED(rv)) return rv;
+ 
+   directoryService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
+                         getter_AddRefs(mPluginRegFile));
+ 
+   if (!mPluginRegFile) {
+     // There is no profile yet, this will tell us if there is going to be one
+     // in the future.
++    nsCOMPtr<nsIFile> tmp;
+     directoryService->Get(NS_APP_PROFILE_DIR_STARTUP, NS_GET_IID(nsIFile),
+-                          getter_AddRefs(mPluginRegFile));
+-    if (!mPluginRegFile)
++                          getter_AddRefs(tmp));
++    if (!tmp) {
+       return NS_ERROR_FAILURE;
++    }
+ 
+     return NS_ERROR_NOT_AVAILABLE;
+   }
+-
+-  PRFileDesc* fd = nullptr;
+-
++  return mPluginRegFile->AppendNative(kPluginRegistryFilename);
++}
++
++nsresult nsPluginHost::ReadPluginInfo() {
++  MOZ_ASSERT(XRE_IsParentProcess());
++
++  return ReadPluginInfoFromDisk();
++}
++
++nsresult nsPluginHost::ReadPluginInfoFromDisk() {
++  nsresult rv = EnsurePluginReg();
++  if (NS_FAILED(rv)) {
++    return rv;
++  }
++
++  // Cloning ensures we don't have a stat cache and get an
++  // accurate filesize.
+   nsCOMPtr<nsIFile> pluginReg;
+ 
+   rv = mPluginRegFile->Clone(getter_AddRefs(pluginReg));
+   if (NS_FAILED(rv))
+     return rv;
+ 
+-  rv = pluginReg->AppendNative(kPluginRegistryFilename);
+-  if (NS_FAILED(rv))
+-    return rv;
+-
+   int64_t fileSize;
+   rv = pluginReg->GetFileSize(&fileSize);
+   if (NS_FAILED(rv))
+     return rv;
+ 
+   if (fileSize > INT32_MAX) {
+     return NS_ERROR_FAILURE;
+   }
+@@ -2824,16 +2717,17 @@ nsPluginHost::ReadPluginInfo()
+     return NS_OK; // ERROR CONDITION
+   }
+ 
+   nsPluginManifestLineReader reader;
+   char* registry = reader.Init(flen);
+   if (!registry)
+     return NS_ERROR_OUT_OF_MEMORY;
+ 
++  PRFileDesc* fd = nullptr;
+   rv = pluginReg->OpenNSPRFileDesc(PR_RDONLY, 0444, &fd);
+   if (NS_FAILED(rv))
+     return rv;
+ 
+   // set rv to return an error on goto out
+   rv = NS_ERROR_FAILURE;
+ 
+   // We know how many octes we are supposed to read.
+@@ -2849,36 +2743,35 @@ nsPluginHost::ReadPluginInfo()
+     return rv;
+   }
+ 
+   // short read error, so to speak.
+   if (flen > bread)
+     return rv;
+ 
+   if (!ReadSectionHeader(reader, "HEADER"))
+-    return rv;;
++    return rv;
+ 
+   if (!reader.NextLine())
+     return rv;
+ 
+   char* values[6];
+ 
+   // VersionLiteral, kPluginRegistryVersion
+   if (2 != reader.ParseLine(values, 2))
+     return rv;
+ 
+   // VersionLiteral
+   if (PL_strcmp(values[0], "Version"))
+     return rv;
+ 
+   // If we're reading an old registry, ignore it
+   // If we flipped the flash-only pref, ignore it
+-  bool flashOnly = Preferences::GetBool("plugin.load_flash_only", true);
+   nsAutoCString expectedVersion(kPluginRegistryVersion);
+-  expectedVersion.Append(flashOnly ? 't' : 'f');
++  expectedVersion.Append('t');
+ 
+   if (!expectedVersion.Equals(values[1])) {
+     return rv;
+   }
+ 
+   char* archValues[6];
+   if (!reader.NextLine()) {
+     return rv;
+@@ -2912,104 +2805,20 @@ nsPluginHost::ReadPluginInfo()
+   if (!ReadSectionHeader(reader, "PLUGINS"))
+     return rv;
+ 
+   while (reader.NextLine()) {
+     if (*reader.LinePtr() == '[') {
+       break;
+     }
+ 
+-    const char* filename = reader.LinePtr();
+-    if (!reader.NextLine())
+-      return rv;
+-
+-    const char* fullpath = reader.LinePtr();
+-    if (!reader.NextLine())
+-      return rv;
+-
+-    const char *version;
+-    version = reader.LinePtr();
+-    if (!reader.NextLine())
+-      return rv;
+-
+-    // lastModifiedTimeStamp|canUnload|tag.mFlag|fromExtension
+-    if (4 != reader.ParseLine(values, 4))
+-      return rv;
+-
+-    int64_t lastmod = nsCRT::atoll(values[0]);
+-    if (!reader.NextLine())
+-      return rv;
+-
+-    char *description = reader.LinePtr();
+-    if (!reader.NextLine())
+-      return rv;
+-
+-    const char *name = reader.LinePtr();
+-    if (!reader.NextLine())
+-      return rv;
+-
+-    long mimetypecount = std::strtol(reader.LinePtr(), nullptr, 10);
+-    if (mimetypecount == LONG_MAX || mimetypecount == LONG_MIN ||
+-        mimetypecount >= PLUGIN_REG_MAX_MIMETYPES || mimetypecount < 0) {
+-      return NS_ERROR_FAILURE;
+-    }
+-
+-    char *stackalloced[PLUGIN_REG_MIMETYPES_ARRAY_SIZE * 3];
+-    char **mimetypes;
+-    char **mimedescriptions;
+-    char **extensions;
+-    char **heapalloced = 0;
+-    if (mimetypecount > PLUGIN_REG_MIMETYPES_ARRAY_SIZE - 1) {
+-      heapalloced = new char *[mimetypecount * 3];
+-      mimetypes = heapalloced;
+-    } else {
+-      mimetypes = stackalloced;
+-    }
+-    mimedescriptions = mimetypes + mimetypecount;
+-    extensions = mimedescriptions + mimetypecount;
+-
+-    int mtr = 0; //mimetype read
+-    for (; mtr < mimetypecount; mtr++) {
+-      if (!reader.NextLine())
+-        break;
+-
+-      //line number|mimetype|description|extension
+-      if (4 != reader.ParseLine(values, 4))
+-        break;
+-      int line = atoi(values[0]);
+-      if (line != mtr)
+-        break;
+-      mimetypes[mtr] = values[1];
+-      mimedescriptions[mtr] = values[2];
+-      extensions[mtr] = values[3];
+-    }
+-
+-    if (mtr != mimetypecount) {
+-      delete [] heapalloced;
+-      return rv;
+-    }
+-
+-    RefPtr<nsPluginTag> tag = new nsPluginTag(name,
+-      description,
+-      filename,
+-      fullpath,
+-      version,
+-      (const char* const*)mimetypes,
+-      (const char* const*)mimedescriptions,
+-      (const char* const*)extensions,
+-      mimetypecount, lastmod, true);
+-
+-    delete [] heapalloced;
+-
+-    // Import flags from registry into prefs for old registry versions
+-    MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_BASIC,
+-      ("LoadCachedPluginsInfo : Loading Cached plugininfo for %s\n", tag->FileName().get()));
+-
+-    tag->mNext = mCachedPlugins;
+-    mCachedPlugins = tag;
++    // Ignore all listed plugins if we're in flash-only mode.
++    // In that case, we're only reading this file to find invalid plugin info
++    // so we can avoid reading/loading those.
++    continue;
+   }
+ 
+   if (!ReadSectionHeader(reader, "INVALID")) {
+     return rv;
+   }
+ 
+   while (reader.NextLine()) {
+     const char *fullpath = reader.LinePtr();
+diff --git a/dom/plugins/base/nsPluginHost.h b/dom/plugins/base/nsPluginHost.h
+--- a/dom/plugins/base/nsPluginHost.h
++++ b/dom/plugins/base/nsPluginHost.h
+@@ -89,23 +89,16 @@ public:
+   static already_AddRefed<nsPluginHost> GetInst();
+ 
+   NS_DECL_ISUPPORTS
+   NS_DECL_NSIPLUGINHOST
+   NS_DECL_NSIOBSERVER
+   NS_DECL_NSITIMERCALLBACK
+   NS_DECL_NSINAMED
+ 
+-  nsresult LoadPlugins();
+-  nsresult UnloadPlugins();
+-
+-  nsresult SetUpPluginInstance(const nsACString &aMimeType,
+-                               nsIURI *aURL,
+-                               nsPluginInstanceOwner *aOwner);
+-
+   // Acts like a bitfield
+   enum PluginFilter {
+     eExcludeNone     = nsIPluginHost::EXCLUDE_NONE,
+     eExcludeDisabled = nsIPluginHost::EXCLUDE_DISABLED,
+     eExcludeFake     = nsIPluginHost::EXCLUDE_FAKE
+   };
+   // FIXME-jsplugins comment about fake
+   bool HavePluginForType(const nsACString & aMimeType,
+@@ -114,21 +107,16 @@ public:
+   // FIXME-jsplugins what if fake has different extensions
+   bool HavePluginForExtension(const nsACString & aExtension,
+                               /* out */ nsACString & aMimeType,
+                               PluginFilter aFilter = eExcludeDisabled);
+ 
+   void GetPlugins(nsTArray<nsCOMPtr<nsIInternalPluginTag>>& aPluginArray,
+                   bool aIncludeDisabled = false);
+ 
+-  nsresult FindPluginsForContent(uint32_t aPluginEpoch,
+-                                 nsTArray<mozilla::plugins::PluginTag>* aPlugins,
+-                                 nsTArray<mozilla::plugins::FakePluginTag>* aFakePlugins,
+-                                 uint32_t* aNewPluginEpoch);
+-
+   nsresult GetURL(nsISupports* pluginInst,
+                   const char* url,
+                   const char* target,
+                   nsNPAPIPluginStreamListener* streamListener,
+                   const char* altHost,
+                   const char* referrer,
+                   bool forceJSEnabled);
+   nsresult PostURL(nsISupports* pluginInst,
+@@ -249,16 +237,22 @@ public:
+                              InfallibleTArray<nsCString>& result,
+                              bool firstMatchOnly);
+ 
+   nsresult SendPluginsToContent();
+   nsresult SetPluginsInContent(uint32_t aPluginEpoch,
+                                nsTArray<mozilla::plugins::PluginTag>& aPlugins,
+                                nsTArray<mozilla::plugins::FakePluginTag>& aFakePlugins);
+ private:
++  nsresult LoadPlugins();
++  nsresult UnloadPlugins();
++
++  nsresult SetUpPluginInstance(const nsACString& aMimeType, nsIURI* aURL,
++                               nsPluginInstanceOwner* aOwner);
++
+   friend class nsPluginUnloadRunnable;
+ 
+   void DestroyRunningInstances(nsPluginTag* aPluginTag);
+ 
+   // Writes updated plugins settings to disk and unloads the plugin
+   // if it is now disabled. Should only be called by the plugin tag in question
+   void UpdatePluginInfo(nsPluginTag* aPluginTag);
+ 
+@@ -309,37 +303,44 @@ private:
+   // Registers or unregisters the given mime type with the category manager
+   enum nsRegisterType { ePluginRegister,
+                         ePluginUnregister,
+                         // Checks if this type should still be registered first
+                         ePluginMaybeUnregister };
+   void RegisterWithCategoryManager(const nsCString& aMimeType,
+                                    nsRegisterType aType);
+ 
++  bool ShouldAddPlugin(const nsPluginInfo& aInfo);
++
+   void AddPluginTag(nsPluginTag* aPluginTag);
+ 
+   nsresult
+   ScanPluginsDirectory(nsIFile *pluginsDir,
+                        bool aCreatePluginList,
+                        bool *aPluginsChanged);
+ 
+   nsresult
+   ScanPluginsDirectoryList(nsISimpleEnumerator *dirEnum,
+                            bool aCreatePluginList,
+                            bool *aPluginsChanged);
+ 
+   nsresult EnsurePluginLoaded(nsPluginTag* aPluginTag);
+ 
+   bool IsRunningPlugin(nsPluginTag * aPluginTag);
+ 
+-  // Stores all plugins info into the registry
++  nsresult EnsurePluginReg();
++
++  // Read plugin info (either from prefs or disk)
++  nsresult ReadPluginInfo();
++
++  // Stores all plugins info into the plugin registry
+   nsresult WritePluginInfo();
+ 
+-  // Loads all cached plugins info into mCachedPlugins
+-  nsresult ReadPluginInfo();
++  // Loads all plugins info from the plugin registry
++  nsresult ReadPluginInfoFromDisk();
+ 
+   // Given a file path, returns the plugins info from our cache
+   // and removes it from the cache.
+   void RemoveCachedPluginsInfo(const char *filePath,
+                                nsPluginTag **result);
+ 
+   // Checks to see if a tag object is in our list of live tags.
+   bool IsLiveTag(nsIPluginTag* tag);
+@@ -382,16 +383,17 @@ private:
+ 
+   // set by pref plugin.disable
+   bool mPluginsDisabled;
+ 
+   // Any instances in this array will have valid plugin objects via GetPlugin().
+   // When removing an instance it might not die - be sure to null out it's plugin.
+   nsTArray< RefPtr<nsNPAPIPluginInstance> > mInstances;
+ 
++  // An nsIFile for the pluginreg.dat file in the profile.
+   nsCOMPtr<nsIFile> mPluginRegFile;
+ #ifdef XP_WIN
+   RefPtr<nsPluginDirServiceProvider> mPrivateDirServiceProvider;
+ 
+   // In order to reload plugins when they change, we watch the registry via
+   // this object.
+   nsCOMPtr<nsIWindowsRegKey> mRegKeyHKLM;
+   nsCOMPtr<nsIWindowsRegKey> mRegKeyHKCU;
+diff --git a/dom/plugins/ipc/PluginBridge.h b/dom/plugins/ipc/PluginBridge.h
+--- a/dom/plugins/ipc/PluginBridge.h
++++ b/dom/plugins/ipc/PluginBridge.h
+@@ -26,22 +26,16 @@ namespace plugins {
+ 
+ class PPluginModuleParent;
+ 
+ bool
+ SetupBridge(uint32_t aPluginId, dom::ContentParent* aContentParent,
+             nsresult* aResult, uint32_t* aRunID,
+             ipc::Endpoint<PPluginModuleParent>* aEndpoint);
+ 
+-nsresult
+-FindPluginsForContent(uint32_t aPluginEpoch,
+-                      nsTArray<PluginTag>* aPlugins,
+-                      nsTArray<FakePluginTag>* aFakePlugins,
+-                      uint32_t* aNewPluginEpoch);
+-
+ void
+ TakeFullMinidump(uint32_t aPluginId,
+                  base::ProcessId aContentProcessId,
+                  const nsAString& aBrowserDumpId,
+                  std::function<void(nsString)>&& aCallback,
+                  bool aAsync);
+ 
+ void

+ 170 - 0
mozilla-release/patches/1545123-2-72a1.patch

@@ -0,0 +1,170 @@
+# HG changeset patch
+# User Gijs Kruitbosch <gijskruitbosch@gmail.com>
+# Date 1572734053 0
+#      Sat Nov 02 22:34:13 2019 +0000
+# Node ID ccb230067cd9942b379dcf909fd1b7d222905cec
+# Parent  d59147ca8c30e6251d1dc7900a5a39be1256c86a
+Bug 1545123 - remove obsolete things from nsPluginHost, r=handyman
+
+Remove:
+- a list of allowed mimetypes; we only support flash anyway.
+- writing to disk when a plugin's enabled state changes; the plugin's enabled
+  state is not kept on disk so there's no point.
+- tracking which plugins should load in the parent as no plugins should do so
+  if e10s is on.
+
+Depends on D48329
+
+Differential Revision: https://phabricator.services.mozilla.com/D48330
+
+diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp
+--- a/dom/base/nsObjectLoadingContent.cpp
++++ b/dom/base/nsObjectLoadingContent.cpp
+@@ -3239,27 +3239,20 @@ bool
+ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason)
+ {
+   nsresult rv;
+ 
+   if (!sPrefsInitialized) {
+     initializeObjectLoadingContentPrefs();
+   }
+ 
+-  if (BrowserTabsRemoteAutostart()) {
+-    bool shouldLoadInParent = nsPluginHost::ShouldLoadTypeInParent(mContentType);
+-    bool inParent = XRE_IsParentProcess();
+-
+-    if (shouldLoadInParent != inParent) {
+-      // Plugins need to be locked to either the parent process or the content
+-      // process. If a plugin is locked to one process type, it can't be used in
+-      // the other. Otherwise we'll get hangs.
+-      aReason = eFallbackDisabled;
+-      return false;
+-    }
++  if (BrowserTabsRemoteAutostart() && XRE_IsParentProcess()) {
++    // We no longer support loading plugins in the parent process.
++    aReason = eFallbackDisabled;
++    return false;
+   }
+ 
+   RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
+ 
+   // Order of checks:
+   // * Assume a default of click-to-play
+   // * If globally disabled, per-site permissions cannot override.
+   // * If blocklisted, override the reason with the blocklist reason
+diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp
+--- a/dom/plugins/base/nsPluginHost.cpp
++++ b/dom/plugins/base/nsPluginHost.cpp
+@@ -121,18 +121,16 @@ using mozilla::dom::FakePluginMimeEntry;
+   {                                                                  \
+     while (list_) {                                                  \
+       type_ temp = list_->mNext_;                                    \
+       list_->mNext_ = nullptr;                                       \
+       list_ = temp;                                                  \
+     }                                                                \
+   }
+ 
+-static const char *kPrefWhitelist = "plugin.allowed_types";
+-static const char *kPrefLoadInParentPrefix = "plugin.load_in_parent_process.";
+ static const char *kPrefDisableFullPage = "plugin.disable_full_page_plugin_for_types";
+ 
+ // How long we wait before unloading an idle plugin process.
+ // Defaults to 30 seconds.
+ static const char *kPrefUnloadPluginTimeoutSecs = "dom.ipc.plugins.unloadTimeoutSecs";
+ static const uint32_t kDefaultPluginUnloadingTimeout = 30;
+ 
+ static const char *kPluginRegistryVersion = "0.19";
+@@ -2424,44 +2422,21 @@ nsPluginHost::UpdateInMemoryPluginInfo(n
+ }
+ 
+ // This function is not relevant for fake plugins.
+ void
+ nsPluginHost::UpdatePluginInfo(nsPluginTag* aPluginTag)
+ {
+   MOZ_ASSERT(XRE_IsParentProcess());
+ 
+-  ReadPluginInfo();
+-  WritePluginInfo();
+-
+   IncrementChromeEpoch();
+ 
+   UpdateInMemoryPluginInfo(aPluginTag);
+ }
+ 
+-/* static */ bool
+-nsPluginHost::IsTypeWhitelisted(const char *aMimeType)
+-{
+-  nsAutoCString whitelist;
+-  Preferences::GetCString(kPrefWhitelist, whitelist);
+-  if (whitelist.IsEmpty()) {
+-    return true;
+-  }
+-  nsDependentCString wrap(aMimeType);
+-  return IsTypeInList(wrap, whitelist);
+-}
+-
+-/* static */ bool
+-nsPluginHost::ShouldLoadTypeInParent(const nsACString& aMimeType)
+-{
+-  nsCString prefName(kPrefLoadInParentPrefix);
+-  prefName += aMimeType;
+-  return Preferences::GetBool(prefName.get(), false);
+-}
+-
+ void
+ nsPluginHost::RegisterWithCategoryManager(const nsCString& aMimeType,
+                                           nsRegisterType aType)
+ {
+   PLUGIN_LOG(PLUGIN_LOG_NORMAL,
+              ("nsPluginTag::RegisterWithCategoryManager type = %s, removing = %s\n",
+               aMimeType.get(), aType == ePluginUnregister ? "yes" : "no"));
+ 
+diff --git a/dom/plugins/base/nsPluginHost.h b/dom/plugins/base/nsPluginHost.h
+--- a/dom/plugins/base/nsPluginHost.h
++++ b/dom/plugins/base/nsPluginHost.h
+@@ -169,21 +169,16 @@ public:
+   nsresult
+   AddHeadersToChannel(const char *aHeadersData, uint32_t aHeadersDataLen,
+                       nsIChannel *aGenericChannel);
+ 
+   // Helper that checks if a type is whitelisted in plugin.allowed_types.
+   // Always returns true if plugin.allowed_types is not set
+   static bool IsTypeWhitelisted(const char *aType);
+ 
+-  // Helper that checks if a plugin of a given MIME type can be loaded by the
+-  // parent process. It checks the plugin.load_in_parent_process.<mime> pref.
+-  // Always returns false if plugin.load_in_parent_process.<mime> is not set.
+-  static bool ShouldLoadTypeInParent(const nsACString& aMimeType);
+-
+   /**
+    * Returns true if a plugin can be used to load the requested MIME type. Used
+    * for short circuiting before sending things to plugin code.
+    */
+   static bool
+   CanUsePluginForMIMEType(const nsACString& aMIMEType);
+ 
+   // checks whether aType is a type we recognize for potential special handling
+diff --git a/dom/plugins/base/nsPluginTags.cpp b/dom/plugins/base/nsPluginTags.cpp
+--- a/dom/plugins/base/nsPluginTags.cpp
++++ b/dom/plugins/base/nsPluginTags.cpp
+@@ -329,20 +329,16 @@ void nsPluginTag::InitMime(const char* c
+     }
+ 
+     nsAutoCString mimeType(aMimeTypes[i]);
+ 
+     // Convert the MIME type, which is case insensitive, to lowercase in order
+     // to properly handle a mixed-case type.
+     ToLowerCase(mimeType);
+ 
+-    if (!nsPluginHost::IsTypeWhitelisted(mimeType.get())) {
+-      continue;
+-    }
+-
+     // Look for certain special plugins.
+     switch (nsPluginHost::GetSpecialType(mimeType)) {
+       case nsPluginHost::eSpecialType_Flash:
+         // VLC sometimes claims to implement the Flash MIME type, and we want
+         // to allow users to control that separately from Adobe Flash.
+         if (Name().EqualsLiteral("Shockwave Flash")) {
+           mIsFlashPlugin = true;
+         }

+ 769 - 0
mozilla-release/patches/1580282-PARTIAL-71a1.patch

@@ -0,0 +1,769 @@
+# HG changeset patch
+# User Gijs Kruitbosch <gijskruitbosch@gmail.com>
+# Date 1568330149 0
+# Node ID 9b4e603eb86ad6b4804a0b40a16f7fd5a7ee826f
+# Parent  eb7529d43c5403426310b91df963303cb2b08203
+Bug 1580282 - Remove checks for plugins that are part of extensions and support for loading plugins from the app and profile dir, r=mconley,mixedpuppy
+
+Differential Revision: https://phabricator.services.mozilla.com/D45450
+
+diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp
+--- a/dom/plugins/base/nsPluginHost.cpp
++++ b/dom/plugins/base/nsPluginHost.cpp
+@@ -1830,62 +1830,16 @@ int64_t GetPluginLastModifiedTime(const 
+   }
+ #else
+   localfile->GetLastModifiedTime(&fileModTime);
+ #endif
+ 
+   return fileModTime;
+ }
+ 
+-bool
+-GetPluginIsFromExtension(const nsCOMPtr<nsIFile>& pluginFile,
+-                         const nsCOMArray<nsIFile>& extensionDirs)
+-{
+-  for (uint32_t i = 0; i < extensionDirs.Length(); ++i) {
+-    bool contains;
+-    if (NS_FAILED(extensionDirs[i]->Contains(pluginFile, &contains)) || !contains) {
+-      continue;
+-    }
+-
+-    return true;
+-  }
+-
+-  return false;
+-}
+-
+-void
+-GetExtensionDirectories(nsCOMArray<nsIFile>& dirs)
+-{
+-  nsCOMPtr<nsIProperties> dirService = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
+-  if (!dirService) {
+-    return;
+-  }
+-
+-  nsCOMPtr<nsISimpleEnumerator> list;
+-  nsresult rv = dirService->Get(XRE_EXTENSIONS_DIR_LIST,
+-                                NS_GET_IID(nsISimpleEnumerator),
+-                                getter_AddRefs(list));
+-  if (NS_FAILED(rv)) {
+-    return;
+-  }
+-
+-  bool more;
+-  while (NS_SUCCEEDED(list->HasMoreElements(&more)) && more) {
+-    nsCOMPtr<nsISupports> next;
+-    if (NS_FAILED(list->GetNext(getter_AddRefs(next)))) {
+-      break;
+-    }
+-    nsCOMPtr<nsIFile> file = do_QueryInterface(next);
+-    if (file) {
+-      file->Normalize();
+-      dirs.AppendElement(file.forget());
+-    }
+-  }
+-}
+-
+ struct CompareFilesByTime
+ {
+   bool
+   LessThan(const nsCOMPtr<nsIFile>& a, const nsCOMPtr<nsIFile>& b) const
+   {
+     return GetPluginLastModifiedTime(a) < GetPluginLastModifiedTime(b);
+   }
+ 
+@@ -1985,29 +1939,25 @@ nsresult nsPluginHost::ScanPluginsDirect
+ 
+     if (nsPluginsDir::IsPluginFile(dirEntry)) {
+       pluginFiles.AppendElement(dirEntry);
+     }
+   }
+ 
+   pluginFiles.Sort(CompareFilesByTime());
+ 
+-  nsCOMArray<nsIFile> extensionDirs;
+-  GetExtensionDirectories(extensionDirs);
+-
+   for (int32_t i = (pluginFiles.Length() - 1); i >= 0; i--) {
+     nsCOMPtr<nsIFile>& localfile = pluginFiles[i];
+ 
+     nsString utf16FilePath;
+     rv = localfile->GetPath(utf16FilePath);
+     if (NS_FAILED(rv))
+       continue;
+ 
+     const int64_t fileModTime = GetPluginLastModifiedTime(localfile);
+-    const bool fromExtension = GetPluginIsFromExtension(localfile, extensionDirs);
+ 
+     // Look for it in our cache
+     NS_ConvertUTF16toUTF8 filePath(utf16FilePath);
+     RefPtr<nsPluginTag> pluginTag;
+     RemoveCachedPluginsInfo(filePath.get(), getter_AddRefs(pluginTag));
+ 
+     bool seenBefore = false;
+ 
+@@ -2079,17 +2029,17 @@ nsresult nsPluginHost::ScanPluginsDirect
+         }
+         mInvalidPlugins = invalidTag;
+ 
+         // Mark aPluginsChanged so pluginreg is rewritten
+         *aPluginsChanged = true;
+         continue;
+       }
+ 
+-      pluginTag = new nsPluginTag(&info, fileModTime, fromExtension);
++      pluginTag = new nsPluginTag(&info, fileModTime);
+       pluginFile.FreePluginInfo(info);
+       pluginTag->mLibrary = library;
+       uint32_t state;
+       rv = pluginTag->GetBlocklistState(&state);
+       NS_ENSURE_SUCCESS(rv, rv);
+ 
+       // If the blocklist says it is risky and we have never seen this
+       // plugin before, then disable it.
+@@ -2285,17 +2235,16 @@ nsPluginHost::SetPluginsInContent(uint32
+                                                "", // aFullPath
+                                                tag.version().get(),
+                                                nsTArray<nsCString>(tag.mimeTypes()),
+                                                nsTArray<nsCString>(tag.mimeDescriptions()),
+                                                nsTArray<nsCString>(tag.extensions()),
+                                                tag.isFlashPlugin(),
+                                                tag.supportsAsyncRender(),
+                                                tag.lastModifiedTime(),
+-                                               tag.isFromExtension(),
+                                                tag.sandboxLevel(),
+                                                tag.blocklistState());
+       AddPluginTag(pluginTag);
+     }
+ 
+     for (const auto& tag : aFakePlugins) {
+       // Don't add the same plugin again.
+       for (const auto& existingTag : mFakePlugins) {
+@@ -2379,16 +2328,30 @@ nsresult nsPluginHost::FindPlugins(bool 
+   // Scan the app-defined list of plugin dirs.
+   rv = dirService->Get(NS_APP_PLUGINS_DIR_LIST, NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(dirList));
+   if (NS_SUCCEEDED(rv)) {
+     ScanPluginsDirectoryList(dirList, aCreatePluginList, &pluginschanged);
+ 
+     if (pluginschanged)
+       *aPluginsChanged = true;
+ 
++    // In tests, load plugins from the profile.
++    if (xpc::IsInAutomation()) {
++      nsCOMPtr<nsIFile> profDir;
++      rv = dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
++                           getter_AddRefs(profDir));
++      if (NS_SUCCEEDED(rv)) {
++        profDir->Append(NS_LITERAL_STRING("plugins"));
++        ScanPluginsDirectory(profDir, aCreatePluginList, &pluginschanged);
++        if (pluginschanged) {
++          *aPluginsChanged = true;
++        }
++      }
++    }
++
+     // if we are just looking for possible changes,
+     // no need to proceed if changes are detected
+     if (!aCreatePluginList && *aPluginsChanged) {
+       NS_ITERATIVE_UNREF_LIST(RefPtr<nsPluginTag>, mCachedPlugins, mNext);
+       NS_ITERATIVE_UNREF_LIST(RefPtr<nsInvalidPluginTag>, mInvalidPlugins, mNext);
+       return NS_OK;
+     }
+   }
+@@ -2528,17 +2491,16 @@ nsPluginHost::SendPluginsToContent()
+                                        tag->MimeTypes(),
+                                        tag->MimeDescriptions(),
+                                        tag->Extensions(),
+                                        tag->mIsFlashPlugin,
+                                        tag->mSupportsAsyncRender,
+                                        tag->FileName(),
+                                        tag->Version(),
+                                        tag->mLastModifiedTime,
+-                                       tag->IsFromExtension(),
+                                        tag->mSandboxLevel,
+                                        blocklistState));
+   }
+   nsTArray<dom::ContentParent*> parents;
+   dom::ContentParent::GetAll(parents);
+   for (auto p : parents)
+   {
+     Unused << p->SendSetPluginList(newPluginEpoch, pluginTags, fakePluginTags);
+@@ -2741,17 +2703,17 @@ nsPluginHost::WritePluginInfo()
+     // lastModifiedTimeStamp|canUnload|tag->mFlags|fromExtension
+     PR_fprintf(fd, "%lld%c%d%c%lu%c%d%c%c\n",
+       tag->mLastModifiedTime,
+       PLUGIN_REGISTRY_FIELD_DELIMITER,
+       false, // did store whether or not to unload in-process plugins
+       PLUGIN_REGISTRY_FIELD_DELIMITER,
+       0, // legacy field for flags
+       PLUGIN_REGISTRY_FIELD_DELIMITER,
+-      tag->IsFromExtension(),
++      false,
+       PLUGIN_REGISTRY_FIELD_DELIMITER,
+       PLUGIN_REGISTRY_END_OF_LINE_MARKER);
+ 
+     //description, name & mtypecount are on separate line
+     PR_fprintf(fd, "%s%c%c\n%s%c%c\n%d\n",
+       (tag->Description().get()),
+       PLUGIN_REGISTRY_FIELD_DELIMITER,
+       PLUGIN_REGISTRY_END_OF_LINE_MARKER,
+@@ -2968,17 +2930,16 @@ nsPluginHost::ReadPluginInfo()
+     if (!reader.NextLine())
+       return rv;
+ 
+     // lastModifiedTimeStamp|canUnload|tag.mFlag|fromExtension
+     if (4 != reader.ParseLine(values, 4))
+       return rv;
+ 
+     int64_t lastmod = nsCRT::atoll(values[0]);
+-    bool fromExtension = atoi(values[3]);
+     if (!reader.NextLine())
+       return rv;
+ 
+     char *description = reader.LinePtr();
+     if (!reader.NextLine())
+       return rv;
+ 
+     const char *name = reader.LinePtr();
+@@ -3029,17 +2990,17 @@ nsPluginHost::ReadPluginInfo()
+     RefPtr<nsPluginTag> tag = new nsPluginTag(name,
+       description,
+       filename,
+       fullpath,
+       version,
+       (const char* const*)mimetypes,
+       (const char* const*)mimedescriptions,
+       (const char* const*)extensions,
+-      mimetypecount, lastmod, fromExtension, true);
++      mimetypecount, lastmod, true);
+ 
+     delete [] heapalloced;
+ 
+     // Import flags from registry into prefs for old registry versions
+     MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_BASIC,
+       ("LoadCachedPluginsInfo : Loading Cached plugininfo for %s\n", tag->FileName().get()));
+ 
+     tag->mNext = mCachedPlugins;
+diff --git a/dom/plugins/base/nsPluginTags.cpp b/dom/plugins/base/nsPluginTags.cpp
+--- a/dom/plugins/base/nsPluginTags.cpp
++++ b/dom/plugins/base/nsPluginTags.cpp
+@@ -217,32 +217,30 @@ nsIInternalPluginTag::HasMimeType(const 
+                              nsCaseInsensitiveCStringArrayComparator());
+ }
+ 
+ /* nsPluginTag */
+ 
+ uint32_t nsPluginTag::sNextId;
+ 
+ nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo,
+-                         int64_t aLastModifiedTime,
+-                         bool fromExtension)
++                         int64_t aLastModifiedTime)
+   : nsIInternalPluginTag(aPluginInfo->fName, aPluginInfo->fDescription,
+                          aPluginInfo->fFileName, aPluginInfo->fVersion),
+     mId(sNextId++),
+     mContentProcessRunningCount(0),
+     mHadLocalInstance(false),
+     mLibrary(nullptr),
+     mIsFlashPlugin(false),
+     mSupportsAsyncRender(false),
+     mFullPath(aPluginInfo->fFullPath),
+     mLastModifiedTime(aLastModifiedTime),
+     mSandboxLevel(0),
+     mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
+-    mCachedBlocklistStateValid(false),
+-    mIsFromExtension(fromExtension)
++    mCachedBlocklistStateValid(false)
+ {
+   InitMime(aPluginInfo->fMimeTypeArray,
+            aPluginInfo->fMimeDescriptionArray,
+            aPluginInfo->fExtensionArray,
+            aPluginInfo->fVariantCount);
+   InitSandboxLevel();
+   EnsureMembersAreUTF8();
+   FixupVersion();
+@@ -253,31 +251,29 @@ nsPluginTag::nsPluginTag(const char* aNa
+                          const char* aFileName,
+                          const char* aFullPath,
+                          const char* aVersion,
+                          const char* const* aMimeTypes,
+                          const char* const* aMimeDescriptions,
+                          const char* const* aExtensions,
+                          int32_t aVariants,
+                          int64_t aLastModifiedTime,
+-                         bool fromExtension,
+                          bool aArgsAreUTF8)
+   : nsIInternalPluginTag(aName, aDescription, aFileName, aVersion),
+     mId(sNextId++),
+     mContentProcessRunningCount(0),
+     mHadLocalInstance(false),
+     mLibrary(nullptr),
+     mIsFlashPlugin(false),
+     mSupportsAsyncRender(false),
+     mFullPath(aFullPath),
+     mLastModifiedTime(aLastModifiedTime),
+     mSandboxLevel(0),
+     mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
+-    mCachedBlocklistStateValid(false),
+-    mIsFromExtension(fromExtension)
++    mCachedBlocklistStateValid(false)
+ {
+   InitMime(aMimeTypes, aMimeDescriptions, aExtensions,
+            static_cast<uint32_t>(aVariants));
+   InitSandboxLevel();
+   if (!aArgsAreUTF8)
+     EnsureMembersAreUTF8();
+   FixupVersion();
+ }
+@@ -289,32 +285,30 @@ nsPluginTag::nsPluginTag(uint32_t aId,
+                          const char* aFullPath,
+                          const char* aVersion,
+                          nsTArray<nsCString> aMimeTypes,
+                          nsTArray<nsCString> aMimeDescriptions,
+                          nsTArray<nsCString> aExtensions,
+                          bool aIsFlashPlugin,
+                          bool aSupportsAsyncRender,
+                          int64_t aLastModifiedTime,
+-                         bool aFromExtension,
+                          int32_t aSandboxLevel,
+                          uint16_t aBlocklistState)
+   : nsIInternalPluginTag(aName, aDescription, aFileName, aVersion, aMimeTypes,
+                          aMimeDescriptions, aExtensions),
+     mId(aId),
+     mContentProcessRunningCount(0),
+     mLibrary(nullptr),
+     mIsFlashPlugin(aIsFlashPlugin),
+     mSupportsAsyncRender(aSupportsAsyncRender),
+     mLastModifiedTime(aLastModifiedTime),
+     mSandboxLevel(aSandboxLevel),
+     mNiceFileName(),
+     mCachedBlocklistState(aBlocklistState),
+-    mCachedBlocklistStateValid(true),
+-    mIsFromExtension(aFromExtension)
++    mCachedBlocklistStateValid(true)
+ {
+ }
+ 
+ nsPluginTag::~nsPluginTag()
+ {
+   NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
+ }
+ 
+@@ -570,20 +564,18 @@ nsPluginTag::GetEnabledState(uint32_t *a
+   }
+   if (NS_SUCCEEDED(rv) &&
+       enabledState >= nsIPluginTag::STATE_DISABLED &&
+       enabledState <= nsIPluginTag::STATE_ENABLED) {
+     *aEnabledState = (uint32_t)enabledState;
+     return rv;
+   }
+ 
+-  const char* const pref = mIsFromExtension ? kPrefDefaultEnabledStateXpi
+-                                            : kPrefDefaultEnabledState;
+-
+-  enabledState = Preferences::GetInt(pref, nsIPluginTag::STATE_ENABLED);
++  enabledState = Preferences::GetInt(kPrefDefaultEnabledState,
++                                     nsIPluginTag::STATE_ENABLED);
+   if (enabledState == nsIPluginTag::STATE_ENABLED && mIsFlashPlugin) {
+     enabledState = nsIPluginTag::STATE_CLICKTOPLAY;
+   }
+   if (enabledState >= nsIPluginTag::STATE_DISABLED &&
+       enabledState <= nsIPluginTag::STATE_ENABLED) {
+     *aEnabledState = (uint32_t)enabledState;
+     return NS_OK;
+   }
+@@ -757,21 +749,16 @@ nsPluginTag::InvalidateBlocklistState()
+ NS_IMETHODIMP
+ nsPluginTag::GetLastModifiedTime(PRTime* aLastModifiedTime)
+ {
+   MOZ_ASSERT(aLastModifiedTime);
+   *aLastModifiedTime = mLastModifiedTime;
+   return NS_OK;
+ }
+ 
+-bool nsPluginTag::IsFromExtension() const
+-{
+-  return mIsFromExtension;
+-}
+-
+ /* nsFakePluginTag */
+ 
+ uint32_t nsFakePluginTag::sNextId;
+ 
+ nsFakePluginTag::nsFakePluginTag()
+   : mId(sNextId++),
+     mState(nsPluginTag::ePluginState_Disabled)
+ {
+diff --git a/dom/plugins/base/nsPluginTags.h b/dom/plugins/base/nsPluginTags.h
+--- a/dom/plugins/base/nsPluginTags.h
++++ b/dom/plugins/base/nsPluginTags.h
+@@ -102,43 +102,40 @@ public:
+   enum PluginState {
+     ePluginState_Disabled = 0,
+     ePluginState_Clicktoplay = 1,
+     ePluginState_Enabled = 2,
+     ePluginState_MaxValue = 3,
+   };
+ 
+   nsPluginTag(nsPluginInfo* aPluginInfo,
+-              int64_t aLastModifiedTime,
+-              bool fromExtension);
++              int64_t aLastModifiedTime);
+   nsPluginTag(const char* aName,
+               const char* aDescription,
+               const char* aFileName,
+               const char* aFullPath,
+               const char* aVersion,
+               const char* const* aMimeTypes,
+               const char* const* aMimeDescriptions,
+               const char* const* aExtensions,
+               int32_t aVariants,
+               int64_t aLastModifiedTime,
+-              bool fromExtension,
+               bool aArgsAreUTF8 = false);
+   nsPluginTag(uint32_t aId,
+               const char* aName,
+               const char* aDescription,
+               const char* aFileName,
+               const char* aFullPath,
+               const char* aVersion,
+               nsTArray<nsCString> aMimeTypes,
+               nsTArray<nsCString> aMimeDescriptions,
+               nsTArray<nsCString> aExtensions,
+               bool aIsFlashPlugin,
+               bool aSupportsAsyncRender,
+               int64_t aLastModifiedTime,
+-              bool aFromExtension,
+               int32_t aSandboxLevel,
+               uint16_t aBlocklistState);
+ 
+   void TryUnloadPlugin(bool inShutdown);
+ 
+   // plugin is enabled and not blocklisted
+   bool IsActive();
+ 
+@@ -149,18 +146,16 @@ public:
+ 
+   PluginState GetPluginState();
+   void SetPluginState(PluginState state);
+   void SetBlocklistState(uint16_t aBlocklistState);
+ 
+   bool HasSameNameAndMimes(const nsPluginTag *aPluginTag) const;
+   const nsCString& GetNiceFileName() override;
+ 
+-  bool IsFromExtension() const;
+-
+   RefPtr<nsPluginTag> mNext;
+   uint32_t      mId;
+ 
+   // Number of PluginModuleParents living in all content processes.
+   size_t        mContentProcessRunningCount;
+ 
+   // True if we've ever created an instance of this plugin in the current process.
+   bool          mHadLocalInstance;
+@@ -177,17 +172,16 @@ public:
+   void          InvalidateBlocklistState();
+ 
+ private:
+   virtual ~nsPluginTag();
+ 
+   nsCString     mNiceFileName; // UTF-8
+   uint16_t      mCachedBlocklistState;
+   bool          mCachedBlocklistStateValid;
+-  bool          mIsFromExtension;
+ 
+   void InitMime(const char* const* aMimeTypes,
+                 const char* const* aMimeDescriptions,
+                 const char* const* aExtensions,
+                 uint32_t aVariantCount);
+   void InitSandboxLevel();
+   nsresult EnsureMembersAreUTF8();
+   void FixupVersion();
+diff --git a/dom/plugins/ipc/PluginTypes.ipdlh b/dom/plugins/ipc/PluginTypes.ipdlh
+--- a/dom/plugins/ipc/PluginTypes.ipdlh
++++ b/dom/plugins/ipc/PluginTypes.ipdlh
+@@ -16,17 +16,16 @@ struct PluginTag
+   nsCString[] mimeTypes;
+   nsCString[] mimeDescriptions;
+   nsCString[] extensions;
+   bool isFlashPlugin;
+   bool supportsAsyncRender; // flash specific
+   nsCString filename;
+   nsCString version;
+   int64_t lastModifiedTime;
+-  bool isFromExtension;
+   int32_t sandboxLevel;
+   uint16_t blocklistState;
+ };
+ 
+ struct FakePluginTag
+ {
+   uint32_t id;
+   URIParams handlerURI;
+diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
+--- a/modules/libpref/init/all.js
++++ b/modules/libpref/init/all.js
+@@ -3273,18 +3273,16 @@ pref("input_event_queue.count_for_predic
+ pref("idle_queue.min_period", 3);
+ 
+ // Hang monitor timeout after which we kill the browser, in seconds
+ // (0 is disabled)
+ // Disabled on all platforms per bug 705748 until the found issues are
+ // resolved.
+ pref("hangmonitor.timeout", 0);
+ 
+-pref("plugins.load_appdir_plugins", false);
+-
+ // This only supports one hidden ctp plugin, edit nsPluginArray.cpp if adding a second
+ pref("plugins.navigator.hidden_ctp_plugin", "");
+ 
+ // The default value for nsIPluginTag.enabledState (STATE_ENABLED = 2)
+ pref("plugin.default.state", 2);
+ 
+ // The MIME type that should bind to legacy java-specific invocations like
+ // <applet> and <object data="java:foo">. Setting this to a non-java MIME type
+diff --git a/toolkit/mozapps/extensions/internal/PluginProvider.jsm b/toolkit/mozapps/extensions/internal/PluginProvider.jsm
+--- a/toolkit/mozapps/extensions/internal/PluginProvider.jsm
++++ b/toolkit/mozapps/extensions/internal/PluginProvider.jsm
+@@ -444,23 +444,18 @@ PluginWrapper.prototype = {
+       date = Math.max(date, tag.lastModifiedTime);
+     }
+     return new Date(date);
+   },
+ 
+   get scope() {
+     let { tags: [tag] } = pluginFor(this);
+     let path = tag.fullpath;
+-    // Plugins inside the application directory are in the application scope
+-    let dir = Services.dirsvc.get("APlugns", Ci.nsIFile);
+-    if (path.startsWith(dir.path))
+-      return AddonManager.SCOPE_APPLICATION;
+-
+     // Plugins inside the profile directory are in the profile scope
+-    dir = Services.dirsvc.get("ProfD", Ci.nsIFile);
++    let dir = Services.dirsvc.get("ProfD", Ci.nsIFile);
+     if (path.startsWith(dir.path))
+       return AddonManager.SCOPE_PROFILE;
+ 
+     // Plugins anywhere else in the user's home are in the user scope,
+     // but not all platforms have a home directory.
+     try {
+       dir = Services.dirsvc.get("Home", Ci.nsIFile);
+       if (path.startsWith(dir.path))
+diff --git a/toolkit/xre/nsXREDirProvider.cpp b/toolkit/xre/nsXREDirProvider.cpp
+--- a/toolkit/xre/nsXREDirProvider.cpp
++++ b/toolkit/xre/nsXREDirProvider.cpp
+@@ -835,31 +835,16 @@ DeleteDirIfExists(nsIFile* dir)
+   return NS_OK;
+ }
+ 
+ #endif // (defined(XP_WIN) || defined(XP_MACOSX)) &&
+   // defined(MOZ_CONTENT_SANDBOX)
+ 
+ static const char *const kAppendPrefDir[] = { "defaults", "preferences", nullptr };
+ 
+-#ifdef DEBUG_bsmedberg
+-static void
+-DumpFileArray(const char *key,
+-              nsCOMArray<nsIFile> dirs)
+-{
+-  fprintf(stderr, "nsXREDirProvider::GetFilesInternal(%s)\n", key);
+-
+-  nsAutoCString path;
+-  for (int32_t i = 0; i < dirs.Count(); ++i) {
+-    dirs[i]->GetNativePath(path);
+-    fprintf(stderr, "  %s\n", path.get());
+-  }
+-}
+-#endif // DEBUG_bsmedberg
+-
+ nsresult
+ nsXREDirProvider::GetFilesInternal(const char* aProperty,
+                                    nsISimpleEnumerator** aResult)
+ {
+   nsresult rv = NS_OK;
+   *aResult = nullptr;
+ 
+   if (!strcmp(aProperty, XRE_EXTENSIONS_DIR_LIST)) {
+@@ -914,52 +899,16 @@ nsXREDirProvider::GetFilesInternal(const
+                       kAppendChromeDir,
+                       directories);
+     LoadDirsIntoArray(AddonManagerStartup::GetSingleton().ExtensionPaths(),
+                       kAppendChromeDir,
+                       directories);
+ 
+     rv = NS_NewArrayEnumerator(aResult, directories);
+   }
+-  else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
+-    nsCOMArray<nsIFile> directories;
+-
+-    if (mozilla::Preferences::GetBool("plugins.load_appdir_plugins", false)) {
+-      nsCOMPtr<nsIFile> appdir;
+-      rv = XRE_GetBinaryPath(getter_AddRefs(appdir));
+-      if (NS_SUCCEEDED(rv)) {
+-        appdir->SetNativeLeafName(NS_LITERAL_CSTRING("plugins"));
+-        directories.AppendObject(appdir);
+-      }
+-    }
+-
+-    static const char *const kAppendPlugins[] = { "plugins", nullptr };
+-
+-    // The root dirserviceprovider does quite a bit for us: we're mainly
+-    // interested in xulapp and extension-provided plugins.
+-    LoadDirsIntoArray(mAppBundleDirectories,
+-                      kAppendPlugins,
+-                      directories);
+-    LoadDirsIntoArray(AddonManagerStartup::GetSingleton().ExtensionPaths(),
+-                      kAppendPlugins,
+-                      directories);
+-
+-    if (mProfileDir) {
+-      nsCOMArray<nsIFile> profileDir;
+-      profileDir.AppendObject(mProfileDir);
+-      LoadDirsIntoArray(profileDir,
+-                        kAppendPlugins,
+-                        directories);
+-    }
+-
+-    rv = NS_NewArrayEnumerator(aResult, directories);
+-    NS_ENSURE_SUCCESS(rv, rv);
+-
+-    rv = NS_SUCCESS_AGGREGATE_RESULT;
+-  }
+   else
+     rv = NS_ERROR_FAILURE;
+ 
+   return rv;
+ }
+ 
+ NS_IMETHODIMP
+ nsXREDirProvider::GetDirectory(nsIFile* *aResult)
+diff --git a/xpcom/io/nsAppDirectoryServiceDefs.h b/xpcom/io/nsAppDirectoryServiceDefs.h
+--- a/xpcom/io/nsAppDirectoryServiceDefs.h
++++ b/xpcom/io/nsAppDirectoryServiceDefs.h
+@@ -32,17 +32,16 @@
+ #define NS_APP_DEFAULTS_50_DIR                  "DefRt"         // The root dir of all defaults dirs
+ #define NS_APP_PREF_DEFAULTS_50_DIR             "PrfDef"
+ 
+ #define NS_APP_USER_PROFILES_ROOT_DIR           "DefProfRt"     // The dir where user profile dirs live.
+ #define NS_APP_USER_PROFILES_LOCAL_ROOT_DIR     "DefProfLRt"  // The dir where user profile temp dirs live.
+ 
+ #define NS_APP_RES_DIR                          "ARes"
+ #define NS_APP_CHROME_DIR                       "AChrom"
+-#define NS_APP_PLUGINS_DIR                      "APlugns"       // Deprecated - use NS_APP_PLUGINS_DIR_LIST
+ #define NS_APP_SEARCH_DIR                       "SrchPlugns"
+ 
+ #define NS_APP_CHROME_DIR_LIST                  "AChromDL"
+ #define NS_APP_PLUGINS_DIR_LIST                 "APluginsDL"
+ #define NS_APP_SEARCH_DIR_LIST                  "SrchPluginsDL"
+ #define NS_APP_DISTRIBUTION_SEARCH_DIR_LIST     "SrchPluginsDistDL"
+ 
+ // --------------------------------------------------------------------------------------
+diff --git a/xpcom/io/nsAppFileLocationProvider.cpp b/xpcom/io/nsAppFileLocationProvider.cpp
+--- a/xpcom/io/nsAppFileLocationProvider.cpp
++++ b/xpcom/io/nsAppFileLocationProvider.cpp
+@@ -38,17 +38,16 @@
+ #else
+ #define APP_REGISTRY_NAME NS_LITERAL_CSTRING("appreg")
+ #endif
+ 
+ // define default product directory
+ #define DEFAULT_PRODUCT_DIR NS_LITERAL_CSTRING(MOZ_USER_DIR)
+ 
+ // Locally defined keys used by nsAppDirectoryEnumerator
+-#define NS_ENV_PLUGINS_DIR          "EnvPlugins"    // env var MOZ_PLUGIN_PATH
+ #define NS_USER_PLUGINS_DIR         "UserPlugins"
+ 
+ #ifdef MOZ_WIDGET_COCOA
+ #define NS_MACOSX_USER_PLUGIN_DIR   "OSXUserPlugins"
+ #define NS_MACOSX_LOCAL_PLUGIN_DIR  "OSXLocalPlugins"
+ #elif XP_UNIX
+ #define NS_SYSTEM_PLUGINS_DIR       "SysPlugins"
+ #endif
+@@ -128,21 +127,16 @@ nsAppFileLocationProvider::GetFile(const
+     if (NS_SUCCEEDED(rv)) {
+       rv = localFile->AppendRelativeNativePath(RES_DIR_NAME);
+     }
+   } else if (nsCRT::strcmp(aProp, NS_APP_CHROME_DIR) == 0) {
+     rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+     if (NS_SUCCEEDED(rv)) {
+       rv = localFile->AppendRelativeNativePath(CHROME_DIR_NAME);
+     }
+-  } else if (nsCRT::strcmp(aProp, NS_APP_PLUGINS_DIR) == 0) {
+-    rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+-    if (NS_SUCCEEDED(rv)) {
+-      rv = localFile->AppendRelativeNativePath(PLUGINS_DIR_NAME);
+-    }
+   }
+ #ifdef MOZ_WIDGET_COCOA
+   else if (nsCRT::strcmp(aProp, NS_MACOSX_USER_PLUGIN_DIR) == 0) {
+     if (::FSFindFolder(kUserDomain, kInternetPlugInFolderType, false,
+                        &fileRef) == noErr) {
+       rv = NS_NewLocalFileWithFSRef(&fileRef, true, getter_AddRefs(macFile));
+       if (NS_SUCCEEDED(rv)) {
+         localFile = macFile;
+@@ -153,24 +147,17 @@ nsAppFileLocationProvider::GetFile(const
+                        &fileRef) == noErr) {
+       rv = NS_NewLocalFileWithFSRef(&fileRef, true, getter_AddRefs(macFile));
+       if (NS_SUCCEEDED(rv)) {
+         localFile = macFile;
+       }
+     }
+   }
+ #else
+-  else if (nsCRT::strcmp(aProp, NS_ENV_PLUGINS_DIR) == 0) {
+-    NS_ERROR("Don't use nsAppFileLocationProvider::GetFile(NS_ENV_PLUGINS_DIR, ...). "
+-             "Use nsAppFileLocationProvider::GetFiles(...).");
+-    const char* pathVar = PR_GetEnv("MOZ_PLUGIN_PATH");
+-    if (pathVar && *pathVar)
+-      rv = NS_NewNativeLocalFile(nsDependentCString(pathVar), true,
+-                                 getter_AddRefs(localFile));
+-  } else if (nsCRT::strcmp(aProp, NS_USER_PLUGINS_DIR) == 0) {
++  else if (nsCRT::strcmp(aProp, NS_USER_PLUGINS_DIR) == 0) {
+ #ifdef ENABLE_SYSTEM_EXTENSION_DIRS
+     rv = GetProductDirectory(getter_AddRefs(localFile));
+     if (NS_SUCCEEDED(rv)) {
+       rv = localFile->AppendRelativeNativePath(PLUGINS_DIR_NAME);
+     }
+ #else
+     rv = NS_ERROR_FAILURE;
+ #endif
+@@ -531,34 +518,28 @@ nsAppFileLocationProvider::GetFiles(cons
+     return NS_ERROR_INVALID_ARG;
+   }
+   *aResult = nullptr;
+   nsresult rv = NS_ERROR_FAILURE;
+ 
+   if (!nsCRT::strcmp(aProp, NS_APP_PLUGINS_DIR_LIST)) {
+ #ifdef MOZ_WIDGET_COCOA
+     static const char* keys[] = {
+-      NS_APP_PLUGINS_DIR,
+       NS_MACOSX_USER_PLUGIN_DIR,
+       NS_MACOSX_LOCAL_PLUGIN_DIR,
+       nullptr
+     };
+-    *aResult = new nsAppDirectoryEnumerator(this, keys);
+ #else
+ #ifdef XP_UNIX
+-    static const char* keys[] = { nullptr, NS_USER_PLUGINS_DIR, NS_APP_PLUGINS_DIR, NS_SYSTEM_PLUGINS_DIR, nullptr };
++    static const char* keys[] = { nullptr, NS_USER_PLUGINS_DIR, NS_SYSTEM_PLUGINS_DIR, nullptr };
+ #else
+-    static const char* keys[] = { nullptr, NS_USER_PLUGINS_DIR, NS_APP_PLUGINS_DIR, nullptr };
++    static const char* keys[] = { nullptr, NS_USER_PLUGINS_DIR, nullptr };
+ #endif
+-    if (!keys[0] && !(keys[0] = PR_GetEnv("MOZ_PLUGIN_PATH"))) {
+-      static const char nullstr = 0;
+-      keys[0] = &nullstr;
+-    }
+-    *aResult = new nsPathsDirectoryEnumerator(this, keys);
+ #endif
++    *aResult = new nsAppDirectoryEnumerator(this, keys);
+     NS_ADDREF(*aResult);
+     rv = NS_OK;
+   }
+   if (!nsCRT::strcmp(aProp, NS_APP_SEARCH_DIR_LIST)) {
+     static const char* keys[] = { nullptr, NS_APP_USER_SEARCH_DIR, nullptr };
+     if (!keys[0] && !(keys[0] = PR_GetEnv("MOZ_SEARCH_ENGINE_PATH"))) {
+       static const char nullstr = 0;
+       keys[0] = &nullstr;

+ 201 - 0
mozilla-release/patches/1675349-06-PARTIAL-85a1.patch

@@ -0,0 +1,201 @@
+# HG changeset patch
+# User David Parks <daparks@mozilla.com>
+# Date 1605715030 0
+# Node ID e38cc205b04ccf7d48ae98d20659caa1375e4abe
+# Parent  b716d9071a9484fb3b8e515eace8a02dd2edce4d
+Bug 1675349: Update tests under browser/components for the removal of plugins. r=jmathies,mixedpuppy
+
+UPDATED
+-------
+
+browser/components/extensions/test/browser/browser_ext_browsingData_pluginData.js
+Test plugindata part of the browsingData extension's use of nsIClearDataService.
+Have test attempt to clear non-existent data.  Test that browsingData APIs do not cause exceptions.
+
+REMOVED
+-------
+browser/components/enterprisepolicies/tests/browser/browser_policy_disable_flash_plugin.js
+Bug 1429169
+Flash ctp/disabled by enterprise policy.
+
+Differential Revision: https://phabricator.services.mozilla.com/D95907
+
+diff --git a/browser/components/extensions/test/browser/browser_ext_browsingData_pluginData.js b/browser/components/extensions/test/browser/browser_ext_browsingData_pluginData.js
+--- a/browser/components/extensions/test/browser/browser_ext_browsingData_pluginData.js
++++ b/browser/components/extensions/test/browser/browser_ext_browsingData_pluginData.js
+@@ -1,66 +1,21 @@
+ /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+ /* vim: set sts=2 sw=2 et tw=80: */
+ "use strict";
+ 
+-XPCOMUtils.defineLazyServiceGetter(this, "pluginHost",
+-                                   "@mozilla.org/plugin/host;1",
+-                                   "nsIPluginHost");
+-
+-// Returns the chrome side nsIPluginTag for the test plugin.
+-function getTestPlugin() {
+-  let tags = pluginHost.getPluginTags();
+-  let plugin = tags.find(tag => tag.name == "Test Plug-in");
+-  if (!plugin) {
+-    ok(false, "Unable to find plugin");
+-  }
+-  return plugin;
+-}
+-
+ const TEST_ROOT = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
+ const TEST_URL = TEST_ROOT + "file_clearplugindata.html";
+ const REFERENCE_DATE = Date.now();
+-const PLUGIN_TAG = getTestPlugin();
+-
+-/* Due to layout being async, "PluginBindAttached" may trigger later. This
+-   returns a Promise that resolves once we've forced a layout flush, which
+-   triggers the PluginBindAttached event to fire. This trick only works if
+-   there is some sort of plugin in the page.
+- */
+-function promiseUpdatePluginBindings(browser) {
+-  return ContentTask.spawn(browser, {}, async function() {
+-    let doc = content.document;
+-    let elems = doc.getElementsByTagName("embed");
+-    if (elems && elems.length > 0) {
+-      elems[0].clientTop; // eslint-disable-line no-unused-expressions
+-    }
+-  });
+-}
+-
+-function stored(needles) {
+-  let something = pluginHost.siteHasData(PLUGIN_TAG, null);
+-  if (!needles) {
+-    return something;
+-  }
+-
+-  if (!something) {
+-    return false;
+-  }
+-
+-  if (needles.every(value => pluginHost.siteHasData(PLUGIN_TAG, value))) {
+-    return true;
+-  }
+-
+-  return false;
+-}
+ 
+ add_task(async function testPluginData() {
+   function background() {
+     browser.test.onMessage.addListener(async(msg, options) => {
++      // Plugins are disabled.  We are simply testing that these async APIs
++      // complete without exceptions.
+       if (msg == "removePluginData") {
+         await browser.browsingData.removePluginData(options);
+       } else {
+         await browser.browsingData.remove(options, {pluginData: true});
+       }
+       browser.test.sendMessage("pluginDataRemoved");
+     });
+   }
+@@ -68,65 +23,52 @@ add_task(async function testPluginData()
+   let extension = ExtensionTestUtils.loadExtension({
+     background,
+     manifest: {
+       permissions: ["browsingData"],
+     },
+   });
+ 
+   async function testRemovalMethod(method) {
++    // NB: Since pplugins are disabled, there is never any data to clear.
++    // We are really testing that these operations are no-ops.
++
+     // Clear plugin data with no since value.
+ 
+     // Load page to set data for the plugin.
+     let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
+-    await promiseUpdatePluginBindings(gBrowser.selectedBrowser);
+-
+-    ok(stored(["foo.com", "bar.com", "baz.com", "qux.com"]),
+-       "Data stored for sites");
+ 
+     extension.sendMessage(method, {});
+     await extension.awaitMessage("pluginDataRemoved");
+ 
+-    ok(!stored(null), "All data cleared");
+     await BrowserTestUtils.removeTab(tab);
+ 
+     // Clear history with recent since value.
+ 
+     // Load page to set data for the plugin.
+     tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
+-    await promiseUpdatePluginBindings(gBrowser.selectedBrowser);
+-
+-    ok(stored(["foo.com", "bar.com", "baz.com", "qux.com"]),
+-       "Data stored for sites");
+ 
+     extension.sendMessage(method, {since: REFERENCE_DATE - 20000});
+     await extension.awaitMessage("pluginDataRemoved");
+ 
+-    ok(stored(["bar.com", "qux.com"]), "Data stored for sites");
+-    ok(!stored(["foo.com"]), "Data cleared for foo.com");
+-    ok(!stored(["baz.com"]), "Data cleared for baz.com");
+     await BrowserTestUtils.removeTab(tab);
+ 
+     // Clear history with old since value.
+ 
+     // Load page to set data for the plugin.
+     tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
+-    await promiseUpdatePluginBindings(gBrowser.selectedBrowser);
+-
+-    ok(stored(["foo.com", "bar.com", "baz.com", "qux.com"]),
+-       "Data stored for sites");
+ 
+     extension.sendMessage(method, {since: REFERENCE_DATE - 1000000});
+     await extension.awaitMessage("pluginDataRemoved");
+ 
+-    ok(!stored(null), "All data cleared");
+     await BrowserTestUtils.removeTab(tab);
+   }
+ 
+-  PLUGIN_TAG.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
+-
++  waitForExplicitFinish();
+   await extension.startup();
+ 
+   await testRemovalMethod("removePluginData");
+   await testRemovalMethod("remove");
+ 
+   await extension.unload();
++  ok(true, "should get to the end without throwing an exception");
++  finish();
+ });
+diff --git a/browser/components/extensions/test/browser/file_clearplugindata.html b/browser/components/extensions/test/browser/file_clearplugindata.html
+--- a/browser/components/extensions/test/browser/file_clearplugindata.html
++++ b/browser/components/extensions/test/browser/file_clearplugindata.html
+@@ -1,30 +1,14 @@
+ <!--
+   Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/
+ -->
+ <html>
+   <head>
+-    <title>Plugin Clear Site Data sanitize test</title>
++    <title>Plugin Clear Site Data disabled test</title>
+ 
+     <embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
+ 
+   </head>
+ 
+   <body></body>
+-
+-  <script type="application/javascript">
+-    "use strict";
+-
+-    // Make sure clearing by timerange is supported.
+-    let p = document.getElementById("plugin1");
+-    p.setSitesWithDataCapabilities(true);
+-
+-    p.setSitesWithData(
+-      "foo.com:0:5," +
+-      "bar.com:0:100," +
+-      "baz.com:1:5," +
+-      "qux.com:1:100"
+-    );
+-  </script>
+-
+ </html>

+ 123 - 0
mozilla-release/patches/1675349-07-85a1.patch

@@ -0,0 +1,123 @@
+# HG changeset patch
+# User David Parks <daparks@mozilla.com>
+# Date 1605715047 0
+# Node ID b712e934ced5d0108dfb9bbf02ec93d61a256405
+# Parent  f7a6b781a4a28b564768398aadc5bcd3b3bc04bd
+Bug 1675349: Update tests under dom/base for the removal of plugins. r=jmathies
+
+UPDATED
+-------
+dom/base/test/browser_timeout_throttling_with_audio_playback.js
+Test background tab audio throttling
+Remove plugin portion
+
+Differential Revision: https://phabricator.services.mozilla.com/D95908
+
+diff --git a/dom/base/test/browser.ini b/dom/base/test/browser.ini
+--- a/dom/base/test/browser.ini
++++ b/dom/base/test/browser.ini
+@@ -14,17 +14,16 @@ support-files =
+   file_bug1303838_target_foo.html
+   file_bug1303838_target_bar.html
+   file_bug1303838_target_baz.html
+   file_bug1303838_target_ifoo.html
+   file_bug1303838_target_ibar.html
+   file_bug1303838_target_ibaz.html
+   file_bug1303838_with_iframe.html
+   file_messagemanager_unload.html
+-  file_pluginAudio.html
+   file_use_counter_outer.html
+   file_use_counter_svg_getElementById.svg
+   file_use_counter_svg_currentScale.svg
+   file_use_counter_svg_fill_pattern_definition.svg
+   file_use_counter_svg_fill_pattern.svg
+   file_use_counter_svg_fill_pattern_internal.svg
+   file_use_counter_svg_fill_pattern_data.svg
+   file_webaudioLoop.html
+diff --git a/dom/base/test/browser_timeout_throttling_with_audio_playback.js b/dom/base/test/browser_timeout_throttling_with_audio_playback.js
+--- a/dom/base/test/browser_timeout_throttling_with_audio_playback.js
++++ b/dom/base/test/browser_timeout_throttling_with_audio_playback.js
+@@ -1,36 +1,32 @@
+ // The tab closing code leaves an uncaught rejection. This test has been
+ // whitelisted until the issue is fixed.
+ if (!gMultiProcessBrowser) {
+   ChromeUtils.import("resource://testing-common/PromiseTestUtils.jsm", this);
+   PromiseTestUtils.expectUncaughtRejection(/is no longer, usable/);
+ }
+ 
+ const kBaseURI = "http://mochi.test:8888/browser/dom/base/test/empty.html";
+-const kPluginJS = "chrome://mochitests/content/browser/dom/base/test/plugin.js";
+ var testURLs = [
+   "http://mochi.test:8888/browser/dom/base/test/file_audioLoop.html",
+   "http://mochi.test:8888/browser/dom/base/test/file_audioLoopInIframe.html",
+-  "http://mochi.test:8888/browser/dom/base/test/file_pluginAudio.html",
+   "http://mochi.test:8888/browser/dom/base/test/file_webaudio_startstop.html",
+ ];
+ 
+ // We want to ensure that while audio is being played back, a background tab is
+ // treated the same as a foreground tab as far as timeout throttling is concerned.
+ // So we use a 100,000 second minimum timeout value for background tabs.  This
+ // means that in case the test fails, it will time out in practice, but just for
+ // sanity the test condition ensures that the observed timeout delay falls in
+ // this range.
+ const kMinTimeoutBackground = 100 * 1000 * 1000;
+ 
+ const kDelay = 10;
+ 
+-Services.scriptloader.loadSubScript(kPluginJS, this);
+-
+ async function runTest(url) {
+   let currentTab = gBrowser.selectedTab;
+   let newTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, kBaseURI);
+   let newBrowser = gBrowser.getBrowserForTab(newTab);
+ 
+   // Wait for the UI to indicate that audio is being played back.
+   let promise = BrowserTestUtils.waitForAttribute("soundplaying", newTab, "true");
+   newBrowser.loadURI(url);
+diff --git a/dom/base/test/file_pluginAudio.html b/dom/base/test/file_pluginAudio.html
+deleted file mode 100644
+--- a/dom/base/test/file_pluginAudio.html
++++ /dev/null
+@@ -1,21 +0,0 @@
+-<!DOCTYPE html>
+-<embed type="application/x-test" width="200" height="200"></embed>
+-<script>
+-var plugin = document.querySelector("embed");
+-onload = function() {
+-  plugin.startAudioPlayback();
+-};
+-function stopAudio() {
+-  plugin.stopAudioPlayback();
+-}
+-function pluginMuted() {
+-  return plugin.audioMuted();
+-}
+-function toggleMuteState(muted) {
+-  var Ci = SpecialPowers.Ci;
+-  var utils = SpecialPowers.wrap(window).top
+-                           .QueryInterface(Ci.nsIInterfaceRequestor)
+-                           .getInterface(Ci.nsIDOMWindowUtils);
+-  utils.audioMuted = muted;
+-}
+-</script>
+diff --git a/dom/base/test/mochitest.ini b/dom/base/test/mochitest.ini
+--- a/dom/base/test/mochitest.ini
++++ b/dom/base/test/mochitest.ini
+@@ -206,17 +206,16 @@ support-files =
+   w3element_traversal.svg
+   wholeTexty-helper.xml
+   referrerHelper.js
+   img_referrer_testserver.sjs
+   file_audioLoop.html
+   file_webaudioLoop.html
+   file_webaudioLoop2.html
+   file_webaudio_startstop.html
+-  file_pluginAudio.html
+   file_pluginAudioNonAutoStart.html
+   noaudio.webm
+   referrer_helper.js
+   referrer_testserver.sjs
+   script_postmessages_fileList.js
+   iframe_postMessages.html
+   test_anonymousContent_style_csp.html^headers^
+   file_explicit_user_agent.sjs

+ 8 - 443
mozilla-release/patches/1682030-02-89a1.patch

@@ -3,7 +3,7 @@
 # Date 1617737290 0
 #      Tue Apr 06 19:28:10 2021 +0000
 # Node ID 080aa7b074c3962432415d0ea195ca9ca3135988
-# Parent  c223b7401af94495ecb246ee5cafc34cbb2bb7c0
+# Parent  0e14561c0e4342909beee6c9983aba83dccd24bf
 Bug 1682030 - Remove NPAPI from dom/plugins tests.  r=jmathies
 
 Removes NPAPI plugin tests in dom/plugins, as well as the TestPlugin, as part of removing all of NPAPI plugin support.  A small handful of tests that are still relevant remain in that directory.
@@ -1161,7 +1161,7 @@ deleted file mode 100644
 diff --git a/dom/plugins/test/mochitest/mochitest.ini b/dom/plugins/test/mochitest/mochitest.ini
 --- a/dom/plugins/test/mochitest/mochitest.ini
 +++ b/dom/plugins/test/mochitest/mochitest.ini
-@@ -1,44 +1,10 @@
+@@ -1,43 +1,9 @@
  [DEFAULT]
  prefs =
    plugin.load_flash_only=false
@@ -1179,7 +1179,7 @@ diff --git a/dom/plugins/test/mochitest/mochitest.ini b/dom/plugins/test/mochite
 -  loremipsum_nocache.txt
 -  loremipsum_nocache.txt^headers^
    mixed_case_mime.sjs
-   neverending.sjs
+-  neverending.sjs
 -  npruntime_identifiers_subpage.html
 -  plugin-stream-referer.sjs
 -  plugin_window.html
@@ -1205,7 +1205,6 @@ diff --git a/dom/plugins/test/mochitest/mochitest.ini b/dom/plugins/test/mochite
 -skip-if = (toolkit != "cocoa") || (os != "win")
 -[test_refresh_navigator_plugins.html]
 -skip-if = e10s # Bug 1090576
--[test_twostreams.html]
 diff --git a/dom/plugins/test/mochitest/neverending.sjs b/dom/plugins/test/mochitest/neverending.sjs
 deleted file mode 100644
 --- a/dom/plugins/test/mochitest/neverending.sjs
@@ -2021,65 +2020,6 @@ deleted file mode 100644
 -    </script>
 -  </body>
 -</html>
-diff --git a/dom/plugins/test/mochitest/test_twostreams.html b/dom/plugins/test/mochitest/test_twostreams.html
-deleted file mode 100644
---- a/dom/plugins/test/mochitest/test_twostreams.html
-+++ /dev/null
-@@ -1,54 +0,0 @@
--<html>
--<head>
--  <title>Dual NPAPI NP_ASFILEONLY NPStream Test</title>
--  <script type="text/javascript" 
--          src="/tests/SimpleTest/SimpleTest.js"></script>
--  <script type="text/javascript" src="plugin-utils.js"></script>
--  <link rel="stylesheet" type="text/css" 
--        href="/tests/SimpleTest/test.css" />
--</head>
--<body>
--  <p id="display"></p>
--
--  <script type="text/javascript">
--  SimpleTest.expectAssertions(0, 2);
--
--  SimpleTest.waitForExplicitFinish();
--  setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
--
--  var framesToLoad = 2;
--  function frameLoaded(id) {
--    var frame = document.getElementById('testframe' + id);
--    // We have to use SpecialPowers because nptest.cpp prepends
--    // data: whichs makes the frame cross origin with the including page.
--    var wrappedDoc = SpecialPowers.wrap(frame).contentDocument;
--
--    if (!wrappedDoc.body.innerHTML.length)
--      return;
--
--    --framesToLoad;
--    if (0 == framesToLoad) {
--      var frame1 = document.getElementById('testframe1');
--      var frame2 = document.getElementById('testframe2');
--      var wrappedDocFrame1 = SpecialPowers.wrap(frame1).contentDocument;
--      var wrappedDocFrame2 = SpecialPowers.wrap(frame2).contentDocument;
--
--      is(wrappedDocFrame1.body.innerHTML, wrappedDocFrame2.body.innerHTML,
--         "Frame contents should match");
--      SimpleTest.finish();
--    }
--  }
--  </script>
--
--  <iframe id="testframe1" name="testframe1" onload="frameLoaded(1)"></iframe>
--  <iframe id="testframe2" name="testframe2" onload="frameLoaded(2)"></iframe>
--
--  <embed src="loremipsum_nocache.txt" streammode="asfileonly"
--         frame="testframe1"
--         id="embedtest" style="width: 400px; height: 100px;"
--         type="application/x-test"></embed>
--  <embed src="loremipsum_nocache.txt" streammode="asfileonly"
--	 frame="testframe2"
--	 id="embedtest2" style="width: 400px; height: 100px;"
--	 type="application/x-test"></embed>
--
 diff --git a/dom/plugins/test/moz.build b/dom/plugins/test/moz.build
 --- a/dom/plugins/test/moz.build
 +++ b/dom/plugins/test/moz.build
@@ -3318,7 +3258,7 @@ diff --git a/dom/plugins/test/testplugin/README b/dom/plugins/test/testplugin/RE
 deleted file mode 100644
 --- a/dom/plugins/test/testplugin/README
 +++ /dev/null
-@@ -1,441 +0,0 @@
+@@ -1,424 +0,0 @@
 -= Instructions for using the test plugin =
 -
 -== MIME type ==
@@ -3623,10 +3563,6 @@ deleted file mode 100644
 -
 -The attributes which control stream tests are:
 -
--"streammode": one of "normal", "asfile", "asfileonly", "seek". Sets the
--  stream mode to the specified mode in any call to NPP_NewStream.
--  Defaults to "asfileonly".
--
 -"streamchunksize": the number of bytes the plugin reports it can accept
 -  in calls to NPP_WriteReady.  Defaults to 1,024.
 -
@@ -3654,15 +3590,6 @@ deleted file mode 100644
 -  data: url, and sent back to the browser in another stream via a call to
 -  NPN_GetURL, whereupon it should be displayed in the specified frame.
 -
--"range": one or more byte ranges, in the format "offset,length;offset,length".
--  Only valid when "streammode" = "seek".  When "range" is present, the plugin
--  will request the specified byte ranges from the stream via a call to
--  NPN_RequestRead, which it makes after the browser makes its final call to
--  NPP_Write.  The plugin verifies that the browser makes additional calls
--  to NPP_Write according to the requested byte ranges, and that the data
--  received is correct.  Any errors will appear in the test "frame", if
--  specified.
--
 -"posturl": a url.  After the plugin receives a stream, and NPP_DestroyStream
 -  is called, if "posturl" is specified, the plugin will post the contents
 -  of the stream to the specified url via NPN_PostURL.  See "postmode" for
@@ -3689,10 +3616,6 @@ deleted file mode 100644
 -"failurecode": one of the NPError constants.  Used to specify the error
 -  that will be returned by the "functiontofail".
 -
--If the plugin is instantiated as a full-page plugin, the following defaults
--are used:
--  streammode="seek" frame="testframe" range="100,100"
--
 -* streamTest(url, doPost, postData, writeCallback, notifyCallback, redirectCallback, allowRedirects, postFile = false)
 -This will test how NPN_GetURLNotify and NPN_PostURLNotify behave when they are
 -called with arbitrary (malformed) URLs. The function will return `true` if
@@ -3912,7 +3835,7 @@ diff --git a/dom/plugins/test/testplugin/nptest.cpp b/dom/plugins/test/testplugi
 deleted file mode 100644
 --- a/dom/plugins/test/testplugin/nptest.cpp
 +++ /dev/null
-@@ -1,3898 +0,0 @@
+@@ -1,3551 +0,0 @@
 -/* ***** BEGIN LICENSE BLOCK *****
 - *
 - * Copyright (c) 2008, Mozilla Corporation
@@ -4009,9 +3932,6 @@ deleted file mode 100644
 -static NPNetscapeFuncs* sBrowserFuncs = nullptr;
 -static NPClass sNPClass;
 -
--void
--asyncCallback(void* cookie);
--
 -//
 -// identifiers
 -//
@@ -4056,8 +3976,6 @@ deleted file mode 100644
 -static bool getJavaCodebase(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 -static bool checkObjectValue(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 -static bool enableFPExceptions(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
--static bool asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
--static bool checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 -static bool hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 -static bool stallPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
 -static bool getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
@@ -4130,8 +4048,6 @@ deleted file mode 100644
 -  "getJavaCodebase",
 -  "checkObjectValue",
 -  "enableFPExceptions",
--  "asyncCallbackTest",
--  "checkGCRace",
 -  "hang",
 -  "stall",
 -  "getClipboardText",
@@ -4205,8 +4121,6 @@ deleted file mode 100644
 -  getJavaCodebase,
 -  checkObjectValue,
 -  enableFPExceptions,
--  asyncCallbackTest,
--  checkGCRace,
 -  hangPlugin,
 -  stallPlugin,
 -  getClipboardText,
@@ -4350,27 +4264,6 @@ deleted file mode 100644
 -  sIdentifiersInitialized = false;
 -}
 -
--static void addRange(InstanceData* instanceData, const char* range)
--{
--  /*
--  increased rangestr size from 16 to 17, the 17byte is only for
--  null terminated value, maybe for actual capacity it needs 16 bytes
--  */
--  char rangestr[17];
--  memset(rangestr, 0, sizeof(rangestr));
--  strncpy(rangestr, range, sizeof(rangestr) - sizeof(char));
--  const char* str1 = strtok(rangestr, ",");
--  const char* str2 = str1 ? strtok(nullptr, ",") : nullptr;
--  if (str1 && str2) {
--    TestRange* byterange = new TestRange;
--    byterange->offset = atoi(str1);
--    byterange->length = atoi(str2);
--    byterange->waiting = true;
--    byterange->next = instanceData->testrange;
--    instanceData->testrange = byterange;
--  }
--}
--
 -static void sendBufferToFrame(NPP instance)
 -{
 -  InstanceData* instanceData = (InstanceData*)(instance->pdata);
@@ -4378,11 +4271,6 @@ deleted file mode 100644
 -  if (!instanceData->npnNewStream) outbuf = "data:text/html,";
 -  const char* buf = reinterpret_cast<char *>(instanceData->streamBuf);
 -  int32_t bufsize = instanceData->streamBufSize;
--  if (instanceData->streamMode == NP_ASFILE ||
--      instanceData->streamMode == NP_ASFILEONLY) {
--    buf = reinterpret_cast<char *>(instanceData->fileBuf);
--    bufsize = instanceData->fileBufSize;
--  }
 -  if (instanceData->err.str().length() > 0) {
 -    outbuf.append(instanceData->err.str());
 -  }
@@ -4596,7 +4484,6 @@ deleted file mode 100644
 -  pFuncs->setwindow = NPP_SetWindow;
 -  pFuncs->newstream = NPP_NewStream;
 -  pFuncs->destroystream = NPP_DestroyStream;
--  pFuncs->asfile = NPP_StreamAsFile;
 -  pFuncs->writeready = NPP_WriteReady;
 -  pFuncs->write = NPP_Write;
 -  pFuncs->print = NPP_Print;
@@ -4702,7 +4589,6 @@ deleted file mode 100644
 -  // set up our our instance data
 -  InstanceData* instanceData = new InstanceData;
 -  instanceData->npp = instance;
--  instanceData->streamMode = NP_ASFILEONLY;
 -  instanceData->testFunction = FUNCTION_NONE;
 -  instanceData->functionToFail = FUNCTION_NONE;
 -  instanceData->failureCode = 0;
@@ -4710,12 +4596,9 @@ deleted file mode 100644
 -  instanceData->streamChunkSize = 1024;
 -  instanceData->streamBuf = nullptr;
 -  instanceData->streamBufSize = 0;
--  instanceData->fileBuf = nullptr;
--  instanceData->fileBufSize = 0;
 -  instanceData->throwOnNextInvoke = false;
 -  instanceData->runScriptOnPaint = false;
 -  instanceData->dontTouchElement = false;
--  instanceData->testrange = nullptr;
 -  instanceData->hasWidget = false;
 -  instanceData->npnNewStream = false;
 -  instanceData->invalidateDuringPaint = false;
@@ -4780,21 +4663,6 @@ deleted file mode 100644
 -        requestAsyncDrawing = AD_DXGI;
 -      }
 -    }
--    if (strcmp(argn[i], "streammode") == 0) {
--      if (strcmp(argv[i], "normal") == 0) {
--        instanceData->streamMode = NP_NORMAL;
--      }
--      else if ((strcmp(argv[i], "asfile") == 0) &&
--                strlen(argv[i]) == strlen("asfile")) {
--        instanceData->streamMode = NP_ASFILE;
--      }
--      else if (strcmp(argv[i], "asfileonly") == 0) {
--        instanceData->streamMode = NP_ASFILEONLY;
--      }
--      else if (strcmp(argv[i], "seek") == 0) {
--        instanceData->streamMode = NP_SEEK;
--      }
--    }
 -    if (strcmp(argn[i], "streamchunksize") == 0) {
 -      instanceData->streamChunkSize = atoi(argv[i]);
 -    }
@@ -4827,20 +4695,6 @@ deleted file mode 100644
 -    if (strcmp(argn[i], "frame") == 0) {
 -      instanceData->frame = argv[i];
 -    }
--    if (strcmp(argn[i], "range") == 0) {
--      string range = argv[i];
--      size_t semicolon = range.find(';');
--      while (semicolon != string::npos) {
--        addRange(instanceData, range.substr(0, semicolon).c_str());
--        if (semicolon == range.length()) {
--          range = "";
--          break;
--        }
--        range = range.substr(semicolon + 1);
--        semicolon = range.find(';');
--      }
--      if (range.length()) addRange(instanceData, range.c_str());
--    }
 -    if (strcmp(argn[i], "newstream") == 0 &&
 -        strcmp(argv[i], "true") == 0) {
 -      instanceData->npnNewStream = true;
@@ -4885,15 +4739,6 @@ deleted file mode 100644
 -    if (strcmp(argn[i], "salign") == 0) {
 -      alreadyHasSalign = true;
 -    }
--
--    // We don't support NP_FULL any more, but name="plugin" is an indication
--    // that we're a full-page plugin. We use default seek parameters for
--    // test_fullpage.html
--    if (strcmp(argn[i], "name") == 0 && strcmp(argv[i], "plugin") == 0) {
--      instanceData->streamMode = NP_SEEK;
--      instanceData->frame = "testframe";
--      addRange(instanceData, "100,100");
--    }
 -  }
 -
 -  if (!browserSupportsWindowless || !pluginSupportsWindowlessMode()) {
@@ -5020,17 +4865,6 @@ deleted file mode 100644
 -  if (instanceData->streamBuf) {
 -    free(instanceData->streamBuf);
 -  }
--  if (instanceData->fileBuf) {
--    free(instanceData->fileBuf);
--  }
--
--  TestRange* currentrange = instanceData->testrange;
--  TestRange* nextrange;
--  while (currentrange != nullptr) {
--    nextrange = reinterpret_cast<TestRange*>(currentrange->next);
--    delete currentrange;
--    currentrange = nextrange;
--  }
 -
 -  if (instanceData->frontBuffer) {
 -    NPN_SetCurrentAsyncSurface(instance, nullptr, nullptr);
@@ -5145,7 +4979,7 @@ deleted file mode 100644
 -    *stype = NP_NORMAL;
 -  }
 -  else {
--    *stype = instanceData->streamMode;
+-    *stype = NP_NORMAL;
 -
 -    if (instanceData->streamBufSize) {
 -      free(instanceData->streamBuf);
@@ -5193,26 +5027,6 @@ deleted file mode 100644
 -    return NPERR_NO_ERROR;
 -  }
 -
--  if (instanceData->streamMode == NP_ASFILE &&
--      instanceData->functionToFail == FUNCTION_NONE) {
--    if (!instanceData->streamBuf) {
--      instanceData->err <<
--        "Error: no data written with NPP_Write";
--      return NPERR_GENERIC_ERROR;
--    }
--
--    if (!instanceData->fileBuf) {
--      instanceData->err <<
--        "Error: no data written with NPP_StreamAsFile";
--      return NPERR_GENERIC_ERROR;
--    }
--
--    if (strcmp(reinterpret_cast<char *>(instanceData->fileBuf),
--               reinterpret_cast<char *>(instanceData->streamBuf))) {
--      instanceData->err <<
--        "Error: data passed to NPP_Write and NPP_StreamAsFile differed";
--    }
--  }
 -  if (instanceData->frame.length() > 0 &&
 -      instanceData->testFunction != FUNCTION_NPP_GETURLNOTIFY &&
 -      instanceData->testFunction != FUNCTION_NPP_POSTURL) {
@@ -5294,40 +5108,16 @@ deleted file mode 100644
 -    nd->size = newsize;
 -    return len;
 -  }
--  if (instanceData->streamMode == NP_SEEK &&
--      stream->end != 0 &&
--      stream->end == ((uint32_t)instanceData->streamBufSize + len)) {
--    // If the complete stream has been written, and we're doing a seek test,
--    // then call NPN_RequestRead.
--    // prevent recursion
--    instanceData->streamMode = NP_NORMAL;
--
--    if (instanceData->testrange != nullptr) {
--      NPError err = NPN_RequestRead(stream, instanceData->testrange);
--      if (err != NPERR_NO_ERROR) {
--        instanceData->err << "NPN_RequestRead returned error %d" << err;
--      }
--      printf("called NPN_RequestRead, return %d\n", err);
--    }
--  }
 -
 -  char* streamBuf = reinterpret_cast<char *>(instanceData->streamBuf);
 -  if (offset + len <= instanceData->streamBufSize) {
 -    if (memcmp(buffer, streamBuf + offset, len)) {
 -      instanceData->err <<
--          "Error: data written from NPN_RequestRead doesn't match";
+-          "Error: data written doesn't match";
 -    }
 -    else {
 -      printf("data matches!\n");
 -    }
--    TestRange* range = instanceData->testrange;
--    while(range != nullptr) {
--      if (offset == range->offset &&
--        (uint32_t)len == range->length) {
--        range->waiting = false;
--      }
--      range = reinterpret_cast<TestRange*>(range->next);
--    }
 -  }
 -  else {
 -    if (instanceData->streamBufSize == 0) {
@@ -5348,43 +5138,6 @@ deleted file mode 100644
 -}
 -
 -void
--NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
--{
--  size_t size;
--
--  InstanceData* instanceData = (InstanceData*)(instance->pdata);
--
--  if (instanceData->functionToFail == FUNCTION_NPP_NEWSTREAM ||
--      instanceData->functionToFail == FUNCTION_NPP_WRITE) {
--    instanceData->err << "NPP_StreamAsFile called";
--  }
--
--  if (!fname)
--    return;
--
--  FILE *file = fopen(fname, "rb");
--  if (file) {
--    fseek(file, 0, SEEK_END);
--    size = ftell(file);
--    instanceData->fileBuf = malloc((int32_t)size + 1);
--    char* buf = reinterpret_cast<char *>(instanceData->fileBuf);
--    fseek(file, 0, SEEK_SET);
--    size_t sizeRead = fread(instanceData->fileBuf, 1, size, file);
--    if (sizeRead != size) {
--      printf("Unable to read data from file\n");
--      instanceData->err << "Unable to read data from file " << fname;
--    }
--    fclose(file);
--    buf[size] = '\0';
--    instanceData->fileBufSize = (int32_t)size;
--  }
--  else {
--    printf("Unable to open file\n");
--    instanceData->err << "Unable to open file " << fname;
--  }
--}
--
--void
 -NPP_Print(NPP instance, NPPrint* platformPrint)
 -{
 -}
@@ -5748,12 +5501,6 @@ deleted file mode 100644
 -}
 -
 -NPError
--NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
--{
--  return sBrowserFuncs->requestread(stream, rangeList);
--}
--
--NPError
 -NPN_PostURLNotify(NPP instance, const char* url,
 -                  const char* target, uint32_t len,
 -                  const char* buf, NPBool file, void* notifyData)
@@ -5821,12 +5568,6 @@ deleted file mode 100644
 -}
 -
 -void
--NPN_PluginThreadAsyncCall(NPP plugin, void (*func)(void*), void* userdata)
--{
--  return sBrowserFuncs->pluginthreadasynccall(plugin, func, userdata);
--}
--
--void
 -NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow)
 -{
 -  return sBrowserFuncs->urlredirectresponse(instance, notifyData, allow);
@@ -6929,171 +6670,6 @@ deleted file mode 100644
 -  return id->timerID[event.timerIdSchedule] != 0;
 -}
 -
--#ifdef XP_WIN
--void
--ThreadProc(void* cookie)
--#else
--void*
--ThreadProc(void* cookie)
--#endif
--{
--  NPObject* npobj = (NPObject*)cookie;
--  NPP npp = static_cast<TestNPObject*>(npobj)->npp;
--  InstanceData* id = static_cast<InstanceData*>(npp->pdata);
--  id->asyncTestPhase = 1;
--  NPN_PluginThreadAsyncCall(npp, asyncCallback, (void*)npobj);
--#ifndef XP_WIN
--  return nullptr;
--#endif
--}
--
--void
--asyncCallback(void* cookie)
--{
--  NPObject* npobj = (NPObject*)cookie;
--  NPP npp = static_cast<TestNPObject*>(npobj)->npp;
--  InstanceData* id = static_cast<InstanceData*>(npp->pdata);
--
--  switch (id->asyncTestPhase) {
--    // async callback triggered from same thread
--    case 0:
--#ifdef XP_WIN
--      if (_beginthread(ThreadProc, 0, (void*)npobj) == -1)
--        id->asyncCallbackResult = false;
--#else
--      pthread_t tid;
--      if (pthread_create(&tid, 0, ThreadProc, (void*)npobj))
--        id->asyncCallbackResult = false;
--#endif
--      break;
--
--    // async callback triggered from different thread
--    default:
--      NPObject* windowObject;
--      NPN_GetValue(npp, NPNVWindowNPObject, &windowObject);
--      if (!windowObject)
--        return;
--      NPVariant arg, rval;
--      BOOLEAN_TO_NPVARIANT(id->asyncCallbackResult, arg);
--      NPN_Invoke(npp, windowObject, NPN_GetStringIdentifier(id->asyncTestScriptCallback.c_str()), &arg, 1, &rval);
--      NPN_ReleaseVariantValue(&arg);
--      NPN_ReleaseObject(windowObject);
--      break;
--  }
--}
--
--static bool
--asyncCallbackTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
--{
--  NPP npp = static_cast<TestNPObject*>(npobj)->npp;
--  InstanceData* id = static_cast<InstanceData*>(npp->pdata);
--
--  if (argCount < 1 || !NPVARIANT_IS_STRING(args[0]))
--    return false;
--  const NPString* argstr = &NPVARIANT_TO_STRING(args[0]);
--  id->asyncTestScriptCallback = argstr->UTF8Characters;
--
--  id->asyncTestPhase = 0;
--  id->asyncCallbackResult = true;
--  NPN_PluginThreadAsyncCall(npp, asyncCallback, (void*)npobj);
--
--  return true;
--}
--
--static bool
--GCRaceInvoke(NPObject*, NPIdentifier, const NPVariant*, uint32_t, NPVariant*)
--{
--  return false;
--}
--
--static bool
--GCRaceInvokeDefault(NPObject* o, const NPVariant* args, uint32_t argCount,
--		    NPVariant* result)
--{
--  if (1 != argCount || !NPVARIANT_IS_INT32(args[0]) ||
--      35 != NPVARIANT_TO_INT32(args[0]))
--    return false;
--
--  return true;
--}
--
--static const NPClass kGCRaceClass = {
--  NP_CLASS_STRUCT_VERSION,
--  nullptr,
--  nullptr,
--  nullptr,
--  nullptr,
--  GCRaceInvoke,
--  GCRaceInvokeDefault,
--  nullptr,
--  nullptr,
--  nullptr,
--  nullptr,
--  nullptr,
--  nullptr
--};
--
--struct GCRaceData
--{
--  GCRaceData(NPP npp, NPObject* callback, NPObject* localFunc)
--    : npp_(npp)
--    , callback_(callback)
--    , localFunc_(localFunc)
--  {
--    NPN_RetainObject(callback_);
--    NPN_RetainObject(localFunc_);
--  }
--
--  ~GCRaceData()
--  {
--    NPN_ReleaseObject(callback_);
--    NPN_ReleaseObject(localFunc_);
--  }
--
--  NPP npp_;
--  NPObject* callback_;
--  NPObject* localFunc_;
--};
--
--static void
--FinishGCRace(void* closure)
--{
--  GCRaceData* rd = static_cast<GCRaceData*>(closure);
--
--  XPSleep(5);
--
--  NPVariant arg;
--  OBJECT_TO_NPVARIANT(rd->localFunc_, arg);
--
--  NPVariant result;
--  bool ok = NPN_InvokeDefault(rd->npp_, rd->callback_, &arg, 1, &result);
--  if (!ok)
--    return;
--
--  NPN_ReleaseVariantValue(&result);
--  delete rd;
--}
--
--bool
--checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCount,
--	    NPVariant* result)
--{
--  if (1 != argCount || !NPVARIANT_IS_OBJECT(args[0]))
--    return false;
--
--  NPP npp = static_cast<TestNPObject*>(npobj)->npp;
--
--  NPObject* localFunc =
--    NPN_CreateObject(npp, const_cast<NPClass*>(&kGCRaceClass));
--
--  GCRaceData* rd =
--    new GCRaceData(npp, NPVARIANT_TO_OBJECT(args[0]), localFunc);
--  NPN_PluginThreadAsyncCall(npp, FinishGCRace, rd);
--
--  OBJECT_TO_NPVARIANT(localFunc, *result);
--  return true;
--}
--
 -bool
 -hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount,
 -           NPVariant* result)
@@ -7827,7 +7403,7 @@ diff --git a/dom/plugins/test/testplugin/nptest.h b/dom/plugins/test/testplugin/
 deleted file mode 100644
 --- a/dom/plugins/test/testplugin/nptest.h
 +++ /dev/null
-@@ -1,171 +0,0 @@
+@@ -1,160 +0,0 @@
 -/* ***** BEGIN LICENSE BLOCK *****
 - *
 - * Copyright (c) 2008, Mozilla Corporation
@@ -7921,10 +7497,6 @@ deleted file mode 100644
 -
 -typedef struct _PlatformData PlatformData;
 -
--typedef struct TestRange : NPByteRange {
--  bool waiting;
--} TestRange;
--
 -typedef struct InstanceData {
 -  NPP npp;
 -  NPWindow window;
@@ -7939,7 +7511,6 @@ deleted file mode 100644
 -  bool dontTouchElement;
 -  uint32_t timerID[2];
 -  bool timerTestResult;
--  bool asyncCallbackResult;
 -  bool invalidateDuringPaint;
 -  bool slowPaint;
 -  bool playingAudio;
@@ -7952,7 +7523,6 @@ deleted file mode 100644
 -  int32_t paintCount;
 -  int32_t writeCount;
 -  int32_t writeReadyCount;
--  int32_t asyncTestPhase;
 -  TestFunction testFunction;
 -  TestFunction functionToFail;
 -  NPError failureCode;
@@ -7961,15 +7531,10 @@ deleted file mode 100644
 -  std::string testUrl;
 -  std::string frame;
 -  std::string timerTestScriptCallback;
--  std::string asyncTestScriptCallback;
 -  std::ostringstream err;
--  uint16_t streamMode;
 -  int32_t streamChunkSize;
 -  int32_t streamBufSize;
--  int32_t fileBufSize;
--  TestRange* testrange;
 -  void* streamBuf;
--  void* fileBuf;
 -  bool crashOnDestroy;
 -  bool cleanupWidget;
 -  ActivationState topLevelWindowActivationState;

+ 18 - 18
mozilla-release/patches/1682030-03-89a1.patch

@@ -3,7 +3,7 @@
 # Date 1617737290 0
 #      Tue Apr 06 19:28:10 2021 +0000
 # Node ID 3739f10fd7443069fb3bbb6779cb288eedbe4c18
-# Parent  9808cc6c1688f1b7bbc60f569f1436dae496ab87
+# Parent  0af7ce68b5ffac2702db8d70a48280bda111fb27
 Bug 1682030 - Remove PPluginSurface.   r=jmathies,bas
 
 Removes the PPluginSurface actor used for windowed plugins, as part of removing all of NPAPI plugin support.  SharedDIB is then unused and is also removed.
@@ -155,7 +155,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginIns
  static const TCHAR kPluginIgnoreSubclassProperty[] = TEXT("PluginIgnoreSubclassProperty");
  
  #elif defined(XP_MACOSX)
-@@ -150,20 +146,16 @@ PluginInstanceChild::PluginInstanceChild
+@@ -149,20 +145,16 @@ PluginInstanceChild::PluginInstanceChild
      , mEventModel(NPEventModelCarbon)
  #endif
      , mShColorSpace(nullptr)
@@ -176,7 +176,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginIns
      , mHasPainted(false)
      , mSurfaceDifferenceRect(0,0,0,0)
      , mDestroyed(false)
-@@ -2830,33 +2822,16 @@ PluginInstanceChild::CreateOptSurface(vo
+@@ -2829,33 +2821,16 @@ PluginInstanceChild::CreateOptSurface(vo
          }
          mCurrentSurface =
              gfxXlibSurface::Create(screen, xfmt,
@@ -210,7 +210,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginIns
  
  bool
  PluginInstanceChild::MaybeCreatePlatformHelperSurface(void)
-@@ -3036,31 +3011,16 @@ PluginInstanceChild::UpdateWindowAttribu
+@@ -3035,31 +3010,16 @@ PluginInstanceChild::UpdateWindowAttribu
              GetColormapAndVisual(&colormap, &visual);
          if (visual != mWsInfo.visual || colormap != mWsInfo.colormap) {
              mWsInfo.visual = visual;
@@ -242,7 +242,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginIns
  #ifndef XP_MACOSX
      // Adjusting the window isn't needed for OSX
  #ifndef XP_WIN
-@@ -3145,38 +3105,16 @@ PluginInstanceChild::PaintRectToPlatform
+@@ -3144,38 +3104,16 @@ PluginInstanceChild::PaintRectToPlatform
          exposeEvent.count = 0;
          // information not set:
          exposeEvent.serial = 0;
@@ -281,7 +281,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginIns
  void
  PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect,
                                          gfxASurface* aSurface,
-@@ -3279,59 +3217,31 @@ PluginInstanceChild::PaintRectWithAlphaE
+@@ -3278,59 +3216,31 @@ PluginInstanceChild::PaintRectWithAlphaE
      gfxPoint deviceOffset = -targetRect.TopLeft();
  
      // We always use a temporary "white image"
@@ -341,7 +341,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginIns
      if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage)) {
          return;
      }
-@@ -3538,32 +3448,16 @@ PluginInstanceChild::ShowPluginFrame()
+@@ -3537,32 +3447,16 @@ PluginInstanceChild::ShowPluginFrame()
      if (mCurrentSurface->GetType() == gfxSurfaceType::Xlib) {
          gfxXlibSurface *xsurf = static_cast<gfxXlibSurface*>(mCurrentSurface.get());
          currSurf = SurfaceDescriptorX11(xsurf);
@@ -374,7 +374,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginIns
      }
  
      // Unused, except to possibly return a shmem to us
-@@ -3579,25 +3473,20 @@ PluginInstanceChild::ShowPluginFrame()
+@@ -3578,25 +3472,20 @@ PluginInstanceChild::ShowPluginFrame()
  }
  
  bool
@@ -400,9 +400,9 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginIns
  
      if (mSurfaceDifferenceRect.IsEmpty())
          return true;
-@@ -3842,29 +3731,19 @@ PluginInstanceChild::PostChildAsyncCall(
-     }
-     ProcessChild::message_loop()->PostTask(task.forget());
+@@ -3822,29 +3711,19 @@ PluginInstanceChild::UnscheduleTimer(uin
+ 
+     mTimers.RemoveElement(id, ChildTimer::IDComparator());
  }
  
  void
@@ -430,7 +430,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginIns
      // Dropping obsolete surface
      if (mDoubleBufferCARenderer.HasFrontSurface() &&
          mDoubleBufferCARenderer.HasBackSurface() &&
-@@ -3890,22 +3769,16 @@ void
+@@ -3870,22 +3749,16 @@ void
  PluginInstanceChild::ClearCurrentSurface()
  {
      mCurrentSurface = nullptr;
@@ -453,7 +453,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginIns
  {
      if (mBackSurface) {
          // Get last surface back, and drop it
-@@ -3916,27 +3789,16 @@ PluginInstanceChild::ClearAllSurfaces()
+@@ -3896,27 +3769,16 @@ PluginInstanceChild::ClearAllSurfaces()
  
      if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface))
          DeallocShmem(static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem());
@@ -481,7 +481,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginIns
          SendShow(r, temp, &temp);
      }
  
-@@ -4081,16 +3943,10 @@ PluginInstanceChild::AnswerNPP_Destroy(N
+@@ -4054,16 +3916,10 @@ PluginInstanceChild::AnswerNPP_Destroy(N
      Destroy();
  
      return IPC_OK();
@@ -525,7 +525,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.h b/dom/plugins/ipc/PluginInsta
  
  #include "npfunctions.h"
  #include "nsAutoPtr.h"
-@@ -104,27 +101,16 @@ protected:
+@@ -103,27 +100,16 @@ protected:
      RecvAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
                         const NPRemoteWindow& aWindow) override;
  
@@ -553,7 +553,7 @@ diff --git a/dom/plugins/ipc/PluginInstanceChild.h b/dom/plugins/ipc/PluginInsta
            return IPC_FAIL_NO_REASON(this);
          }
          return IPC_OK();
-@@ -578,22 +564,16 @@ private:
+@@ -569,22 +555,16 @@ private:
  
      // (Not to be confused with mBackSurface).  This is a recent copy
      // of the opaque pixels under our object frame, if
@@ -841,7 +841,7 @@ deleted file mode 100644
 diff --git a/dom/plugins/ipc/moz.build b/dom/plugins/ipc/moz.build
 --- a/dom/plugins/ipc/moz.build
 +++ b/dom/plugins/ipc/moz.build
-@@ -34,22 +34,18 @@ EXPORTS.mozilla.plugins += [
+@@ -33,22 +33,18 @@ EXPORTS.mozilla.plugins += [
      'PluginScriptableObjectUtils-inl.h',
      'PluginScriptableObjectUtils.h',
      'PluginUtilsOSX.h',
@@ -864,7 +864,7 @@ diff --git a/dom/plugins/ipc/moz.build b/dom/plugins/ipc/moz.build
      LOCAL_INCLUDES += [
          '/widget',
          'hangui',
-@@ -103,17 +99,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
+@@ -101,17 +97,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
  
  IPDL_SOURCES += [
      'PBrowserStream.ipdl',

+ 15 - 2
mozilla-release/patches/series

@@ -1781,8 +1781,6 @@ NOBUG-20190118-zlib-66a1.patch
 1602862-7811.patch
 1612116-7811.patch
 1707559-7811.patch
-1682030-02-89a1.patch
-1682030-03-89a1.patch
 739096-7only-90a1.patch
 1601904-90a1.patch
 1711044-2-version-mr-2538.patch
@@ -1922,3 +1920,18 @@ TOP-1746221-NSS3533-9141.patch
 TOP-9999999-fixgithubpolyfill-25312.patch
 TOP-1398895-2a-57a1.patch
 TOP-NOBUG-skiptests-25312.patch
+1352573-2-58a1.patch
+1352567-1-58a1.patch
+1352567-2-58a1.patch
+1352567-3-58a1.patch
+1405312-58a1.patch
+1413845-58a1.patch
+1528586-67a1.patch
+1580282-PARTIAL-71a1.patch
+1682030-02-89a1.patch
+1682030-03-89a1.patch
+1545123-1-SIMPLIFIED-72a1.patch
+1545123-1-72a1.patch
+1545123-2-72a1.patch
+1675349-06-PARTIAL-85a1.patch
+1675349-07-85a1.patch

+ 31 - 0
readme-first.txt

@@ -0,0 +1,31 @@
+This is the patch queue repo for our SeaMonkey 2.53.xx prerelease base directory. It is used for building the next official beta or final version. The mercurial queues and patches in them are subject to change at any time because we are frequently porting back new stuff and now and then fix errors and omissions in the backported patches too.
+
+If you want to build a previously released final or beta 2.53.x release please check out the latest source from our gitlab repositories instead. Instructions for this can be found in the release directoy in the file https://archive.mozilla.org/pub/seamonkey/releases/2.53.<version>/README.txt (replace <version> with the desired version).
+
+The patches here are basically useless without checking out the base sources. We provide a copy of the base sources needed at foss.hepoapod.net. To check out the latest source compatible with the queues in here use the following commands:
+
+hg clone https://foss.heptapod.net/seamonkey/mozilla-release comm-253
+cd comm-253
+hg clone https://foss.heptapod.net/seamonkey/comm-release comm
+
+Afterwards you need to copy the patches in the comm-release/patches dir to .hg/patches in your comm directory. The mozilla-release/patches files go to the .hg/patches directory in your top source comm-253 directory.
+
+To apply them use hg qpush --all in both directories. You need the mercurial queues extension for this to work. You will not be able to build successfully without applying them first.
+
+The documentation for the extensions is located here: https://www.mercurial-scm.org/wiki/MqExtension
+
+While use is discouraged it is still the best and flexible way to apply and maintain a larger patch queue for stuff.
+
+The l10n-release directory contains patches which you can apply against a clone of https://hg.mozilla.org/releases/l10n/mozilla-release/<language>. These are only needed if you want to build a language specific version.
+
+If you want to help out with backporting and submit changes for inclusion please contact us at ircs://libera.chat/SeaMonkey . For new functionality and error fixes in SeaMonkey itself please file a bug in https://bugzilla.mozilla.org/ under product SeaMonkey, attach you patch and ask for review or feedback.
+
+Some Naming conventions:
+
+TOP- Patches which need to be applied at the end. This is usual stuff which is a stopgap solution only and will be replaced later.
+PPPPPPP- Private patches for the prerelease versions only.
+WIP- Work in progress patches for testing. Might have minor problems and will not be included in the official releases.
+
+Patches with a 9999999 in the name still need to be filed in bugzilla and will change then later using the correct bug number. If not they will not be included in an official release.
+
+If this all sounds messy then yes it is :) We would rather not backport and just use the current mozilla repositories but given how much was changed and how much functionality was removed we are still playing catch up there. Rest assured every change in the comm/suite directory whch applies will be put into the bleeding edge comm-central repo when reviewed.