Bug 1147521 - Cannot type into comment area of plugin crash UI. r=smaug, a=lmandel
authorSteven Michaud <smichaud@pobox.com>
Thu, 26 Mar 2015 18:11:00 -0400
changeset 258106 c23a289345ca2891b8b56f0d0e328088546ab2b0
parent 258105 55d8ab6f1700a015fb7ea77bed26d3ea89b0feea
child 258107 d9497593e7aaf342943831f5651c78563ed581f3
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, lmandel
bugs1147521
milestone38.0a2
Bug 1147521 - Cannot type into comment area of plugin crash UI. r=smaug, a=lmandel
dom/base/nsObjectLoadingContent.cpp
dom/html/HTMLObjectElement.cpp
dom/html/HTMLObjectElement.h
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -86,16 +86,23 @@
 
 #ifdef XP_WIN
 // Thanks so much, Microsoft! :(
 #ifdef CreateEvent
 #undef CreateEvent
 #endif
 #endif // XP_WIN
 
+#ifdef XP_MACOSX
+// HandlePluginCrashed() and HandlePluginInstantiated() needed from here to
+// fix bug 1147521.  Should later be replaced by proper interface methods,
+// maybe on nsIObjectLoadingContext.
+#include "mozilla/dom/HTMLObjectElement.h"
+#endif
+
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 static const char *kPrefJavaMIME = "plugin.java.mime";
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #ifdef PR_LOGGING
@@ -881,16 +888,20 @@ nsObjectLoadingContent::InstantiatePlugi
   }
 
   nsCOMPtr<nsIRunnable> ev = \
     new nsSimplePluginEvent(thisContent,
                             doc,
                             NS_LITERAL_STRING("PluginInstantiated"));
   NS_DispatchToCurrentThread(ev);
 
+#ifdef XP_MACOSX
+  HTMLObjectElement::HandlePluginInstantiated(thisContent->AsElement());
+#endif
+
   return NS_OK;
 }
 
 void
 nsObjectLoadingContent::GetPluginAttributes(nsTArray<MozPluginParameter>& aAttributes)
 {
   aAttributes = mCachedAttributes;
 }
@@ -2732,24 +2743,29 @@ NS_IMETHODIMP
 nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
                                       const nsAString& pluginDumpID,
                                       const nsAString& browserDumpID,
                                       bool submittedCrashReport)
 {
   LOG(("OBJLC [%p]: Plugin Crashed, queuing crash event", this));
   NS_ASSERTION(mType == eType_Plugin, "PluginCrashed at non-plugin type");
 
+  nsCOMPtr<nsIContent> thisContent =
+    do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
+
+#ifdef XP_MACOSX
+  HTMLObjectElement::HandlePluginCrashed(thisContent->AsElement());
+#endif
+
   PluginDestroyed();
 
   // Switch to fallback/crashed state, notify
   LoadFallback(eFallbackCrashed, true);
 
   // send nsPluginCrashedEvent
-  nsCOMPtr<nsIContent> thisContent =
-    do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
 
   // Note that aPluginTag in invalidated after we're called, so copy 
   // out any data we need now.
   nsAutoCString pluginName;
   aPluginTag->GetName(pluginName);
   nsAutoCString pluginFilename;
   aPluginTag->GetFilename(pluginFilename);
 
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -18,16 +18,17 @@
 #include "nsFormSubmission.h"
 #include "nsIObjectFrame.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsIWidget.h"
 #include "nsContentUtils.h"
 #ifdef XP_MACOSX
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/dom/Event.h"
+#include "nsFocusManager.h"
 #endif
 
 namespace mozilla {
 namespace dom {
 
 HTMLObjectElement::HTMLObjectElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
                                      FromParser aFromParser)
   : nsGenericHTMLFormElement(aNodeInfo),
@@ -145,29 +146,68 @@ public:
 private:
   nsCOMPtr<nsIWidget> mWidget;
   nsCOMPtr<Element> mElement;
 };
 
 void
 HTMLObjectElement::OnFocusBlurPlugin(Element* aElement, bool aFocus)
 {
+  // In general we don't want to call nsIWidget::SetPluginFocused() for any
+  // Element that doesn't have a plugin running.  But if SetPluginFocused(true)
+  // was just called for aElement while it had a plugin running, we want to
+  // make sure nsIWidget::SetPluginFocused(false) gets called for it now, even
+  // if aFocus is true.
+  if (aFocus) {
+    nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(aElement);
+    bool hasRunningPlugin = false;
+    if (olc) {
+      olc->GetHasRunningPlugin(&hasRunningPlugin);
+    }
+    if (!hasRunningPlugin) {
+      aFocus = false;
+    }
+  }
+
   if (aFocus || aElement == sLastFocused) {
     if (!aFocus) {
       sLastFocused = nullptr;
     }
     nsIWidget* widget = GetWidget(aElement);
     if (widget) {
       nsContentUtils::AddScriptRunner(
         new PluginFocusSetter(widget, aFocus ? aElement : nullptr));
     }
   }
 }
 
 void
+HTMLObjectElement::HandlePluginCrashed(Element* aElement)
+{
+  OnFocusBlurPlugin(aElement, false);
+}
+
+void
+HTMLObjectElement::HandlePluginInstantiated(Element* aElement)
+{
+  // If aElement is already focused when a plugin is instantiated, we need
+  // to initiate a call to nsIWidget::SetPluginFocused(true).  Otherwise
+  // keyboard input won't work in a click-to-play plugin until aElement
+  // loses focus and regains it.
+  nsIContent* focusedContent = nullptr;
+  nsFocusManager *fm = nsFocusManager::GetFocusManager();
+  if (fm) {
+    focusedContent = fm->GetFocusedContent();
+  }
+  if (SameCOMIdentity(focusedContent, aElement)) {
+    OnFocusBlurPlugin(aElement, true);
+  }
+}
+
+void
 HTMLObjectElement::HandleFocusBlurPlugin(Element* aElement,
                                          WidgetEvent* aEvent)
 {
   if (!aEvent->mFlags.mIsTrusted) {
     return;
   }
   switch (aEvent->message) {
     case NS_FOCUS_CONTENT: {
--- a/dom/html/HTMLObjectElement.h
+++ b/dom/html/HTMLObjectElement.h
@@ -31,16 +31,18 @@ public:
   virtual int32_t TabIndexDefault() override;
 
 #ifdef XP_MACOSX
   // nsIDOMEventTarget
   NS_IMETHOD PostHandleEvent(EventChainPostVisitor& aVisitor) override;
   // Helper methods
   static void OnFocusBlurPlugin(Element* aElement, bool aFocus);
   static void HandleFocusBlurPlugin(Element* aElement, WidgetEvent* aEvent);
+  static void HandlePluginCrashed(Element* aElement);
+  static void HandlePluginInstantiated(Element* aElement);
   // Weak pointer. Null if last action was blur.
   static Element* sLastFocused;
 #endif
 
   // Element
   virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
 
   // nsIDOMHTMLObjectElement