1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 Neil Deakin
18 : * Portions created by the Initial Developer are Copyright (C) 2006
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Laurent Jouanneau <laurent.jouanneau@disruptive-innovations.com>
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "nsCOMPtr.h"
39 : #include "nsAutoPtr.h"
40 : #include "nsIDOMDocument.h"
41 : #include "nsIDOMXMLDocument.h"
42 : #include "nsIDOMNode.h"
43 : #include "nsIDOMNodeList.h"
44 : #include "nsIDOMElement.h"
45 : #include "nsIDOMEvent.h"
46 : #include "nsIDOMEventTarget.h"
47 : #include "nsIDOMXPathNSResolver.h"
48 : #include "nsIDocument.h"
49 : #include "nsIContent.h"
50 : #include "nsINameSpaceManager.h"
51 : #include "nsGkAtoms.h"
52 : #include "nsIServiceManager.h"
53 : #include "nsUnicharUtils.h"
54 : #include "nsIURI.h"
55 : #include "nsIArray.h"
56 : #include "nsContentUtils.h"
57 : #include "nsArrayUtils.h"
58 : #include "nsPIDOMWindow.h"
59 : #include "nsXULContentUtils.h"
60 :
61 : #include "nsXULTemplateBuilder.h"
62 : #include "nsXULTemplateQueryProcessorXML.h"
63 : #include "nsXULTemplateResultXML.h"
64 : #include "nsXULSortService.h"
65 :
66 0 : NS_IMPL_ISUPPORTS1(nsXMLQuery, nsXMLQuery)
67 :
68 : //----------------------------------------------------------------------
69 : //
70 : // nsXULTemplateResultSetXML
71 : //
72 :
73 0 : NS_IMPL_ISUPPORTS1(nsXULTemplateResultSetXML, nsISimpleEnumerator)
74 :
75 : NS_IMETHODIMP
76 0 : nsXULTemplateResultSetXML::HasMoreElements(bool *aResult)
77 : {
78 : // if GetSnapshotLength failed, then the return type was not a set of
79 : // nodes, so just return false in this case.
80 : PRUint32 length;
81 0 : if (NS_SUCCEEDED(mResults->GetSnapshotLength(&length)))
82 0 : *aResult = (mPosition < length);
83 : else
84 0 : *aResult = false;
85 :
86 0 : return NS_OK;
87 : }
88 :
89 : NS_IMETHODIMP
90 0 : nsXULTemplateResultSetXML::GetNext(nsISupports **aResult)
91 : {
92 0 : nsCOMPtr<nsIDOMNode> node;
93 0 : nsresult rv = mResults->SnapshotItem(mPosition, getter_AddRefs(node));
94 0 : NS_ENSURE_SUCCESS(rv, rv);
95 :
96 : nsXULTemplateResultXML* result =
97 0 : new nsXULTemplateResultXML(mQuery, node, mBindingSet);
98 0 : NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
99 :
100 0 : ++mPosition;
101 0 : *aResult = result;
102 0 : NS_ADDREF(result);
103 0 : return NS_OK;
104 : }
105 :
106 :
107 : //----------------------------------------------------------------------
108 : //
109 : // nsXULTemplateQueryProcessorXML
110 : //
111 :
112 : static PLDHashOperator
113 0 : TraverseRuleToBindingsMap(nsISupports* aKey, nsXMLBindingSet* aMatch, void* aContext)
114 : {
115 : nsCycleCollectionTraversalCallback *cb =
116 0 : static_cast<nsCycleCollectionTraversalCallback*>(aContext);
117 0 : NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap key");
118 0 : cb->NoteXPCOMChild(aKey);
119 0 : NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap value");
120 0 : cb->NoteNativeChild(aMatch, &NS_CYCLE_COLLECTION_NAME(nsXMLBindingSet));
121 0 : return PL_DHASH_NEXT;
122 : }
123 :
124 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorXML)
125 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorXML)
126 0 : if (tmp->mRuleToBindingsMap.IsInitialized()) {
127 0 : tmp->mRuleToBindingsMap.Clear();
128 : }
129 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRoot)
130 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mEvaluator)
131 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTemplateBuilder)
132 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRequest)
133 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
134 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateQueryProcessorXML)
135 0 : if (tmp->mRuleToBindingsMap.IsInitialized()) {
136 0 : tmp->mRuleToBindingsMap.EnumerateRead(TraverseRuleToBindingsMap, &cb);
137 : }
138 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
139 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEvaluator)
140 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTemplateBuilder)
141 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRequest)
142 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
143 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULTemplateQueryProcessorXML)
144 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULTemplateQueryProcessorXML)
145 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULTemplateQueryProcessorXML)
146 0 : NS_INTERFACE_MAP_ENTRY(nsIXULTemplateQueryProcessor)
147 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
148 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULTemplateQueryProcessor)
149 0 : NS_INTERFACE_MAP_END
150 :
151 : /*
152 : * Only the first datasource in aDataSource is used, which should be either an
153 : * nsIURI of an XML document, or a DOM node. If the former, GetDatasource will
154 : * load the document asynchronously and return null in aResult. Once the
155 : * document has loaded, the builder's datasource will be set to the XML
156 : * document. If the datasource is a DOM node, the node will be returned in
157 : * aResult.
158 : */
159 : NS_IMETHODIMP
160 0 : nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
161 : nsIDOMNode* aRootNode,
162 : bool aIsTrusted,
163 : nsIXULTemplateBuilder* aBuilder,
164 : bool* aShouldDelayBuilding,
165 : nsISupports** aResult)
166 : {
167 0 : *aResult = nsnull;
168 0 : *aShouldDelayBuilding = false;
169 :
170 : nsresult rv;
171 : PRUint32 length;
172 :
173 0 : aDataSources->GetLength(&length);
174 0 : if (length == 0)
175 0 : return NS_OK;
176 :
177 : // we get only the first item, because the query processor supports only
178 : // one document as a datasource
179 :
180 0 : nsCOMPtr<nsIDOMNode> node = do_QueryElementAt(aDataSources, 0);
181 0 : if (node) {
182 0 : return CallQueryInterface(node, aResult);
183 : }
184 :
185 0 : nsCOMPtr<nsIURI> uri = do_QueryElementAt(aDataSources, 0);
186 0 : if (!uri)
187 0 : return NS_ERROR_UNEXPECTED;
188 :
189 0 : nsCAutoString uriStr;
190 0 : rv = uri->GetSpec(uriStr);
191 0 : NS_ENSURE_SUCCESS(rv, rv);
192 :
193 0 : nsCOMPtr<nsIContent> root = do_QueryInterface(aRootNode);
194 0 : if (!root)
195 0 : return NS_ERROR_UNEXPECTED;
196 :
197 0 : nsCOMPtr<nsIDocument> doc = root->GetCurrentDoc();
198 0 : if (!doc)
199 0 : return NS_ERROR_UNEXPECTED;
200 :
201 0 : nsIPrincipal *docPrincipal = doc->NodePrincipal();
202 :
203 0 : bool hasHadScriptObject = true;
204 : nsIScriptGlobalObject* scriptObject =
205 0 : doc->GetScriptHandlingObject(hasHadScriptObject);
206 0 : NS_ENSURE_STATE(scriptObject);
207 :
208 0 : nsIScriptContext *context = scriptObject->GetContext();
209 0 : NS_ENSURE_TRUE(context, NS_OK);
210 :
211 : nsCOMPtr<nsIXMLHttpRequest> req =
212 0 : do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
213 0 : NS_ENSURE_SUCCESS(rv, rv);
214 :
215 0 : nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(scriptObject);
216 0 : req->Init(docPrincipal, context, owner, nsnull);
217 :
218 0 : rv = req->Open(NS_LITERAL_CSTRING("GET"), uriStr, true,
219 0 : EmptyString(), EmptyString());
220 0 : NS_ENSURE_SUCCESS(rv, rv);
221 :
222 0 : nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(req));
223 0 : rv = target->AddEventListener(NS_LITERAL_STRING("load"), this, false);
224 0 : NS_ENSURE_SUCCESS(rv, rv);
225 :
226 0 : rv = target->AddEventListener(NS_LITERAL_STRING("error"), this, false);
227 0 : NS_ENSURE_SUCCESS(rv, rv);
228 :
229 0 : rv = req->Send(nsnull);
230 0 : NS_ENSURE_SUCCESS(rv, rv);
231 :
232 0 : mTemplateBuilder = aBuilder;
233 0 : mRequest = req;
234 :
235 0 : *aShouldDelayBuilding = true;
236 0 : return NS_OK;
237 : }
238 :
239 : NS_IMETHODIMP
240 0 : nsXULTemplateQueryProcessorXML::InitializeForBuilding(nsISupports* aDatasource,
241 : nsIXULTemplateBuilder* aBuilder,
242 : nsIDOMNode* aRootNode)
243 : {
244 0 : if (mGenerationStarted)
245 0 : return NS_ERROR_UNEXPECTED;
246 :
247 : // the datasource is either a document or a DOM element
248 0 : nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDatasource);
249 0 : if (doc)
250 0 : doc->GetDocumentElement(getter_AddRefs(mRoot));
251 : else
252 0 : mRoot = do_QueryInterface(aDatasource);
253 0 : NS_ENSURE_STATE(mRoot);
254 :
255 0 : mEvaluator = do_CreateInstance("@mozilla.org/dom/xpath-evaluator;1");
256 0 : NS_ENSURE_TRUE(mEvaluator, NS_ERROR_OUT_OF_MEMORY);
257 :
258 0 : if (!mRuleToBindingsMap.IsInitialized() &&
259 0 : !mRuleToBindingsMap.Init())
260 0 : return NS_ERROR_OUT_OF_MEMORY;
261 :
262 0 : return NS_OK;
263 : }
264 :
265 : NS_IMETHODIMP
266 0 : nsXULTemplateQueryProcessorXML::Done()
267 : {
268 0 : mGenerationStarted = false;
269 :
270 0 : if (mRuleToBindingsMap.IsInitialized())
271 0 : mRuleToBindingsMap.Clear();
272 :
273 0 : return NS_OK;
274 : }
275 :
276 : NS_IMETHODIMP
277 0 : nsXULTemplateQueryProcessorXML::CompileQuery(nsIXULTemplateBuilder* aBuilder,
278 : nsIDOMNode* aQueryNode,
279 : nsIAtom* aRefVariable,
280 : nsIAtom* aMemberVariable,
281 : nsISupports** _retval)
282 : {
283 0 : nsresult rv = NS_OK;
284 :
285 0 : *_retval = nsnull;
286 :
287 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(aQueryNode);
288 :
289 0 : nsAutoString expr;
290 0 : content->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
291 :
292 : // if an expression is not specified, then the default is to
293 : // just take all of the children
294 0 : if (expr.IsEmpty())
295 0 : expr.AssignLiteral("*");
296 :
297 0 : nsCOMPtr<nsIDOMXPathExpression> compiledexpr;
298 0 : rv = CreateExpression(expr, aQueryNode, getter_AddRefs(compiledexpr));
299 0 : if (NS_FAILED(rv)) {
300 0 : nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_XPATH);
301 0 : return rv;
302 : }
303 :
304 : nsRefPtr<nsXMLQuery> query =
305 0 : new nsXMLQuery(this, aMemberVariable, compiledexpr);
306 0 : NS_ENSURE_TRUE(query, NS_ERROR_OUT_OF_MEMORY);
307 :
308 0 : for (nsIContent* condition = content->GetFirstChild();
309 : condition;
310 0 : condition = condition->GetNextSibling()) {
311 :
312 0 : if (condition->NodeInfo()->Equals(nsGkAtoms::assign,
313 0 : kNameSpaceID_XUL)) {
314 0 : nsAutoString var;
315 0 : condition->GetAttr(kNameSpaceID_None, nsGkAtoms::var, var);
316 :
317 0 : nsAutoString expr;
318 0 : condition->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
319 :
320 : // ignore assignments without a variable or an expression
321 0 : if (!var.IsEmpty() && !expr.IsEmpty()) {
322 : nsCOMPtr<nsIDOMNode> conditionNode =
323 0 : do_QueryInterface(condition);
324 : rv = CreateExpression(expr, conditionNode,
325 0 : getter_AddRefs(compiledexpr));
326 0 : if (NS_FAILED(rv)) {
327 0 : nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_ASSIGN_XPATH);
328 0 : return rv;
329 : }
330 :
331 0 : nsCOMPtr<nsIAtom> varatom = do_GetAtom(var);
332 :
333 0 : rv = query->AddBinding(varatom, compiledexpr);
334 0 : NS_ENSURE_SUCCESS(rv, rv);
335 : }
336 : }
337 : }
338 :
339 0 : *_retval = query;
340 0 : NS_ADDREF(*_retval);
341 :
342 0 : return rv;
343 : }
344 :
345 : NS_IMETHODIMP
346 0 : nsXULTemplateQueryProcessorXML::GenerateResults(nsISupports* aDatasource,
347 : nsIXULTemplateResult* aRef,
348 : nsISupports* aQuery,
349 : nsISimpleEnumerator** aResults)
350 : {
351 0 : if (!aQuery)
352 0 : return NS_ERROR_INVALID_ARG;
353 :
354 0 : mGenerationStarted = true;
355 :
356 0 : nsCOMPtr<nsXMLQuery> xmlquery = do_QueryInterface(aQuery);
357 0 : if (!xmlquery)
358 0 : return NS_ERROR_INVALID_ARG;
359 :
360 0 : nsCOMPtr<nsIDOMNode> context;
361 0 : if (aRef)
362 : aRef->GetBindingObjectFor(xmlquery->GetMemberVariable(),
363 0 : getter_AddRefs(context));
364 0 : if (!context)
365 0 : context = mRoot;
366 :
367 0 : nsIDOMXPathExpression* expr = xmlquery->GetResultsExpression();
368 0 : if (!expr)
369 0 : return NS_ERROR_FAILURE;
370 :
371 0 : nsCOMPtr<nsISupports> exprsupportsresults;
372 : nsresult rv = expr->Evaluate(context,
373 : nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
374 0 : nsnull, getter_AddRefs(exprsupportsresults));
375 0 : NS_ENSURE_SUCCESS(rv, rv);
376 :
377 : nsCOMPtr<nsIDOMXPathResult> exprresults =
378 0 : do_QueryInterface(exprsupportsresults);
379 :
380 : nsXULTemplateResultSetXML* results =
381 : new nsXULTemplateResultSetXML(xmlquery, exprresults,
382 0 : xmlquery->GetBindingSet());
383 0 : NS_ENSURE_TRUE(results, NS_ERROR_OUT_OF_MEMORY);
384 :
385 0 : *aResults = results;
386 0 : NS_ADDREF(*aResults);
387 :
388 0 : return NS_OK;
389 : }
390 :
391 : NS_IMETHODIMP
392 0 : nsXULTemplateQueryProcessorXML::AddBinding(nsIDOMNode* aRuleNode,
393 : nsIAtom* aVar,
394 : nsIAtom* aRef,
395 : const nsAString& aExpr)
396 : {
397 0 : if (mGenerationStarted)
398 0 : return NS_ERROR_FAILURE;
399 :
400 0 : nsRefPtr<nsXMLBindingSet> bindings = mRuleToBindingsMap.GetWeak(aRuleNode);
401 0 : if (!bindings) {
402 0 : bindings = new nsXMLBindingSet();
403 0 : if (!bindings || !mRuleToBindingsMap.Put(aRuleNode, bindings))
404 0 : return NS_ERROR_OUT_OF_MEMORY;
405 : }
406 :
407 0 : nsCOMPtr<nsIDOMXPathExpression> compiledexpr;
408 : nsresult rv =
409 0 : CreateExpression(aExpr, aRuleNode, getter_AddRefs(compiledexpr));
410 0 : if (NS_FAILED(rv)) {
411 0 : nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_BINDING_XPATH);
412 0 : return NS_OK;
413 : }
414 :
415 : // aRef isn't currently used for XML query processors
416 0 : return bindings->AddBinding(aVar, compiledexpr);
417 : }
418 :
419 : NS_IMETHODIMP
420 0 : nsXULTemplateQueryProcessorXML::TranslateRef(nsISupports* aDatasource,
421 : const nsAString& aRefString,
422 : nsIXULTemplateResult** aRef)
423 : {
424 0 : *aRef = nsnull;
425 :
426 : // the datasource is either a document or a DOM element
427 0 : nsCOMPtr<nsIDOMElement> rootElement;
428 0 : nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDatasource);
429 0 : if (doc)
430 0 : doc->GetDocumentElement(getter_AddRefs(rootElement));
431 : else
432 0 : rootElement = do_QueryInterface(aDatasource);
433 :
434 : // if no root element, just return. The document may not have loaded yet
435 0 : if (!rootElement)
436 0 : return NS_OK;
437 :
438 : nsXULTemplateResultXML* result =
439 0 : new nsXULTemplateResultXML(nsnull, rootElement, nsnull);
440 0 : NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
441 :
442 0 : *aRef = result;
443 0 : NS_ADDREF(*aRef);
444 :
445 0 : return NS_OK;
446 : }
447 :
448 :
449 : NS_IMETHODIMP
450 0 : nsXULTemplateQueryProcessorXML::CompareResults(nsIXULTemplateResult* aLeft,
451 : nsIXULTemplateResult* aRight,
452 : nsIAtom* aVar,
453 : PRUint32 aSortHints,
454 : PRInt32* aResult)
455 : {
456 0 : *aResult = 0;
457 0 : if (!aVar)
458 0 : return NS_OK;
459 :
460 0 : nsAutoString leftVal;
461 0 : if (aLeft)
462 0 : aLeft->GetBindingFor(aVar, leftVal);
463 :
464 0 : nsAutoString rightVal;
465 0 : if (aRight)
466 0 : aRight->GetBindingFor(aVar, rightVal);
467 :
468 0 : *aResult = XULSortServiceImpl::CompareValues(leftVal, rightVal, aSortHints);
469 0 : return NS_OK;
470 : }
471 :
472 : nsXMLBindingSet*
473 0 : nsXULTemplateQueryProcessorXML::GetOptionalBindingsForRule(nsIDOMNode* aRuleNode)
474 : {
475 0 : return mRuleToBindingsMap.GetWeak(aRuleNode);
476 : }
477 :
478 : nsresult
479 0 : nsXULTemplateQueryProcessorXML::CreateExpression(const nsAString& aExpr,
480 : nsIDOMNode* aNode,
481 : nsIDOMXPathExpression** aCompiledExpr)
482 : {
483 0 : nsCOMPtr<nsIDOMXPathNSResolver> nsResolver;
484 :
485 0 : nsCOMPtr<nsIDOMDocument> doc;
486 0 : aNode->GetOwnerDocument(getter_AddRefs(doc));
487 :
488 0 : nsCOMPtr<nsIDOMXPathEvaluator> eval = do_QueryInterface(doc);
489 0 : if (eval) {
490 : nsresult rv =
491 0 : eval->CreateNSResolver(aNode, getter_AddRefs(nsResolver));
492 0 : NS_ENSURE_SUCCESS(rv, rv);
493 : }
494 :
495 0 : return mEvaluator->CreateExpression(aExpr, nsResolver, aCompiledExpr);
496 : }
497 :
498 : NS_IMETHODIMP
499 0 : nsXULTemplateQueryProcessorXML::HandleEvent(nsIDOMEvent* aEvent)
500 : {
501 0 : NS_PRECONDITION(aEvent, "aEvent null");
502 0 : nsAutoString eventType;
503 0 : aEvent->GetType(eventType);
504 :
505 0 : if (eventType.EqualsLiteral("load") && mTemplateBuilder) {
506 0 : NS_ASSERTION(mRequest, "request was not set");
507 0 : nsCOMPtr<nsIDOMDocument> doc;
508 0 : if (NS_SUCCEEDED(mRequest->GetResponseXML(getter_AddRefs(doc))))
509 0 : mTemplateBuilder->SetDatasource(doc);
510 :
511 : // to avoid leak. we don't need it after...
512 0 : mTemplateBuilder = nsnull;
513 0 : mRequest = nsnull;
514 : }
515 0 : else if (eventType.EqualsLiteral("error")) {
516 0 : mTemplateBuilder = nsnull;
517 0 : mRequest = nsnull;
518 : }
519 :
520 0 : return NS_OK;
521 4392 : }
|