Bug 889788 - Plugin doorhanger breaks when plugins are dynamically removed from a page. This implements the short-term solution of hiding the plugin doorhanger when no more plugins are on the page (the better long-term solution will keep showing the UI and track all the plugins a page ever uses). This also implements a short-term solution when a user enables a plugin. Also bug 887088 - Short-term UI solution: when a user loads multiple tabs from a site and enables a plugin on one of them, the plugins are not enabled on other tabs but the "continue allowing" button does nothing. This patch makes the "Continue Allowing" button enable existing plugins of that type. r=jaws r=jschoenick

--HG--
extra : rebase_source : 4b24a6d5bf3b5c33b1e19702eca676b340b5d8b1
This commit is contained in:
Benjamin Smedberg 2013-07-17 09:21:02 -04:00
Родитель 4119d6b9de
Коммит 02bb483c7e
4 изменённых файлов: 67 добавлений и 34 удалений

Просмотреть файл

@ -217,14 +217,21 @@ var gPluginHandler = {
},
handleEvent : function(event) {
let plugin = event.target;
let doc = plugin.ownerDocument;
// We're expecting the target to be a plugin.
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
return;
let plugin;
let doc;
let eventType = event.type;
if (eventType === "PluginRemoved") {
doc = event.target;
}
else {
plugin = event.target;
doc = plugin.ownerDocument;
if (!(plugin instanceof Ci.nsIObjectLoadingContent))
return;
}
if (eventType == "PluginBindingAttached") {
// The plugin binding fires this event when it is created.
// As an untrusted event, ensure that this object actually has a binding
@ -304,6 +311,7 @@ var gPluginHandler = {
break;
case "PluginInstantiated":
case "PluginRemoved":
this._showClickToPlayNotification(browser);
break;
}
@ -686,18 +694,12 @@ var gPluginHandler = {
switch (aNewState) {
case "allownow":
if (aPluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
return;
}
permission = Ci.nsIPermissionManager.ALLOW_ACTION;
expireType = Ci.nsIPermissionManager.EXPIRE_SESSION;
expireTime = Date.now() + Services.prefs.getIntPref(this.PREF_SESSION_PERSIST_MINUTES) * 60 * 1000;
break;
case "allowalways":
if (aPluginInfo.fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
return;
}
permission = Ci.nsIPermissionManager.ALLOW_ACTION;
expireType = Ci.nsIPermissionManager.EXPIRE_TIME;
expireTime = Date.now() +
@ -705,25 +707,28 @@ var gPluginHandler = {
break;
case "block":
if (aPluginInfo.fallbackType != Ci.nsIObjectLoadingContent.PLUGIN_ACTIVE) {
return;
}
permission = Ci.nsIPermissionManager.PROMPT_ACTION;
expireType = Ci.nsIPermissionManager.EXPIRE_NEVER;
expireTime = 0;
break;
// In case a plugin has already been allowed in another tab, the "continue allowing" button
// shouldn't change any permissions but should run the plugin-enablement code below.
case "continue":
break;
default:
Cu.reportError(Error("Unexpected plugin state: " + aNewState));
return;
}
let browser = aNotification.browser;
Services.perms.add(browser.currentURI, aPluginInfo.permissionString,
permission, expireType, expireTime);
if (aNewState != "continue") {
Services.perms.add(browser.currentURI, aPluginInfo.permissionString,
permission, expireType, expireTime);
if (aNewState == "block") {
return;
if (aNewState == "block") {
return;
}
}
// Manually activate the plugins that would have been automatically

Просмотреть файл

@ -755,6 +755,7 @@ var gBrowserInit = {
gBrowser.addEventListener("PluginCrashed", gPluginHandler, true);
gBrowser.addEventListener("PluginOutdated", gPluginHandler, true);
gBrowser.addEventListener("PluginInstantiated", gPluginHandler, true);
gBrowser.addEventListener("PluginRemoved", gPluginHandler, true);
gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true);

Просмотреть файл

@ -1574,12 +1574,19 @@
this.appendChild(item);
this._items.push(item);
}
if (this.notification.options.centerActions.length == 1) {
this._setState(this._states.SINGLE);
} else if (this.notification.options.primaryPlugin) {
this._setState(this._states.MULTI_COLLAPSED);
} else {
this._setState(this._states.MULTI_EXPANDED);
switch (this.notification.options.centerActions.length) {
case 0:
PopupNotifications._dismiss();
break;
case 1:
this._setState(this._states.SINGLE);
break;
default:
if (this.notification.options.primaryPlugin) {
this._setState(this._states.MULTI_COLLAPSED);
} else {
this._setState(this._states.MULTI_EXPANDED);
}
}
]]></constructor>
<method name="_setState">
@ -1645,7 +1652,7 @@
button2 = {
label: "pluginContinue.label",
accesskey: "pluginContinue.accesskey",
action: "_cancel",
action: "_singleContinue",
default: true
};
switch (action.blocklistState) {
@ -1819,6 +1826,14 @@
this._cancel();
]]></body>
</method>
<method name="_singleContinue">
<body><![CDATA[
gPluginHandler._updatePluginPermission(this.notification,
this.notification.options.centerActions[0],
"continue");
this._cancel();
]]></body>
</method>
<method name="_multiAccept">
<body><![CDATA[
for (let item of this._items) {

Просмотреть файл

@ -196,26 +196,36 @@ CheckPluginStopEvent::Run()
*/
class nsSimplePluginEvent : public nsRunnable {
public:
nsSimplePluginEvent(nsIContent* aContent, const nsAString &aEvent)
: mContent(aContent),
mEvent(aEvent)
{}
nsSimplePluginEvent(nsIContent* aTarget, const nsAString &aEvent)
: mTarget(aTarget)
, mDocument(aTarget->GetCurrentDoc())
, mEvent(aEvent)
{
}
nsSimplePluginEvent(nsIDocument* aTarget, const nsAString& aEvent)
: mTarget(aTarget)
, mDocument(aTarget)
, mEvent(aEvent)
{
}
~nsSimplePluginEvent() {}
NS_IMETHOD Run();
private:
nsCOMPtr<nsIContent> mContent;
nsCOMPtr<nsISupports> mTarget;
nsCOMPtr<nsIDocument> mDocument;
nsString mEvent;
};
NS_IMETHODIMP
nsSimplePluginEvent::Run()
{
LOG(("OBJLC [%p]: nsSimplePluginEvent firing event \"%s\"", mContent.get(),
LOG(("OBJLC [%p]: nsSimplePluginEvent firing event \"%s\"", mTarget.get(),
mEvent.get()));
nsContentUtils::DispatchTrustedEvent(mContent->GetDocument(), mContent,
nsContentUtils::DispatchTrustedEvent(mDocument, mTarget,
mEvent, true, true);
return NS_OK;
}
@ -674,7 +684,9 @@ nsObjectLoadingContent::UnbindFromTree(bool aDeep, bool aNullParent)
/// would keep the docshell around, but trash the frameloader
UnloadObject();
}
nsCOMPtr<nsIRunnable> ev = new nsSimplePluginEvent(thisContent->GetCurrentDoc(),
NS_LITERAL_STRING("PluginRemoved"));
NS_DispatchToCurrentThread(ev);
}
nsObjectLoadingContent::nsObjectLoadingContent()