зеркало из https://github.com/mozilla/gecko-dev.git
bug 781971 - hack around plugin hangs r=surkov
This commit is contained in:
Родитель
324cc006a6
Коммит
126a5f25c7
|
@ -37,6 +37,7 @@
|
|||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "mozilla/a11y/Compatibility.h"
|
||||
#include "HTMLWin32ObjectAccessible.h"
|
||||
#endif
|
||||
|
||||
|
@ -63,6 +64,7 @@
|
|||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsDeckFrame.h"
|
||||
|
||||
|
@ -210,6 +212,45 @@ nsAccessibilityService::GetRootDocumentAccessible(nsIPresShell* aPresShell,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
static StaticAutoPtr<nsTArray<nsCOMPtr<nsIContent> > > sPendingPlugins;
|
||||
static StaticAutoPtr<nsTArray<nsCOMPtr<nsITimer> > > sPluginTimers;
|
||||
|
||||
class PluginTimerCallBack MOZ_FINAL : public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
PluginTimerCallBack(nsIContent* aContent) : mContent(aContent) {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHODIMP Notify(nsITimer* aTimer) MOZ_FINAL
|
||||
{
|
||||
nsIPresShell* ps = mContent->OwnerDoc()->GetShell();
|
||||
if (ps) {
|
||||
DocAccessible* doc = ps->GetDocAccessible();
|
||||
if (doc) {
|
||||
// Make sure that if we created an accessible for the plugin that wasn't
|
||||
// a plugin accessible we remove it before creating the right accessible.
|
||||
doc->RecreateAccessible(mContent);
|
||||
sPluginTimers->RemoveElement(aTimer);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// We couldn't get a doc accessible so presumably the document went away.
|
||||
// In this case don't leak our ref to the content or timer.
|
||||
sPendingPlugins->RemoveElement(mContent);
|
||||
sPluginTimers->RemoveElement(aTimer);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(PluginTimerCallBack, nsITimerCallback)
|
||||
#endif
|
||||
|
||||
already_AddRefed<Accessible>
|
||||
nsAccessibilityService::CreatePluginAccessible(nsObjectFrame* aFrame,
|
||||
nsIContent* aContent,
|
||||
|
@ -225,6 +266,23 @@ nsAccessibilityService::CreatePluginAccessible(nsObjectFrame* aFrame,
|
|||
if (NS_SUCCEEDED(aFrame->GetPluginInstance(getter_AddRefs(pluginInstance))) &&
|
||||
pluginInstance) {
|
||||
#ifdef XP_WIN
|
||||
if (!sPendingPlugins->Contains(aContent) &&
|
||||
(Preferences::GetBool("accessibility.delay_plugins") ||
|
||||
Compatibility::IsJAWS() || Compatibility::IsWE())) {
|
||||
nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
nsRefPtr<PluginTimerCallBack> cb = new PluginTimerCallBack(aContent);
|
||||
timer->InitWithCallback(cb, Preferences::GetUint("accessibility.delay_plugin_time"),
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
sPluginTimers->AppendElement(timer);
|
||||
sPendingPlugins->AppendElement(aContent);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We need to remove aContent from the pending plugins here to avoid
|
||||
// reentrancy. When the timer fires it calls
|
||||
// DocAccessible::ContentInserted() which does the work async.
|
||||
sPendingPlugins->RemoveElement(aContent);
|
||||
|
||||
// Note: pluginPort will be null if windowless.
|
||||
HWND pluginPort = nullptr;
|
||||
aFrame->GetPluginPort(&pluginPort);
|
||||
|
@ -1004,6 +1062,11 @@ nsAccessibilityService::Init()
|
|||
NS_LITERAL_CSTRING("Active"));
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
sPendingPlugins = new nsTArray<nsCOMPtr<nsIContent> >;
|
||||
sPluginTimers = new nsTArray<nsCOMPtr<nsITimer> >;
|
||||
#endif
|
||||
|
||||
gIsShutdown = false;
|
||||
|
||||
// Now its safe to start platform accessibility.
|
||||
|
@ -1030,6 +1093,16 @@ nsAccessibilityService::Shutdown()
|
|||
|
||||
SelectionManager::Shutdown();
|
||||
|
||||
#ifdef XP_WIN
|
||||
sPendingPlugins = nullptr;
|
||||
|
||||
uint32_t timerCount = sPluginTimers->Length();
|
||||
for (uint32_t i = 0; i < timerCount; i++)
|
||||
sPluginTimers->ElementAt(i)->Cancel();
|
||||
|
||||
sPluginTimers = nullptr;
|
||||
#endif
|
||||
|
||||
// Application is going to be closed, shutdown accessibility and mark
|
||||
// accessibility service as shutdown to prevent calls of its methods.
|
||||
// Don't null accessibility service static member at this point to be safe
|
||||
|
|
|
@ -331,6 +331,16 @@ pref("accessibility.tabfocus_applies_to_xul", true);
|
|||
// further checks.
|
||||
pref("accessibility.force_disabled", 0);
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Some accessibility tools poke at windows in the plugin process during setup
|
||||
// which can cause hangs. To hack around this set accessibility.delay_plugins
|
||||
// to true, you can also try increasing accessibility.delay_plugin_time if your
|
||||
// machine is slow and you still experience hangs.
|
||||
// See bug 781791.
|
||||
pref("accessibility.delay_plugins", false);
|
||||
pref("accessibility.delay_plugin_time", 10000);
|
||||
#endif
|
||||
|
||||
pref("focusmanager.testmode", false);
|
||||
|
||||
pref("accessibility.usetexttospeech", "");
|
||||
|
|
Загрузка…
Ссылка в новой задаче