Bug 1419091: Switch to a compiled C++ table for html key bindings for browser and editor. r=masayuki

Rather than loading an XBL binding for <browser> and <editor> elements this
generates the handlers from static C arrays.

Differential Revision: https://phabricator.services.mozilla.com/D6181

--HG--
extra : rebase_source : 690dee71ad81fad157052f342451047f10ef3811
extra : intermediate-source : ac56492b6ed6f03cd61389db83a73e0fdf970089
extra : source : a33e19d9f6d584e51153205efc7b5693119818cc
This commit is contained in:
Dave Townsend 2018-10-08 11:09:31 -07:00
Родитель 6ea60e6b82
Коммит c8c2fa1025
7 изменённых файлов: 164 добавлений и 130 удалений

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

@ -0,0 +1,94 @@
#include "mozilla/ShortcutKeys.h"
#include "../nsXBLPrototypeHandler.h"
#include "nsContentUtils.h"
namespace mozilla {
NS_IMPL_ISUPPORTS(ShortcutKeys, nsIObserver);
StaticRefPtr<ShortcutKeys> ShortcutKeys::sInstance;
ShortcutKeys::ShortcutKeys()
: mBrowserHandlers(nullptr)
, mEditorHandlers(nullptr)
, mInputHandlers(nullptr)
, mTextAreaHandlers(nullptr)
{
MOZ_ASSERT(!sInstance, "Attempt to instantiate a second ShortcutKeys.");
nsContentUtils::RegisterShutdownObserver(this);
}
ShortcutKeys::~ShortcutKeys()
{
delete mBrowserHandlers;
delete mEditorHandlers;
delete mInputHandlers;
delete mTextAreaHandlers;
}
nsresult
ShortcutKeys::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
{
// Clear our strong reference so we can clean up.
sInstance = nullptr;
return NS_OK;
}
/* static */ nsXBLPrototypeHandler*
ShortcutKeys::GetHandlers(HandlerType aType)
{
if (!sInstance) {
sInstance = new ShortcutKeys();
}
return sInstance->EnsureHandlers(aType);
}
nsXBLPrototypeHandler*
ShortcutKeys::EnsureHandlers(HandlerType aType)
{
ShortcutKeyData* keyData;
nsXBLPrototypeHandler** cache;
switch (aType) {
case HandlerType::eBrowser:
keyData = &sBrowserHandlers[0];
cache = &mBrowserHandlers;
break;
case HandlerType::eEditor:
keyData = &sEditorHandlers[0];
cache = &mEditorHandlers;
break;
case HandlerType::eInput:
keyData = &sInputHandlers[0];
cache = &mInputHandlers;
break;
case HandlerType::eTextArea:
keyData = &sTextAreaHandlers[0];
cache = &mTextAreaHandlers;
break;
default:
MOZ_ASSERT(false, "Unknown handler type requested.");
}
if (*cache) {
return *cache;
}
nsXBLPrototypeHandler* lastHandler = nullptr;
while (keyData->event) {
nsXBLPrototypeHandler* handler =
new nsXBLPrototypeHandler(keyData);
if (lastHandler) {
lastHandler->SetNextHandler(handler);
} else {
*cache = handler;
}
lastHandler = handler;
keyData++;
}
return *cache;
}
} // namespace mozilla

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

@ -5,6 +5,10 @@
#ifndef mozilla_dom_ShortcutKeys_h
#define mozilla_dom_ShortcutKeys_h
#include "nsIObserver.h"
class nsXBLPrototypeHandler;
namespace mozilla {
typedef struct
@ -16,13 +20,44 @@ typedef struct
const char16_t* command;
} ShortcutKeyData;
class ShortcutKeys
enum class HandlerType
{
eInput,
eTextArea,
eBrowser,
eEditor,
};
class ShortcutKeys : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
// Returns a pointer to the first handler for the given type.
static nsXBLPrototypeHandler* GetHandlers(HandlerType aType);
protected:
ShortcutKeys();
virtual ~ShortcutKeys();
// Returns a pointer to the first handler for the given type.
nsXBLPrototypeHandler* EnsureHandlers(HandlerType aType);
// Maintains a strong reference to the only instance.
static StaticRefPtr<ShortcutKeys> sInstance;
// Shortcut keys for different elements.
static ShortcutKeyData sBrowserHandlers[];
static ShortcutKeyData sEditorHandlers[];
static ShortcutKeyData sInputHandlers[];
static ShortcutKeyData sTextAreaHandlers[];
// Cached event handlers generated from the above data.
nsXBLPrototypeHandler* mBrowserHandlers;
nsXBLPrototypeHandler* mEditorHandlers;
nsXBLPrototypeHandler* mInputHandlers;
nsXBLPrototypeHandler* mTextAreaHandlers;
};
} // namespace mozilla

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

@ -15,3 +15,8 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
else:
DIRS += ['emacs']
EXPORTS.mozilla += ['ShortcutKeys.h']
SOURCES += ['ShortcutKeys.cpp']
FINAL_LIBRARY = 'xul'

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

@ -106,11 +106,11 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(const char16_t* aEvent,
}
nsXBLPrototypeHandler::nsXBLPrototypeHandler(Element* aHandlerElement, XBLReservedKey aReserved)
: mHandlerElement(nullptr),
mLineNumber(0),
mReserved(aReserved),
mNextHandler(nullptr),
mPrototypeBinding(nullptr)
: mHandlerElement(nullptr)
, mLineNumber(0)
, mReserved(aReserved)
, mNextHandler(nullptr)
, mPrototypeBinding(nullptr)
{
Init();
@ -118,6 +118,21 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(Element* aHandlerElement, XBLReserv
ConstructPrototype(aHandlerElement);
}
nsXBLPrototypeHandler::nsXBLPrototypeHandler(ShortcutKeyData* aKeyData)
: mHandlerText(nullptr),
mLineNumber(0),
mReserved(XBLReservedKey_False),
mNextHandler(nullptr),
mPrototypeBinding(nullptr)
{
Init();
ConstructPrototype(nullptr, aKeyData->event, nullptr, nullptr,
aKeyData->command, aKeyData->keycode, aKeyData->key,
aKeyData->modifiers, nullptr, nullptr, nullptr, nullptr,
nullptr);
}
nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding)
: mHandlerText(nullptr),
mLineNumber(0),

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

@ -18,6 +18,7 @@
#include "nsIWeakReference.h"
#include "nsCycleCollectionParticipant.h"
#include "js/TypeDecls.h"
#include "mozilla/ShortcutKeys.h"
class nsIContent;
class nsIObjectInputStream;
@ -93,6 +94,10 @@ public:
// This constructor is used only by XUL key handlers (e.g., <key>)
explicit nsXBLPrototypeHandler(mozilla::dom::Element* aKeyElement, XBLReservedKey aReserved);
// This constructor is used for keyboard handlers for browser, editor, input
// and textarea elements.
explicit nsXBLPrototypeHandler(mozilla::ShortcutKeyData* aKeyData);
// This constructor is used for handlers loaded from the cache
explicit nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding);

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

@ -34,119 +34,18 @@
#include "mozilla/dom/EventBinding.h"
#include "mozilla/dom/KeyboardEvent.h"
#include "mozilla/layers/KeyboardMap.h"
#include "mozilla/ShortcutKeys.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::layers;
class nsXBLSpecialDocInfo : public nsIObserver
{
public:
RefPtr<nsXBLDocumentInfo> mHTMLBindings;
static const char sHTMLBindingStr[];
static const char sUserHTMLBindingStr[];
bool mInitialized;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
void LoadDocInfo();
void GetHandlers(const nsACString& aRef,
nsXBLPrototypeHandler** handler);
nsXBLSpecialDocInfo() : mInitialized(false) {}
protected:
virtual ~nsXBLSpecialDocInfo() {}
};
const char nsXBLSpecialDocInfo::sHTMLBindingStr[] =
"chrome://global/content/platformHTMLBindings.xml";
NS_IMPL_ISUPPORTS(nsXBLSpecialDocInfo, nsIObserver)
NS_IMETHODIMP
nsXBLSpecialDocInfo::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"), "wrong topic");
// On shutdown, clear our fields to avoid an extra cycle collection.
mHTMLBindings = nullptr;
mInitialized = false;
nsContentUtils::UnregisterShutdownObserver(this);
return NS_OK;
}
void nsXBLSpecialDocInfo::LoadDocInfo()
{
if (mInitialized)
return;
mInitialized = true;
nsContentUtils::RegisterShutdownObserver(this);
nsXBLService* xblService = nsXBLService::GetInstance();
if (!xblService)
return;
// Obtain the platform doc info
nsCOMPtr<nsIURI> bindingURI;
NS_NewURI(getter_AddRefs(bindingURI), sHTMLBindingStr);
if (!bindingURI) {
return;
}
xblService->LoadBindingDocumentInfo(nullptr, nullptr,
bindingURI,
nullptr,
true,
getter_AddRefs(mHTMLBindings));
}
//
// GetHandlers
//
//
void
nsXBLSpecialDocInfo::GetHandlers(const nsACString& aRef,
nsXBLPrototypeHandler** aHandler)
{
if (mHTMLBindings) {
nsXBLPrototypeBinding* binding = mHTMLBindings->GetPrototypeBinding(aRef);
NS_ASSERTION(binding, "No binding found for the XBL window key handler.");
if (!binding)
return;
*aHandler = binding->GetPrototypeHandlers();
}
}
// Init statics
static StaticRefPtr<nsXBLSpecialDocInfo> sXBLSpecialDocInfo;
uint32_t nsXBLWindowKeyHandler::sRefCnt = 0;
/* static */ void
nsXBLWindowKeyHandler::EnsureSpecialDocInfo()
{
if (!sXBLSpecialDocInfo) {
sXBLSpecialDocInfo = new nsXBLSpecialDocInfo();
}
sXBLSpecialDocInfo->LoadDocInfo();
}
nsXBLWindowKeyHandler::nsXBLWindowKeyHandler(Element* aElement,
EventTarget* aTarget)
: mTarget(aTarget),
mHandler(nullptr)
{
mWeakPtrForElement = do_GetWeakReference(aElement);
++sRefCnt;
}
nsXBLWindowKeyHandler::~nsXBLWindowKeyHandler()
@ -154,11 +53,6 @@ nsXBLWindowKeyHandler::~nsXBLWindowKeyHandler()
// If mWeakPtrForElement is non-null, we created a prototype handler.
if (mWeakPtrForElement)
delete mHandler;
--sRefCnt;
if (!sRefCnt) {
sXBLSpecialDocInfo = nullptr;
}
}
NS_IMPL_ISUPPORTS(nsXBLWindowKeyHandler,
@ -230,14 +124,12 @@ nsXBLWindowKeyHandler::EnsureHandlers()
BuildHandlerChain(el, &mHandler);
} else { // We are an XBL file of handlers.
EnsureSpecialDocInfo();
// Now determine which handlers we should be using.
if (IsHTMLEditableFieldFocused()) {
sXBLSpecialDocInfo->GetHandlers(NS_LITERAL_CSTRING("editor"), &mHandler);
mHandler = ShortcutKeys::GetHandlers(HandlerType::eEditor);
}
else {
sXBLSpecialDocInfo->GetHandlers(NS_LITERAL_CSTRING("browser"), &mHandler);
mHandler = ShortcutKeys::GetHandlers(HandlerType::eBrowser);
}
}
@ -396,11 +288,7 @@ nsXBLWindowKeyHandler::RemoveKeyboardEventListenersFrom(
/* static */ KeyboardMap
nsXBLWindowKeyHandler::CollectKeyboardShortcuts()
{
// Load the XBL handlers
EnsureSpecialDocInfo();
nsXBLPrototypeHandler* handlers = nullptr;
sXBLSpecialDocInfo->GetHandlers(NS_LITERAL_CSTRING("browser"), &handlers);
nsXBLPrototypeHandler* handlers = ShortcutKeys::GetHandlers(HandlerType::eBrowser);
// Convert the handlers into keyboard shortcuts, using an AutoTArray with
// the maximum amount of shortcuts used on any platform to minimize allocations

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

@ -88,9 +88,6 @@ protected:
nsAtom* ConvertEventToDOMEventType(
const mozilla::WidgetKeyboardEvent& aWidgetKeyboardEvent) const;
// lazily load the special doc info for loading handlers
static void EnsureSpecialDocInfo();
// lazily load the handlers. Overridden to handle being attached
// to a particular element rather than the document
nsresult EnsureHandlers();
@ -126,12 +123,7 @@ protected:
nsWeakPtr mWeakPtrForElement;
mozilla::dom::EventTarget* mTarget; // weak ref
// these are not owning references; the prototype handlers are owned
// by the prototype bindings which are owned by the docinfo.
nsXBLPrototypeHandler* mHandler; // platform bindings
// holds reference count to document info about bindings
static uint32_t sRefCnt;
};
already_AddRefed<nsXBLWindowKeyHandler>