Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsString.h"
8 #include "nsIController.h"
9 #include "nsIControllers.h"
10 #include "nsIObserver.h"
12 #include "nsIComponentManager.h"
14 #include "nsServiceManagerUtils.h"
15 #include "nsIScriptSecurityManager.h"
17 #include "nsIDOMWindow.h"
18 #include "nsPIDOMWindow.h"
19 #include "nsPIWindowRoot.h"
20 #include "nsIFocusManager.h"
22 #include "nsCOMArray.h"
24 #include "nsCommandManager.h"
27 nsCommandManager::nsCommandManager()
28 : mWindow(nullptr)
29 {
30 /* member initializers and constructor code */
31 }
33 nsCommandManager::~nsCommandManager()
34 {
35 /* destructor code */
36 }
39 static PLDHashOperator
40 TraverseCommandObservers(const char* aKey,
41 nsCommandManager::ObserverList* aObservers,
42 void* aClosure)
43 {
44 nsCycleCollectionTraversalCallback *cb =
45 static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
47 int32_t i, numItems = aObservers->Length();
48 for (i = 0; i < numItems; ++i) {
49 cb->NoteXPCOMChild(aObservers->ElementAt(i));
50 }
52 return PL_DHASH_NEXT;
53 }
55 NS_IMPL_CYCLE_COLLECTION_CLASS(nsCommandManager)
57 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCommandManager)
58 tmp->mObserversTable.Clear();
59 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
60 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCommandManager)
61 tmp->mObserversTable.EnumerateRead(TraverseCommandObservers, &cb);
62 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
64 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCommandManager)
65 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsCommandManager)
67 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsCommandManager)
68 NS_INTERFACE_MAP_ENTRY(nsICommandManager)
69 NS_INTERFACE_MAP_ENTRY(nsPICommandUpdater)
70 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
71 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICommandManager)
72 NS_INTERFACE_MAP_END
74 #if 0
75 #pragma mark -
76 #endif
78 /* void init (in nsIDOMWindow aWindow); */
79 NS_IMETHODIMP
80 nsCommandManager::Init(nsIDOMWindow *aWindow)
81 {
82 NS_ENSURE_ARG_POINTER(aWindow);
84 NS_ASSERTION(aWindow, "Need non-null window here");
85 mWindow = aWindow; // weak ptr
86 return NS_OK;
87 }
89 /* void commandStatusChanged (in DOMString aCommandName, in long aChangeFlags); */
90 NS_IMETHODIMP
91 nsCommandManager::CommandStatusChanged(const char * aCommandName)
92 {
93 ObserverList* commandObservers;
94 mObserversTable.Get(aCommandName, &commandObservers);
96 if (commandObservers)
97 {
98 // XXX Should we worry about observers removing themselves from Observe()?
99 int32_t i, numItems = commandObservers->Length();
100 for (i = 0; i < numItems; ++i)
101 {
102 nsCOMPtr<nsIObserver> observer = commandObservers->ElementAt(i);
103 // should we get the command state to pass here? This might be expensive.
104 observer->Observe(NS_ISUPPORTS_CAST(nsICommandManager*, this),
105 aCommandName,
106 MOZ_UTF16("command_status_changed"));
107 }
108 }
110 return NS_OK;
111 }
113 #if 0
114 #pragma mark -
115 #endif
117 /* void addCommandObserver (in nsIObserver aCommandObserver, in wstring aCommandToObserve); */
118 NS_IMETHODIMP
119 nsCommandManager::AddCommandObserver(nsIObserver *aCommandObserver, const char *aCommandToObserve)
120 {
121 NS_ENSURE_ARG(aCommandObserver);
123 // XXX todo: handle special cases of aCommandToObserve being null, or empty
125 // for each command in the table, we make a list of observers for that command
126 ObserverList* commandObservers;
127 if (!mObserversTable.Get(aCommandToObserve, &commandObservers))
128 {
129 commandObservers = new ObserverList;
130 mObserversTable.Put(aCommandToObserve, commandObservers);
131 }
133 // need to check that this command observer hasn't already been registered
134 int32_t existingIndex = commandObservers->IndexOf(aCommandObserver);
135 if (existingIndex == -1)
136 commandObservers->AppendElement(aCommandObserver);
137 else
138 NS_WARNING("Registering command observer twice on the same command");
140 return NS_OK;
141 }
143 /* void removeCommandObserver (in nsIObserver aCommandObserver, in wstring aCommandObserved); */
144 NS_IMETHODIMP
145 nsCommandManager::RemoveCommandObserver(nsIObserver *aCommandObserver, const char *aCommandObserved)
146 {
147 NS_ENSURE_ARG(aCommandObserver);
149 // XXX todo: handle special cases of aCommandToObserve being null, or empty
151 ObserverList* commandObservers;
152 if (!mObserversTable.Get(aCommandObserved, &commandObservers))
153 return NS_ERROR_UNEXPECTED;
155 commandObservers->RemoveElement(aCommandObserver);
157 return NS_OK;
158 }
160 /* boolean isCommandSupported(in string aCommandName,
161 in nsIDOMWindow aTargetWindow); */
162 NS_IMETHODIMP
163 nsCommandManager::IsCommandSupported(const char *aCommandName,
164 nsIDOMWindow *aTargetWindow,
165 bool *outCommandSupported)
166 {
167 NS_ENSURE_ARG_POINTER(outCommandSupported);
169 nsCOMPtr<nsIController> controller;
170 GetControllerForCommand(aCommandName, aTargetWindow, getter_AddRefs(controller));
171 *outCommandSupported = (controller.get() != nullptr);
172 return NS_OK;
173 }
175 /* boolean isCommandEnabled(in string aCommandName,
176 in nsIDOMWindow aTargetWindow); */
177 NS_IMETHODIMP
178 nsCommandManager::IsCommandEnabled(const char *aCommandName,
179 nsIDOMWindow *aTargetWindow,
180 bool *outCommandEnabled)
181 {
182 NS_ENSURE_ARG_POINTER(outCommandEnabled);
184 bool commandEnabled = false;
186 nsCOMPtr<nsIController> controller;
187 GetControllerForCommand(aCommandName, aTargetWindow, getter_AddRefs(controller));
188 if (controller)
189 {
190 controller->IsCommandEnabled(aCommandName, &commandEnabled);
191 }
192 *outCommandEnabled = commandEnabled;
193 return NS_OK;
194 }
196 /* void getCommandState (in DOMString aCommandName,
197 in nsIDOMWindow aTargetWindow,
198 inout nsICommandParams aCommandParams); */
199 NS_IMETHODIMP
200 nsCommandManager::GetCommandState(const char *aCommandName,
201 nsIDOMWindow *aTargetWindow,
202 nsICommandParams *aCommandParams)
203 {
204 nsCOMPtr<nsIController> controller;
205 nsAutoString tValue;
206 nsresult rv = GetControllerForCommand(aCommandName, aTargetWindow, getter_AddRefs(controller));
207 if (!controller)
208 return NS_ERROR_FAILURE;
210 nsCOMPtr<nsICommandController> commandController = do_QueryInterface(controller);
211 if (commandController)
212 rv = commandController->GetCommandStateWithParams(aCommandName, aCommandParams);
213 else
214 rv = NS_ERROR_NOT_IMPLEMENTED;
215 return rv;
216 }
218 /* void doCommand(in string aCommandName,
219 in nsICommandParams aCommandParams,
220 in nsIDOMWindow aTargetWindow); */
221 NS_IMETHODIMP
222 nsCommandManager::DoCommand(const char *aCommandName,
223 nsICommandParams *aCommandParams,
224 nsIDOMWindow *aTargetWindow)
225 {
226 nsCOMPtr<nsIController> controller;
227 nsresult rv = GetControllerForCommand(aCommandName, aTargetWindow, getter_AddRefs(controller));
228 if (!controller)
229 return NS_ERROR_FAILURE;
231 nsCOMPtr<nsICommandController> commandController = do_QueryInterface(controller);
232 if (commandController && aCommandParams)
233 rv = commandController->DoCommandWithParams(aCommandName, aCommandParams);
234 else
235 rv = controller->DoCommand(aCommandName);
236 return rv;
237 }
239 nsresult
240 nsCommandManager::IsCallerChrome(bool *is_caller_chrome)
241 {
242 *is_caller_chrome = false;
243 nsresult rv = NS_OK;
244 nsCOMPtr<nsIScriptSecurityManager> secMan =
245 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
246 if (NS_FAILED(rv))
247 return rv;
248 if (!secMan)
249 return NS_ERROR_FAILURE;
251 rv = secMan->SubjectPrincipalIsSystem(is_caller_chrome);
252 return rv;
253 }
255 nsresult
256 nsCommandManager::GetControllerForCommand(const char *aCommand,
257 nsIDOMWindow *aTargetWindow,
258 nsIController** outController)
259 {
260 nsresult rv = NS_ERROR_FAILURE;
261 *outController = nullptr;
263 // check if we're in content or chrome
264 // if we're not chrome we must have a target window or we bail
265 bool isChrome = false;
266 rv = IsCallerChrome(&isChrome);
267 if (NS_FAILED(rv))
268 return rv;
270 if (!isChrome) {
271 if (!aTargetWindow)
272 return rv;
274 // if a target window is specified, it must be the window we expect
275 if (aTargetWindow != mWindow)
276 return NS_ERROR_FAILURE;
277 }
279 if (aTargetWindow) {
280 // get the controller for this particular window
281 nsCOMPtr<nsIControllers> controllers;
282 rv = aTargetWindow->GetControllers(getter_AddRefs(controllers));
283 if (NS_FAILED(rv))
284 return rv;
285 if (!controllers)
286 return NS_ERROR_FAILURE;
288 // dispatch the command
289 return controllers->GetControllerForCommand(aCommand, outController);
290 }
292 nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mWindow));
293 NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
294 nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
295 NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
297 // no target window; send command to focus controller
298 return root->GetControllerForCommand(aCommand, outController);
299 }