2015-05-12 09:30:00 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2001-04-06 05:27:53 +04:00
|
|
|
|
|
|
|
#include "nsString.h"
|
|
|
|
|
|
|
|
#include "nsIController.h"
|
2002-11-11 23:15:40 +03:00
|
|
|
#include "nsIControllers.h"
|
2001-04-06 05:27:53 +04:00
|
|
|
#include "nsIObserver.h"
|
|
|
|
|
|
|
|
#include "nsIComponentManager.h"
|
|
|
|
|
2004-11-25 01:48:45 +03:00
|
|
|
#include "nsServiceManagerUtils.h"
|
2002-11-11 23:15:40 +03:00
|
|
|
#include "nsIScriptSecurityManager.h"
|
|
|
|
|
2014-05-07 02:43:03 +04:00
|
|
|
#include "nsContentUtils.h"
|
2001-04-06 05:27:53 +04:00
|
|
|
#include "nsIDOMWindow.h"
|
|
|
|
#include "nsPIDOMWindow.h"
|
2010-02-20 19:07:03 +03:00
|
|
|
#include "nsPIWindowRoot.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsIFocusManager.h"
|
2001-04-06 05:27:53 +04:00
|
|
|
|
2007-03-18 14:07:52 +03:00
|
|
|
#include "nsCOMArray.h"
|
2002-01-30 08:15:42 +03:00
|
|
|
|
2001-04-06 05:27:53 +04:00
|
|
|
#include "nsCommandManager.h"
|
|
|
|
|
|
|
|
nsCommandManager::nsCommandManager()
|
2015-05-11 22:35:14 +03:00
|
|
|
: mWindow(nullptr)
|
2001-04-06 05:27:53 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCommandManager::~nsCommandManager()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-08-02 05:29:05 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsCommandManager)
|
|
|
|
|
2007-03-08 14:17:16 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCommandManager)
|
2007-03-18 14:07:52 +03:00
|
|
|
tmp->mObserversTable.Clear();
|
2007-03-08 14:17:16 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCommandManager)
|
2015-11-02 05:41:40 +03:00
|
|
|
for (auto iter = tmp->mObserversTable.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
nsCommandManager::ObserverList* observers = iter.UserData();
|
|
|
|
int32_t numItems = observers->Length();
|
|
|
|
for (int32_t i = 0; i < numItems; ++i) {
|
|
|
|
cb.NoteXPCOMChild(observers->ElementAt(i));
|
|
|
|
}
|
|
|
|
}
|
2007-03-08 14:17:16 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
2011-03-06 14:11:31 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCommandManager)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCommandManager)
|
2007-03-08 14:17:16 +03:00
|
|
|
|
2007-04-25 20:35:27 +04:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCommandManager)
|
2015-05-11 22:35:14 +03:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsICommandManager)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsPICommandUpdater)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
|
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICommandManager)
|
2007-03-08 14:17:16 +03:00
|
|
|
NS_INTERFACE_MAP_END
|
2001-04-06 05:27:53 +04:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCommandManager::Init(mozIDOMWindowProxy* aWindow)
|
2001-04-06 05:27:53 +04:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aWindow);
|
2015-05-11 22:35:14 +03:00
|
|
|
|
|
|
|
mWindow = aWindow; // weak ptr
|
2001-04-06 05:27:53 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-05-11 22:35:14 +03:00
|
|
|
nsCommandManager::CommandStatusChanged(const char* aCommandName)
|
2001-04-06 05:27:53 +04:00
|
|
|
{
|
2012-07-30 17:48:02 +04:00
|
|
|
ObserverList* commandObservers;
|
2007-03-18 14:07:52 +03:00
|
|
|
mObserversTable.Get(aCommandName, &commandObservers);
|
|
|
|
|
2015-05-11 22:35:14 +03:00
|
|
|
if (commandObservers) {
|
2007-03-18 14:07:52 +03:00
|
|
|
// XXX Should we worry about observers removing themselves from Observe()?
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t i, numItems = commandObservers->Length();
|
2015-05-11 22:35:14 +03:00
|
|
|
for (i = 0; i < numItems; ++i) {
|
2012-07-30 17:48:02 +04:00
|
|
|
nsCOMPtr<nsIObserver> observer = commandObservers->ElementAt(i);
|
2007-03-18 14:07:52 +03:00
|
|
|
// should we get the command state to pass here? This might be expensive.
|
|
|
|
observer->Observe(NS_ISUPPORTS_CAST(nsICommandManager*, this),
|
|
|
|
aCommandName,
|
2016-07-21 08:03:25 +03:00
|
|
|
u"command_status_changed");
|
2007-03-18 14:07:52 +03:00
|
|
|
}
|
|
|
|
}
|
2001-04-06 05:27:53 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
#pragma mark -
|
|
|
|
#endif
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-05-11 22:35:14 +03:00
|
|
|
nsCommandManager::AddCommandObserver(nsIObserver* aCommandObserver,
|
|
|
|
const char* aCommandToObserve)
|
2001-04-06 05:27:53 +04:00
|
|
|
{
|
2007-03-18 14:07:52 +03:00
|
|
|
NS_ENSURE_ARG(aCommandObserver);
|
|
|
|
|
|
|
|
// XXX todo: handle special cases of aCommandToObserve being null, or empty
|
|
|
|
|
|
|
|
// for each command in the table, we make a list of observers for that command
|
2017-06-14 17:11:22 +03:00
|
|
|
ObserverList* commandObservers =
|
|
|
|
mObserversTable.LookupForAdd(aCommandToObserve).OrInsert(
|
|
|
|
[] () { return new ObserverList; });
|
2007-03-18 14:07:52 +03:00
|
|
|
|
|
|
|
// need to check that this command observer hasn't already been registered
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t existingIndex = commandObservers->IndexOf(aCommandObserver);
|
2015-05-11 22:35:14 +03:00
|
|
|
if (existingIndex == -1) {
|
2012-07-30 17:48:02 +04:00
|
|
|
commandObservers->AppendElement(aCommandObserver);
|
2015-05-11 22:35:14 +03:00
|
|
|
} else {
|
2002-01-30 08:15:42 +03:00
|
|
|
NS_WARNING("Registering command observer twice on the same command");
|
2015-05-11 22:35:14 +03:00
|
|
|
}
|
|
|
|
|
2012-07-30 17:48:02 +04:00
|
|
|
return NS_OK;
|
2001-04-06 05:27:53 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-05-11 22:35:14 +03:00
|
|
|
nsCommandManager::RemoveCommandObserver(nsIObserver* aCommandObserver,
|
|
|
|
const char* aCommandObserved)
|
2001-04-06 05:27:53 +04:00
|
|
|
{
|
2007-03-18 14:07:52 +03:00
|
|
|
NS_ENSURE_ARG(aCommandObserver);
|
|
|
|
|
|
|
|
// XXX todo: handle special cases of aCommandToObserve being null, or empty
|
|
|
|
|
2012-07-30 17:48:02 +04:00
|
|
|
ObserverList* commandObservers;
|
2015-05-11 22:35:14 +03:00
|
|
|
if (!mObserversTable.Get(aCommandObserved, &commandObservers)) {
|
2007-03-18 14:07:52 +03:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
2015-05-11 22:35:14 +03:00
|
|
|
}
|
2007-03-18 14:07:52 +03:00
|
|
|
|
2012-07-30 17:48:02 +04:00
|
|
|
commandObservers->RemoveElement(aCommandObserver);
|
|
|
|
|
|
|
|
return NS_OK;
|
2001-04-06 05:27:53 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-05-11 22:35:14 +03:00
|
|
|
nsCommandManager::IsCommandSupported(const char* aCommandName,
|
2016-01-30 20:05:36 +03:00
|
|
|
mozIDOMWindowProxy* aTargetWindow,
|
2015-05-11 22:35:14 +03:00
|
|
|
bool* aResult)
|
2001-04-06 05:27:53 +04:00
|
|
|
{
|
2015-05-11 22:35:14 +03:00
|
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
2001-04-06 05:27:53 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIController> controller;
|
2015-05-11 22:35:14 +03:00
|
|
|
GetControllerForCommand(aCommandName, aTargetWindow,
|
|
|
|
getter_AddRefs(controller));
|
|
|
|
*aResult = (controller.get() != nullptr);
|
2001-04-06 05:27:53 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-05-11 22:35:14 +03:00
|
|
|
nsCommandManager::IsCommandEnabled(const char* aCommandName,
|
2016-01-30 20:05:36 +03:00
|
|
|
mozIDOMWindowProxy* aTargetWindow,
|
2015-05-11 22:35:14 +03:00
|
|
|
bool* aResult)
|
2001-04-06 05:27:53 +04:00
|
|
|
{
|
2015-05-11 22:35:14 +03:00
|
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
|
|
|
|
|
|
bool commandEnabled = false;
|
|
|
|
|
2001-04-06 05:27:53 +04:00
|
|
|
nsCOMPtr<nsIController> controller;
|
2015-05-11 22:35:14 +03:00
|
|
|
GetControllerForCommand(aCommandName, aTargetWindow,
|
|
|
|
getter_AddRefs(controller));
|
|
|
|
if (controller) {
|
2001-04-06 05:27:53 +04:00
|
|
|
controller->IsCommandEnabled(aCommandName, &commandEnabled);
|
|
|
|
}
|
2015-05-11 22:35:14 +03:00
|
|
|
*aResult = commandEnabled;
|
2001-04-06 05:27:53 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-05-11 22:35:14 +03:00
|
|
|
nsCommandManager::GetCommandState(const char* aCommandName,
|
2016-01-30 20:05:36 +03:00
|
|
|
mozIDOMWindowProxy* aTargetWindow,
|
2015-05-11 22:35:14 +03:00
|
|
|
nsICommandParams* aCommandParams)
|
2001-04-06 05:27:53 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIController> controller;
|
2002-01-30 08:15:42 +03:00
|
|
|
nsAutoString tValue;
|
2015-05-11 22:35:14 +03:00
|
|
|
nsresult rv = GetControllerForCommand(aCommandName, aTargetWindow,
|
|
|
|
getter_AddRefs(controller));
|
|
|
|
if (!controller) {
|
2002-07-16 02:04:13 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
2015-05-11 22:35:14 +03:00
|
|
|
}
|
2002-07-16 02:04:13 +04:00
|
|
|
|
2015-05-11 22:35:14 +03:00
|
|
|
nsCOMPtr<nsICommandController> commandController =
|
|
|
|
do_QueryInterface(controller);
|
|
|
|
if (commandController) {
|
|
|
|
rv = commandController->GetCommandStateWithParams(aCommandName,
|
|
|
|
aCommandParams);
|
|
|
|
} else {
|
2002-07-16 02:04:13 +04:00
|
|
|
rv = NS_ERROR_NOT_IMPLEMENTED;
|
2015-05-11 22:35:14 +03:00
|
|
|
}
|
2002-01-30 08:15:42 +03:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-05-11 22:35:14 +03:00
|
|
|
nsCommandManager::DoCommand(const char* aCommandName,
|
|
|
|
nsICommandParams* aCommandParams,
|
2016-01-30 20:05:36 +03:00
|
|
|
mozIDOMWindowProxy* aTargetWindow)
|
2002-01-30 08:15:42 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIController> controller;
|
2015-05-11 22:35:14 +03:00
|
|
|
nsresult rv = GetControllerForCommand(aCommandName, aTargetWindow,
|
|
|
|
getter_AddRefs(controller));
|
|
|
|
if (!controller) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2002-07-16 02:04:13 +04:00
|
|
|
|
2015-05-11 22:35:14 +03:00
|
|
|
nsCOMPtr<nsICommandController> commandController =
|
|
|
|
do_QueryInterface(controller);
|
|
|
|
if (commandController && aCommandParams) {
|
2003-07-18 06:28:09 +04:00
|
|
|
rv = commandController->DoCommandWithParams(aCommandName, aCommandParams);
|
2015-05-11 22:35:14 +03:00
|
|
|
} else {
|
2003-07-18 06:28:09 +04:00
|
|
|
rv = controller->DoCommand(aCommandName);
|
2015-05-11 22:35:14 +03:00
|
|
|
}
|
2002-01-30 08:15:42 +03:00
|
|
|
return rv;
|
2001-04-06 05:27:53 +04:00
|
|
|
}
|
|
|
|
|
2002-11-11 23:15:40 +03:00
|
|
|
nsresult
|
2015-05-11 22:35:14 +03:00
|
|
|
nsCommandManager::GetControllerForCommand(const char* aCommand,
|
2016-01-30 20:05:36 +03:00
|
|
|
mozIDOMWindowProxy* aTargetWindow,
|
2015-05-11 22:35:14 +03:00
|
|
|
nsIController** aResult)
|
2001-04-06 05:27:53 +04:00
|
|
|
{
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
2015-05-11 22:35:14 +03:00
|
|
|
*aResult = nullptr;
|
2002-11-11 23:15:40 +03:00
|
|
|
|
|
|
|
// check if we're in content or chrome
|
|
|
|
// if we're not chrome we must have a target window or we bail
|
2014-09-25 13:04:45 +04:00
|
|
|
if (!nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
|
2015-05-11 22:35:14 +03:00
|
|
|
if (!aTargetWindow) {
|
2002-11-11 23:15:40 +03:00
|
|
|
return rv;
|
2015-05-11 22:35:14 +03:00
|
|
|
}
|
2002-11-11 23:15:40 +03:00
|
|
|
|
|
|
|
// if a target window is specified, it must be the window we expect
|
2015-05-11 22:35:14 +03:00
|
|
|
if (aTargetWindow != mWindow) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2002-11-11 23:15:40 +03:00
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
if (auto* targetWindow = nsPIDOMWindowOuter::From(aTargetWindow)) {
|
2002-11-11 23:15:40 +03:00
|
|
|
// get the controller for this particular window
|
|
|
|
nsCOMPtr<nsIControllers> controllers;
|
2015-10-27 00:37:32 +03:00
|
|
|
rv = targetWindow->GetControllers(getter_AddRefs(controllers));
|
2015-05-11 22:35:14 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
2002-11-11 23:15:40 +03:00
|
|
|
return rv;
|
2015-05-11 22:35:14 +03:00
|
|
|
}
|
|
|
|
if (!controllers) {
|
2002-11-11 23:15:40 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
2015-05-11 22:35:14 +03:00
|
|
|
}
|
2002-11-11 23:15:40 +03:00
|
|
|
|
|
|
|
// dispatch the command
|
2015-05-11 22:35:14 +03:00
|
|
|
return controllers->GetControllerForCommand(aCommand, aResult);
|
2002-11-11 23:15:40 +03:00
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
auto* window = nsPIDOMWindowOuter::From(mWindow);
|
2010-02-20 19:07:03 +03:00
|
|
|
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
|
|
|
nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
|
|
|
|
NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
|
2001-04-06 05:27:53 +04:00
|
|
|
|
2002-11-11 23:15:40 +03:00
|
|
|
// no target window; send command to focus controller
|
2015-05-11 22:35:14 +03:00
|
|
|
return root->GetControllerForCommand(aCommand, aResult);
|
2001-04-06 05:27:53 +04:00
|
|
|
}
|