1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Original Author: David W. Hyatt (hyatt@netscape.com)
24 : * Mark Hammond <MarkH@ActiveState.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : /*
41 :
42 : This file provides the implementation for the XUL "controllers"
43 : object.
44 :
45 : */
46 :
47 : #include "nsString.h"
48 :
49 : #include "nsIControllers.h"
50 : #include "nsIDOMElement.h"
51 : #include "nsXULControllers.h"
52 : #include "nsString.h"
53 : #include "nsContentUtils.h"
54 :
55 : //----------------------------------------------------------------------
56 :
57 0 : nsXULControllers::nsXULControllers()
58 0 : : mCurControllerID(0)
59 : {
60 0 : }
61 :
62 0 : nsXULControllers::~nsXULControllers(void)
63 : {
64 0 : DeleteControllers();
65 0 : }
66 :
67 : void
68 0 : nsXULControllers::DeleteControllers()
69 : {
70 0 : PRUint32 count = mControllers.Length();
71 0 : for (PRUint32 i = 0; i < count; i++)
72 : {
73 0 : nsXULControllerData* controllerData = mControllers.ElementAt(i);
74 0 : delete controllerData; // releases the nsIController
75 : }
76 :
77 0 : mControllers.Clear();
78 0 : }
79 :
80 :
81 : nsresult
82 0 : NS_NewXULControllers(nsISupports* aOuter, REFNSIID aIID, void** aResult)
83 : {
84 0 : NS_PRECONDITION(aOuter == nsnull, "no aggregation");
85 0 : if (aOuter)
86 0 : return NS_ERROR_NO_AGGREGATION;
87 :
88 0 : nsXULControllers* controllers = new nsXULControllers();
89 0 : if (! controllers)
90 0 : return NS_ERROR_OUT_OF_MEMORY;
91 :
92 : nsresult rv;
93 0 : NS_ADDREF(controllers);
94 0 : rv = controllers->QueryInterface(aIID, aResult);
95 0 : NS_RELEASE(controllers);
96 0 : return rv;
97 : }
98 :
99 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULControllers)
100 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULControllers)
101 0 : tmp->DeleteControllers();
102 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
103 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULControllers)
104 : {
105 0 : PRUint32 i, count = tmp->mControllers.Length();
106 0 : for (i = 0; i < count; ++i) {
107 0 : nsXULControllerData* controllerData = tmp->mControllers[i];
108 0 : if (controllerData) {
109 0 : cb.NoteXPCOMChild(controllerData->mController);
110 : }
111 : }
112 : }
113 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
114 :
115 : DOMCI_DATA(XULControllers, nsXULControllers)
116 :
117 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULControllers)
118 0 : NS_INTERFACE_MAP_ENTRY(nsIControllers)
119 0 : NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
120 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIControllers)
121 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULControllers)
122 0 : NS_INTERFACE_MAP_END
123 :
124 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULControllers)
125 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULControllers)
126 :
127 : NS_IMETHODIMP
128 0 : nsXULControllers::GetControllerForCommand(const char *aCommand, nsIController** _retval)
129 : {
130 0 : NS_ENSURE_ARG_POINTER(_retval);
131 0 : *_retval = nsnull;
132 :
133 0 : PRUint32 count = mControllers.Length();
134 0 : for (PRUint32 i=0; i < count; i++)
135 : {
136 0 : nsXULControllerData* controllerData = mControllers.ElementAt(i);
137 0 : if (controllerData)
138 : {
139 0 : nsCOMPtr<nsIController> controller;
140 0 : controllerData->GetController(getter_AddRefs(controller));
141 0 : if (controller)
142 : {
143 : bool supportsCommand;
144 0 : controller->SupportsCommand(aCommand, &supportsCommand);
145 0 : if (supportsCommand) {
146 0 : *_retval = controller;
147 0 : NS_ADDREF(*_retval);
148 0 : return NS_OK;
149 : }
150 : }
151 : }
152 : }
153 :
154 0 : return NS_OK;
155 : }
156 :
157 : NS_IMETHODIMP
158 0 : nsXULControllers::InsertControllerAt(PRUint32 aIndex, nsIController *controller)
159 : {
160 0 : nsXULControllerData* controllerData = new nsXULControllerData(++mCurControllerID, controller);
161 0 : if (!controllerData) return NS_ERROR_OUT_OF_MEMORY;
162 : #ifdef DEBUG
163 : nsXULControllerData** inserted =
164 : #endif
165 0 : mControllers.InsertElementAt(aIndex, controllerData);
166 0 : NS_ASSERTION(inserted != nsnull, "Insertion of controller failed");
167 0 : return NS_OK;
168 : }
169 :
170 : NS_IMETHODIMP
171 0 : nsXULControllers::RemoveControllerAt(PRUint32 aIndex, nsIController **_retval)
172 : {
173 0 : NS_ENSURE_ARG_POINTER(_retval);
174 0 : *_retval = nsnull;
175 :
176 0 : nsXULControllerData* controllerData = mControllers.SafeElementAt(aIndex);
177 0 : if (!controllerData) return NS_ERROR_FAILURE;
178 :
179 0 : mControllers.RemoveElementAt(aIndex);
180 :
181 0 : controllerData->GetController(_retval);
182 0 : delete controllerData;
183 :
184 0 : return NS_OK;
185 : }
186 :
187 :
188 : NS_IMETHODIMP
189 0 : nsXULControllers::GetControllerAt(PRUint32 aIndex, nsIController **_retval)
190 : {
191 0 : NS_ENSURE_ARG_POINTER(_retval);
192 0 : *_retval = nsnull;
193 :
194 0 : nsXULControllerData* controllerData = mControllers.SafeElementAt(aIndex);
195 0 : if (!controllerData) return NS_ERROR_FAILURE;
196 :
197 0 : return controllerData->GetController(_retval); // does the addref
198 : }
199 :
200 : NS_IMETHODIMP
201 0 : nsXULControllers::AppendController(nsIController *controller)
202 : {
203 : // This assigns controller IDs starting at 1 so we can use 0 to test if an ID was obtained
204 0 : nsXULControllerData* controllerData = new nsXULControllerData(++mCurControllerID, controller);
205 0 : if (!controllerData) return NS_ERROR_OUT_OF_MEMORY;
206 :
207 : #ifdef DEBUG
208 : nsXULControllerData** appended =
209 : #endif
210 0 : mControllers.AppendElement(controllerData);
211 0 : NS_ASSERTION(appended != nsnull, "Appending controller failed");
212 0 : return NS_OK;
213 : }
214 :
215 : NS_IMETHODIMP
216 0 : nsXULControllers::RemoveController(nsIController *controller)
217 : {
218 : // first get the identity pointer
219 0 : nsCOMPtr<nsISupports> controllerSup(do_QueryInterface(controller));
220 : // then find it
221 0 : PRUint32 count = mControllers.Length();
222 0 : for (PRUint32 i = 0; i < count; i++)
223 : {
224 0 : nsXULControllerData* controllerData = mControllers.ElementAt(i);
225 0 : if (controllerData)
226 : {
227 0 : nsCOMPtr<nsIController> thisController;
228 0 : controllerData->GetController(getter_AddRefs(thisController));
229 0 : nsCOMPtr<nsISupports> thisControllerSup(do_QueryInterface(thisController)); // get identity
230 0 : if (thisControllerSup == controllerSup)
231 : {
232 0 : mControllers.RemoveElementAt(i);
233 0 : delete controllerData;
234 0 : return NS_OK;
235 : }
236 : }
237 : }
238 0 : return NS_ERROR_FAILURE; // right thing to return if no controller found?
239 : }
240 :
241 : /* unsigned long getControllerId (in nsIController controller); */
242 : NS_IMETHODIMP
243 0 : nsXULControllers::GetControllerId(nsIController *controller, PRUint32 *_retval)
244 : {
245 0 : NS_ENSURE_ARG_POINTER(_retval);
246 :
247 0 : PRUint32 count = mControllers.Length();
248 0 : for (PRUint32 i = 0; i < count; i++)
249 : {
250 0 : nsXULControllerData* controllerData = mControllers.ElementAt(i);
251 0 : if (controllerData)
252 : {
253 0 : nsCOMPtr<nsIController> thisController;
254 0 : controllerData->GetController(getter_AddRefs(thisController));
255 0 : if (thisController.get() == controller)
256 : {
257 0 : *_retval = controllerData->GetControllerID();
258 0 : return NS_OK;
259 : }
260 : }
261 : }
262 0 : return NS_ERROR_FAILURE; // none found
263 : }
264 :
265 : /* nsIController getControllerById (in unsigned long controllerID); */
266 : NS_IMETHODIMP
267 0 : nsXULControllers::GetControllerById(PRUint32 controllerID, nsIController **_retval)
268 : {
269 0 : NS_ENSURE_ARG_POINTER(_retval);
270 :
271 0 : PRUint32 count = mControllers.Length();
272 0 : for (PRUint32 i = 0; i < count; i++)
273 : {
274 0 : nsXULControllerData* controllerData = mControllers.ElementAt(i);
275 0 : if (controllerData && controllerData->GetControllerID() == controllerID)
276 : {
277 0 : return controllerData->GetController(_retval);
278 : }
279 : }
280 0 : return NS_ERROR_FAILURE; // none found
281 : }
282 :
283 : NS_IMETHODIMP
284 0 : nsXULControllers::GetControllerCount(PRUint32 *_retval)
285 : {
286 0 : NS_ENSURE_ARG_POINTER(_retval);
287 0 : *_retval = mControllers.Length();
288 0 : return NS_OK;
289 : }
290 :
291 : // nsISecurityCheckedComponent implementation
292 :
293 0 : static char* cloneAllAccess()
294 : {
295 : static const char allAccess[] = "AllAccess";
296 0 : return (char*)nsMemory::Clone(allAccess, sizeof(allAccess));
297 : }
298 :
299 0 : static char* cloneUniversalXPConnect()
300 : {
301 : static const char universalXPConnect[] = "UniversalXPConnect";
302 0 : return (char*)nsMemory::Clone(universalXPConnect, sizeof(universalXPConnect));
303 : }
304 :
305 : NS_IMETHODIMP
306 0 : nsXULControllers::CanCreateWrapper(const nsIID * iid, char **_retval)
307 : {
308 0 : *_retval = cloneAllAccess();
309 0 : return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
310 : }
311 :
312 : NS_IMETHODIMP
313 0 : nsXULControllers::CanCallMethod(const nsIID * iid, const PRUnichar *methodName,
314 : char **_retval)
315 : {
316 : // OK if you're cool enough
317 0 : *_retval = cloneUniversalXPConnect();
318 0 : return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
319 : }
320 :
321 : NS_IMETHODIMP
322 0 : nsXULControllers::CanGetProperty(const nsIID * iid,
323 : const PRUnichar *propertyName,
324 : char **_retval)
325 : {
326 : // OK if you're cool enough
327 0 : *_retval = cloneUniversalXPConnect();
328 0 : return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
329 : }
330 :
331 :
332 : NS_IMETHODIMP
333 0 : nsXULControllers::CanSetProperty(const nsIID * iid,
334 : const PRUnichar *propertyName,
335 : char **_retval)
336 : {
337 : // OK if you're cool enough
338 0 : *_retval = cloneUniversalXPConnect();
339 0 : return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
340 4392 : }
|