Merge beta to m-r. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 19 Feb 2015 19:54:14 -0500
changeset 245420 a2ffa9047bf4
parent 245415 2f2abd6ffebb (current diff)
parent 245419 7d4016a05dd3 (diff)
child 245421 50543f1c582a
child 245423 59eefd8af5d7
child 245425 88c5342693e3
child 245427 784a4c059370
push id662
push userryanvm@gmail.com
push date2015-02-20 00:54 +0000
treeherdermozilla-release@a2ffa9047bf4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone36.0
Merge beta to m-r. a=merge
--- a/addon-sdk/source/lib/sdk/panel.js
+++ b/addon-sdk/source/lib/sdk/panel.js
@@ -292,16 +292,19 @@ let hides = filter(panelEvents, ({type})
 
 // Panel events emitted after content inside panel is ready. For different
 // panels ready may mean different state based on `contentScriptWhen` attribute.
 // Weather given event represents readyness is detected by `getAttachEventType`
 // helper function.
 let ready = filter(panelEvents, ({type, target}) =>
   getAttachEventType(modelFor(panelFor(target))) === type);
 
+// Panel event emitted when the contents of the panel has been loaded.
+let readyToShow = filter(panelEvents, ({type}) => type === "DOMContentLoaded");
+
 // Styles should be always added as soon as possible, and doesn't makes them
 // depends on `contentScriptWhen`
 let start = filter(panelEvents, ({type}) => type === "document-element-inserted");
 
 // Forward panel show / hide events to panel's own event listeners.
 on(shows, "data", ({target}) => {
   let panel = panelFor(target);
   if (modelFor(panel).ready)
@@ -314,16 +317,20 @@ on(hides, "data", ({target}) => {
     emit(panel, "hide");
 });
 
 on(ready, "data", ({target}) => {
   let panel = panelFor(target);
   let window = domPanel.getContentDocument(target).defaultView;
 
   workerFor(panel).attach(window);
+});
+
+on(readyToShow, "data", ({target}) => {
+  let panel = panelFor(target);
 
   if (!modelFor(panel).ready) {
     modelFor(panel).ready = true;
 
     if (viewFor(panel).state == "open")
       emit(panel, "show");
   }
 });
--- a/addon-sdk/source/test/test-panel.js
+++ b/addon-sdk/source/test/test-panel.js
@@ -1288,17 +1288,16 @@ exports["test panel addon global object"
   assert.pass("Received an event from the document");
 
   loader.unload();
 }
 
 exports["test panel load doesn't show"] = function*(assert) {
   let loader = Loader(module);
 
-  let showCount = 0;
   let panel = loader.require("sdk/panel").Panel({
     contentScript: "addEventListener('load', function(event) { self.postMessage('load'); });",
     contentScriptWhen: "start",
     contentURL: "data:text/html;charset=utf-8,",
   });
 
   let shown = defer();
   let messaged = defer();
@@ -1326,16 +1325,34 @@ exports["test panel load doesn't show"] 
   });
 
   panel.contentURL = "data:text/html;charset=utf-8,<html/>";
 
   yield messaged.promise;
   loader.unload();
 }
 
+exports["test Panel without contentURL and contentScriptWhen=start should show"] = function*(assert) {
+  let loader = Loader(module);
+
+  let panel = loader.require("sdk/panel").Panel({
+    contentScriptWhen: "start",
+    // No contentURL, the bug only shows up when contentURL is not explicitly set.
+  });
+
+  yield new Promise(resolve => {
+    panel.once("show", resolve);
+    panel.show();
+  });
+
+  assert.pass("Received show event");
+
+  loader.unload();
+}
+
 if (isWindowPBSupported) {
   exports.testGetWindow = function(assert, done) {
     let activeWindow = getMostRecentBrowserWindow();
     open(null, { features: {
       toolbar: true,
       chrome: true,
       private: true
     } }).then(window => {
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -76,17 +76,16 @@ class TextureChild MOZ_FINAL : public PT
 {
   ~TextureChild() {}
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureChild)
 
   TextureChild()
   : mForwarder(nullptr)
   , mTextureClient(nullptr)
-  , mKeep(nullptr)
   , mIPCOpen(false)
   {
   }
 
   bool Recv__delete__() MOZ_OVERRIDE;
 
   bool RecvCompositorRecycle()
   {
@@ -125,17 +124,17 @@ private:
     MOZ_ASSERT(mIPCOpen == true);
     mIPCOpen = false;
     Release();
   }
 
   RefPtr<CompositableForwarder> mForwarder;
   RefPtr<TextureClient> mWaitForRecycle;
   TextureClient* mTextureClient;
-  KeepAlive* mKeep;
+  UniquePtr<KeepAlive> mKeep;
   bool mIPCOpen;
 
   friend class TextureClient;
 };
 
 bool
 TextureChild::Recv__delete__()
 {
@@ -144,17 +143,17 @@ TextureChild::Recv__delete__()
 
 void
 TextureChild::ActorDestroy(ActorDestroyReason why)
 {
   if (mTextureClient) {
     mTextureClient->mActor = nullptr;
   }
   mWaitForRecycle = nullptr;
-  delete mKeep;
+  mKeep = nullptr;
 }
 
 // static
 PTextureChild*
 TextureClient::CreateIPDLActor()
 {
   TextureChild* c = new TextureChild();
   c->AddIPDLReference();
@@ -482,21 +481,21 @@ TextureClient::TextureClient(TextureFlag
 
 TextureClient::~TextureClient()
 {
   // All the destruction code that may lead to virtual method calls must
   // be in Finalize() which is called just before the destructor.
 }
 
 void
-TextureClient::KeepUntilFullDeallocation(KeepAlive* aKeep)
+TextureClient::KeepUntilFullDeallocation(UniquePtr<KeepAlive> aKeep)
 {
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(!mActor->mKeep);
-  mActor->mKeep = aKeep;
+  mActor->mKeep = Move(aKeep);
 }
 
 void TextureClient::ForceRemove(bool sync)
 {
   if (mValid && mActor) {
     if (sync || GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
       if (mActor->IPCOpen()) {
         mActor->SendClearTextureHostSync();
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -356,17 +356,17 @@ public:
   bool IsAddedToCompositableClient() const { return mAddedToCompositableClient; }
 
   /**
    * kee the passed object alive until the IPDL actor is destroyed. This can
    * help avoid race conditions in some cases.
    * It's a temporary hack to ensure that DXGI textures don't get destroyed
    * between serialization and deserialization.
    */
-  void KeepUntilFullDeallocation(KeepAlive* aKeep);
+  void KeepUntilFullDeallocation(UniquePtr<KeepAlive> aKeep);
 
   /**
    * Create and init the TextureChild/Parent IPDL actor pair.
    *
    * Should be called only once per TextureClient.
    */
   bool InitIPDLActor(CompositableForwarder* aForwarder);
 
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -168,19 +168,19 @@ TextureClientD3D11::TextureClientD3D11(g
   , mNeedsClear(false)
   , mNeedsClearWhite(false)
 {}
 
 TextureClientD3D11::~TextureClientD3D11()
 {
   if (mActor) {
     if (mTexture) {
-      KeepUntilFullDeallocation(new TKeepAlive<ID3D10Texture2D>(mTexture10));
+      KeepUntilFullDeallocation(MakeUnique<TKeepAlive<ID3D10Texture2D>>(mTexture10));
     } else if (mTexture10) {
-      KeepUntilFullDeallocation(new TKeepAlive<ID3D11Texture2D>(mTexture));
+      KeepUntilFullDeallocation(MakeUnique<TKeepAlive<ID3D11Texture2D>>(mTexture));
     }
   }
 #ifdef DEBUG
   // An Azure DrawTarget needs to be locked when it gets nullptr'ed as this is
   // when it calls EndDraw. This EndDraw should not execute anything so it
   // shouldn't -really- need the lock but the debug layer chokes on this.
   if (mDrawTarget) {
     MOZ_ASSERT(!mIsLocked);
@@ -413,21 +413,21 @@ TextureClientD3D11::ToSurfaceDescriptor(
 
   aOutDescriptor = SurfaceDescriptorD3D10((WindowsHandle)sharedHandle, mFormat, mSize);
   return true;
 }
 
 DXGITextureHostD3D11::DXGITextureHostD3D11(TextureFlags aFlags,
                                            const SurfaceDescriptorD3D10& aDescriptor)
   : TextureHost(aFlags)
+  , mSize(aDescriptor.size())
   , mHandle(aDescriptor.handle())
   , mFormat(aDescriptor.format())
   , mIsLocked(false)
 {
-  OpenSharedHandle();
 }
 
 bool
 DXGITextureHostD3D11::OpenSharedHandle()
 {
   if (!GetDevice()) {
     return false;
   }
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -729,17 +729,17 @@ SharedTextureClientD3D9::SharedTextureCl
   , mIsLocked(false)
 {
   MOZ_COUNT_CTOR(SharedTextureClientD3D9);
 }
 
 SharedTextureClientD3D9::~SharedTextureClientD3D9()
 {
   if (mTexture && mActor) {
-    KeepUntilFullDeallocation(new TKeepAlive<IDirect3DTexture9>(mTexture));
+    KeepUntilFullDeallocation(MakeUnique<TKeepAlive<IDirect3DTexture9>>(mTexture));
   }
   MOZ_COUNT_DTOR(SharedTextureClientD3D9);
 }
 
 bool
 SharedTextureClientD3D9::Lock(OpenMode)
 {
   MOZ_ASSERT(!mIsLocked);
--- a/toolkit/mozapps/extensions/nsBlocklistService.js
+++ b/toolkit/mozapps/extensions/nsBlocklistService.js
@@ -269,25 +269,25 @@ function parseRegExp(aStr) {
  * Helper function to test if the blockEntry matches with the plugin.
  *
  * @param   blockEntry
  *          The plugin blocklist entries to compare against.
  * @param   plugin
  *          The nsIPluginTag to get the blocklist state for.
  * @returns True if the blockEntry matches the plugin, false otherwise.
  */
-function hasMatchingPluginName(blockEntry, plugin) {
+function matchesAllPluginNames(blockEntry, plugin) {
   for (let name in blockEntry.matches) {
-    if ((name in plugin) &&
-        typeof(plugin[name]) == "string" &&
-        blockEntry.matches[name].test(plugin[name])) {
-      return true;
+    if (!(name in plugin) ||
+        typeof(plugin[name]) != "string" ||
+        !blockEntry.matches[name].test(plugin[name])) {
+      return false;
     }
   }
-  return false;
+  return true;
 }
 
 /**
  * Manages the Blocklist. The Blocklist is a representation of the contents of
  * blocklist.xml and allows us to remotely disable / re-enable blocklisted
  * items managed by the Extension Manager with an item's appDisabled property.
  * It also blocklists plugins with data from blocklist.xml.
  */
@@ -1068,17 +1068,17 @@ Blocklist.prototype = {
   _getPluginBlockEntry: function (plugin) {
     if (!gBlocklistEnabled)
       return null;
 
     if (!this._isBlocklistLoaded())
       this._loadBlocklist();
 
     for each (let blockEntry in this._pluginEntries) {
-      if (hasMatchingPluginName(blockEntry, plugin)) {
+      if (matchesAllPluginNames(blockEntry, plugin)) {
         return blockEntry;
       }
     }
 
 	  return null;
   },
 
   /* See nsIBlocklistService */
--- a/toolkit/mozapps/extensions/test/xpcshell/data/pluginInfoURL_block.xml
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/pluginInfoURL_block.xml
@@ -1,15 +1,21 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
   <emItems>
   </emItems>
   <pluginItems>
     <pluginItem blockID="test_plugin_wInfoURL">
       <match name="name" exp="^test_with_infoURL"/>
+      <match name="version" exp="^5"/>
       <infoURL>http://test.url.com/</infoURL>
     </pluginItem>
+    <pluginItem blockID="test_plugin_wAltInfoURL">
+      <match name="name" exp="^test_with_altInfoURL"/>
+      <match name="version" exp="^5"/>
+      <infoURL>http://alt.test.url.com/</infoURL>
+    </pluginItem>
     <pluginItem blockID="test_plugin_noInfoURL">
       <match name="name" exp="^test_no_infoURL"/>
     </pluginItem>
   </pluginItems>
 </blocklist>
--- a/toolkit/mozapps/extensions/test/xpcshell/test_pluginInfoURL.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_pluginInfoURL.js
@@ -24,16 +24,17 @@ MockPlugin.prototype = {
   get disabled() {
     return this.enabledState == Ci.nsIPluginTag.STATE_DISABLED;
   }
 };
 
 // The mocked blocked plugin used to test the blocklist.
 const PLUGINS = [
   new MockPlugin('test_with_infoURL', '5', Ci.nsIPluginTag.STATE_ENABLED),
+  new MockPlugin('test_with_altInfoURL', '5', Ci.nsIPluginTag.STATE_ENABLED),
   new MockPlugin('test_no_infoURL', '5', Ci.nsIPluginTag.STATE_ENABLED)
 ];
 
 /**
  * The entry point of the unit tests, which is also responsible of
  * copying the blocklist file to the profile folder.
  */
 function run_test() {
@@ -41,28 +42,39 @@ function run_test() {
 
   createAppInfo('xpcshell@tests.mozilla.org', 'XPCShell', '3', '8');
   startupManager();
 
   run_next_test();
 }
 
 /**
- * Test that the blocklist service correctly loads and returns the infoURL
- * from the blocklist file for a matched plugin.
+ * Test that the blocklist service correctly loads and returns the infoURL for
+ * a plugin that matches the first entry in the blocklist.
  */
 add_task(function* test_infoURL() {
   // The testInfoURL must match the value within the
   // <infoURL> tag in pluginInfoURL_block.xml.
   let testInfoURL = 'http://test.url.com/';
 
   Assert.strictEqual(Services.blocklist.getPluginInfoURL(PLUGINS[0]),
-    testInfoURL, 'Plugin info urls should match');
+    testInfoURL, 'Should be the provided url when an infoURL tag is available');
+});
+
+/**
+ * Test that the blocklist service correctly loads and returns the infoURL for
+ * a plugin that partially matches an earlier entry in the blocklist.
+ */
+add_task(function* test_altInfoURL() {
+  let altTestInfoURL = 'http://alt.test.url.com/';
+
+  Assert.strictEqual(Services.blocklist.getPluginInfoURL(PLUGINS[1]),
+    altTestInfoURL, 'Should be the alternative infoURL');
 });
 
 /**
  * Test that the blocklist service correctly returns null
  * if the infoURL tag is missing in the blocklist.xml file.
  */
 add_task(function* test_infoURL_missing() {
-  Assert.strictEqual(Services.blocklist.getPluginInfoURL(PLUGINS[1]), null,
+  Assert.strictEqual(Services.blocklist.getPluginInfoURL(PLUGINS[2]), null,
     'Should be null when no infoURL tag is available.');
 });