1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=2 sw=2 et tw=78:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is Mozilla Communicator client code, released
20 * The Initial Developer of the Original Code is
21 * Netscape Communications Corporation.
22 * Portions created by the Initial Developer are Copyright (C) 1998
23 * the Initial Developer. All Rights Reserved.
26 * Johnny Stenback <jst@netscape.com>
27 * Christopher A. Aillon <christopher@aillon.com>
29 * Alternatively, the contents of this file may be used under the terms of
30 * either of the GNU General Public License Version 2 or later (the "GPL"),
31 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32 * in which case the provisions of the GPL or the LGPL are applicable instead
33 * of those above. If you wish to allow use of your version of this file only
34 * under the terms of either the GPL or the LGPL, and not to allow others to
35 * use your version of this file under the terms of the MPL, indicate your
36 * decision by deleting the provisions above and replace them with the notice
37 * and other provisions required by the GPL or the LGPL. If you do not delete
38 * the provisions above, a recipient may use your version of this file under
39 * the terms of any one of the MPL, the GPL or the LGPL.
41 * ***** END LICENSE BLOCK ***** */
43 /* A namespace class for static layout utilities. */
47 #include "nsJSUtils.h"
49 #include "nsAString.h"
50 #include "nsPrintfCString.h"
51 #include "nsUnicharUtils.h"
52 #include "nsIPrefService.h"
53 #include "nsIPrefBranch2.h"
54 #include "nsIPrefLocalizedString.h"
55 #include "nsServiceManagerUtils.h"
56 #include "nsIScriptGlobalObject.h"
57 #include "nsIScriptContext.h"
58 #include "nsIDOMScriptObjectFactory.h"
60 #include "nsContentUtils.h"
61 #include "nsIContentUtils.h"
62 #include "nsIXPConnect.h"
63 #include "nsIContent.h"
64 #include "mozilla/dom/Element.h"
65 #include "nsIDocument.h"
66 #include "nsINodeInfo.h"
67 #include "nsReadableUtils.h"
68 #include "nsIDOMDocument.h"
69 #include "nsIDOMNodeList.h"
70 #include "nsIDOMNode.h"
71 #include "nsIDOM3Node.h"
72 #include "nsIIOService.h"
74 #include "nsNetUtil.h"
75 #include "nsIScriptSecurityManager.h"
76 #include "nsDOMError.h"
77 #include "nsPIDOMWindow.h"
78 #include "nsIJSContextStack.h"
79 #include "nsIDocShell.h"
80 #include "nsIDocShellTreeItem.h"
81 #include "nsParserCIID.h"
82 #include "nsIParser.h"
83 #include "nsIFragmentContentSink.h"
84 #include "nsIContentSink.h"
85 #include "nsIHTMLContentSink.h"
86 #include "nsIXMLContentSink.h"
87 #include "nsHTMLParts.h"
88 #include "nsIParserService.h"
89 #include "nsIServiceManager.h"
90 #include "nsIAttribute.h"
91 #include "nsContentList.h"
92 #include "nsIHTMLDocument.h"
93 #include "nsIDOMHTMLDocument.h"
94 #include "nsIDOMHTMLCollection.h"
95 #include "nsIDOMHTMLFormElement.h"
96 #include "nsIDOMNSHTMLElement.h"
98 #include "nsIFormControl.h"
99 #include "nsGkAtoms.h"
100 #include "nsISupportsPrimitives.h"
101 #include "imgIDecoderObserver.h"
102 #include "imgIRequest.h"
103 #include "imgIContainer.h"
104 #include "imgILoader.h"
105 #include "mozilla/IHistory.h"
106 #include "nsDocShellCID.h"
107 #include "nsIImageLoadingContent.h"
108 #include "nsIInterfaceRequestor.h"
109 #include "nsIInterfaceRequestorUtils.h"
110 #include "nsILoadGroup.h"
111 #include "nsIObserver.h"
112 #include "nsIObserverService.h"
113 #include "nsContentPolicyUtils.h"
114 #include "nsNodeInfoManager.h"
115 #include "nsIXBLService.h"
117 #include "nsIDOMEvent.h"
118 #include "nsIDOMEventTarget.h"
119 #include "nsIPrivateDOMEvent.h"
120 #include "nsIDOMDocumentEvent.h"
122 #include "nsIXTFService.h"
123 static NS_DEFINE_CID(kXTFServiceCID
, NS_XTFSERVICE_CID
);
125 #include "nsIMIMEService.h"
126 #include "nsLWBrkCIID.h"
127 #include "nsILineBreaker.h"
128 #include "nsIWordBreaker.h"
129 #include "jsdbgapi.h"
130 #include "nsIJSRuntimeService.h"
131 #include "nsIDOMDocumentXBL.h"
132 #include "nsBindingManager.h"
135 #include "nsXBLBinding.h"
136 #include "nsXBLPrototypeBinding.h"
137 #include "nsEscape.h"
138 #include "nsICharsetConverterManager.h"
139 #include "nsIEventListenerManager.h"
140 #include "nsAttrName.h"
141 #include "nsIDOMUserDataHandler.h"
142 #include "nsContentCreatorFunctions.h"
143 #include "nsTPtrArray.h"
144 #include "nsGUIEvent.h"
145 #include "nsMutationEvent.h"
146 #include "nsIMEStateManager.h"
147 #include "nsContentErrors.h"
148 #include "nsUnicharUtilCIID.h"
149 #include "nsICaseConversion.h"
150 #include "nsCompressedCharMap.h"
151 #include "nsINativeKeyBindings.h"
152 #include "nsIDOMNSUIEvent.h"
153 #include "nsIDOMNSEvent.h"
154 #include "nsIPrivateDOMEvent.h"
155 #include "nsXULPopupManager.h"
156 #include "nsIPermissionManager.h"
157 #include "nsIScriptObjectPrincipal.h"
158 #include "nsIRunnable.h"
159 #include "nsDOMJSUtils.h"
160 #include "nsGenericHTMLElement.h"
161 #include "nsAttrValue.h"
162 #include "nsReferencedElement.h"
163 #include "nsIUGenCategory.h"
164 #include "nsIDragService.h"
165 #include "nsIChannelEventSink.h"
166 #include "nsIInterfaceRequestor.h"
167 #include "nsIOfflineCacheUpdate.h"
168 #include "nsCPrefetchService.h"
169 #include "nsIChromeRegistry.h"
170 #include "nsIMIMEHeaderParam.h"
171 #include "nsIDOMXULCommandEvent.h"
172 #include "nsIDOMAbstractView.h"
173 #include "nsIDOMDragEvent.h"
174 #include "nsDOMDataTransfer.h"
175 #include "nsHtml5Module.h"
176 #include "nsPresContext.h"
177 #include "nsLayoutStatics.h"
178 #include "nsLayoutUtils.h"
179 #include "nsFrameManager.h"
180 #include "BasicLayers.h"
181 #include "nsFocusManager.h"
182 #include "nsTextEditorState.h"
185 #include "nsIBidiKeyboard.h"
187 #include "nsCycleCollectionParticipant.h"
189 // for ReportToConsole
190 #include "nsIStringBundle.h"
191 #include "nsIScriptError.h"
192 #include "nsIConsoleService.h"
194 #include "mozAutoDocUpdate.h"
195 #include "imgICache.h"
196 #include "jsinterp.h"
199 #include "jsregexp.h"
200 #include "jstypedarray.h"
201 #include "xpcprivate.h"
202 #include "nsScriptSecurityManager.h"
203 #include "nsIChannelPolicy.h"
204 #include "nsChannelPolicy.h"
205 #include "nsIContentSecurityPolicy.h"
207 using namespace mozilla::dom
;
209 const char kLoadAsData
[] = "loadAsData";
211 static const char kJSStackContractID
[] = "@mozilla.org/js/xpc/ContextStack;1";
212 static NS_DEFINE_CID(kParserServiceCID
, NS_PARSERSERVICE_CID
);
213 static NS_DEFINE_CID(kCParserCID
, NS_PARSER_CID
);
215 nsIDOMScriptObjectFactory
*nsContentUtils::sDOMScriptObjectFactory
= nsnull
;
216 nsIXPConnect
*nsContentUtils::sXPConnect
;
217 nsIScriptSecurityManager
*nsContentUtils::sSecurityManager
;
218 nsIThreadJSContextStack
*nsContentUtils::sThreadJSContextStack
;
219 nsIParserService
*nsContentUtils::sParserService
= nsnull
;
220 nsINameSpaceManager
*nsContentUtils::sNameSpaceManager
;
221 nsIIOService
*nsContentUtils::sIOService
;
223 nsIXTFService
*nsContentUtils::sXTFService
= nsnull
;
225 nsIPrefBranch2
*nsContentUtils::sPrefBranch
= nsnull
;
226 imgILoader
*nsContentUtils::sImgLoader
;
227 imgICache
*nsContentUtils::sImgCache
;
228 mozilla::IHistory
*nsContentUtils::sHistory
;
229 nsIConsoleService
*nsContentUtils::sConsoleService
;
230 nsDataHashtable
<nsISupportsHashKey
, EventNameMapping
>* nsContentUtils::sEventTable
= nsnull
;
231 nsIStringBundleService
*nsContentUtils::sStringBundleService
;
232 nsIStringBundle
*nsContentUtils::sStringBundles
[PropertiesFile_COUNT
];
233 nsIContentPolicy
*nsContentUtils::sContentPolicyService
;
234 PRBool
nsContentUtils::sTriedToGetContentPolicy
= PR_FALSE
;
235 nsILineBreaker
*nsContentUtils::sLineBreaker
;
236 nsIWordBreaker
*nsContentUtils::sWordBreaker
;
237 nsICaseConversion
*nsContentUtils::sCaseConv
;
238 nsIUGenCategory
*nsContentUtils::sGenCat
;
239 nsTArray
<nsISupports
**> *nsContentUtils::sPtrsToPtrsToRelease
;
240 nsIScriptRuntime
*nsContentUtils::sScriptRuntimes
[NS_STID_ARRAY_UBOUND
];
241 PRInt32
nsContentUtils::sScriptRootCount
[NS_STID_ARRAY_UBOUND
];
242 PRUint32
nsContentUtils::sJSGCThingRootCount
;
244 nsIBidiKeyboard
*nsContentUtils::sBidiKeyboard
= nsnull
;
246 PRUint32
nsContentUtils::sScriptBlockerCount
= 0;
247 PRUint32
nsContentUtils::sRemovableScriptBlockerCount
= 0;
248 nsCOMArray
<nsIRunnable
>* nsContentUtils::sBlockedScriptRunners
= nsnull
;
249 PRUint32
nsContentUtils::sRunnersCountAtFirstBlocker
= 0;
250 PRUint32
nsContentUtils::sScriptBlockerCountWhereRunnersPrevented
= 0;
251 nsIInterfaceRequestor
* nsContentUtils::sSameOriginChecker
= nsnull
;
253 nsIJSRuntimeService
*nsAutoGCRoot::sJSRuntimeService
;
254 JSRuntime
*nsAutoGCRoot::sJSScriptRuntime
;
256 PRBool
nsContentUtils::sIsHandlingKeyBoardEvent
= PR_FALSE
;
258 PRBool
nsContentUtils::sInitialized
= PR_FALSE
;
260 nsCOMArray
<nsPrefOldCallback
> *nsContentUtils::sPrefCallbackList
= nsnull
;
262 static PLDHashTable sEventListenerManagersHash
;
264 class EventListenerManagerMapEntry
: public PLDHashEntryHdr
267 EventListenerManagerMapEntry(const void *aKey
)
272 ~EventListenerManagerMapEntry()
274 NS_ASSERTION(!mListenerManager
, "caller must release and disconnect ELM");
278 const void *mKey
; // must be first, to look like PLDHashEntryStub
281 nsCOMPtr
<nsIEventListenerManager
> mListenerManager
;
285 EventListenerManagerHashInitEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
288 // Initialize the entry with placement new
289 new (entry
) EventListenerManagerMapEntry(key
);
294 EventListenerManagerHashClearEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
)
296 EventListenerManagerMapEntry
*lm
=
297 static_cast<EventListenerManagerMapEntry
*>(entry
);
299 // Let the EventListenerManagerMapEntry clean itself up...
300 lm
->~EventListenerManagerMapEntry();
303 class nsSameOriginChecker
: public nsIChannelEventSink
,
304 public nsIInterfaceRequestor
307 NS_DECL_NSICHANNELEVENTSINK
308 NS_DECL_NSIINTERFACEREQUESTOR
311 // For nsContentUtils::RegisterPrefCallback/UnregisterPrefCallback
312 class nsPrefOldCallback
: public nsIObserver
319 nsPrefOldCallback(const char *aPref
, PrefChangedFunc aCallback
, void *aClosure
) : mPref(aPref
), mCallback(aCallback
), mClosure(aClosure
) {
322 PRBool
IsEqual(const char *aPref
, PrefChangedFunc aCallback
, void *aClosure
) {
323 return aCallback
== mCallback
&&
324 aClosure
== mClosure
&&
330 PrefChangedFunc mCallback
;
334 NS_IMPL_ISUPPORTS1(nsPrefOldCallback
, nsIObserver
)
337 nsPrefOldCallback::Observe(nsISupports
*aSubject
,
339 const PRUnichar
*aData
)
341 NS_ASSERTION(!strcmp(aTopic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
),
343 mCallback(NS_LossyConvertUTF16toASCII(aData
).get(), mClosure
);
348 struct PrefCacheData
{
351 PRBool defaultValueBool
;
352 PRInt32 defaultValueInt
;
356 nsTArray
<nsAutoPtr
<PrefCacheData
> >* sPrefCacheData
= nsnull
;
360 nsContentUtils::Init()
363 NS_WARNING("Init() called twice");
368 sPrefCacheData
= new nsTArray
<nsAutoPtr
<PrefCacheData
> >();
370 // It's ok to not have a pref service.
371 CallGetService(NS_PREFSERVICE_CONTRACTID
, &sPrefBranch
);
373 nsresult rv
= NS_GetNameSpaceManager(&sNameSpaceManager
);
374 NS_ENSURE_SUCCESS(rv
, rv
);
376 nsXPConnect
* xpconnect
= nsXPConnect::GetXPConnect();
377 NS_ENSURE_TRUE(xpconnect
, NS_ERROR_FAILURE
);
379 sXPConnect
= xpconnect
;
380 sThreadJSContextStack
= xpconnect
;
382 sSecurityManager
= nsScriptSecurityManager::GetScriptSecurityManager();
383 if(!sSecurityManager
)
384 return NS_ERROR_FAILURE
;
385 NS_ADDREF(sSecurityManager
);
387 rv
= CallGetService(NS_IOSERVICE_CONTRACTID
, &sIOService
);
389 // This makes life easier, but we can live without it.
394 rv
= CallGetService(NS_LBRK_CONTRACTID
, &sLineBreaker
);
395 NS_ENSURE_SUCCESS(rv
, rv
);
397 rv
= CallGetService(NS_WBRK_CONTRACTID
, &sWordBreaker
);
398 NS_ENSURE_SUCCESS(rv
, rv
);
400 rv
= CallGetService(NS_UNICHARUTIL_CONTRACTID
, &sCaseConv
);
401 NS_ENSURE_SUCCESS(rv
, rv
);
403 rv
= CallGetService(NS_UNICHARCATEGORY_CONTRACTID
, &sGenCat
);
404 NS_ENSURE_SUCCESS(rv
, rv
);
406 // Ignore failure and just don't load images
407 rv
= CallGetService("@mozilla.org/image/loader;1", &sImgLoader
);
409 // no image loading for us. Oh, well.
413 if (NS_FAILED(CallGetService("@mozilla.org/image/cache;1", &sImgCache
)))
417 rv
= CallGetService(NS_IHISTORY_CONTRACTID
, &sHistory
);
419 NS_RUNTIMEABORT("Cannot get the history service");
423 sPtrsToPtrsToRelease
= new nsTArray
<nsISupports
**>();
424 if (!sPtrsToPtrsToRelease
) {
425 return NS_ERROR_OUT_OF_MEMORY
;
428 if (!InitializeEventTable())
429 return NS_ERROR_FAILURE
;
431 if (!sEventListenerManagersHash
.ops
) {
432 static PLDHashTableOps hash_table_ops
=
436 PL_DHashVoidPtrKeyStub
,
437 PL_DHashMatchEntryStub
,
438 PL_DHashMoveEntryStub
,
439 EventListenerManagerHashClearEntry
,
440 PL_DHashFinalizeStub
,
441 EventListenerManagerHashInitEntry
444 if (!PL_DHashTableInit(&sEventListenerManagersHash
, &hash_table_ops
,
445 nsnull
, sizeof(EventListenerManagerMapEntry
), 16)) {
446 sEventListenerManagersHash
.ops
= nsnull
;
448 return NS_ERROR_OUT_OF_MEMORY
;
452 sBlockedScriptRunners
= new nsCOMArray
<nsIRunnable
>;
453 NS_ENSURE_TRUE(sBlockedScriptRunners
, NS_ERROR_OUT_OF_MEMORY
);
455 sInitialized
= PR_TRUE
;
461 nsContentUtils::InitializeEventTable() {
462 NS_ASSERTION(!sEventTable
, "EventTable already initialized!");
467 EventNameMapping mValue
;
470 static const EventItem eventArray
[] = {
471 { &nsGkAtoms::onmousedown
, { NS_MOUSE_BUTTON_DOWN
, EventNameType_All
}},
472 { &nsGkAtoms::onmouseup
, { NS_MOUSE_BUTTON_UP
, EventNameType_All
}},
473 { &nsGkAtoms::onclick
, { NS_MOUSE_CLICK
, EventNameType_All
}},
474 { &nsGkAtoms::ondblclick
, { NS_MOUSE_DOUBLECLICK
, EventNameType_HTMLXUL
}},
475 { &nsGkAtoms::onmouseover
, { NS_MOUSE_ENTER_SYNTH
, EventNameType_All
}},
476 { &nsGkAtoms::onmouseout
, { NS_MOUSE_EXIT_SYNTH
, EventNameType_All
}},
477 { &nsGkAtoms::onmousemove
, { NS_MOUSE_MOVE
, EventNameType_All
}},
478 { &nsGkAtoms::oncontextmenu
, { NS_CONTEXTMENU
, EventNameType_HTMLXUL
}},
479 { &nsGkAtoms::onkeydown
, { NS_KEY_DOWN
, EventNameType_HTMLXUL
}},
480 { &nsGkAtoms::onkeyup
, { NS_KEY_UP
, EventNameType_HTMLXUL
}},
481 { &nsGkAtoms::onkeypress
, { NS_KEY_PRESS
, EventNameType_HTMLXUL
}},
482 { &nsGkAtoms::onfocus
, { NS_FOCUS_CONTENT
, EventNameType_HTMLXUL
}},
483 { &nsGkAtoms::onblur
, { NS_BLUR_CONTENT
, EventNameType_HTMLXUL
}},
484 { &nsGkAtoms::onoffline
, { NS_OFFLINE
, EventNameType_HTMLXUL
}},
485 { &nsGkAtoms::ononline
, { NS_ONLINE
, EventNameType_HTMLXUL
}},
486 { &nsGkAtoms::onsubmit
, { NS_FORM_SUBMIT
, EventNameType_HTMLXUL
}},
487 { &nsGkAtoms::onreset
, { NS_FORM_RESET
, EventNameType_HTMLXUL
}},
488 { &nsGkAtoms::onchange
, { NS_FORM_CHANGE
, EventNameType_HTMLXUL
}},
489 { &nsGkAtoms::onselect
, { NS_FORM_SELECTED
, EventNameType_HTMLXUL
}},
490 { &nsGkAtoms::onload
, { NS_LOAD
, EventNameType_All
}},
491 { &nsGkAtoms::onpopstate
, { NS_POPSTATE
, EventNameType_HTMLXUL
}},
492 { &nsGkAtoms::onunload
, { NS_PAGE_UNLOAD
,
493 (EventNameType_HTMLXUL
| EventNameType_SVGSVG
) }},
494 { &nsGkAtoms::onhashchange
, { NS_HASHCHANGE
, EventNameType_HTMLXUL
}},
495 { &nsGkAtoms::onbeforeunload
, { NS_BEFORE_PAGE_UNLOAD
, EventNameType_HTMLXUL
}},
496 { &nsGkAtoms::onabort
, { NS_IMAGE_ABORT
,
497 (EventNameType_HTMLXUL
| EventNameType_SVGSVG
) }},
498 { &nsGkAtoms::onerror
, { NS_LOAD_ERROR
,
499 (EventNameType_HTMLXUL
| EventNameType_SVGSVG
) }},
500 { &nsGkAtoms::onDOMAttrModified
, { NS_MUTATION_ATTRMODIFIED
, EventNameType_HTMLXUL
}},
501 { &nsGkAtoms::onDOMCharacterDataModified
, { NS_MUTATION_CHARACTERDATAMODIFIED
, EventNameType_HTMLXUL
}},
502 { &nsGkAtoms::onDOMNodeInserted
, { NS_MUTATION_NODEINSERTED
, EventNameType_HTMLXUL
}},
503 { &nsGkAtoms::onDOMNodeRemoved
, { NS_MUTATION_NODEREMOVED
, EventNameType_HTMLXUL
}},
504 { &nsGkAtoms::onDOMNodeInsertedIntoDocument
, { NS_MUTATION_NODEINSERTEDINTODOCUMENT
, EventNameType_HTMLXUL
}},
505 { &nsGkAtoms::onDOMNodeRemovedFromDocument
, { NS_MUTATION_NODEREMOVEDFROMDOCUMENT
, EventNameType_HTMLXUL
}},
506 { &nsGkAtoms::onDOMSubtreeModified
, { NS_MUTATION_SUBTREEMODIFIED
, EventNameType_HTMLXUL
}},
507 { &nsGkAtoms::onDOMActivate
, { NS_UI_ACTIVATE
, EventNameType_HTMLXUL
}},
508 { &nsGkAtoms::onDOMFocusIn
, { NS_UI_FOCUSIN
, EventNameType_HTMLXUL
}},
509 { &nsGkAtoms::onDOMFocusOut
, { NS_UI_FOCUSOUT
, EventNameType_HTMLXUL
}},
510 { &nsGkAtoms::onDOMMouseScroll
, { NS_MOUSE_SCROLL
, EventNameType_HTMLXUL
}},
511 { &nsGkAtoms::onMozMousePixelScroll
, { NS_MOUSE_PIXEL_SCROLL
, EventNameType_HTMLXUL
}},
512 { &nsGkAtoms::oninput
, { NS_FORM_INPUT
, EventNameType_HTMLXUL
}},
513 { &nsGkAtoms::onpageshow
, { NS_PAGE_SHOW
, EventNameType_HTML
}},
514 { &nsGkAtoms::onpagehide
, { NS_PAGE_HIDE
, EventNameType_HTML
}},
515 { &nsGkAtoms::onresize
, { NS_RESIZE_EVENT
,
516 (EventNameType_HTMLXUL
| EventNameType_SVGSVG
) }},
517 { &nsGkAtoms::onscroll
, { NS_SCROLL_EVENT
,
518 (EventNameType_HTMLXUL
| EventNameType_SVGSVG
) }},
519 { &nsGkAtoms::oncopy
, { NS_COPY
, EventNameType_HTMLXUL
}},
520 { &nsGkAtoms::oncut
, { NS_CUT
, EventNameType_HTMLXUL
}},
521 { &nsGkAtoms::onpaste
, { NS_PASTE
, EventNameType_HTMLXUL
}},
522 // XUL specific events
523 { &nsGkAtoms::ontext
, { NS_TEXT_TEXT
, EventNameType_XUL
}},
524 { &nsGkAtoms::oncompositionstart
, { NS_COMPOSITION_START
, EventNameType_XUL
}},
525 { &nsGkAtoms::oncompositionend
, { NS_COMPOSITION_END
, EventNameType_XUL
}},
526 { &nsGkAtoms::onclose
, { NS_XUL_CLOSE
, EventNameType_XUL
}},
527 { &nsGkAtoms::onpopupshowing
, { NS_XUL_POPUP_SHOWING
, EventNameType_XUL
}},
528 { &nsGkAtoms::onpopupshown
, { NS_XUL_POPUP_SHOWN
, EventNameType_XUL
}},
529 { &nsGkAtoms::onpopuphiding
, { NS_XUL_POPUP_HIDING
, EventNameType_XUL
}},
530 { &nsGkAtoms::onpopuphidden
, { NS_XUL_POPUP_HIDDEN
, EventNameType_XUL
}},
531 { &nsGkAtoms::oncommand
, { NS_XUL_COMMAND
, EventNameType_XUL
}},
532 { &nsGkAtoms::onbroadcast
, { NS_XUL_BROADCAST
, EventNameType_XUL
}},
533 { &nsGkAtoms::oncommandupdate
, { NS_XUL_COMMAND_UPDATE
, EventNameType_XUL
}},
534 { &nsGkAtoms::ondragenter
, { NS_DRAGDROP_ENTER
, EventNameType_HTMLXUL
}},
535 { &nsGkAtoms::ondragover
, { NS_DRAGDROP_OVER_SYNTH
, EventNameType_HTMLXUL
}},
536 { &nsGkAtoms::ondragexit
, { NS_DRAGDROP_EXIT_SYNTH
, EventNameType_XUL
}},
537 { &nsGkAtoms::ondragdrop
, { NS_DRAGDROP_DRAGDROP
, EventNameType_XUL
}},
538 { &nsGkAtoms::ondraggesture
, { NS_DRAGDROP_GESTURE
, EventNameType_XUL
}},
539 { &nsGkAtoms::ondrag
, { NS_DRAGDROP_DRAG
, EventNameType_HTMLXUL
}},
540 { &nsGkAtoms::ondragend
, { NS_DRAGDROP_END
, EventNameType_HTMLXUL
}},
541 { &nsGkAtoms::ondragstart
, { NS_DRAGDROP_START
, EventNameType_HTMLXUL
}},
542 { &nsGkAtoms::ondragleave
, { NS_DRAGDROP_LEAVE_SYNTH
, EventNameType_HTMLXUL
}},
543 { &nsGkAtoms::ondrop
, { NS_DRAGDROP_DROP
, EventNameType_HTMLXUL
}},
544 { &nsGkAtoms::onoverflow
, { NS_SCROLLPORT_OVERFLOW
, EventNameType_XUL
}},
545 { &nsGkAtoms::onunderflow
, { NS_SCROLLPORT_UNDERFLOW
, EventNameType_XUL
}},
547 { &nsGkAtoms::onSVGLoad
, { NS_SVG_LOAD
, EventNameType_None
}},
548 { &nsGkAtoms::onSVGUnload
, { NS_SVG_UNLOAD
, EventNameType_None
}},
549 { &nsGkAtoms::onSVGAbort
, { NS_SVG_ABORT
, EventNameType_None
}},
550 { &nsGkAtoms::onSVGError
, { NS_SVG_ERROR
, EventNameType_None
}},
551 { &nsGkAtoms::onSVGResize
, { NS_SVG_RESIZE
, EventNameType_None
}},
552 { &nsGkAtoms::onSVGScroll
, { NS_SVG_SCROLL
, EventNameType_None
}},
553 { &nsGkAtoms::onSVGZoom
, { NS_SVG_ZOOM
, EventNameType_None
}},
554 { &nsGkAtoms::onzoom
, { NS_SVG_ZOOM
, EventNameType_SVGSVG
}},
557 { &nsGkAtoms::onloadstart
, { NS_LOADSTART
, EventNameType_HTML
}},
558 { &nsGkAtoms::onprogress
, { NS_PROGRESS
, EventNameType_HTML
}},
559 { &nsGkAtoms::onsuspend
, { NS_SUSPEND
, EventNameType_HTML
}},
560 { &nsGkAtoms::onemptied
, { NS_EMPTIED
, EventNameType_HTML
}},
561 { &nsGkAtoms::onstalled
, { NS_STALLED
, EventNameType_HTML
}},
562 { &nsGkAtoms::onplay
, { NS_PLAY
, EventNameType_HTML
}},
563 { &nsGkAtoms::onpause
, { NS_PAUSE
, EventNameType_HTML
}},
564 { &nsGkAtoms::onloadedmetadata
, { NS_LOADEDMETADATA
, EventNameType_HTML
}},
565 { &nsGkAtoms::onloadeddata
, { NS_LOADEDDATA
, EventNameType_HTML
}},
566 { &nsGkAtoms::onwaiting
, { NS_WAITING
, EventNameType_HTML
}},
567 { &nsGkAtoms::onplaying
, { NS_PLAYING
, EventNameType_HTML
}},
568 { &nsGkAtoms::oncanplay
, { NS_CANPLAY
, EventNameType_HTML
}},
569 { &nsGkAtoms::oncanplaythrough
, { NS_CANPLAYTHROUGH
, EventNameType_HTML
}},
570 { &nsGkAtoms::onseeking
, { NS_SEEKING
, EventNameType_HTML
}},
571 { &nsGkAtoms::onseeked
, { NS_SEEKED
, EventNameType_HTML
}},
572 { &nsGkAtoms::ontimeupdate
, { NS_TIMEUPDATE
, EventNameType_HTML
}},
573 { &nsGkAtoms::onended
, { NS_ENDED
, EventNameType_HTML
}},
574 { &nsGkAtoms::onratechange
, { NS_RATECHANGE
, EventNameType_HTML
}},
575 { &nsGkAtoms::ondurationchange
, { NS_DURATIONCHANGE
, EventNameType_HTML
}},
576 { &nsGkAtoms::onvolumechange
, { NS_VOLUMECHANGE
, EventNameType_HTML
}},
578 { &nsGkAtoms::onMozAfterPaint
, { NS_AFTERPAINT
, EventNameType_None
}},
579 { &nsGkAtoms::onMozScrolledAreaChanged
, { NS_SCROLLEDAREACHANGED
, EventNameType_None
}},
581 // Simple gesture events
582 { &nsGkAtoms::onMozSwipeGesture
, { NS_SIMPLE_GESTURE_SWIPE
, EventNameType_None
} },
583 { &nsGkAtoms::onMozMagnifyGestureStart
, { NS_SIMPLE_GESTURE_MAGNIFY_START
, EventNameType_None
} },
584 { &nsGkAtoms::onMozMagnifyGestureUpdate
, { NS_SIMPLE_GESTURE_MAGNIFY_UPDATE
, EventNameType_None
} },
585 { &nsGkAtoms::onMozMagnifyGesture
, { NS_SIMPLE_GESTURE_MAGNIFY
, EventNameType_None
} },
586 { &nsGkAtoms::onMozRotateGestureStart
, { NS_SIMPLE_GESTURE_ROTATE_START
, EventNameType_None
} },
587 { &nsGkAtoms::onMozRotateGestureUpdate
, { NS_SIMPLE_GESTURE_ROTATE_UPDATE
, EventNameType_None
} },
588 { &nsGkAtoms::onMozRotateGesture
, { NS_SIMPLE_GESTURE_ROTATE
, EventNameType_None
} },
589 { &nsGkAtoms::onMozTapGesture
, { NS_SIMPLE_GESTURE_TAP
, EventNameType_None
} },
590 { &nsGkAtoms::onMozPressTapGesture
, { NS_SIMPLE_GESTURE_PRESSTAP
, EventNameType_None
} },
592 { &nsGkAtoms::ontransitionend
, { NS_TRANSITION_END
, EventNameType_None
}},
595 sEventTable
= new nsDataHashtable
<nsISupportsHashKey
, EventNameMapping
>;
597 !sEventTable
->Init(int(NS_ARRAY_LENGTH(eventArray
) / 0.75) + 1)) {
599 sEventTable
= nsnull
;
603 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(eventArray
); ++i
) {
604 if (!sEventTable
->Put(*(eventArray
[i
].mAtom
), eventArray
[i
].mValue
)) {
606 sEventTable
= nsnull
;
615 * Access a cached parser service. Don't addref. We need only one
616 * reference to it and this class has that one.
620 nsContentUtils::GetParserService()
622 // XXX: This isn't accessed from several threads, is it?
623 if (!sParserService
) {
624 // Lock, recheck sCachedParserService and aquire if this should be
625 // safe for multiple threads.
626 nsresult rv
= CallGetService(kParserServiceCID
, &sParserService
);
628 sParserService
= nsnull
;
632 return sParserService
;
637 nsContentUtils::GetXTFService()
640 nsresult rv
= CallGetService(kXTFServiceCID
, &sXTFService
);
642 sXTFService
= nsnull
;
652 nsContentUtils::GetBidiKeyboard()
654 if (!sBidiKeyboard
) {
655 nsresult rv
= CallGetService("@mozilla.org/widget/bidikeyboard;1", &sBidiKeyboard
);
657 sBidiKeyboard
= nsnull
;
660 return sBidiKeyboard
;
664 template <class OutputIterator
>
665 struct NormalizeNewlinesCharTraits
{
667 typedef typename
OutputIterator::value_type value_type
;
670 NormalizeNewlinesCharTraits(OutputIterator
& aIterator
) : mIterator(aIterator
) { }
671 void writechar(typename
OutputIterator::value_type aChar
) {
672 *mIterator
++ = aChar
;
676 OutputIterator mIterator
;
679 #ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
681 template <class CharT
>
682 struct NormalizeNewlinesCharTraits
<CharT
*> {
684 typedef CharT value_type
;
687 NormalizeNewlinesCharTraits(CharT
* aCharPtr
) : mCharPtr(aCharPtr
) { }
688 void writechar(CharT aChar
) {
698 NS_SPECIALIZE_TEMPLATE
699 struct NormalizeNewlinesCharTraits
<char*> {
701 typedef char value_type
;
704 NormalizeNewlinesCharTraits(char* aCharPtr
) : mCharPtr(aCharPtr
) { }
705 void writechar(char aChar
) {
713 NS_SPECIALIZE_TEMPLATE
714 struct NormalizeNewlinesCharTraits
<PRUnichar
*> {
716 typedef PRUnichar value_type
;
719 NormalizeNewlinesCharTraits(PRUnichar
* aCharPtr
) : mCharPtr(aCharPtr
) { }
720 void writechar(PRUnichar aChar
) {
730 template <class OutputIterator
>
731 class CopyNormalizeNewlines
734 typedef typename
OutputIterator::value_type value_type
;
737 CopyNormalizeNewlines(OutputIterator
* aDestination
,
738 PRBool aLastCharCR
=PR_FALSE
) :
739 mLastCharCR(aLastCharCR
),
740 mDestination(aDestination
),
744 PRUint32
GetCharsWritten() {
748 PRBool
IsLastCharCR() {
752 void write(const typename
OutputIterator::value_type
* aSource
, PRUint32 aSourceLength
) {
754 const typename
OutputIterator::value_type
* done_writing
= aSource
+ aSourceLength
;
756 // If the last source buffer ended with a CR...
758 // ..and if the next one is a LF, then skip it since
759 // we've already written out a newline
760 if (aSourceLength
&& (*aSource
== value_type('\n'))) {
763 mLastCharCR
= PR_FALSE
;
766 PRUint32 num_written
= 0;
767 while ( aSource
< done_writing
) {
768 if (*aSource
== value_type('\r')) {
769 mDestination
->writechar('\n');
771 // If we've reached the end of the buffer, record
772 // that we wrote out a CR
773 if (aSource
== done_writing
) {
774 mLastCharCR
= PR_TRUE
;
776 // If the next character is a LF, skip it
777 else if (*aSource
== value_type('\n')) {
782 mDestination
->writechar(*aSource
++);
787 mWritten
+= num_written
;
792 OutputIterator
* mDestination
;
798 nsContentUtils::CopyNewlineNormalizedUnicodeTo(const nsAString
& aSource
,
804 typedef NormalizeNewlinesCharTraits
<PRUnichar
*> sink_traits
;
806 sink_traits
dest_traits(aDest
);
807 CopyNormalizeNewlines
<sink_traits
> normalizer(&dest_traits
,aLastCharCR
);
808 nsReadingIterator
<PRUnichar
> fromBegin
, fromEnd
;
809 copy_string(aSource
.BeginReading(fromBegin
).advance( PRInt32(aSrcOffset
) ),
810 aSource
.BeginReading(fromEnd
).advance( PRInt32(aSrcOffset
+aLength
) ),
812 aLastCharCR
= normalizer
.IsLastCharCR();
813 return normalizer
.GetCharsWritten();
818 nsContentUtils::CopyNewlineNormalizedUnicodeTo(nsReadingIterator
<PRUnichar
>& aSrcStart
, const nsReadingIterator
<PRUnichar
>& aSrcEnd
, nsAString
& aDest
)
820 typedef nsWritingIterator
<PRUnichar
> WritingIterator
;
821 typedef NormalizeNewlinesCharTraits
<WritingIterator
> sink_traits
;
823 WritingIterator iter
;
824 aDest
.BeginWriting(iter
);
825 sink_traits
dest_traits(iter
);
826 CopyNormalizeNewlines
<sink_traits
> normalizer(&dest_traits
);
827 copy_string(aSrcStart
, aSrcEnd
, normalizer
);
828 return normalizer
.GetCharsWritten();
831 // Replaced by precompiled CCMap (see bug 180266). To update the list
832 // of characters, see one of files included below. As for the way
833 // the original list of characters was obtained by Frank Tang, see bug 54467.
834 // Updated to fix the regression (bug 263411). The list contains
835 // characters of the following Unicode character classes : Ps, Pi, Po, Pf, Pe.
836 // (ref.: http://www.w3.org/TR/2004/CR-CSS21-20040225/selector.html#first-letter)
837 #include "punct_marks.x-ccmap"
838 DEFINE_X_CCMAP(gPuncCharsCCMapExt
, const);
842 nsContentUtils::IsPunctuationMark(PRUint32 aChar
)
844 return CCMAP_HAS_CHAR_EXT(gPuncCharsCCMapExt
, aChar
);
849 nsContentUtils::IsPunctuationMarkAt(const nsTextFragment
* aFrag
, PRUint32 aOffset
)
851 PRUnichar h
= aFrag
->CharAt(aOffset
);
852 if (!IS_SURROGATE(h
)) {
853 return IsPunctuationMark(h
);
855 if (NS_IS_HIGH_SURROGATE(h
) && aOffset
+ 1 < aFrag
->GetLength()) {
856 PRUnichar l
= aFrag
->CharAt(aOffset
+ 1);
857 if (NS_IS_LOW_SURROGATE(l
)) {
858 return IsPunctuationMark(SURROGATE_TO_UCS4(h
, l
));
865 PRBool
nsContentUtils::IsAlphanumeric(PRUint32 aChar
)
867 nsIUGenCategory::nsUGenCategory cat
= sGenCat
->Get(aChar
);
869 return (cat
== nsIUGenCategory::kLetter
|| cat
== nsIUGenCategory::kNumber
);
873 PRBool
nsContentUtils::IsAlphanumericAt(const nsTextFragment
* aFrag
, PRUint32 aOffset
)
875 PRUnichar h
= aFrag
->CharAt(aOffset
);
876 if (!IS_SURROGATE(h
)) {
877 return IsAlphanumeric(h
);
879 if (NS_IS_HIGH_SURROGATE(h
) && aOffset
+ 1 < aFrag
->GetLength()) {
880 PRUnichar l
= aFrag
->CharAt(aOffset
+ 1);
881 if (NS_IS_LOW_SURROGATE(l
)) {
882 return IsAlphanumeric(SURROGATE_TO_UCS4(h
, l
));
890 nsContentUtils::IsHTMLWhitespace(PRUnichar aChar
)
892 return aChar
== PRUnichar(0x0009) ||
893 aChar
== PRUnichar(0x000A) ||
894 aChar
== PRUnichar(0x000C) ||
895 aChar
== PRUnichar(0x000D) ||
896 aChar
== PRUnichar(0x0020);
902 nsContentUtils::GetOfflineAppManifest(nsIDocument
*aDocument
, nsIURI
**aURI
)
904 Element
* docElement
= aDocument
->GetRootElement();
909 nsAutoString manifestSpec
;
910 docElement
->GetAttr(kNameSpaceID_None
, nsGkAtoms::manifest
, manifestSpec
);
912 // Manifest URIs can't have fragment identifiers.
913 if (manifestSpec
.IsEmpty() ||
914 manifestSpec
.FindChar('#') != kNotFound
) {
918 nsContentUtils::NewURIWithDocumentCharset(aURI
, manifestSpec
,
920 aDocument
->GetDocBaseURI());
925 nsContentUtils::OfflineAppAllowed(nsIURI
*aURI
)
927 nsCOMPtr
<nsIOfflineCacheUpdateService
> updateService
=
928 do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID
);
929 if (!updateService
) {
934 nsresult rv
= updateService
->OfflineAppAllowedForURI(aURI
,
937 return NS_SUCCEEDED(rv
) && allowed
;
942 nsContentUtils::OfflineAppAllowed(nsIPrincipal
*aPrincipal
)
944 nsCOMPtr
<nsIOfflineCacheUpdateService
> updateService
=
945 do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID
);
946 if (!updateService
) {
951 nsresult rv
= updateService
->OfflineAppAllowed(aPrincipal
,
954 return NS_SUCCEEDED(rv
) && allowed
;
959 nsContentUtils::Shutdown()
961 sInitialized
= PR_FALSE
;
963 NS_HTMLParanoidFragmentSinkShutdown();
964 NS_XHTMLParanoidFragmentSinkShutdown();
966 NS_IF_RELEASE(sContentPolicyService
);
967 sTriedToGetContentPolicy
= PR_FALSE
;
969 for (i
= 0; i
< PropertiesFile_COUNT
; ++i
)
970 NS_IF_RELEASE(sStringBundles
[i
]);
972 // Clean up c-style's observer
973 if (sPrefCallbackList
) {
974 while (sPrefCallbackList
->Count() > 0) {
975 nsRefPtr
<nsPrefOldCallback
> callback
= (*sPrefCallbackList
)[0];
976 NS_ABORT_IF_FALSE(callback
, "Invalid c-style callback is appended");
978 sPrefBranch
->RemoveObserver(callback
->mPref
.get(), callback
);
979 sPrefCallbackList
->RemoveObject(callback
);
981 delete sPrefCallbackList
;
982 sPrefCallbackList
= nsnull
;
985 delete sPrefCacheData
;
986 sPrefCacheData
= nsnull
;
988 NS_IF_RELEASE(sStringBundleService
);
989 NS_IF_RELEASE(sConsoleService
);
990 NS_IF_RELEASE(sDOMScriptObjectFactory
);
992 sThreadJSContextStack
= nsnull
;
993 NS_IF_RELEASE(sSecurityManager
);
994 NS_IF_RELEASE(sNameSpaceManager
);
995 NS_IF_RELEASE(sParserService
);
996 NS_IF_RELEASE(sIOService
);
997 NS_IF_RELEASE(sLineBreaker
);
998 NS_IF_RELEASE(sWordBreaker
);
999 NS_IF_RELEASE(sCaseConv
);
1000 NS_IF_RELEASE(sGenCat
);
1002 NS_IF_RELEASE(sXTFService
);
1004 NS_IF_RELEASE(sImgLoader
);
1005 NS_IF_RELEASE(sImgCache
);
1006 NS_IF_RELEASE(sHistory
);
1007 NS_IF_RELEASE(sPrefBranch
);
1009 NS_IF_RELEASE(sBidiKeyboard
);
1013 sEventTable
= nsnull
;
1015 if (sPtrsToPtrsToRelease
) {
1016 for (i
= 0; i
< sPtrsToPtrsToRelease
->Length(); ++i
) {
1017 nsISupports
** ptrToPtr
= sPtrsToPtrsToRelease
->ElementAt(i
);
1018 NS_RELEASE(*ptrToPtr
);
1020 delete sPtrsToPtrsToRelease
;
1021 sPtrsToPtrsToRelease
= nsnull
;
1024 if (sEventListenerManagersHash
.ops
) {
1025 NS_ASSERTION(sEventListenerManagersHash
.entryCount
== 0,
1026 "Event listener manager hash not empty at shutdown!");
1028 // See comment above.
1030 // However, we have to handle this table differently. If it still
1031 // has entries, we want to leak it too, so that we can keep it alive
1032 // in case any elements are destroyed. Because if they are, we need
1033 // their event listener managers to be destroyed too, or otherwise
1034 // it could leave dangling references in DOMClassInfo's preserved
1037 if (sEventListenerManagersHash
.entryCount
== 0) {
1038 PL_DHashTableFinish(&sEventListenerManagersHash
);
1039 sEventListenerManagersHash
.ops
= nsnull
;
1043 NS_ASSERTION(!sBlockedScriptRunners
||
1044 sBlockedScriptRunners
->Count() == 0,
1045 "How'd this happen?");
1046 delete sBlockedScriptRunners
;
1047 sBlockedScriptRunners
= nsnull
;
1049 NS_IF_RELEASE(sSameOriginChecker
);
1051 nsAutoGCRoot::Shutdown();
1053 nsTextEditorState::ShutDown();
1058 nsContentUtils::IsCallerTrustedForCapability(const char* aCapability
)
1060 // The secman really should handle UniversalXPConnect case, since that
1061 // should include UniversalBrowserRead... doesn't right now, though.
1063 if (NS_FAILED(sSecurityManager
->IsCapabilityEnabled(aCapability
, &hasCap
)))
1068 if (NS_FAILED(sSecurityManager
->IsCapabilityEnabled("UniversalXPConnect",
1075 * Checks whether two nodes come from the same origin. aTrustedNode is
1076 * considered 'safe' in that a user can operate on it and that it isn't
1077 * a js-object that implements nsIDOMNode.
1078 * Never call this function with the first node provided by script, it
1079 * must always be known to be a 'real' node!
1083 nsContentUtils::CheckSameOrigin(nsINode
*aTrustedNode
,
1084 nsIDOMNode
*aUnTrustedNode
)
1086 NS_PRECONDITION(aTrustedNode
, "There must be a trusted node");
1088 PRBool isSystem
= PR_FALSE
;
1089 sSecurityManager
->SubjectPrincipalIsSystem(&isSystem
);
1091 // we're running as system, grant access to the node.
1097 * Get hold of each node's principal
1099 nsCOMPtr
<nsINode
> unTrustedNode
= do_QueryInterface(aUnTrustedNode
);
1101 // Make sure these are both real nodes
1102 NS_ENSURE_TRUE(aTrustedNode
&& unTrustedNode
, NS_ERROR_UNEXPECTED
);
1104 nsIPrincipal
* trustedPrincipal
= aTrustedNode
->NodePrincipal();
1105 nsIPrincipal
* unTrustedPrincipal
= unTrustedNode
->NodePrincipal();
1107 if (trustedPrincipal
== unTrustedPrincipal
) {
1112 // XXXbz should we actually have a Subsumes() check here instead? Or perhaps
1113 // a separate method for that, with callers using one or the other?
1114 if (NS_FAILED(trustedPrincipal
->Equals(unTrustedPrincipal
, &equal
)) ||
1116 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
1124 nsContentUtils::CanCallerAccess(nsIPrincipal
* aSubjectPrincipal
,
1125 nsIPrincipal
* aPrincipal
)
1128 nsresult rv
= aSubjectPrincipal
->Subsumes(aPrincipal
, &subsumes
);
1129 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
1135 // The subject doesn't subsume aPrincipal. Allow access only if the subject
1136 // has either "UniversalXPConnect" (if aPrincipal is system principal) or
1137 // "UniversalBrowserRead" (in all other cases).
1139 rv
= sSecurityManager
->IsSystemPrincipal(aPrincipal
, &isSystem
);
1140 isSystem
= NS_FAILED(rv
) || isSystem
;
1141 const char* capability
=
1142 NS_FAILED(rv
) || isSystem
? "UniversalXPConnect" : "UniversalBrowserRead";
1144 return IsCallerTrustedForCapability(capability
);
1149 nsContentUtils::CanCallerAccess(nsIDOMNode
*aNode
)
1151 // XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
1152 // with the system principal games? But really, there should be a simpler
1153 // API here, dammit.
1154 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
1155 sSecurityManager
->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
1157 if (!subjectPrincipal
) {
1158 // we're running as system, grant access to the node.
1163 nsCOMPtr
<nsINode
> node
= do_QueryInterface(aNode
);
1164 NS_ENSURE_TRUE(node
, PR_FALSE
);
1166 return CanCallerAccess(subjectPrincipal
, node
->NodePrincipal());
1171 nsContentUtils::CanCallerAccess(nsPIDOMWindow
* aWindow
)
1173 // XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
1174 // with the system principal games? But really, there should be a simpler
1175 // API here, dammit.
1176 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
1177 sSecurityManager
->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
1179 if (!subjectPrincipal
) {
1180 // we're running as system, grant access to the node.
1185 nsCOMPtr
<nsIScriptObjectPrincipal
> scriptObject
=
1186 do_QueryInterface(aWindow
->IsOuterWindow() ?
1187 aWindow
->GetCurrentInnerWindow() : aWindow
);
1188 NS_ENSURE_TRUE(scriptObject
, PR_FALSE
);
1190 return CanCallerAccess(subjectPrincipal
, scriptObject
->GetPrincipal());
1195 nsContentUtils::InProlog(nsINode
*aNode
)
1197 NS_PRECONDITION(aNode
, "missing node to nsContentUtils::InProlog");
1199 nsINode
* parent
= aNode
->GetNodeParent();
1200 if (!parent
|| !parent
->IsNodeOfType(nsINode::eDOCUMENT
)) {
1204 nsIDocument
* doc
= static_cast<nsIDocument
*>(parent
);
1205 nsIContent
* root
= doc
->GetRootElement();
1207 return !root
|| doc
->IndexOf(aNode
) < doc
->IndexOf(root
);
1211 GetContextFromDocument(nsIDocument
*aDocument
, JSObject
** aGlobalObject
)
1213 nsIScriptGlobalObject
*sgo
= aDocument
->GetScopeObject();
1215 // No script global, no context.
1217 *aGlobalObject
= nsnull
;
1222 *aGlobalObject
= sgo
->GetGlobalJSObject();
1224 nsIScriptContext
*scx
= sgo
->GetContext();
1226 // No context left in the old scope...
1231 return (JSContext
*)scx
->GetNativeContext();
1236 nsContentUtils::GetContextAndScopes(nsIDocument
*aOldDocument
,
1237 nsIDocument
*aNewDocument
, JSContext
**aCx
,
1238 JSObject
**aOldScope
, JSObject
**aNewScope
)
1241 *aOldScope
= nsnull
;
1242 *aNewScope
= nsnull
;
1244 JSObject
*newScope
= nsnull
;
1245 nsIScriptGlobalObject
*newSGO
= aNewDocument
->GetScopeObject();
1246 if (!newSGO
|| !(newScope
= newSGO
->GetGlobalJSObject())) {
1250 NS_ENSURE_TRUE(sXPConnect
, NS_ERROR_NOT_INITIALIZED
);
1252 // Make sure to get our hands on the right scope object, since
1253 // GetWrappedNativeOfNativeObject doesn't call PreCreate and hence won't get
1254 // the right scope if we pass in something bogus. The right scope lives on
1255 // the script global of the old document.
1256 // XXXbz note that if GetWrappedNativeOfNativeObject did call PreCreate it
1257 // would get the wrong scope (that of the _new_ document), so we should be
1259 JSObject
*oldScope
= nsnull
;
1260 JSContext
*cx
= GetContextFromDocument(aOldDocument
, &oldScope
);
1268 cx
= GetContextFromDocument(aNewDocument
, &dummy
);
1271 // No context reachable from the old or new document, use the
1272 // calling context, or the safe context if no caller can be
1275 sThreadJSContextStack
->Peek(&cx
);
1278 sThreadJSContextStack
->GetSafeJSContext(&cx
);
1281 // No safe context reachable, bail.
1282 NS_WARNING("No context reachable in GetContextAndScopes()!");
1284 return NS_ERROR_NOT_AVAILABLE
;
1291 *aOldScope
= oldScope
;
1292 *aNewScope
= newScope
;
1298 nsContentUtils::ReparentContentWrappersInScope(nsIScriptGlobalObject
*aOldScope
,
1299 nsIScriptGlobalObject
*aNewScope
)
1301 JSContext
*cx
= nsnull
;
1303 // Try really hard to find a context to work on.
1304 nsIScriptContext
*context
= aOldScope
->GetContext();
1306 cx
= static_cast<JSContext
*>(context
->GetNativeContext());
1310 context
= aNewScope
->GetContext();
1312 cx
= static_cast<JSContext
*>(context
->GetNativeContext());
1316 sThreadJSContextStack
->Peek(&cx
);
1319 sThreadJSContextStack
->GetSafeJSContext(&cx
);
1322 // Wow, this is really bad!
1323 NS_WARNING("No context reachable in ReparentContentWrappers()!");
1325 return NS_ERROR_NOT_AVAILABLE
;
1331 // Now that we have a context, let's get the global objects from the two
1332 // scopes and ask XPConnect to do the rest of the work.
1334 JSObject
*oldScopeObj
= aOldScope
->GetGlobalJSObject();
1335 JSObject
*newScopeObj
= aNewScope
->GetGlobalJSObject();
1337 if (!newScopeObj
|| !oldScopeObj
) {
1338 // We can't really do anything without the JSObjects.
1340 return NS_ERROR_NOT_AVAILABLE
;
1343 return sXPConnect
->MoveWrappers(cx
, oldScopeObj
, newScopeObj
);
1347 nsContentUtils::GetDocShellFromCaller()
1349 JSContext
*cx
= nsnull
;
1350 sThreadJSContextStack
->Peek(&cx
);
1353 nsIScriptGlobalObject
*sgo
= nsJSUtils::GetDynamicScriptGlobal(cx
);
1354 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(sgo
));
1357 return win
->GetDocShell();
1365 nsContentUtils::GetDocumentFromCaller()
1367 JSContext
*cx
= nsnull
;
1368 sThreadJSContextStack
->Peek(&cx
);
1370 nsIDOMDocument
*doc
= nsnull
;
1373 JSObject
*callee
= nsnull
;
1374 JSStackFrame
*fp
= nsnull
;
1375 while (!callee
&& (fp
= ::JS_FrameIterator(cx
, &fp
))) {
1376 callee
= ::JS_GetFrameCalleeObject(cx
, fp
);
1379 nsCOMPtr
<nsPIDOMWindow
> win
=
1380 do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx
, callee
));
1382 doc
= win
->GetExtantDocument();
1390 nsContentUtils::GetDocumentFromContext()
1392 JSContext
*cx
= nsnull
;
1393 sThreadJSContextStack
->Peek(&cx
);
1396 nsIScriptGlobalObject
*sgo
= nsJSUtils::GetDynamicScriptGlobal(cx
);
1399 nsCOMPtr
<nsPIDOMWindow
> pwin
= do_QueryInterface(sgo
);
1401 return pwin
->GetExtantDocument();
1410 nsContentUtils::IsCallerChrome()
1412 PRBool is_caller_chrome
= PR_FALSE
;
1413 nsresult rv
= sSecurityManager
->SubjectPrincipalIsSystem(&is_caller_chrome
);
1414 if (NS_FAILED(rv
)) {
1418 return is_caller_chrome
;
1422 nsContentUtils::IsCallerTrustedForRead()
1424 return IsCallerTrustedForCapability("UniversalBrowserRead");
1428 nsContentUtils::IsCallerTrustedForWrite()
1430 return IsCallerTrustedForCapability("UniversalBrowserWrite");
1435 nsContentUtils::ContentIsDescendantOf(const nsINode
* aPossibleDescendant
,
1436 const nsINode
* aPossibleAncestor
)
1438 NS_PRECONDITION(aPossibleDescendant
, "The possible descendant is null!");
1439 NS_PRECONDITION(aPossibleAncestor
, "The possible ancestor is null!");
1442 if (aPossibleDescendant
== aPossibleAncestor
)
1444 aPossibleDescendant
= aPossibleDescendant
->GetNodeParent();
1445 } while (aPossibleDescendant
);
1452 nsContentUtils::ContentIsCrossDocDescendantOf(nsINode
* aPossibleDescendant
,
1453 nsINode
* aPossibleAncestor
)
1455 NS_PRECONDITION(aPossibleDescendant
, "The possible descendant is null!");
1456 NS_PRECONDITION(aPossibleAncestor
, "The possible ancestor is null!");
1459 if (aPossibleDescendant
== aPossibleAncestor
)
1461 nsINode
* parent
= aPossibleDescendant
->GetNodeParent();
1462 if (!parent
&& aPossibleDescendant
->IsNodeOfType(nsINode::eDOCUMENT
)) {
1463 nsIDocument
* doc
= static_cast<nsIDocument
*>(aPossibleDescendant
);
1464 nsIDocument
* parentDoc
= doc
->GetParentDocument();
1465 aPossibleDescendant
= parentDoc
?
1466 parentDoc
->FindContentForSubDocument(doc
) : nsnull
;
1469 aPossibleDescendant
= parent
;
1471 } while (aPossibleDescendant
);
1479 nsContentUtils::GetAncestors(nsINode
* aNode
,
1480 nsTArray
<nsINode
*>& aArray
)
1483 aArray
.AppendElement(aNode
);
1484 aNode
= aNode
->GetNodeParent();
1491 nsContentUtils::GetAncestorsAndOffsets(nsIDOMNode
* aNode
,
1493 nsTArray
<nsIContent
*>* aAncestorNodes
,
1494 nsTArray
<PRInt32
>* aAncestorOffsets
)
1496 NS_ENSURE_ARG_POINTER(aNode
);
1498 nsCOMPtr
<nsIContent
> content(do_QueryInterface(aNode
));
1501 return NS_ERROR_FAILURE
;
1504 if (!aAncestorNodes
->IsEmpty()) {
1505 NS_WARNING("aAncestorNodes is not empty");
1506 aAncestorNodes
->Clear();
1509 if (!aAncestorOffsets
->IsEmpty()) {
1510 NS_WARNING("aAncestorOffsets is not empty");
1511 aAncestorOffsets
->Clear();
1514 // insert the node itself
1515 aAncestorNodes
->AppendElement(content
.get());
1516 aAncestorOffsets
->AppendElement(aOffset
);
1518 // insert all the ancestors
1519 nsIContent
* child
= content
;
1520 nsIContent
* parent
= child
->GetParent();
1522 aAncestorNodes
->AppendElement(parent
);
1523 aAncestorOffsets
->AppendElement(parent
->IndexOf(child
));
1525 parent
= parent
->GetParent();
1533 nsContentUtils::GetCommonAncestor(nsIDOMNode
*aNode
,
1535 nsIDOMNode
** aCommonAncestor
)
1537 *aCommonAncestor
= nsnull
;
1539 nsCOMPtr
<nsINode
> node1
= do_QueryInterface(aNode
);
1540 nsCOMPtr
<nsINode
> node2
= do_QueryInterface(aOther
);
1542 NS_ENSURE_TRUE(node1
&& node2
, NS_ERROR_UNEXPECTED
);
1544 nsINode
* common
= GetCommonAncestor(node1
, node2
);
1545 NS_ENSURE_TRUE(common
, NS_ERROR_NOT_AVAILABLE
);
1547 return CallQueryInterface(common
, aCommonAncestor
);
1552 nsContentUtils::GetCommonAncestor(nsINode
* aNode1
,
1555 if (aNode1
== aNode2
) {
1559 // Build the chain of parents
1560 nsAutoTPtrArray
<nsINode
, 30> parents1
, parents2
;
1562 parents1
.AppendElement(aNode1
);
1563 aNode1
= aNode1
->GetNodeParent();
1566 parents2
.AppendElement(aNode2
);
1567 aNode2
= aNode2
->GetNodeParent();
1570 // Find where the parent chain differs
1571 PRUint32 pos1
= parents1
.Length();
1572 PRUint32 pos2
= parents2
.Length();
1573 nsINode
* parent
= nsnull
;
1575 for (len
= NS_MIN(pos1
, pos2
); len
> 0; --len
) {
1576 nsINode
* child1
= parents1
.ElementAt(--pos1
);
1577 nsINode
* child2
= parents2
.ElementAt(--pos2
);
1578 if (child1
!= child2
) {
1589 nsContentUtils::ComparePoints(nsINode
* aParent1
, PRInt32 aOffset1
,
1590 nsINode
* aParent2
, PRInt32 aOffset2
,
1591 PRBool
* aDisconnected
)
1593 if (aParent1
== aParent2
) {
1594 return aOffset1
< aOffset2
? -1 :
1595 aOffset1
> aOffset2
? 1 :
1599 nsAutoTArray
<nsINode
*, 32> parents1
, parents2
;
1600 nsINode
* node1
= aParent1
;
1601 nsINode
* node2
= aParent2
;
1603 parents1
.AppendElement(node1
);
1604 node1
= node1
->GetNodeParent();
1607 parents2
.AppendElement(node2
);
1608 node2
= node2
->GetNodeParent();
1611 PRUint32 pos1
= parents1
.Length() - 1;
1612 PRUint32 pos2
= parents2
.Length() - 1;
1614 PRBool disconnected
= parents1
.ElementAt(pos1
) != parents2
.ElementAt(pos2
);
1615 if (aDisconnected
) {
1616 *aDisconnected
= disconnected
;
1619 NS_ASSERTION(aDisconnected
, "unexpected disconnected nodes");
1623 // Find where the parent chains differ
1624 nsINode
* parent
= parents1
.ElementAt(pos1
);
1626 for (len
= NS_MIN(pos1
, pos2
); len
> 0; --len
) {
1627 nsINode
* child1
= parents1
.ElementAt(--pos1
);
1628 nsINode
* child2
= parents2
.ElementAt(--pos2
);
1629 if (child1
!= child2
) {
1630 return parent
->IndexOf(child1
) < parent
->IndexOf(child2
) ? -1 : 1;
1636 // The parent chains never differed, so one of the nodes is an ancestor of
1639 NS_ASSERTION(!pos1
|| !pos2
,
1640 "should have run out of parent chain for one of the nodes");
1643 nsINode
* child2
= parents2
.ElementAt(--pos2
);
1644 return aOffset1
<= parent
->IndexOf(child2
) ? -1 : 1;
1647 nsINode
* child1
= parents1
.ElementAt(--pos1
);
1648 return parent
->IndexOf(child1
) < aOffset2
? -1 : 1;
1652 nsContentUtils::FindFirstChildWithResolvedTag(nsIContent
* aParent
,
1657 if (!aParent
|| !(doc
= aParent
->GetOwnerDoc())) {
1661 nsBindingManager
* bindingManager
= doc
->BindingManager();
1663 PRInt32 namespaceID
;
1664 PRUint32 count
= aParent
->GetChildCount();
1668 for (i
= 0; i
< count
; i
++) {
1669 nsIContent
*child
= aParent
->GetChildAt(i
);
1670 nsIAtom
* tag
= bindingManager
->ResolveTag(child
, &namespaceID
);
1671 if (tag
== aTag
&& namespaceID
== aNamespace
) {
1676 // now look for children in XBL
1677 nsCOMPtr
<nsIDOMNodeList
> children
;
1678 bindingManager
->GetXBLChildNodesFor(aParent
, getter_AddRefs(children
));
1684 children
->GetLength(&length
);
1685 for (i
= 0; i
< length
; i
++) {
1686 nsCOMPtr
<nsIDOMNode
> childNode
;
1687 children
->Item(i
, getter_AddRefs(childNode
));
1688 nsCOMPtr
<nsIContent
> childContent
= do_QueryInterface(childNode
);
1689 nsIAtom
* tag
= bindingManager
->ResolveTag(childContent
, &namespaceID
);
1690 if (tag
== aTag
&& namespaceID
== aNamespace
) {
1691 return childContent
;
1699 IsCharInSet(const char* aSet
,
1700 const PRUnichar aChar
)
1703 while ((ch
= *aSet
)) {
1704 if (aChar
== PRUnichar(ch
)) {
1713 * This method strips leading/trailing chars, in given set, from string.
1717 const nsDependentSubstring
1718 nsContentUtils::TrimCharsInSet(const char* aSet
,
1719 const nsAString
& aValue
)
1721 nsAString::const_iterator valueCurrent
, valueEnd
;
1723 aValue
.BeginReading(valueCurrent
);
1724 aValue
.EndReading(valueEnd
);
1726 // Skip characters in the beginning
1727 while (valueCurrent
!= valueEnd
) {
1728 if (!IsCharInSet(aSet
, *valueCurrent
)) {
1734 if (valueCurrent
!= valueEnd
) {
1737 if (!IsCharInSet(aSet
, *valueEnd
)) {
1741 ++valueEnd
; // Step beyond the last character we want in the value.
1744 // valueEnd should point to the char after the last to copy
1745 return Substring(valueCurrent
, valueEnd
);
1749 * This method strips leading and trailing whitespace from a string.
1753 const nsDependentSubstring
1754 nsContentUtils::TrimWhitespace(const nsAString
& aStr
, PRBool aTrimTrailing
)
1756 nsAString::const_iterator start
, end
;
1758 aStr
.BeginReading(start
);
1759 aStr
.EndReading(end
);
1761 // Skip whitespace characters in the beginning
1762 while (start
!= end
&& nsCRT::IsAsciiSpace(*start
)) {
1766 if (aTrimTrailing
) {
1767 // Skip whitespace characters in the end.
1768 while (end
!= start
) {
1771 if (!nsCRT::IsAsciiSpace(*end
)) {
1772 // Step back to the last non-whitespace character.
1780 // Return a substring for the string w/o leading and/or trailing
1783 return Substring(start
, end
);
1786 static inline void KeyAppendSep(nsACString
& aKey
)
1788 if (!aKey
.IsEmpty()) {
1793 static inline void KeyAppendString(const nsAString
& aString
, nsACString
& aKey
)
1797 // Could escape separator here if collisions happen. > is not a legal char
1798 // for a name or type attribute, so we should be safe avoiding that extra work.
1800 AppendUTF16toUTF8(aString
, aKey
);
1803 static inline void KeyAppendString(const nsACString
& aString
, nsACString
& aKey
)
1807 // Could escape separator here if collisions happen. > is not a legal char
1808 // for a name or type attribute, so we should be safe avoiding that extra work.
1810 aKey
.Append(aString
);
1813 static inline void KeyAppendInt(PRInt32 aInt
, nsACString
& aKey
)
1817 aKey
.Append(nsPrintfCString("%d", aInt
));
1820 static inline void KeyAppendAtom(nsIAtom
* aAtom
, nsACString
& aKey
)
1822 NS_PRECONDITION(aAtom
, "KeyAppendAtom: aAtom can not be null!\n");
1824 KeyAppendString(nsAtomCString(aAtom
), aKey
);
1827 static inline PRBool
IsAutocompleteOff(nsIDOMElement
* aElement
)
1829 nsAutoString autocomplete
;
1830 aElement
->GetAttribute(NS_LITERAL_STRING("autocomplete"), autocomplete
);
1831 return autocomplete
.LowerCaseEqualsLiteral("off");
1835 nsContentUtils::GenerateStateKey(nsIContent
* aContent
,
1836 nsIDocument
* aDocument
,
1837 nsIStatefulFrame::SpecialStateID aID
,
1842 PRUint32 partID
= aDocument
? aDocument
->GetPartID() : 0;
1844 // SpecialStateID case - e.g. scrollbars around the content window
1845 // The key in this case is a special state id
1846 if (nsIStatefulFrame::eNoID
!= aID
) {
1847 KeyAppendInt(partID
, aKey
); // first append a partID
1848 KeyAppendInt(aID
, aKey
);
1852 // We must have content if we're not using a special state id
1853 NS_ENSURE_TRUE(aContent
, NS_ERROR_FAILURE
);
1855 // Don't capture state for anonymous content
1856 if (aContent
->IsInAnonymousSubtree()) {
1860 nsCOMPtr
<nsIDOMElement
> element(do_QueryInterface(aContent
));
1861 if (element
&& IsAutocompleteOff(element
)) {
1865 nsCOMPtr
<nsIHTMLDocument
> htmlDocument(do_QueryInterface(aContent
->GetCurrentDoc()));
1867 KeyAppendInt(partID
, aKey
); // first append a partID
1868 // Make sure we can't possibly collide with an nsIStatefulFrame
1869 // special id of some sort
1870 KeyAppendInt(nsIStatefulFrame::eNoID
, aKey
);
1871 PRBool generatedUniqueKey
= PR_FALSE
;
1874 // Flush our content model so it'll be up to date
1875 // If this becomes unnecessary and the following line is removed,
1876 // please also remove the corresponding flush operation from
1877 // nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
1878 aContent
->GetCurrentDoc()->FlushPendingNotifications(Flush_Content
);
1880 nsContentList
*htmlForms
= htmlDocument
->GetForms();
1881 nsContentList
*htmlFormControls
= htmlDocument
->GetFormControls();
1883 NS_ENSURE_TRUE(htmlForms
&& htmlFormControls
, NS_ERROR_OUT_OF_MEMORY
);
1885 // If we have a form control and can calculate form information, use that
1886 // as the key - it is more reliable than just recording position in the
1888 // XXXbz Is it, really? We have bugs on this, I think...
1889 // Important to have a unique key, and tag/type/name may not be.
1891 // If the control has a form, the format of the key is:
1892 // f>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
1894 // d>type>IndOfControlInDoc>name
1896 // XXX We don't need to use index if name is there
1897 // XXXbz We don't? Why not? I don't follow.
1899 nsCOMPtr
<nsIFormControl
> control(do_QueryInterface(aContent
));
1900 if (control
&& htmlFormControls
&& htmlForms
) {
1902 // Append the control type
1903 KeyAppendInt(control
->GetType(), aKey
);
1905 // If in a form, add form name / index of form / index in form
1907 nsCOMPtr
<nsIDOMHTMLFormElement
> formElement
;
1908 control
->GetForm(getter_AddRefs(formElement
));
1911 if (IsAutocompleteOff(formElement
)) {
1916 KeyAppendString(NS_LITERAL_CSTRING("f"), aKey
);
1918 // Append the index of the form in the document
1919 nsCOMPtr
<nsIContent
> formContent(do_QueryInterface(formElement
));
1920 index
= htmlForms
->IndexOf(formContent
, PR_FALSE
);
1923 // XXX HACK this uses some state that was dumped into the document
1924 // specifically to fix bug 138892. What we are trying to do is *guess*
1925 // which form this control's state is found in, with the highly likely
1926 // guess that the highest form parsed so far is the one.
1927 // This code should not be on trunk, only branch.
1929 index
= htmlDocument
->GetNumFormsSynchronous() - 1;
1932 KeyAppendInt(index
, aKey
);
1934 // Append the index of the control in the form
1935 nsCOMPtr
<nsIForm
> form(do_QueryInterface(formElement
));
1936 index
= form
->IndexOfControl(control
);
1939 KeyAppendInt(index
, aKey
);
1940 generatedUniqueKey
= PR_TRUE
;
1944 // Append the form name
1945 nsAutoString formName
;
1946 formElement
->GetName(formName
);
1947 KeyAppendString(formName
, aKey
);
1951 KeyAppendString(NS_LITERAL_CSTRING("d"), aKey
);
1953 // If not in a form, add index of control in document
1954 // Less desirable than indexing by form info.
1956 // Hash by index of control in doc (we are not in a form)
1957 // These are important as they are unique, and type/name may not be.
1959 // We have to flush sink notifications at this point to make
1960 // sure that htmlFormControls is up to date.
1961 index
= htmlFormControls
->IndexOf(aContent
, PR_TRUE
);
1963 KeyAppendInt(index
, aKey
);
1964 generatedUniqueKey
= PR_TRUE
;
1968 // Append the control name
1970 aContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::name
, name
);
1971 KeyAppendString(name
, aKey
);
1975 if (!generatedUniqueKey
) {
1976 // Either we didn't have a form control or we aren't in an HTML document so
1977 // we can't figure out form info. First append a character that is not "d"
1978 // or "f" to disambiguate from the case when we were a form control in an
1980 KeyAppendString(NS_LITERAL_CSTRING("o"), aKey
);
1982 // Now start at aContent and append the indices of it and all its ancestors
1983 // in their containers. That should at least pin down its position in the
1985 nsINode
* parent
= aContent
->GetNodeParent();
1986 nsINode
* content
= aContent
;
1988 KeyAppendInt(parent
->IndexOf(content
), aKey
);
1990 parent
= content
->GetNodeParent();
1999 nsContentUtils::NewURIWithDocumentCharset(nsIURI
** aResult
,
2000 const nsAString
& aSpec
,
2001 nsIDocument
* aDocument
,
2004 return NS_NewURI(aResult
, aSpec
,
2005 aDocument
? aDocument
->GetDocumentCharacterSet().get() : nsnull
,
2006 aBaseURI
, sIOService
);
2011 nsContentUtils::BelongsInForm(nsIDOMHTMLFormElement
*aForm
,
2012 nsIContent
*aContent
)
2014 NS_PRECONDITION(aForm
, "Must have a form");
2015 NS_PRECONDITION(aContent
, "Must have a content node");
2017 nsCOMPtr
<nsIContent
> form(do_QueryInterface(aForm
));
2020 NS_ERROR("This should not happen, form is not an nsIContent!");
2025 if (form
== aContent
) {
2026 // A form does not belong inside itself, so we return false here
2031 nsIContent
* content
= aContent
->GetParent();
2034 if (content
== form
) {
2035 // aContent is contained within the form so we return true.
2040 if (content
->Tag() == nsGkAtoms::form
&&
2041 content
->IsHTML()) {
2042 // The child is contained within a form, but not the right form
2048 content
= content
->GetParent();
2051 if (form
->GetChildCount() > 0) {
2052 // The form is a container but aContent wasn't inside the form,
2058 // The form is a leaf and aContent wasn't inside any other form so
2059 // we check whether the content comes after the form. If it does,
2060 // return true. If it does not, then it couldn't have been inside
2061 // the form in the HTML.
2062 if (PositionIsBefore(form
, aContent
)) {
2063 // We could be in this form!
2064 // In the future, we may want to get document.forms, look at the
2065 // form after aForm, and if aContent is after that form after
2066 // aForm return false here....
2075 nsContentUtils::CheckQName(const nsAString
& aQualifiedName
,
2076 PRBool aNamespaceAware
)
2078 nsIParserService
*parserService
= GetParserService();
2079 NS_ENSURE_TRUE(parserService
, NS_ERROR_FAILURE
);
2081 const PRUnichar
*colon
;
2082 return parserService
->CheckQName(PromiseFlatString(aQualifiedName
),
2083 aNamespaceAware
, &colon
);
2088 nsContentUtils::SplitQName(nsIContent
* aNamespaceResolver
,
2089 const nsAFlatString
& aQName
,
2090 PRInt32
*aNamespace
, nsIAtom
**aLocalName
)
2092 nsIParserService
* parserService
= GetParserService();
2093 NS_ENSURE_TRUE(parserService
, NS_ERROR_FAILURE
);
2095 const PRUnichar
* colon
;
2096 nsresult rv
= parserService
->CheckQName(aQName
, PR_TRUE
, &colon
);
2097 NS_ENSURE_SUCCESS(rv
, rv
);
2100 const PRUnichar
* end
;
2101 aQName
.EndReading(end
);
2102 nsAutoString nameSpace
;
2103 rv
= aNamespaceResolver
->LookupNamespaceURI(Substring(aQName
.get(), colon
),
2105 NS_ENSURE_SUCCESS(rv
, rv
);
2107 *aNamespace
= NameSpaceManager()->GetNameSpaceID(nameSpace
);
2108 if (*aNamespace
== kNameSpaceID_Unknown
)
2109 return NS_ERROR_FAILURE
;
2111 *aLocalName
= NS_NewAtom(Substring(colon
+ 1, end
));
2114 *aNamespace
= kNameSpaceID_None
;
2115 *aLocalName
= NS_NewAtom(aQName
);
2117 NS_ENSURE_TRUE(aLocalName
, NS_ERROR_OUT_OF_MEMORY
);
2123 nsContentUtils::GetNodeInfoFromQName(const nsAString
& aNamespaceURI
,
2124 const nsAString
& aQualifiedName
,
2125 nsNodeInfoManager
* aNodeInfoManager
,
2126 nsINodeInfo
** aNodeInfo
)
2128 nsIParserService
* parserService
= GetParserService();
2129 NS_ENSURE_TRUE(parserService
, NS_ERROR_FAILURE
);
2131 const nsAFlatString
& qName
= PromiseFlatString(aQualifiedName
);
2132 const PRUnichar
* colon
;
2133 nsresult rv
= parserService
->CheckQName(qName
, PR_TRUE
, &colon
);
2134 NS_ENSURE_SUCCESS(rv
, rv
);
2137 sNameSpaceManager
->RegisterNameSpace(aNamespaceURI
, nsID
);
2139 const PRUnichar
* end
;
2140 qName
.EndReading(end
);
2142 nsCOMPtr
<nsIAtom
> prefix
= do_GetAtom(Substring(qName
.get(), colon
));
2144 rv
= aNodeInfoManager
->GetNodeInfo(Substring(colon
+ 1, end
), prefix
,
2148 rv
= aNodeInfoManager
->GetNodeInfo(aQualifiedName
, nsnull
, nsID
,
2151 NS_ENSURE_SUCCESS(rv
, rv
);
2153 return nsContentUtils::IsValidNodeName((*aNodeInfo
)->NameAtom(),
2154 (*aNodeInfo
)->GetPrefixAtom(),
2155 (*aNodeInfo
)->NamespaceID()) ?
2156 NS_OK
: NS_ERROR_DOM_NAMESPACE_ERR
;
2161 nsContentUtils::SplitExpatName(const PRUnichar
*aExpatName
, nsIAtom
**aPrefix
,
2162 nsIAtom
**aLocalName
, PRInt32
* aNameSpaceID
)
2165 * Expat can send the following:
2167 * namespaceURI<separator>localName
2168 * namespaceURI<separator>localName<separator>prefix
2170 * and we use 0xFFFF for the <separator>.
2174 const PRUnichar
*uriEnd
= nsnull
;
2175 const PRUnichar
*nameEnd
= nsnull
;
2176 const PRUnichar
*pos
;
2177 for (pos
= aExpatName
; *pos
; ++pos
) {
2178 if (*pos
== 0xFFFF) {
2188 const PRUnichar
*nameStart
;
2190 if (sNameSpaceManager
) {
2191 sNameSpaceManager
->RegisterNameSpace(nsDependentSubstring(aExpatName
,
2196 *aNameSpaceID
= kNameSpaceID_Unknown
;
2199 nameStart
= (uriEnd
+ 1);
2201 const PRUnichar
*prefixStart
= nameEnd
+ 1;
2202 *aPrefix
= NS_NewAtom(Substring(prefixStart
, pos
));
2210 *aNameSpaceID
= kNameSpaceID_None
;
2211 nameStart
= aExpatName
;
2215 *aLocalName
= NS_NewAtom(Substring(nameStart
, nameEnd
));
2220 nsContentUtils::GetContextForContent(nsIContent
* aContent
)
2222 nsIDocument
* doc
= aContent
->GetCurrentDoc();
2224 nsIPresShell
*presShell
= doc
->GetPrimaryShell();
2226 return presShell
->GetPresContext();
2234 nsContentUtils::CanLoadImage(nsIURI
* aURI
, nsISupports
* aContext
,
2235 nsIDocument
* aLoadingDocument
,
2236 nsIPrincipal
* aLoadingPrincipal
,
2237 PRInt16
* aImageBlockingStatus
)
2239 NS_PRECONDITION(aURI
, "Must have a URI");
2240 NS_PRECONDITION(aLoadingDocument
, "Must have a document");
2241 NS_PRECONDITION(aLoadingPrincipal
, "Must have a loading principal");
2245 PRUint32 appType
= nsIDocShell::APP_TYPE_UNKNOWN
;
2248 nsCOMPtr
<nsISupports
> container
= aLoadingDocument
->GetContainer();
2249 nsCOMPtr
<nsIDocShellTreeItem
> docShellTreeItem
=
2250 do_QueryInterface(container
);
2252 if (docShellTreeItem
) {
2253 nsCOMPtr
<nsIDocShellTreeItem
> root
;
2254 docShellTreeItem
->GetRootTreeItem(getter_AddRefs(root
));
2256 nsCOMPtr
<nsIDocShell
> docShell(do_QueryInterface(root
));
2258 if (!docShell
|| NS_FAILED(docShell
->GetAppType(&appType
))) {
2259 appType
= nsIDocShell::APP_TYPE_UNKNOWN
;
2264 if (appType
!= nsIDocShell::APP_TYPE_EDITOR
) {
2265 // Editor apps get special treatment here, editors can load images
2266 // from anywhere. This allows editor to insert images from file://
2267 // into documents that are being edited.
2268 rv
= sSecurityManager
->
2269 CheckLoadURIWithPrincipal(aLoadingPrincipal
, aURI
,
2270 nsIScriptSecurityManager::ALLOW_CHROME
);
2271 if (NS_FAILED(rv
)) {
2272 if (aImageBlockingStatus
) {
2273 // Reject the request itself, not all requests to the relevant
2275 *aImageBlockingStatus
= nsIContentPolicy::REJECT_REQUEST
;
2281 PRInt16 decision
= nsIContentPolicy::ACCEPT
;
2283 rv
= NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_IMAGE
,
2287 EmptyCString(), //mime guess
2293 if (aImageBlockingStatus
) {
2294 *aImageBlockingStatus
=
2295 NS_FAILED(rv
) ? nsIContentPolicy::REJECT_REQUEST
: decision
;
2297 return NS_FAILED(rv
) ? PR_FALSE
: NS_CP_ACCEPTED(decision
);
2302 nsContentUtils::IsImageInCache(nsIURI
* aURI
)
2304 if (!sImgCache
) return PR_FALSE
;
2306 // If something unexpected happened we return false, otherwise if props
2307 // is set, the image is cached and we return true
2308 nsCOMPtr
<nsIProperties
> props
;
2309 nsresult rv
= sImgCache
->FindEntryProperties(aURI
, getter_AddRefs(props
));
2310 return (NS_SUCCEEDED(rv
) && props
);
2315 nsContentUtils::LoadImage(nsIURI
* aURI
, nsIDocument
* aLoadingDocument
,
2316 nsIPrincipal
* aLoadingPrincipal
, nsIURI
* aReferrer
,
2317 imgIDecoderObserver
* aObserver
, PRInt32 aLoadFlags
,
2318 imgIRequest
** aRequest
)
2320 NS_PRECONDITION(aURI
, "Must have a URI");
2321 NS_PRECONDITION(aLoadingDocument
, "Must have a document");
2322 NS_PRECONDITION(aLoadingPrincipal
, "Must have a principal");
2323 NS_PRECONDITION(aRequest
, "Null out param");
2326 // nothing we can do here
2330 nsCOMPtr
<nsILoadGroup
> loadGroup
= aLoadingDocument
->GetDocumentLoadGroup();
2331 NS_ASSERTION(loadGroup
, "Could not get loadgroup; onload may fire too early");
2333 nsIURI
*documentURI
= aLoadingDocument
->GetDocumentURI();
2335 // check for a Content Security Policy to pass down to the channel that
2336 // will get created to load the image
2337 nsCOMPtr
<nsIChannelPolicy
> channelPolicy
;
2338 nsCOMPtr
<nsIContentSecurityPolicy
> csp
;
2339 if (aLoadingPrincipal
) {
2340 nsresult rv
= aLoadingPrincipal
->GetCsp(getter_AddRefs(csp
));
2341 NS_ENSURE_SUCCESS(rv
, rv
);
2343 channelPolicy
= do_CreateInstance("@mozilla.org/nschannelpolicy;1");
2344 channelPolicy
->SetContentSecurityPolicy(csp
);
2345 channelPolicy
->SetLoadType(nsIContentPolicy::TYPE_IMAGE
);
2349 // Make the URI immutable so people won't change it under us
2350 NS_TryToSetImmutable(aURI
);
2352 // XXXbz using "documentURI" for the initialDocumentURI is not quite
2353 // right, but the best we can do here...
2354 return sImgLoader
->LoadImage(aURI
, /* uri to load */
2355 documentURI
, /* initialDocumentURI */
2356 aReferrer
, /* referrer */
2357 loadGroup
, /* loadgroup */
2358 aObserver
, /* imgIDecoderObserver */
2359 aLoadingDocument
, /* uniquification key */
2360 aLoadFlags
, /* load flags */
2361 nsnull
, /* cache key */
2362 nsnull
, /* existing request*/
2363 channelPolicy
, /* CSP info */
2368 already_AddRefed
<imgIContainer
>
2369 nsContentUtils::GetImageFromContent(nsIImageLoadingContent
* aContent
,
2370 imgIRequest
**aRequest
)
2376 NS_ENSURE_TRUE(aContent
, nsnull
);
2378 nsCOMPtr
<imgIRequest
> imgRequest
;
2379 aContent
->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST
,
2380 getter_AddRefs(imgRequest
));
2385 nsCOMPtr
<imgIContainer
> imgContainer
;
2386 imgRequest
->GetImage(getter_AddRefs(imgContainer
));
2388 if (!imgContainer
) {
2393 imgRequest
.swap(*aRequest
);
2396 return imgContainer
.forget();
2400 already_AddRefed
<imgIRequest
>
2401 nsContentUtils::GetStaticRequest(imgIRequest
* aRequest
)
2403 NS_ENSURE_TRUE(aRequest
, nsnull
);
2404 nsCOMPtr
<imgIRequest
> retval
;
2405 aRequest
->GetStaticRequest(getter_AddRefs(retval
));
2406 return retval
.forget();
2411 nsContentUtils::ContentIsDraggable(nsIContent
* aContent
)
2413 nsCOMPtr
<nsIDOMNSHTMLElement
> htmlElement
= do_QueryInterface(aContent
);
2415 PRBool draggable
= PR_FALSE
;
2416 htmlElement
->GetDraggable(&draggable
);
2420 if (aContent
->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::draggable
,
2421 nsGkAtoms::_false
, eIgnoreCase
))
2425 // special handling for content area image and link dragging
2426 return IsDraggableImage(aContent
) || IsDraggableLink(aContent
);
2431 nsContentUtils::IsDraggableImage(nsIContent
* aContent
)
2433 NS_PRECONDITION(aContent
, "Must have content node to test");
2435 nsCOMPtr
<nsIImageLoadingContent
> imageContent(do_QueryInterface(aContent
));
2436 if (!imageContent
) {
2440 nsCOMPtr
<imgIRequest
> imgRequest
;
2441 imageContent
->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST
,
2442 getter_AddRefs(imgRequest
));
2444 // XXXbz It may be draggable even if the request resulted in an error. Why?
2445 // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
2446 return imgRequest
!= nsnull
;
2451 nsContentUtils::IsDraggableLink(nsIContent
* aContent
) {
2452 nsCOMPtr
<nsIURI
> absURI
;
2453 return aContent
->IsLink(getter_AddRefs(absURI
));
2458 nsContentUtils::GetCharPref(const char *aPref
)
2460 nsAdoptingCString result
;
2463 sPrefBranch
->GetCharPref(aPref
, getter_Copies(result
));
2471 nsContentUtils::GetBoolPref(const char *aPref
, PRBool aDefault
)
2476 NS_FAILED(sPrefBranch
->GetBoolPref(aPref
, &result
))) {
2480 return (PRPackedBool
)result
;
2485 nsContentUtils::GetIntPref(const char *aPref
, PRInt32 aDefault
)
2490 NS_FAILED(sPrefBranch
->GetIntPref(aPref
, &result
))) {
2499 nsContentUtils::GetLocalizedStringPref(const char *aPref
)
2501 nsAdoptingString result
;
2504 nsCOMPtr
<nsIPrefLocalizedString
> prefLocalString
;
2505 sPrefBranch
->GetComplexValue(aPref
, NS_GET_IID(nsIPrefLocalizedString
),
2506 getter_AddRefs(prefLocalString
));
2507 if (prefLocalString
) {
2508 prefLocalString
->GetData(getter_Copies(result
));
2517 nsContentUtils::GetStringPref(const char *aPref
)
2519 nsAdoptingString result
;
2522 nsCOMPtr
<nsISupportsString
> theString
;
2523 sPrefBranch
->GetComplexValue(aPref
, NS_GET_IID(nsISupportsString
),
2524 getter_AddRefs(theString
));
2526 theString
->ToString(getter_Copies(result
));
2533 // RegisterPrefCallback/UnregisterPrefCallback are backward compatiblity for
2534 // c-style observer.
2538 nsContentUtils::RegisterPrefCallback(const char *aPref
,
2539 PrefChangedFunc aCallback
,
2543 if (!sPrefCallbackList
) {
2544 sPrefCallbackList
= new nsCOMArray
<nsPrefOldCallback
> ();
2545 if (!sPrefCallbackList
)
2549 nsPrefOldCallback
*callback
= new nsPrefOldCallback(aPref
, aCallback
, aClosure
);
2551 if (NS_SUCCEEDED(sPrefBranch
->AddObserver(aPref
, callback
, PR_FALSE
))) {
2552 sPrefCallbackList
->AppendObject(callback
);
2555 // error to get/add nsIPrefBranch2. Destroy callback information
2563 nsContentUtils::UnregisterPrefCallback(const char *aPref
,
2564 PrefChangedFunc aCallback
,
2568 if (!sPrefCallbackList
)
2572 for (i
= 0; i
< sPrefCallbackList
->Count(); i
++) {
2573 nsRefPtr
<nsPrefOldCallback
> callback
= (*sPrefCallbackList
)[i
];
2574 if (callback
&& callback
->IsEqual(aPref
, aCallback
, aClosure
)) {
2575 sPrefBranch
->RemoveObserver(aPref
, callback
);
2576 sPrefCallbackList
->RemoveObject(callback
);
2584 BoolVarChanged(const char *aPref
, void *aClosure
)
2586 PrefCacheData
* cache
= static_cast<PrefCacheData
*>(aClosure
);
2587 *((PRBool
*)cache
->cacheLocation
) =
2588 nsContentUtils::GetBoolPref(aPref
, cache
->defaultValueBool
);
2594 nsContentUtils::AddBoolPrefVarCache(const char *aPref
,
2598 *aCache
= GetBoolPref(aPref
, aDefault
);
2599 PrefCacheData
* data
= new PrefCacheData
;
2600 data
->cacheLocation
= aCache
;
2601 data
->defaultValueBool
= aDefault
;
2602 sPrefCacheData
->AppendElement(data
);
2603 RegisterPrefCallback(aPref
, BoolVarChanged
, data
);
2607 IntVarChanged(const char *aPref
, void *aClosure
)
2609 PrefCacheData
* cache
= static_cast<PrefCacheData
*>(aClosure
);
2610 *((PRInt32
*)cache
->cacheLocation
) =
2611 nsContentUtils::GetIntPref(aPref
, cache
->defaultValueInt
);
2617 nsContentUtils::AddIntPrefVarCache(const char *aPref
,
2621 *aCache
= GetIntPref(aPref
, aDefault
);
2622 PrefCacheData
* data
= new PrefCacheData
;
2623 data
->cacheLocation
= aCache
;
2624 data
->defaultValueInt
= aDefault
;
2625 sPrefCacheData
->AppendElement(data
);
2626 RegisterPrefCallback(aPref
, IntVarChanged
, data
);
2629 static const char *gEventNames
[] = {"event"};
2630 static const char *gSVGEventNames
[] = {"evt"};
2631 // for b/w compat, the first name to onerror is still 'event', even though it
2632 // is actually the error message. (pre this code, the other 2 were not avail.)
2633 // XXXmarkh - a quick lxr shows no affected code - should we correct this?
2634 static const char *gOnErrorNames
[] = {"event", "source", "lineno"};
2638 nsContentUtils::GetEventArgNames(PRInt32 aNameSpaceID
,
2639 nsIAtom
*aEventName
,
2640 PRUint32
*aArgCount
,
2641 const char*** aArgArray
)
2643 #define SET_EVENT_ARG_NAMES(names) \
2644 *aArgCount = sizeof(names)/sizeof(names[0]); \
2647 // nsJSEventListener is what does the arg magic for onerror, and it does
2648 // not seem to take the namespace into account. So we let onerror in all
2649 // namespaces get the 3 arg names.
2650 if (aEventName
== nsGkAtoms::onerror
) {
2651 SET_EVENT_ARG_NAMES(gOnErrorNames
);
2652 } else if (aNameSpaceID
== kNameSpaceID_SVG
) {
2653 SET_EVENT_ARG_NAMES(gSVGEventNames
);
2655 SET_EVENT_ARG_NAMES(gEventNames
);
2659 nsCxPusher::nsCxPusher()
2660 : mScriptIsRunning(PR_FALSE
),
2661 mPushedSomething(PR_FALSE
)
2665 nsCxPusher::~nsCxPusher()
2671 IsContextOnStack(nsIJSContextStack
*aStack
, JSContext
*aContext
)
2673 JSContext
*ctx
= nsnull
;
2677 if (ctx
== aContext
)
2680 nsCOMPtr
<nsIJSContextStackIterator
>
2681 iterator(do_CreateInstance("@mozilla.org/js/xpc/ContextStackIterator;1"));
2682 NS_ENSURE_TRUE(iterator
, PR_FALSE
);
2684 nsresult rv
= iterator
->Reset(aStack
);
2685 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
2688 while (NS_SUCCEEDED(iterator
->Done(&done
)) && !done
) {
2689 rv
= iterator
->Prev(&ctx
);
2690 NS_ASSERTION(NS_SUCCEEDED(rv
), "Broken iterator implementation");
2696 if (nsJSUtils::GetDynamicScriptContext(ctx
) && ctx
== aContext
)
2704 nsCxPusher::Push(nsPIDOMEventTarget
*aCurrentTarget
)
2706 if (mPushedSomething
) {
2707 NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
2712 NS_ENSURE_TRUE(aCurrentTarget
, PR_FALSE
);
2714 nsIScriptContext
* scx
=
2715 aCurrentTarget
->GetContextForEventHandlers(&rv
);
2716 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
2719 // The target may have a special JS context for event handlers.
2720 JSContext
* cx
= aCurrentTarget
->GetJSContextForEventHandlers();
2725 // Nothing to do here, I guess. Have to return true so that event firing
2726 // will still work correctly even if there is no associated JSContext
2730 JSContext
* cx
= nsnull
;
2733 cx
= static_cast<JSContext
*>(scx
->GetNativeContext());
2734 // Bad, no JSContext from script context!
2735 NS_ENSURE_TRUE(cx
, PR_FALSE
);
2738 // If there's no native context in the script context it must be
2739 // in the process or being torn down. We don't want to notify the
2740 // script context about scripts having been evaluated in such a
2741 // case, calling with a null cx is fine in that case.
2746 nsCxPusher::RePush(nsPIDOMEventTarget
*aCurrentTarget
)
2748 if (!mPushedSomething
) {
2749 return Push(aCurrentTarget
);
2752 if (aCurrentTarget
) {
2754 nsIScriptContext
* scx
=
2755 aCurrentTarget
->GetContextForEventHandlers(&rv
);
2756 if (NS_FAILED(rv
)) {
2761 // If we have the same script context and native context is still
2762 // alive, no need to Pop/Push.
2763 if (scx
&& scx
== mScx
&&
2764 scx
->GetNativeContext()) {
2770 return Push(aCurrentTarget
);
2774 nsCxPusher::Push(JSContext
*cx
, PRBool aRequiresScriptContext
)
2776 if (mPushedSomething
) {
2777 NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
2786 // Hold a strong ref to the nsIScriptContext, just in case
2787 // XXXbz do we really need to? If we don't get one of these in Pop(), is
2788 // that really a problem? Or do we need to do this to effectively root |cx|?
2789 mScx
= GetScriptContextFromJSContext(cx
);
2790 if (!mScx
&& aRequiresScriptContext
) {
2791 // Should probably return PR_FALSE. See bug 416916.
2799 nsCxPusher::DoPush(JSContext
* cx
)
2801 nsIThreadJSContextStack
* stack
= nsContentUtils::ThreadJSContextStack();
2806 if (cx
&& IsContextOnStack(stack
, cx
)) {
2807 // If the context is on the stack, that means that a script
2808 // is running at the moment in the context.
2809 mScriptIsRunning
= PR_TRUE
;
2812 if (NS_FAILED(stack
->Push(cx
))) {
2813 mScriptIsRunning
= PR_FALSE
;
2818 mPushedSomething
= PR_TRUE
;
2820 mPushedContext
= cx
;
2826 nsCxPusher::PushNull()
2828 return DoPush(nsnull
);
2834 nsIThreadJSContextStack
* stack
= nsContentUtils::ThreadJSContextStack();
2835 if (!mPushedSomething
|| !stack
) {
2837 mPushedSomething
= PR_FALSE
;
2839 NS_ASSERTION(!mScriptIsRunning
, "Huh, this can't be happening, "
2840 "mScriptIsRunning can't be set here!");
2846 stack
->Pop(&unused
);
2848 NS_ASSERTION(unused
== mPushedContext
, "Unexpected context popped");
2850 if (!mScriptIsRunning
&& mScx
) {
2851 // No JS is running in the context, but executing the event handler might have
2852 // caused some JS to run. Tell the script context that it's done.
2854 mScx
->ScriptEvaluated(PR_TRUE
);
2858 mScriptIsRunning
= PR_FALSE
;
2859 mPushedSomething
= PR_FALSE
;
2862 static const char gPropertiesFiles
[nsContentUtils::PropertiesFile_COUNT
][56] = {
2863 // Must line up with the enum values in |PropertiesFile| enum.
2864 "chrome://global/locale/css.properties",
2865 "chrome://global/locale/xbl.properties",
2866 "chrome://global/locale/xul.properties",
2867 "chrome://global/locale/layout_errors.properties",
2868 "chrome://global/locale/layout/HtmlForm.properties",
2869 "chrome://global/locale/printing.properties",
2870 "chrome://global/locale/dom/dom.properties",
2872 "chrome://global/locale/svg/svg.properties",
2874 "chrome://branding/locale/brand.properties",
2875 "chrome://global/locale/commonDialogs.properties"
2878 /* static */ nsresult
2879 nsContentUtils::EnsureStringBundle(PropertiesFile aFile
)
2881 if (!sStringBundles
[aFile
]) {
2882 if (!sStringBundleService
) {
2884 CallGetService(NS_STRINGBUNDLE_CONTRACTID
, &sStringBundleService
);
2885 NS_ENSURE_SUCCESS(rv
, rv
);
2887 nsIStringBundle
*bundle
;
2889 sStringBundleService
->CreateBundle(gPropertiesFiles
[aFile
], &bundle
);
2890 NS_ENSURE_SUCCESS(rv
, rv
);
2891 sStringBundles
[aFile
] = bundle
; // transfer ownership
2897 nsresult
nsContentUtils::GetLocalizedString(PropertiesFile aFile
,
2899 nsXPIDLString
& aResult
)
2901 nsresult rv
= EnsureStringBundle(aFile
);
2902 NS_ENSURE_SUCCESS(rv
, rv
);
2903 nsIStringBundle
*bundle
= sStringBundles
[aFile
];
2905 return bundle
->GetStringFromName(NS_ConvertASCIItoUTF16(aKey
).get(),
2906 getter_Copies(aResult
));
2910 nsresult
nsContentUtils::FormatLocalizedString(PropertiesFile aFile
,
2912 const PRUnichar
**aParams
,
2913 PRUint32 aParamsLength
,
2914 nsXPIDLString
& aResult
)
2916 nsresult rv
= EnsureStringBundle(aFile
);
2917 NS_ENSURE_SUCCESS(rv
, rv
);
2918 nsIStringBundle
*bundle
= sStringBundles
[aFile
];
2920 return bundle
->FormatStringFromName(NS_ConvertASCIItoUTF16(aKey
).get(),
2921 aParams
, aParamsLength
,
2922 getter_Copies(aResult
));
2925 /* static */ nsresult
2926 nsContentUtils::ReportToConsole(PropertiesFile aFile
,
2927 const char *aMessageName
,
2928 const PRUnichar
**aParams
,
2929 PRUint32 aParamsLength
,
2931 const nsAFlatString
& aSourceLine
,
2932 PRUint32 aLineNumber
,
2933 PRUint32 aColumnNumber
,
2934 PRUint32 aErrorFlags
,
2935 const char *aCategory
)
2937 NS_ASSERTION((aParams
&& aParamsLength
) || (!aParams
&& !aParamsLength
),
2938 "Supply either both parameters and their number or no"
2939 "parameters and 0.");
2942 if (!sConsoleService
) { // only need to bother null-checking here
2943 rv
= CallGetService(NS_CONSOLESERVICE_CONTRACTID
, &sConsoleService
);
2944 NS_ENSURE_SUCCESS(rv
, rv
);
2947 nsXPIDLString errorText
;
2949 rv
= FormatLocalizedString(aFile
, aMessageName
, aParams
, aParamsLength
,
2953 rv
= GetLocalizedString(aFile
, aMessageName
, errorText
);
2955 NS_ENSURE_SUCCESS(rv
, rv
);
2959 aURI
->GetSpec(spec
);
2961 nsCOMPtr
<nsIScriptError
> errorObject
=
2962 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID
, &rv
);
2963 NS_ENSURE_SUCCESS(rv
, rv
);
2964 rv
= errorObject
->Init(errorText
.get(),
2965 NS_ConvertUTF8toUTF16(spec
).get(), // file name
2967 aLineNumber
, aColumnNumber
,
2968 aErrorFlags
, aCategory
);
2969 NS_ENSURE_SUCCESS(rv
, rv
);
2971 return sConsoleService
->LogMessage(errorObject
);
2975 nsContentUtils::IsChromeDoc(nsIDocument
*aDocument
)
2981 nsCOMPtr
<nsIPrincipal
> systemPrincipal
;
2982 sSecurityManager
->GetSystemPrincipal(getter_AddRefs(systemPrincipal
));
2984 return aDocument
->NodePrincipal() == systemPrincipal
;
2988 nsContentUtils::IsChildOfSameType(nsIDocument
* aDoc
)
2990 nsCOMPtr
<nsISupports
> container
= aDoc
->GetContainer();
2991 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(container
));
2992 nsCOMPtr
<nsIDocShellTreeItem
> sameTypeParent
;
2993 if (docShellAsItem
) {
2994 docShellAsItem
->GetSameTypeParent(getter_AddRefs(sameTypeParent
));
2996 return sameTypeParent
!= nsnull
;
3000 nsContentUtils::GetWrapperSafeScriptFilename(nsIDocument
*aDocument
,
3002 nsACString
& aScriptURI
)
3004 PRBool scriptFileNameModified
= PR_FALSE
;
3005 aURI
->GetSpec(aScriptURI
);
3007 if (IsChromeDoc(aDocument
)) {
3008 nsCOMPtr
<nsIChromeRegistry
> chromeReg
=
3009 mozilla::services::GetChromeRegistryService();
3012 // If we're running w/o a chrome registry we won't modify any
3013 // script file names.
3015 return scriptFileNameModified
;
3018 PRBool docWrappersEnabled
=
3019 chromeReg
->WrappersEnabled(aDocument
->GetDocumentURI());
3021 PRBool uriWrappersEnabled
= chromeReg
->WrappersEnabled(aURI
);
3023 nsIURI
*docURI
= aDocument
->GetDocumentURI();
3025 if (docURI
&& docWrappersEnabled
&& !uriWrappersEnabled
) {
3026 // aURI is a script from a URL that doesn't get wrapper
3027 // automation. aDocument is a chrome document that does get
3028 // wrapper automation. Prepend the chrome document's URI
3029 // followed by the string " -> " to the URI of the script we're
3030 // loading here so that script in that URI gets the same wrapper
3031 // automation that the chrome document expects.
3033 docURI
->GetSpec(spec
);
3034 spec
.AppendASCII(" -> ");
3035 spec
.Append(aScriptURI
);
3039 scriptFileNameModified
= PR_TRUE
;
3043 return scriptFileNameModified
;
3048 nsContentUtils::IsInChromeDocshell(nsIDocument
*aDocument
)
3054 if (aDocument
->GetDisplayDocument()) {
3055 return IsInChromeDocshell(aDocument
->GetDisplayDocument());
3058 nsCOMPtr
<nsISupports
> docContainer
= aDocument
->GetContainer();
3059 nsCOMPtr
<nsIDocShellTreeItem
> docShell(do_QueryInterface(docContainer
));
3060 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
3062 docShell
->GetItemType(&itemType
);
3065 return itemType
== nsIDocShellTreeItem::typeChrome
;
3070 nsContentUtils::GetContentPolicy()
3072 if (!sTriedToGetContentPolicy
) {
3073 CallGetService(NS_CONTENTPOLICY_CONTRACTID
, &sContentPolicyService
);
3074 // It's OK to not have a content policy service
3075 sTriedToGetContentPolicy
= PR_TRUE
;
3078 return sContentPolicyService
;
3083 nsAutoGCRoot::AddJSGCRoot(void* aPtr
, const char* aName
)
3085 if (!sJSScriptRuntime
) {
3086 nsresult rv
= CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
3087 &sJSRuntimeService
);
3088 NS_ENSURE_TRUE(sJSRuntimeService
, rv
);
3090 sJSRuntimeService
->GetRuntime(&sJSScriptRuntime
);
3091 if (!sJSScriptRuntime
) {
3092 NS_RELEASE(sJSRuntimeService
);
3093 NS_WARNING("Unable to get JS runtime from JS runtime service");
3094 return NS_ERROR_FAILURE
;
3099 ok
= ::JS_AddNamedRootRT(sJSScriptRuntime
, aPtr
, aName
);
3101 NS_WARNING("JS_AddNamedRootRT failed");
3102 return NS_ERROR_OUT_OF_MEMORY
;
3110 nsAutoGCRoot::RemoveJSGCRoot(void* aPtr
)
3112 if (!sJSScriptRuntime
) {
3113 NS_NOTREACHED("Trying to remove a JS GC root when none were added");
3114 return NS_ERROR_UNEXPECTED
;
3117 ::JS_RemoveRootRT(sJSScriptRuntime
, aPtr
);
3124 nsContentUtils::IsEventAttributeName(nsIAtom
* aName
, PRInt32 aType
)
3126 const PRUnichar
* name
= aName
->GetUTF16String();
3127 if (name
[0] != 'o' || name
[1] != 'n')
3130 EventNameMapping mapping
;
3131 return (sEventTable
->Get(aName
, &mapping
) && mapping
.mType
& aType
);
3136 nsContentUtils::GetEventId(nsIAtom
* aName
)
3138 EventNameMapping mapping
;
3139 if (sEventTable
->Get(aName
, &mapping
))
3142 return NS_USER_DEFINED_EVENT
;
3146 nsresult
GetEventAndTarget(nsIDocument
* aDoc
, nsISupports
* aTarget
,
3147 const nsAString
& aEventName
,
3148 PRBool aCanBubble
, PRBool aCancelable
,
3149 nsIDOMEvent
** aEvent
,
3150 nsIDOMEventTarget
** aTargetOut
)
3152 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent(do_QueryInterface(aDoc
));
3153 nsCOMPtr
<nsIDOMEventTarget
> target(do_QueryInterface(aTarget
));
3154 NS_ENSURE_TRUE(docEvent
&& target
, NS_ERROR_INVALID_ARG
);
3156 nsCOMPtr
<nsIDOMEvent
> event
;
3158 docEvent
->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event
));
3159 NS_ENSURE_SUCCESS(rv
, rv
);
3161 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(event
));
3162 NS_ENSURE_TRUE(privateEvent
, NS_ERROR_FAILURE
);
3164 rv
= event
->InitEvent(aEventName
, aCanBubble
, aCancelable
);
3165 NS_ENSURE_SUCCESS(rv
, rv
);
3167 rv
= privateEvent
->SetTrusted(PR_TRUE
);
3168 NS_ENSURE_SUCCESS(rv
, rv
);
3170 rv
= privateEvent
->SetTarget(target
);
3171 NS_ENSURE_SUCCESS(rv
, rv
);
3173 event
.forget(aEvent
);
3174 target
.forget(aTargetOut
);
3180 nsContentUtils::DispatchTrustedEvent(nsIDocument
* aDoc
, nsISupports
* aTarget
,
3181 const nsAString
& aEventName
,
3182 PRBool aCanBubble
, PRBool aCancelable
,
3183 PRBool
*aDefaultAction
)
3185 nsCOMPtr
<nsIDOMEvent
> event
;
3186 nsCOMPtr
<nsIDOMEventTarget
> target
;
3187 nsresult rv
= GetEventAndTarget(aDoc
, aTarget
, aEventName
, aCanBubble
,
3188 aCancelable
, getter_AddRefs(event
),
3189 getter_AddRefs(target
));
3190 NS_ENSURE_SUCCESS(rv
, rv
);
3193 return target
->DispatchEvent(event
, aDefaultAction
? aDefaultAction
: &dummy
);
3197 nsContentUtils::DispatchChromeEvent(nsIDocument
*aDoc
,
3198 nsISupports
*aTarget
,
3199 const nsAString
& aEventName
,
3200 PRBool aCanBubble
, PRBool aCancelable
,
3201 PRBool
*aDefaultAction
)
3204 nsCOMPtr
<nsIDOMEvent
> event
;
3205 nsCOMPtr
<nsIDOMEventTarget
> target
;
3206 nsresult rv
= GetEventAndTarget(aDoc
, aTarget
, aEventName
, aCanBubble
,
3207 aCancelable
, getter_AddRefs(event
),
3208 getter_AddRefs(target
));
3209 NS_ENSURE_SUCCESS(rv
, rv
);
3211 NS_ASSERTION(aDoc
, "GetEventAndTarget lied?");
3212 if (!aDoc
->GetWindow())
3213 return NS_ERROR_INVALID_ARG
;
3215 nsPIDOMEventTarget
* piTarget
= aDoc
->GetWindow()->GetChromeEventHandler();
3217 return NS_ERROR_INVALID_ARG
;
3219 nsCOMPtr
<nsIFrameLoaderOwner
> flo
= do_QueryInterface(piTarget
);
3221 nsRefPtr
<nsFrameLoader
> fl
= flo
->GetFrameLoader();
3223 nsPIDOMEventTarget
* t
= fl
->GetTabChildGlobalAsEventTarget();
3224 piTarget
= t
? t
: piTarget
;
3228 nsEventStatus status
= nsEventStatus_eIgnore
;
3229 rv
= piTarget
->DispatchDOMEvent(nsnull
, event
, nsnull
, &status
);
3230 if (aDefaultAction
) {
3231 *aDefaultAction
= (status
!= nsEventStatus_eConsumeNoDefault
);
3238 nsContentUtils::MatchElementId(nsIContent
*aContent
, nsIAtom
* aId
)
3240 for (nsIContent
* cur
= aContent
;
3242 cur
= cur
->GetNextNode(aContent
)) {
3243 if (aId
== cur
->GetID()) {
3244 return cur
->AsElement();
3253 nsContentUtils::MatchElementId(nsIContent
*aContent
, const nsAString
& aId
)
3255 NS_PRECONDITION(!aId
.IsEmpty(), "Will match random elements");
3257 // ID attrs are generally stored as atoms, so just atomize this up front
3258 nsCOMPtr
<nsIAtom
> id(do_GetAtom(aId
));
3260 // OOM, so just bail
3264 return MatchElementId(aContent
, id
);
3267 // Convert the string from the given charset to Unicode.
3270 nsContentUtils::ConvertStringFromCharset(const nsACString
& aCharset
,
3271 const nsACString
& aInput
,
3274 if (aCharset
.IsEmpty()) {
3275 // Treat the string as UTF8
3276 CopyUTF8toUTF16(aInput
, aOutput
);
3281 nsCOMPtr
<nsICharsetConverterManager
> ccm
=
3282 do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID
, &rv
);
3286 nsCOMPtr
<nsIUnicodeDecoder
> decoder
;
3287 rv
= ccm
->GetUnicodeDecoder(PromiseFlatCString(aCharset
).get(),
3288 getter_AddRefs(decoder
));
3292 nsPromiseFlatCString
flatInput(aInput
);
3293 PRInt32 srcLen
= flatInput
.Length();
3295 rv
= decoder
->GetMaxLength(flatInput
.get(), srcLen
, &dstLen
);
3299 PRUnichar
*ustr
= (PRUnichar
*)nsMemory::Alloc((dstLen
+ 1) *
3302 return NS_ERROR_OUT_OF_MEMORY
;
3304 rv
= decoder
->Convert(flatInput
.get(), &srcLen
, ustr
, &dstLen
);
3305 if (NS_SUCCEEDED(rv
)) {
3307 aOutput
.Assign(ustr
, dstLen
);
3310 nsMemory::Free(ustr
);
3316 nsContentUtils::CheckForBOM(const unsigned char* aBuffer
, PRUint32 aLength
,
3317 nsACString
& aCharset
, PRBool
*bigEndian
)
3319 PRBool found
= PR_TRUE
;
3320 aCharset
.Truncate();
3322 aBuffer
[0] == 0xEF &&
3323 aBuffer
[1] == 0xBB &&
3324 aBuffer
[2] == 0xBF) {
3327 else if (aLength
>= 4 &&
3328 aBuffer
[0] == 0x00 &&
3329 aBuffer
[1] == 0x00 &&
3330 aBuffer
[2] == 0xFE &&
3331 aBuffer
[3] == 0xFF) {
3332 aCharset
= "UTF-32";
3334 *bigEndian
= PR_TRUE
;
3336 else if (aLength
>= 4 &&
3337 aBuffer
[0] == 0xFF &&
3338 aBuffer
[1] == 0xFE &&
3339 aBuffer
[2] == 0x00 &&
3340 aBuffer
[3] == 0x00) {
3341 aCharset
= "UTF-32";
3343 *bigEndian
= PR_FALSE
;
3345 else if (aLength
>= 2 &&
3346 aBuffer
[0] == 0xFE && aBuffer
[1] == 0xFF) {
3347 aCharset
= "UTF-16";
3349 *bigEndian
= PR_TRUE
;
3351 else if (aLength
>= 2 &&
3352 aBuffer
[0] == 0xFF && aBuffer
[1] == 0xFE) {
3353 aCharset
= "UTF-16";
3355 *bigEndian
= PR_FALSE
;
3365 nsContentUtils::GetReferencedElement(nsIURI
* aURI
, nsIContent
*aFromContent
)
3367 nsReferencedElement ref
;
3368 ref
.Reset(aFromContent
, aURI
);
3374 nsContentUtils::RegisterShutdownObserver(nsIObserver
* aObserver
)
3376 nsCOMPtr
<nsIObserverService
> observerService
=
3377 mozilla::services::GetObserverService();
3378 if (observerService
) {
3379 observerService
->AddObserver(aObserver
,
3380 NS_XPCOM_SHUTDOWN_OBSERVER_ID
,
3387 nsContentUtils::UnregisterShutdownObserver(nsIObserver
* aObserver
)
3389 nsCOMPtr
<nsIObserverService
> observerService
=
3390 mozilla::services::GetObserverService();
3391 if (observerService
) {
3392 observerService
->RemoveObserver(aObserver
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
);
3398 nsContentUtils::HasNonEmptyAttr(nsIContent
* aContent
, PRInt32 aNameSpaceID
,
3401 static nsIContent::AttrValuesArray strings
[] = {&nsGkAtoms::_empty
, nsnull
};
3402 return aContent
->FindAttrValueIn(aNameSpaceID
, aName
, strings
, eCaseMatters
)
3403 == nsIContent::ATTR_VALUE_NO_MATCH
;
3408 nsContentUtils::HasMutationListeners(nsINode
* aNode
,
3410 nsINode
* aTargetForSubtreeModified
)
3412 nsIDocument
* doc
= aNode
->GetOwnerDoc();
3417 NS_ASSERTION((aNode
->IsNodeOfType(nsINode::eCONTENT
) &&
3418 static_cast<nsIContent
*>(aNode
)->
3419 IsInNativeAnonymousSubtree()) ||
3420 sScriptBlockerCount
== sRemovableScriptBlockerCount
,
3421 "Want to fire mutation events, but it's not safe");
3423 // global object will be null for documents that don't have windows.
3424 nsPIDOMWindow
* window
= doc
->GetInnerWindow();
3425 // This relies on nsEventListenerManager::AddEventListener, which sets
3426 // all mutation bits when there is a listener for DOMSubtreeModified event.
3427 if (window
&& !window
->HasMutationListeners(aType
)) {
3431 if (aNode
->IsNodeOfType(nsINode::eCONTENT
) &&
3432 static_cast<nsIContent
*>(aNode
)->IsInNativeAnonymousSubtree()) {
3436 doc
->MayDispatchMutationEvent(aTargetForSubtreeModified
);
3438 // If we have a window, we can check it for mutation listeners now.
3439 if (aNode
->IsInDoc()) {
3440 nsCOMPtr
<nsPIDOMEventTarget
> piTarget(do_QueryInterface(window
));
3442 nsIEventListenerManager
* manager
= piTarget
->GetListenerManager(PR_FALSE
);
3444 PRBool hasListeners
= PR_FALSE
;
3445 manager
->HasMutationListeners(&hasListeners
);
3453 // If we have a window, we know a mutation listener is registered, but it
3454 // might not be in our chain. If we don't have a window, we might have a
3455 // mutation listener. Check quickly to see.
3457 nsIEventListenerManager
* manager
= aNode
->GetListenerManager(PR_FALSE
);
3459 PRBool hasListeners
= PR_FALSE
;
3460 manager
->HasMutationListeners(&hasListeners
);
3466 if (aNode
->IsNodeOfType(nsINode::eCONTENT
)) {
3467 nsIContent
* content
= static_cast<nsIContent
*>(aNode
);
3468 nsIContent
* insertionParent
=
3469 doc
->BindingManager()->GetInsertionParent(content
);
3470 if (insertionParent
) {
3471 aNode
= insertionParent
;
3475 aNode
= aNode
->GetNodeParent();
3483 nsContentUtils::TraverseListenerManager(nsINode
*aNode
,
3484 nsCycleCollectionTraversalCallback
&cb
)
3486 if (!sEventListenerManagersHash
.ops
) {
3487 // We're already shut down, just return.
3491 EventListenerManagerMapEntry
*entry
=
3492 static_cast<EventListenerManagerMapEntry
*>
3493 (PL_DHashTableOperate(&sEventListenerManagersHash
, aNode
,
3495 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
3496 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "[via hash] mListenerManager");
3497 cb
.NoteXPCOMChild(entry
->mListenerManager
);
3501 nsIEventListenerManager
*
3502 nsContentUtils::GetListenerManager(nsINode
*aNode
,
3503 PRBool aCreateIfNotFound
)
3505 if (!aCreateIfNotFound
&& !aNode
->HasFlag(NODE_HAS_LISTENERMANAGER
)) {
3509 if (!sEventListenerManagersHash
.ops
) {
3510 // We're already shut down, don't bother creating an event listener
3516 if (!aCreateIfNotFound
) {
3517 EventListenerManagerMapEntry
*entry
=
3518 static_cast<EventListenerManagerMapEntry
*>
3519 (PL_DHashTableOperate(&sEventListenerManagersHash
, aNode
,
3521 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
3522 return entry
->mListenerManager
;
3527 EventListenerManagerMapEntry
*entry
=
3528 static_cast<EventListenerManagerMapEntry
*>
3529 (PL_DHashTableOperate(&sEventListenerManagersHash
, aNode
,
3536 if (!entry
->mListenerManager
) {
3538 NS_NewEventListenerManager(getter_AddRefs(entry
->mListenerManager
));
3540 if (NS_FAILED(rv
)) {
3541 PL_DHashTableRawRemove(&sEventListenerManagersHash
, entry
);
3546 entry
->mListenerManager
->SetListenerTarget(aNode
);
3548 aNode
->SetFlags(NODE_HAS_LISTENERMANAGER
);
3551 return entry
->mListenerManager
;
3556 nsContentUtils::RemoveListenerManager(nsINode
*aNode
)
3558 if (sEventListenerManagersHash
.ops
) {
3559 EventListenerManagerMapEntry
*entry
=
3560 static_cast<EventListenerManagerMapEntry
*>
3561 (PL_DHashTableOperate(&sEventListenerManagersHash
, aNode
,
3563 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
3564 nsCOMPtr
<nsIEventListenerManager
> listenerManager
;
3565 listenerManager
.swap(entry
->mListenerManager
);
3566 // Remove the entry and *then* do operations that could cause further
3567 // modification of sEventListenerManagersHash. See bug 334177.
3568 PL_DHashTableRawRemove(&sEventListenerManagersHash
, entry
);
3569 if (listenerManager
) {
3570 listenerManager
->Disconnect();
3578 nsContentUtils::IsValidNodeName(nsIAtom
*aLocalName
, nsIAtom
*aPrefix
,
3579 PRInt32 aNamespaceID
)
3581 if (aNamespaceID
== kNameSpaceID_Unknown
) {
3586 // If the prefix is null, then either the QName must be xmlns or the
3587 // namespace must not be XMLNS.
3588 return (aLocalName
== nsGkAtoms::xmlns
) ==
3589 (aNamespaceID
== kNameSpaceID_XMLNS
);
3592 // If the prefix is non-null then the namespace must not be null.
3593 if (aNamespaceID
== kNameSpaceID_None
) {
3597 // If the namespace is the XMLNS namespace then the prefix must be xmlns,
3598 // but the localname must not be xmlns.
3599 if (aNamespaceID
== kNameSpaceID_XMLNS
) {
3600 return aPrefix
== nsGkAtoms::xmlns
&& aLocalName
!= nsGkAtoms::xmlns
;
3603 // If the namespace is not the XMLNS namespace then the prefix must not be
3605 // If the namespace is the XML namespace then the prefix can be anything.
3606 // If the namespace is not the XML namespace then the prefix must not be xml.
3607 return aPrefix
!= nsGkAtoms::xmlns
&&
3608 (aNamespaceID
== kNameSpaceID_XML
|| aPrefix
!= nsGkAtoms::xml
);
3613 nsContentUtils::CreateContextualFragment(nsINode
* aContextNode
,
3614 const nsAString
& aFragment
,
3615 PRBool aWillOwnFragment
,
3616 nsIDOMDocumentFragment
** aReturn
)
3619 NS_ENSURE_ARG(aContextNode
);
3623 // If we don't have a document here, we can't get the right security context
3624 // for compiling event handlers... so just bail out.
3625 nsCOMPtr
<nsIDocument
> document
= aContextNode
->GetOwnerDoc();
3626 NS_ENSURE_TRUE(document
, NS_ERROR_NOT_AVAILABLE
);
3628 PRBool isHTML
= document
->IsHTML();
3630 nsCOMPtr
<nsIHTMLDocument
> htmlDoc
= do_QueryInterface(document
);
3631 NS_ASSERTION(!isHTML
|| htmlDoc
, "Should have HTMLDocument here!");
3634 if (isHTML
&& nsHtml5Module::sEnabled
) {
3635 // See if the document has a cached fragment parser. nsHTMLDocument is the
3636 // only one that should really have one at the moment.
3637 nsCOMPtr
<nsIParser
> parser
= document
->GetFragmentParser();
3639 // Get the parser ready to use.
3643 // Create a new parser for this operation.
3644 parser
= nsHtml5Module::NewHtml5Parser();
3646 return NS_ERROR_OUT_OF_MEMORY
;
3649 nsCOMPtr
<nsIDOMDocumentFragment
> frag
;
3650 rv
= NS_NewDocumentFragment(getter_AddRefs(frag
), document
->NodeInfoManager());
3651 NS_ENSURE_SUCCESS(rv
, rv
);
3653 nsCOMPtr
<nsIContent
> contextAsContent
= do_QueryInterface(aContextNode
);
3654 if (contextAsContent
&& !contextAsContent
->IsElement()) {
3655 contextAsContent
= contextAsContent
->GetParent();
3656 if (contextAsContent
&& !contextAsContent
->IsElement()) {
3657 // can this even happen?
3658 contextAsContent
= nsnull
;
3662 if (contextAsContent
) {
3663 parser
->ParseFragment(aFragment
,
3665 contextAsContent
->Tag(),
3666 contextAsContent
->GetNameSpaceID(),
3667 (document
->GetCompatibilityMode() == eCompatibility_NavQuirks
));
3669 parser
->ParseFragment(aFragment
,
3673 (document
->GetCompatibilityMode() == eCompatibility_NavQuirks
));
3676 frag
.swap(*aReturn
);
3677 document
->SetFragmentParser(parser
);
3681 nsAutoTArray
<nsString
, 32> tagStack
;
3682 nsAutoString uriStr
, nameStr
;
3683 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(aContextNode
);
3684 // just in case we have a text node
3685 if (content
&& !content
->IsElement())
3686 content
= content
->GetParent();
3688 while (content
&& content
->IsElement()) {
3689 nsString
& tagName
= *tagStack
.AppendElement();
3690 NS_ENSURE_TRUE(&tagName
, NS_ERROR_OUT_OF_MEMORY
);
3692 content
->NodeInfo()->GetQualifiedName(tagName
);
3694 // see if we need to add xmlns declarations
3695 PRUint32 count
= content
->GetAttrCount();
3696 PRBool setDefaultNamespace
= PR_FALSE
;
3700 for (index
= 0; index
< count
; index
++) {
3701 const nsAttrName
* name
= content
->GetAttrNameAt(index
);
3702 if (name
->NamespaceEquals(kNameSpaceID_XMLNS
)) {
3703 content
->GetAttr(kNameSpaceID_XMLNS
, name
->LocalName(), uriStr
);
3705 // really want something like nsXMLContentSerializer::SerializeAttr
3706 tagName
.Append(NS_LITERAL_STRING(" xmlns")); // space important
3707 if (name
->GetPrefix()) {
3708 tagName
.Append(PRUnichar(':'));
3709 name
->LocalName()->ToString(nameStr
);
3710 tagName
.Append(nameStr
);
3712 setDefaultNamespace
= PR_TRUE
;
3714 tagName
.Append(NS_LITERAL_STRING("=\"") + uriStr
+
3715 NS_LITERAL_STRING("\""));
3720 if (!setDefaultNamespace
) {
3721 nsINodeInfo
* info
= content
->NodeInfo();
3722 if (!info
->GetPrefixAtom() &&
3723 info
->NamespaceID() != kNameSpaceID_None
) {
3724 // We have no namespace prefix, but have a namespace ID. Push
3725 // default namespace attr in, so that our kids will be in our
3727 info
->GetNamespaceURI(uriStr
);
3728 tagName
.Append(NS_LITERAL_STRING(" xmlns=\"") + uriStr
+
3729 NS_LITERAL_STRING("\""));
3733 content
= content
->GetParent();
3736 nsCAutoString contentType
;
3738 document
->GetContentType(buf
);
3739 LossyCopyUTF16toASCII(buf
, contentType
);
3741 // See if the document has a cached fragment parser. nsHTMLDocument is the
3742 // only one that should really have one at the moment.
3743 nsCOMPtr
<nsIParser
> parser
= document
->GetFragmentParser();
3745 // Get the parser ready to use.
3749 // Create a new parser for this operation.
3750 parser
= do_CreateInstance(kCParserCID
, &rv
);
3751 NS_ENSURE_SUCCESS(rv
, rv
);
3754 // See if the parser already has a content sink that we can reuse.
3755 nsCOMPtr
<nsIFragmentContentSink
> sink
;
3756 nsCOMPtr
<nsIContentSink
> contentsink
= parser
->GetContentSink();
3758 // Make sure it's the correct type.
3760 nsCOMPtr
<nsIHTMLContentSink
> htmlsink
= do_QueryInterface(contentsink
);
3761 sink
= do_QueryInterface(htmlsink
);
3764 nsCOMPtr
<nsIXMLContentSink
> xmlsink
= do_QueryInterface(contentsink
);
3765 sink
= do_QueryInterface(xmlsink
);
3770 // Either there was no cached content sink or it was the wrong type. Make a
3773 rv
= NS_NewHTMLFragmentContentSink(getter_AddRefs(sink
));
3775 rv
= NS_NewXMLFragmentContentSink(getter_AddRefs(sink
));
3777 NS_ENSURE_SUCCESS(rv
, rv
);
3779 contentsink
= do_QueryInterface(sink
);
3780 NS_ASSERTION(contentsink
, "Sink doesn't QI to nsIContentSink!");
3782 parser
->SetContentSink(contentsink
);
3785 sink
->SetTargetDocument(document
);
3787 nsDTDMode mode
= eDTDMode_autodetect
;
3788 switch (document
->GetCompatibilityMode()) {
3789 case eCompatibility_NavQuirks
:
3790 mode
= eDTDMode_quirks
;
3792 case eCompatibility_AlmostStandards
:
3793 mode
= eDTDMode_almost_standards
;
3795 case eCompatibility_FullStandards
:
3796 mode
= eDTDMode_full_standards
;
3799 NS_NOTREACHED("unknown mode");
3803 rv
= parser
->ParseFragment(aFragment
, nsnull
, tagStack
,
3804 !isHTML
, contentType
, mode
);
3805 if (NS_SUCCEEDED(rv
)) {
3806 rv
= sink
->GetFragment(aWillOwnFragment
, aReturn
);
3809 document
->SetFragmentParser(parser
);
3816 nsContentUtils::CreateDocument(const nsAString
& aNamespaceURI
,
3817 const nsAString
& aQualifiedName
,
3818 nsIDOMDocumentType
* aDoctype
,
3819 nsIURI
* aDocumentURI
, nsIURI
* aBaseURI
,
3820 nsIPrincipal
* aPrincipal
,
3821 nsIScriptGlobalObject
* aEventObject
,
3822 nsIDOMDocument
** aResult
)
3824 nsresult rv
= NS_NewDOMDocument(aResult
, aNamespaceURI
, aQualifiedName
,
3825 aDoctype
, aDocumentURI
, aBaseURI
, aPrincipal
,
3827 NS_ENSURE_SUCCESS(rv
, rv
);
3829 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(*aResult
);
3830 document
->SetScriptHandlingObject(aEventObject
);
3832 // created documents are immediately "complete" (ready to use)
3833 document
->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE
);
3839 nsContentUtils::SetNodeTextContent(nsIContent
* aContent
,
3840 const nsAString
& aValue
,
3843 // Might as well stick a batch around this since we're performing several
3845 mozAutoDocUpdate
updateBatch(aContent
->GetCurrentDoc(),
3846 UPDATE_CONTENT_MODEL
, PR_TRUE
);
3848 PRUint32 childCount
= aContent
->GetChildCount();
3850 if (aTryReuse
&& !aValue
.IsEmpty()) {
3851 PRUint32 removeIndex
= 0;
3853 // i is unsigned, so i >= is always true
3854 for (PRUint32 i
= 0; i
< childCount
; ++i
) {
3855 nsIContent
* child
= aContent
->GetChildAt(removeIndex
);
3856 if (removeIndex
== 0 && child
&& child
->IsNodeOfType(nsINode::eTEXT
)) {
3857 nsresult rv
= child
->SetText(aValue
, PR_TRUE
);
3858 NS_ENSURE_SUCCESS(rv
, rv
);
3863 aContent
->RemoveChildAt(removeIndex
, PR_TRUE
);
3867 if (removeIndex
== 1) {
3872 // i is unsigned, so i >= is always true
3873 for (PRUint32 i
= childCount
; i
-- != 0; ) {
3874 aContent
->RemoveChildAt(i
, PR_TRUE
);
3878 if (aValue
.IsEmpty()) {
3882 nsCOMPtr
<nsIContent
> textContent
;
3883 nsresult rv
= NS_NewTextNode(getter_AddRefs(textContent
),
3884 aContent
->NodeInfo()->NodeInfoManager());
3885 NS_ENSURE_SUCCESS(rv
, rv
);
3887 textContent
->SetText(aValue
, PR_TRUE
);
3889 return aContent
->AppendChildTo(textContent
, PR_TRUE
);
3892 static void AppendNodeTextContentsRecurse(nsINode
* aNode
, nsAString
& aResult
)
3896 for (i
= 0; (child
= aNode
->GetChildAt(i
)); ++i
) {
3897 if (child
->IsElement()) {
3898 AppendNodeTextContentsRecurse(child
, aResult
);
3900 else if (child
->IsNodeOfType(nsINode::eTEXT
)) {
3901 child
->AppendTextTo(aResult
);
3908 nsContentUtils::AppendNodeTextContent(nsINode
* aNode
, PRBool aDeep
,
3911 if (aNode
->IsNodeOfType(nsINode::eTEXT
)) {
3912 static_cast<nsIContent
*>(aNode
)->AppendTextTo(aResult
);
3915 AppendNodeTextContentsRecurse(aNode
, aResult
);
3920 for (i
= 0; (child
= aNode
->GetChildAt(i
)); ++i
) {
3921 if (child
->IsNodeOfType(nsINode::eTEXT
)) {
3922 child
->AppendTextTo(aResult
);
3929 nsContentUtils::HasNonEmptyTextContent(nsINode
* aNode
)
3933 for (i
= 0; (child
= aNode
->GetChildAt(i
)); ++i
) {
3934 if (child
->IsNodeOfType(nsINode::eTEXT
) &&
3935 child
->TextLength() > 0) {
3945 nsContentUtils::IsInSameAnonymousTree(nsINode
* aNode
,
3946 nsIContent
* aContent
)
3948 NS_PRECONDITION(aNode
,
3949 "Must have a node to work with");
3950 NS_PRECONDITION(aContent
,
3951 "Must have a content to work with");
3953 if (!aNode
->IsNodeOfType(nsINode::eCONTENT
)) {
3955 * The root isn't an nsIContent, so it's a document or attribute. The only
3956 * nodes in the same anonymous subtree as it will have a null
3959 * XXXbz strictly speaking, that's not true for attribute nodes.
3961 return aContent
->GetBindingParent() == nsnull
;
3964 return static_cast<nsIContent
*>(aNode
)->GetBindingParent() ==
3965 aContent
->GetBindingParent();
3969 class AnonymousContentDestroyer
: public nsRunnable
{
3971 AnonymousContentDestroyer(nsCOMPtr
<nsIContent
>* aContent
) {
3972 mContent
.swap(*aContent
);
3973 mParent
= mContent
->GetParent();
3974 mDoc
= mContent
->GetOwnerDoc();
3977 mContent
->UnbindFromTree();
3981 nsCOMPtr
<nsIContent
> mContent
;
3982 // Hold strong refs to the parent content and document so that they
3983 // don't die unexpectedly
3984 nsCOMPtr
<nsIDocument
> mDoc
;
3985 nsCOMPtr
<nsIContent
> mParent
;
3990 nsContentUtils::DestroyAnonymousContent(nsCOMPtr
<nsIContent
>* aContent
)
3993 AddScriptRunner(new AnonymousContentDestroyer(aContent
));
3998 nsIDOMScriptObjectFactory
*
3999 nsContentUtils::GetDOMScriptObjectFactory()
4001 if (!sDOMScriptObjectFactory
) {
4002 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID
,
4003 NS_DOM_SCRIPT_OBJECT_FACTORY_CID
);
4005 CallGetService(kDOMScriptObjectFactoryCID
, &sDOMScriptObjectFactory
);
4008 return sDOMScriptObjectFactory
;
4013 nsContentUtils::HoldScriptObject(PRUint32 aLangID
, void *aObject
)
4015 NS_ASSERTION(aObject
, "unexpected null object");
4016 NS_ASSERTION(aLangID
!= nsIProgrammingLanguage::JAVASCRIPT
,
4017 "Should use HoldJSObjects.");
4020 PRUint32 langIndex
= NS_STID_INDEX(aLangID
);
4021 nsIScriptRuntime
*runtime
= sScriptRuntimes
[langIndex
];
4023 nsIDOMScriptObjectFactory
*factory
= GetDOMScriptObjectFactory();
4024 NS_ENSURE_TRUE(factory
, NS_ERROR_FAILURE
);
4026 rv
= factory
->GetScriptRuntimeByID(aLangID
, &runtime
);
4027 NS_ENSURE_SUCCESS(rv
, rv
);
4029 // This makes sScriptRuntimes hold a strong ref.
4030 sScriptRuntimes
[langIndex
] = runtime
;
4033 rv
= runtime
->HoldScriptObject(aObject
);
4034 NS_ENSURE_SUCCESS(rv
, rv
);
4036 ++sScriptRootCount
[langIndex
];
4037 NS_LOG_ADDREF(sScriptRuntimes
[langIndex
], sScriptRootCount
[langIndex
],
4038 "HoldScriptObject", sizeof(void*));
4045 nsContentUtils::DropScriptObject(PRUint32 aLangID
, void *aObject
,
4048 NS_ASSERTION(aObject
, "unexpected null object");
4049 NS_ASSERTION(aLangID
!= nsIProgrammingLanguage::JAVASCRIPT
,
4050 "Should use DropJSObjects.");
4051 PRUint32 langIndex
= NS_STID_INDEX(aLangID
);
4052 NS_LOG_RELEASE(sScriptRuntimes
[langIndex
], sScriptRootCount
[langIndex
] - 1,
4053 "HoldScriptObject");
4054 sScriptRuntimes
[langIndex
]->DropScriptObject(aObject
);
4055 if (--sScriptRootCount
[langIndex
] == 0) {
4056 NS_RELEASE(sScriptRuntimes
[langIndex
]);
4062 nsContentUtils::HoldJSObjects(void* aScriptObjectHolder
,
4063 nsScriptObjectTracer
* aTracer
)
4065 NS_ENSURE_TRUE(sXPConnect
, NS_ERROR_UNEXPECTED
);
4067 nsresult rv
= sXPConnect
->AddJSHolder(aScriptObjectHolder
, aTracer
);
4068 NS_ENSURE_SUCCESS(rv
, rv
);
4070 if (sJSGCThingRootCount
++ == 0) {
4071 nsLayoutStatics::AddRef();
4073 NS_LOG_ADDREF(sXPConnect
, sJSGCThingRootCount
, "HoldJSObjects",
4081 nsContentUtils::DropJSObjects(void* aScriptObjectHolder
)
4083 NS_LOG_RELEASE(sXPConnect
, sJSGCThingRootCount
- 1, "HoldJSObjects");
4084 nsresult rv
= sXPConnect
->RemoveJSHolder(aScriptObjectHolder
);
4085 if (--sJSGCThingRootCount
== 0) {
4086 nsLayoutStatics::Release();
4093 nsContentUtils::GetWidgetStatusFromIMEStatus(PRUint32 aState
)
4095 switch (aState
& nsIContent::IME_STATUS_MASK_ENABLED
) {
4096 case nsIContent::IME_STATUS_DISABLE
:
4097 return nsIWidget::IME_STATUS_DISABLED
;
4098 case nsIContent::IME_STATUS_ENABLE
:
4099 return nsIWidget::IME_STATUS_ENABLED
;
4100 case nsIContent::IME_STATUS_PASSWORD
:
4101 return nsIWidget::IME_STATUS_PASSWORD
;
4102 case nsIContent::IME_STATUS_PLUGIN
:
4103 return nsIWidget::IME_STATUS_PLUGIN
;
4105 NS_ERROR("The given state doesn't have valid enable state");
4106 return nsIWidget::IME_STATUS_ENABLED
;
4112 nsContentUtils::NotifyInstalledMenuKeyboardListener(PRBool aInstalling
)
4114 nsIMEStateManager::OnInstalledMenuKeyboardListener(aInstalling
);
4117 static PRBool
SchemeIs(nsIURI
* aURI
, const char* aScheme
)
4119 nsCOMPtr
<nsIURI
> baseURI
= NS_GetInnermostURI(aURI
);
4120 NS_ENSURE_TRUE(baseURI
, PR_FALSE
);
4122 PRBool isScheme
= PR_FALSE
;
4123 return NS_SUCCEEDED(baseURI
->SchemeIs(aScheme
, &isScheme
)) && isScheme
;
4128 nsContentUtils::CheckSecurityBeforeLoad(nsIURI
* aURIToLoad
,
4129 nsIPrincipal
* aLoadingPrincipal
,
4130 PRUint32 aCheckLoadFlags
,
4132 PRUint32 aContentPolicyType
,
4133 nsISupports
* aContext
,
4134 const nsACString
& aMimeGuess
,
4135 nsISupports
* aExtra
)
4137 NS_PRECONDITION(aLoadingPrincipal
, "Must have a loading principal here");
4139 PRBool isSystemPrin
= PR_FALSE
;
4140 if (NS_SUCCEEDED(sSecurityManager
->IsSystemPrincipal(aLoadingPrincipal
,
4146 // XXXbz do we want to fast-path skin stylesheets loading XBL here somehow?
4147 // CheckLoadURIWithPrincipal
4148 nsresult rv
= sSecurityManager
->
4149 CheckLoadURIWithPrincipal(aLoadingPrincipal
, aURIToLoad
, aCheckLoadFlags
);
4150 NS_ENSURE_SUCCESS(rv
, rv
);
4153 PRInt16 shouldLoad
= nsIContentPolicy::ACCEPT
;
4154 rv
= NS_CheckContentLoadPolicy(aContentPolicyType
,
4163 NS_ENSURE_SUCCESS(rv
, rv
);
4164 if (NS_CP_REJECTED(shouldLoad
)) {
4165 return NS_ERROR_CONTENT_BLOCKED
;
4169 if ((aAllowData
&& SchemeIs(aURIToLoad
, "data")) ||
4170 ((aCheckLoadFlags
& nsIScriptSecurityManager::ALLOW_CHROME
) &&
4171 SchemeIs(aURIToLoad
, "chrome"))) {
4175 return aLoadingPrincipal
->CheckMayLoad(aURIToLoad
, PR_TRUE
);
4179 nsContentUtils::IsSystemPrincipal(nsIPrincipal
* aPrincipal
)
4182 nsresult rv
= sSecurityManager
->IsSystemPrincipal(aPrincipal
, &isSystem
);
4183 return NS_SUCCEEDED(rv
) && isSystem
;
4188 nsContentUtils::TriggerLink(nsIContent
*aContent
, nsPresContext
*aPresContext
,
4189 nsIURI
*aLinkURI
, const nsString
&aTargetSpec
,
4190 PRBool aClick
, PRBool aIsUserTriggered
)
4192 NS_ASSERTION(aPresContext
, "Need a nsPresContext");
4193 NS_PRECONDITION(aLinkURI
, "No link URI");
4195 if (aContent
->IsEditable()) {
4199 nsILinkHandler
*handler
= aPresContext
->GetLinkHandler();
4205 handler
->OnOverLink(aContent
, aLinkURI
, aTargetSpec
.get());
4210 // Check that this page is allowed to load this URI.
4211 nsresult proceed
= NS_OK
;
4213 if (sSecurityManager
) {
4216 (PRUint32
)nsIScriptSecurityManager::STANDARD
:
4217 (PRUint32
)nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
;
4219 sSecurityManager
->CheckLoadURIWithPrincipal(aContent
->NodePrincipal(),
4223 // Only pass off the click event if the script security manager says it's ok.
4224 if (NS_SUCCEEDED(proceed
)) {
4225 handler
->OnLinkClick(aContent
, aLinkURI
, aTargetSpec
.get());
4231 nsContentUtils::GetTopLevelWidget(nsIWidget
* aWidget
)
4236 return aWidget
->GetTopLevelWidget();
4240 const nsDependentString
4241 nsContentUtils::GetLocalizedEllipsis()
4243 static PRUnichar sBuf
[4] = { 0, 0, 0, 0 };
4245 nsAutoString
tmp(GetLocalizedStringPref("intl.ellipsis"));
4246 PRUint32 len
= NS_MIN(PRUint32(tmp
.Length()),
4247 PRUint32(NS_ARRAY_LENGTH(sBuf
) - 1));
4248 CopyUnicodeTo(tmp
, 0, sBuf
, len
);
4250 sBuf
[0] = PRUnichar(0x2026);
4252 return nsDependentString(sBuf
);
4257 nsContentUtils::GetNativeEvent(nsIDOMEvent
* aDOMEvent
)
4259 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aDOMEvent
));
4262 return privateEvent
->GetInternalNSEvent();
4267 nsContentUtils::DOMEventToNativeKeyEvent(nsIDOMKeyEvent
* aKeyEvent
,
4268 nsNativeKeyEvent
* aNativeEvent
,
4269 PRBool aGetCharCode
)
4271 nsCOMPtr
<nsIDOMNSUIEvent
> uievent
= do_QueryInterface(aKeyEvent
);
4272 PRBool defaultPrevented
;
4273 uievent
->GetPreventDefault(&defaultPrevented
);
4274 if (defaultPrevented
)
4277 nsCOMPtr
<nsIDOMNSEvent
> nsevent
= do_QueryInterface(aKeyEvent
);
4278 PRBool trusted
= PR_FALSE
;
4279 nsevent
->GetIsTrusted(&trusted
);
4284 aKeyEvent
->GetCharCode(&aNativeEvent
->charCode
);
4286 aNativeEvent
->charCode
= 0;
4288 aKeyEvent
->GetKeyCode(&aNativeEvent
->keyCode
);
4289 aKeyEvent
->GetAltKey(&aNativeEvent
->altKey
);
4290 aKeyEvent
->GetCtrlKey(&aNativeEvent
->ctrlKey
);
4291 aKeyEvent
->GetShiftKey(&aNativeEvent
->shiftKey
);
4292 aKeyEvent
->GetMetaKey(&aNativeEvent
->metaKey
);
4294 aNativeEvent
->nativeEvent
= GetNativeEvent(aKeyEvent
);
4300 HasASCIIDigit(const nsTArray
<nsShortcutCandidate
>& aCandidates
)
4302 for (PRUint32 i
= 0; i
< aCandidates
.Length(); ++i
) {
4303 PRUint32 ch
= aCandidates
[i
].mCharCode
;
4304 if (ch
>= '0' && ch
<= '9')
4311 CharsCaseInsensitiveEqual(PRUint32 aChar1
, PRUint32 aChar2
)
4313 return aChar1
== aChar2
||
4314 (IS_IN_BMP(aChar1
) && IS_IN_BMP(aChar2
) &&
4315 ToLowerCase(PRUnichar(aChar1
)) == ToLowerCase(PRUnichar(aChar2
)));
4319 IsCaseChangeableChar(PRUint32 aChar
)
4321 return IS_IN_BMP(aChar
) &&
4322 ToLowerCase(PRUnichar(aChar
)) != ToUpperCase(PRUnichar(aChar
));
4327 nsContentUtils::GetAccelKeyCandidates(nsIDOMKeyEvent
* aDOMKeyEvent
,
4328 nsTArray
<nsShortcutCandidate
>& aCandidates
)
4330 NS_PRECONDITION(aCandidates
.IsEmpty(), "aCandidates must be empty");
4332 nsAutoString eventType
;
4333 aDOMKeyEvent
->GetType(eventType
);
4334 // Don't process if aDOMKeyEvent is not a keypress event.
4335 if (!eventType
.EqualsLiteral("keypress"))
4338 nsKeyEvent
* nativeKeyEvent
=
4339 static_cast<nsKeyEvent
*>(GetNativeEvent(aDOMKeyEvent
));
4340 if (nativeKeyEvent
) {
4341 NS_ASSERTION(nativeKeyEvent
->eventStructType
== NS_KEY_EVENT
,
4342 "wrong type of native event");
4343 // nsShortcutCandidate::mCharCode is a candidate charCode.
4344 // nsShoftcutCandidate::mIgnoreShift means the mCharCode should be tried to
4345 // execute a command with/without shift key state. If this is TRUE, the
4346 // shifted key state should be ignored. Otherwise, don't ignore the state.
4347 // the priority of the charCodes are (shift key is not pressed):
4348 // 0: charCode/PR_FALSE,
4349 // 1: unshiftedCharCodes[0]/PR_FALSE, 2: unshiftedCharCodes[1]/PR_FALSE...
4350 // the priority of the charCodes are (shift key is pressed):
4351 // 0: charCode/PR_FALSE,
4352 // 1: shiftedCharCodes[0]/PR_FALSE, 2: shiftedCharCodes[0]/PR_TRUE,
4353 // 3: shiftedCharCodes[1]/PR_FALSE, 4: shiftedCharCodes[1]/PR_TRUE...
4354 if (nativeKeyEvent
->charCode
) {
4355 nsShortcutCandidate
key(nativeKeyEvent
->charCode
, PR_FALSE
);
4356 aCandidates
.AppendElement(key
);
4359 PRUint32 len
= nativeKeyEvent
->alternativeCharCodes
.Length();
4360 if (!nativeKeyEvent
->isShift
) {
4361 for (PRUint32 i
= 0; i
< len
; ++i
) {
4363 nativeKeyEvent
->alternativeCharCodes
[i
].mUnshiftedCharCode
;
4364 if (!ch
|| ch
== nativeKeyEvent
->charCode
)
4367 nsShortcutCandidate
key(ch
, PR_FALSE
);
4368 aCandidates
.AppendElement(key
);
4370 // If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
4371 // this keyboard layout is AZERTY or similar layout, probably.
4372 // In this case, Accel+[0-9] should be accessible without shift key.
4373 // However, the priority should be lowest.
4374 if (!HasASCIIDigit(aCandidates
)) {
4375 for (PRUint32 i
= 0; i
< len
; ++i
) {
4377 nativeKeyEvent
->alternativeCharCodes
[i
].mShiftedCharCode
;
4378 if (ch
>= '0' && ch
<= '9') {
4379 nsShortcutCandidate
key(ch
, PR_FALSE
);
4380 aCandidates
.AppendElement(key
);
4386 for (PRUint32 i
= 0; i
< len
; ++i
) {
4387 PRUint32 ch
= nativeKeyEvent
->alternativeCharCodes
[i
].mShiftedCharCode
;
4391 if (ch
!= nativeKeyEvent
->charCode
) {
4392 nsShortcutCandidate
key(ch
, PR_FALSE
);
4393 aCandidates
.AppendElement(key
);
4396 // If the char is an alphabet, the shift key state should not be
4397 // ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
4399 // And checking the charCode is same as unshiftedCharCode too.
4400 // E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
4401 PRUint32 unshiftCh
=
4402 nativeKeyEvent
->alternativeCharCodes
[i
].mUnshiftedCharCode
;
4403 if (CharsCaseInsensitiveEqual(ch
, unshiftCh
))
4406 // On the Hebrew keyboard layout on Windows, the unshifted char is a
4407 // localized character but the shifted char is a Latin alphabet,
4408 // then, we should not execute without the shift state. See bug 433192.
4409 if (IsCaseChangeableChar(ch
))
4412 // Setting the alternative charCode candidates for retry without shift
4413 // key state only when the shift key is pressed.
4414 nsShortcutCandidate
key(ch
, PR_TRUE
);
4415 aCandidates
.AppendElement(key
);
4420 aDOMKeyEvent
->GetCharCode(&charCode
);
4422 nsShortcutCandidate
key(charCode
, PR_FALSE
);
4423 aCandidates
.AppendElement(key
);
4430 nsContentUtils::GetAccessKeyCandidates(nsKeyEvent
* aNativeKeyEvent
,
4431 nsTArray
<PRUint32
>& aCandidates
)
4433 NS_PRECONDITION(aCandidates
.IsEmpty(), "aCandidates must be empty");
4435 // return the lower cased charCode candidates for access keys.
4436 // the priority of the charCodes are:
4437 // 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
4438 // 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
4439 if (aNativeKeyEvent
->charCode
) {
4440 PRUint32 ch
= aNativeKeyEvent
->charCode
;
4442 ch
= ToLowerCase(PRUnichar(ch
));
4443 aCandidates
.AppendElement(ch
);
4445 for (PRUint32 i
= 0;
4446 i
< aNativeKeyEvent
->alternativeCharCodes
.Length(); ++i
) {
4448 { aNativeKeyEvent
->alternativeCharCodes
[i
].mUnshiftedCharCode
,
4449 aNativeKeyEvent
->alternativeCharCodes
[i
].mShiftedCharCode
};
4450 for (PRUint32 j
= 0; j
< 2; ++j
) {
4453 if (IS_IN_BMP(ch
[j
]))
4454 ch
[j
] = ToLowerCase(PRUnichar(ch
[j
]));
4455 // Don't append the charCode that was already appended.
4456 if (aCandidates
.IndexOf(ch
[j
]) == aCandidates
.NoIndex
)
4457 aCandidates
.AppendElement(ch
[j
]);
4465 nsContentUtils::AddScriptBlocker()
4467 if (!sScriptBlockerCount
) {
4468 NS_ASSERTION(sRunnersCountAtFirstBlocker
== 0,
4469 "Should not already have a count");
4470 sRunnersCountAtFirstBlocker
= sBlockedScriptRunners
->Count();
4472 ++sScriptBlockerCount
;
4477 nsContentUtils::AddScriptBlockerAndPreventAddingRunners()
4480 if (sScriptBlockerCountWhereRunnersPrevented
== 0) {
4481 sScriptBlockerCountWhereRunnersPrevented
= sScriptBlockerCount
;
4487 nsContentUtils::RemoveScriptBlocker()
4489 NS_ASSERTION(sScriptBlockerCount
!= 0, "Negative script blockers");
4490 --sScriptBlockerCount
;
4491 if (sScriptBlockerCount
< sScriptBlockerCountWhereRunnersPrevented
) {
4492 sScriptBlockerCountWhereRunnersPrevented
= 0;
4494 if (sScriptBlockerCount
) {
4498 PRUint32 firstBlocker
= sRunnersCountAtFirstBlocker
;
4499 PRUint32 lastBlocker
= (PRUint32
)sBlockedScriptRunners
->Count();
4500 sRunnersCountAtFirstBlocker
= 0;
4501 NS_ASSERTION(firstBlocker
<= lastBlocker
,
4502 "bad sRunnersCountAtFirstBlocker");
4504 while (firstBlocker
< lastBlocker
) {
4505 nsCOMPtr
<nsIRunnable
> runnable
= (*sBlockedScriptRunners
)[firstBlocker
];
4506 sBlockedScriptRunners
->RemoveObjectAt(firstBlocker
);
4510 NS_ASSERTION(lastBlocker
== (PRUint32
)sBlockedScriptRunners
->Count() &&
4511 sRunnersCountAtFirstBlocker
== 0,
4513 NS_ASSERTION(!sScriptBlockerCount
, "This is really bad");
4519 nsContentUtils::AddScriptRunner(nsIRunnable
* aRunnable
)
4525 if (sScriptBlockerCount
) {
4526 if (sScriptBlockerCountWhereRunnersPrevented
> 0) {
4527 NS_ERROR("Adding a script runner when that is prevented!");
4530 return sBlockedScriptRunners
->AppendObject(aRunnable
);
4533 nsCOMPtr
<nsIRunnable
> run
= aRunnable
;
4540 * Helper function for nsContentUtils::ProcessViewportInfo.
4542 * Handles a single key=value pair. If it corresponds to a valid viewport
4543 * attribute, add it to the document header data. No validation is done on the
4544 * value itself (this is done at display time).
4546 static void ProcessViewportToken(nsIDocument
*aDocument
,
4547 const nsAString
&token
) {
4550 nsAString::const_iterator tip
, tail
, end
;
4551 token
.BeginReading(tip
);
4553 token
.EndReading(end
);
4555 /* Move tip to the '='. */
4556 while ((tip
!= end
) && (*tip
!= '='))
4559 /* If we didn't find an '=', punt. */
4563 /* Extract the key and value. */
4564 const nsAString
&key
= Substring(tail
, tip
);
4565 const nsAString
&value
= Substring(++tip
, end
);
4567 /* Check for known keys. If we find a match, insert the appropriate
4568 * information into the document header. */
4569 nsCOMPtr
<nsIAtom
> key_atom
= do_GetAtom(key
);
4570 if (key_atom
== nsGkAtoms::height
)
4571 aDocument
->SetHeaderData(nsGkAtoms::viewport_height
, value
);
4572 else if (key_atom
== nsGkAtoms::width
)
4573 aDocument
->SetHeaderData(nsGkAtoms::viewport_width
, value
);
4574 else if (key_atom
== nsGkAtoms::initial_scale
)
4575 aDocument
->SetHeaderData(nsGkAtoms::viewport_initial_scale
, value
);
4576 else if (key_atom
== nsGkAtoms::minimum_scale
)
4577 aDocument
->SetHeaderData(nsGkAtoms::viewport_minimum_scale
, value
);
4578 else if (key_atom
== nsGkAtoms::maximum_scale
)
4579 aDocument
->SetHeaderData(nsGkAtoms::viewport_maximum_scale
, value
);
4580 else if (key_atom
== nsGkAtoms::user_scalable
)
4581 aDocument
->SetHeaderData(nsGkAtoms::viewport_user_scalable
, value
);
4584 #define IS_SEPARATOR(c) ((c == ' ') || (c == ',') || (c == ';'))
4587 nsContentUtils::ProcessViewportInfo(nsIDocument
*aDocument
,
4588 const nsAString
&viewportInfo
) {
4590 /* We never fail. */
4591 nsresult rv
= NS_OK
;
4594 nsAString::const_iterator tip
, tail
, end
;
4595 viewportInfo
.BeginReading(tip
);
4597 viewportInfo
.EndReading(end
);
4599 /* Read the tip to the first non-separator character. */
4600 while ((tip
!= end
) && IS_SEPARATOR(*tip
))
4603 /* Read through and find tokens separated by separators. */
4604 while (tip
!= end
) {
4606 /* Synchronize tip and tail. */
4609 /* Advance tip past non-separator characters. */
4610 while ((tip
!= end
) && !IS_SEPARATOR(*tip
))
4613 /* Our token consists of the characters between tail and tip. */
4614 ProcessViewportToken(aDocument
, Substring(tail
, tip
));
4616 /* Skip separators. */
4617 while ((tip
!= end
) && IS_SEPARATOR(*tip
))
4629 nsContentUtils::HidePopupsInDocument(nsIDocument
* aDocument
)
4632 nsXULPopupManager
* pm
= nsXULPopupManager::GetInstance();
4633 if (pm
&& aDocument
) {
4634 nsCOMPtr
<nsISupports
> container
= aDocument
->GetContainer();
4635 nsCOMPtr
<nsIDocShellTreeItem
> docShellToHide
= do_QueryInterface(container
);
4637 pm
->HidePopupsInDocShell(docShellToHide
);
4643 already_AddRefed
<nsIDragSession
>
4644 nsContentUtils::GetDragSession()
4646 nsIDragSession
* dragSession
= nsnull
;
4647 nsCOMPtr
<nsIDragService
> dragService
=
4648 do_GetService("@mozilla.org/widget/dragservice;1");
4650 dragService
->GetCurrentSession(&dragSession
);
4656 nsContentUtils::SetDataTransferInEvent(nsDragEvent
* aDragEvent
)
4658 if (aDragEvent
->dataTransfer
|| !NS_IS_TRUSTED_EVENT(aDragEvent
))
4661 // For draggesture and dragstart events, the data transfer object is
4662 // created before the event fires, so it should already be set. For other
4663 // drag events, get the object from the drag session.
4664 NS_ASSERTION(aDragEvent
->message
!= NS_DRAGDROP_GESTURE
&&
4665 aDragEvent
->message
!= NS_DRAGDROP_START
,
4666 "draggesture event created without a dataTransfer");
4668 nsCOMPtr
<nsIDragSession
> dragSession
= GetDragSession();
4669 NS_ENSURE_TRUE(dragSession
, NS_OK
); // no drag in progress
4671 nsCOMPtr
<nsIDOMDataTransfer
> initialDataTransfer
;
4672 dragSession
->GetDataTransfer(getter_AddRefs(initialDataTransfer
));
4673 if (!initialDataTransfer
) {
4674 // A dataTransfer won't exist when a drag was started by some other
4675 // means, for instance calling the drag service directly, or a drag
4676 // from another application. In either case, a new dataTransfer should
4677 // be created that reflects the data. Pass true to the constructor for
4678 // the aIsExternal argument, so that only system access is allowed.
4679 PRUint32 action
= 0;
4680 dragSession
->GetDragAction(&action
);
4681 initialDataTransfer
=
4682 new nsDOMDataTransfer(aDragEvent
->message
, action
);
4683 NS_ENSURE_TRUE(initialDataTransfer
, NS_ERROR_OUT_OF_MEMORY
);
4685 // now set it in the drag session so we don't need to create it again
4686 dragSession
->SetDataTransfer(initialDataTransfer
);
4689 // each event should use a clone of the original dataTransfer.
4690 nsCOMPtr
<nsIDOMNSDataTransfer
> initialDataTransferNS
=
4691 do_QueryInterface(initialDataTransfer
);
4692 NS_ENSURE_TRUE(initialDataTransferNS
, NS_ERROR_FAILURE
);
4693 initialDataTransferNS
->Clone(aDragEvent
->message
, aDragEvent
->userCancelled
,
4694 getter_AddRefs(aDragEvent
->dataTransfer
));
4695 NS_ENSURE_TRUE(aDragEvent
->dataTransfer
, NS_ERROR_OUT_OF_MEMORY
);
4697 // for the dragenter and dragover events, initialize the drop effect
4698 // from the drop action, which platform specific widget code sets before
4699 // the event is fired based on the keyboard state.
4700 if (aDragEvent
->message
== NS_DRAGDROP_ENTER
||
4701 aDragEvent
->message
== NS_DRAGDROP_OVER
) {
4702 nsCOMPtr
<nsIDOMNSDataTransfer
> newDataTransfer
=
4703 do_QueryInterface(aDragEvent
->dataTransfer
);
4704 NS_ENSURE_TRUE(newDataTransfer
, NS_ERROR_FAILURE
);
4706 PRUint32 action
, effectAllowed
;
4707 dragSession
->GetDragAction(&action
);
4708 newDataTransfer
->GetEffectAllowedInt(&effectAllowed
);
4709 newDataTransfer
->SetDropEffectInt(FilterDropEffect(action
, effectAllowed
));
4711 else if (aDragEvent
->message
== NS_DRAGDROP_DROP
||
4712 aDragEvent
->message
== NS_DRAGDROP_DRAGDROP
||
4713 aDragEvent
->message
== NS_DRAGDROP_END
) {
4714 // For the drop and dragend events, set the drop effect based on the
4715 // last value that the dropEffect had. This will have been set in
4716 // nsEventStateManager::PostHandleEvent for the last dragenter or
4718 nsCOMPtr
<nsIDOMNSDataTransfer
> newDataTransfer
=
4719 do_QueryInterface(aDragEvent
->dataTransfer
);
4720 NS_ENSURE_TRUE(newDataTransfer
, NS_ERROR_FAILURE
);
4722 PRUint32 dropEffect
;
4723 initialDataTransferNS
->GetDropEffectInt(&dropEffect
);
4724 newDataTransfer
->SetDropEffectInt(dropEffect
);
4732 nsContentUtils::FilterDropEffect(PRUint32 aAction
, PRUint32 aEffectAllowed
)
4734 // It is possible for the drag action to include more than one action, but
4735 // the widget code which sets the action from the keyboard state should only
4736 // be including one. If multiple actions were set, we just consider them in
4737 // the following order:
4739 if (aAction
& nsIDragService::DRAGDROP_ACTION_COPY
)
4740 aAction
= nsIDragService::DRAGDROP_ACTION_COPY
;
4741 else if (aAction
& nsIDragService::DRAGDROP_ACTION_LINK
)
4742 aAction
= nsIDragService::DRAGDROP_ACTION_LINK
;
4743 else if (aAction
& nsIDragService::DRAGDROP_ACTION_MOVE
)
4744 aAction
= nsIDragService::DRAGDROP_ACTION_MOVE
;
4746 // Filter the action based on the effectAllowed. If the effectAllowed
4747 // doesn't include the action, then that action cannot be done, so adjust
4748 // the action to something that is allowed. For a copy, adjust to move or
4749 // link. For a move, adjust to copy or link. For a link, adjust to move or
4750 // link. Otherwise, use none.
4751 if (aAction
& aEffectAllowed
||
4752 aEffectAllowed
== nsIDragService::DRAGDROP_ACTION_UNINITIALIZED
)
4754 if (aEffectAllowed
& nsIDragService::DRAGDROP_ACTION_MOVE
)
4755 return nsIDragService::DRAGDROP_ACTION_MOVE
;
4756 if (aEffectAllowed
& nsIDragService::DRAGDROP_ACTION_COPY
)
4757 return nsIDragService::DRAGDROP_ACTION_COPY
;
4758 if (aEffectAllowed
& nsIDragService::DRAGDROP_ACTION_LINK
)
4759 return nsIDragService::DRAGDROP_ACTION_LINK
;
4760 return nsIDragService::DRAGDROP_ACTION_NONE
;
4765 nsContentUtils::URIIsLocalFile(nsIURI
*aURI
)
4768 nsCOMPtr
<nsINetUtil
> util
= do_QueryInterface(sIOService
);
4770 return util
&& NS_SUCCEEDED(util
->ProtocolHasFlags(aURI
,
4771 nsIProtocolHandler::URI_IS_LOCAL_FILE
,
4778 nsContentUtils::GetContextForEventHandlers(nsINode
* aNode
,
4782 nsIDocument
* ownerDoc
= aNode
->GetOwnerDoc();
4784 *aRv
= NS_ERROR_UNEXPECTED
;
4788 PRBool hasHadScriptObject
= PR_TRUE
;
4789 nsIScriptGlobalObject
* sgo
=
4790 ownerDoc
->GetScriptHandlingObject(hasHadScriptObject
);
4791 // It is bad if the document doesn't have event handling context,
4792 // but it used to have one.
4793 if (!sgo
&& hasHadScriptObject
) {
4794 *aRv
= NS_ERROR_UNEXPECTED
;
4799 nsIScriptContext
* scx
= sgo
->GetContext();
4800 // Bad, no context from script global object!
4802 *aRv
= NS_ERROR_UNEXPECTED
;
4813 nsContentUtils::GetCurrentJSContext()
4815 JSContext
*cx
= nsnull
;
4817 sThreadJSContextStack
->Peek(&cx
);
4824 nsContentUtils::ASCIIToLower(const nsAString
& aSource
, nsAString
& aDest
)
4826 PRUint32 len
= aSource
.Length();
4827 aDest
.SetLength(len
);
4828 if (aDest
.Length() == len
) {
4829 PRUnichar
* dest
= aDest
.BeginWriting();
4830 const PRUnichar
* iter
= aSource
.BeginReading();
4831 const PRUnichar
* end
= aSource
.EndReading();
4832 while (iter
!= end
) {
4833 PRUnichar c
= *iter
;
4834 *dest
= (c
>= 'A' && c
<= 'Z') ?
4835 c
+ ('a' - 'A') : c
;
4844 nsContentUtils::ASCIIToUpper(nsAString
& aStr
)
4846 PRUnichar
* iter
= aStr
.BeginWriting();
4847 PRUnichar
* end
= aStr
.EndWriting();
4848 while (iter
!= end
) {
4849 PRUnichar c
= *iter
;
4850 if (c
>= 'a' && c
<= 'z') {
4851 *iter
= c
+ ('A' - 'a');
4858 nsContentUtils::EqualsIgnoreASCIICase(const nsAString
& aStr1
,
4859 const nsAString
& aStr2
)
4861 PRUint32 len
= aStr1
.Length();
4862 if (len
!= aStr2
.Length()) {
4866 const PRUnichar
* str1
= aStr1
.BeginReading();
4867 const PRUnichar
* str2
= aStr2
.BeginReading();
4868 const PRUnichar
* end
= str1
+ len
;
4870 while (str1
< end
) {
4871 PRUnichar c1
= *str1
++;
4872 PRUnichar c2
= *str2
++;
4874 // First check if any bits other than the 0x0020 differs
4875 if ((c1
^ c2
) & 0xffdf) {
4879 // We know they only differ in the 0x0020 bit.
4880 // Likely the two chars are the same, so check that first
4882 // They do differ, but since it's only in the 0x0020 bit, check if it's
4883 // the same ascii char, but just differing in case
4884 PRUnichar c1Upper
= c1
& 0xffdf;
4885 if (!('A' <= c1Upper
&& c1Upper
<= 'Z')) {
4896 nsAutoGCRoot::Shutdown()
4898 NS_IF_RELEASE(sJSRuntimeService
);
4902 nsIInterfaceRequestor
*
4903 nsContentUtils::GetSameOriginChecker()
4905 if (!sSameOriginChecker
) {
4906 sSameOriginChecker
= new nsSameOriginChecker();
4907 NS_IF_ADDREF(sSameOriginChecker
);
4909 return sSameOriginChecker
;
4913 NS_IMPL_ISUPPORTS2(nsSameOriginChecker
,
4914 nsIChannelEventSink
,
4915 nsIInterfaceRequestor
)
4918 nsSameOriginChecker::OnChannelRedirect(nsIChannel
*aOldChannel
,
4919 nsIChannel
*aNewChannel
,
4922 NS_PRECONDITION(aNewChannel
, "Redirecting to null channel?");
4923 if (!nsContentUtils::GetSecurityManager()) {
4924 return NS_ERROR_NOT_AVAILABLE
;
4927 nsCOMPtr
<nsIPrincipal
> oldPrincipal
;
4928 nsContentUtils::GetSecurityManager()->
4929 GetChannelPrincipal(aOldChannel
, getter_AddRefs(oldPrincipal
));
4931 nsCOMPtr
<nsIURI
> newURI
;
4932 aNewChannel
->GetURI(getter_AddRefs(newURI
));
4933 nsCOMPtr
<nsIURI
> newOriginalURI
;
4934 aNewChannel
->GetOriginalURI(getter_AddRefs(newOriginalURI
));
4936 NS_ENSURE_STATE(oldPrincipal
&& newURI
&& newOriginalURI
);
4938 nsresult rv
= oldPrincipal
->CheckMayLoad(newURI
, PR_FALSE
);
4939 if (NS_SUCCEEDED(rv
) && newOriginalURI
!= newURI
) {
4940 rv
= oldPrincipal
->CheckMayLoad(newOriginalURI
, PR_FALSE
);
4946 nsSameOriginChecker::GetInterface(const nsIID
& aIID
, void **aResult
)
4948 return QueryInterface(aIID
, aResult
);
4953 nsContentUtils::GetASCIIOrigin(nsIPrincipal
* aPrincipal
, nsCString
& aOrigin
)
4955 NS_PRECONDITION(aPrincipal
, "missing principal");
4959 nsCOMPtr
<nsIURI
> uri
;
4960 nsresult rv
= aPrincipal
->GetURI(getter_AddRefs(uri
));
4961 NS_ENSURE_SUCCESS(rv
, rv
);
4964 return GetASCIIOrigin(uri
, aOrigin
);
4967 aOrigin
.AssignLiteral("null");
4974 nsContentUtils::GetASCIIOrigin(nsIURI
* aURI
, nsCString
& aOrigin
)
4976 NS_PRECONDITION(aURI
, "missing uri");
4980 nsCOMPtr
<nsIURI
> uri
= NS_GetInnermostURI(aURI
);
4981 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
4984 nsresult rv
= uri
->GetAsciiHost(host
);
4986 if (NS_SUCCEEDED(rv
) && !host
.IsEmpty()) {
4988 rv
= uri
->GetScheme(scheme
);
4989 NS_ENSURE_SUCCESS(rv
, rv
);
4991 aOrigin
= scheme
+ NS_LITERAL_CSTRING("://") + host
;
4993 // If needed, append the port
4995 uri
->GetPort(&port
);
4997 PRInt32 defaultPort
= NS_GetDefaultPort(scheme
.get());
4998 if (port
!= defaultPort
) {
4999 aOrigin
.Append(':');
5000 aOrigin
.AppendInt(port
);
5005 aOrigin
.AssignLiteral("null");
5013 nsContentUtils::GetUTFOrigin(nsIPrincipal
* aPrincipal
, nsString
& aOrigin
)
5015 NS_PRECONDITION(aPrincipal
, "missing principal");
5019 nsCOMPtr
<nsIURI
> uri
;
5020 nsresult rv
= aPrincipal
->GetURI(getter_AddRefs(uri
));
5021 NS_ENSURE_SUCCESS(rv
, rv
);
5024 return GetUTFOrigin(uri
, aOrigin
);
5027 aOrigin
.AssignLiteral("null");
5034 nsContentUtils::GetUTFOrigin(nsIURI
* aURI
, nsString
& aOrigin
)
5036 NS_PRECONDITION(aURI
, "missing uri");
5040 nsCOMPtr
<nsIURI
> uri
= NS_GetInnermostURI(aURI
);
5041 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
5044 nsresult rv
= uri
->GetHost(host
);
5046 if (NS_SUCCEEDED(rv
) && !host
.IsEmpty()) {
5048 rv
= uri
->GetScheme(scheme
);
5049 NS_ENSURE_SUCCESS(rv
, rv
);
5051 aOrigin
= NS_ConvertUTF8toUTF16(scheme
+ NS_LITERAL_CSTRING("://") + host
);
5053 // If needed, append the port
5055 uri
->GetPort(&port
);
5057 PRInt32 defaultPort
= NS_GetDefaultPort(scheme
.get());
5058 if (port
!= defaultPort
) {
5059 aOrigin
.Append(':');
5060 aOrigin
.AppendInt(port
);
5065 aOrigin
.AssignLiteral("null");
5072 already_AddRefed
<nsIDocument
>
5073 nsContentUtils::GetDocumentFromScriptContext(nsIScriptContext
*aScriptContext
)
5075 if (!aScriptContext
)
5078 nsCOMPtr
<nsIDOMWindow
> window
=
5079 do_QueryInterface(aScriptContext
->GetGlobalObject());
5080 nsIDocument
*doc
= nsnull
;
5082 nsCOMPtr
<nsIDOMDocument
> domdoc
;
5083 window
->GetDocument(getter_AddRefs(domdoc
));
5085 CallQueryInterface(domdoc
, &doc
);
5091 nsContentTypeParser::nsContentTypeParser(const nsAString
& aString
)
5092 : mString(aString
), mService(nsnull
)
5094 CallGetService("@mozilla.org/network/mime-hdrparam;1", &mService
);
5097 nsContentTypeParser::~nsContentTypeParser()
5099 NS_IF_RELEASE(mService
);
5103 nsContentTypeParser::GetParameter(const char* aParameterName
, nsAString
& aResult
)
5105 NS_ENSURE_TRUE(mService
, NS_ERROR_FAILURE
);
5106 return mService
->GetParameter(mString
, aParameterName
,
5107 EmptyCString(), PR_FALSE
, nsnull
,
5113 // If you change this code, change also AllowedToAct() in
5114 // XPCSystemOnlyWrapper.cpp!
5116 nsContentUtils::CanAccessNativeAnon()
5118 JSContext
* cx
= nsnull
;
5119 sThreadJSContextStack
->Peek(&cx
);
5124 nsIPrincipal
* principal
=
5125 sSecurityManager
->GetCxSubjectPrincipalAndFrame(cx
, &fp
);
5126 NS_ENSURE_TRUE(principal
, PR_FALSE
);
5129 if (!JS_FrameIterator(cx
, &fp
)) {
5130 // No code at all is running. So we must be arriving here as the result
5131 // of C++ code asking us to do something. Allow access.
5135 // Some code is running, we can't make the assumption, as above, but we
5136 // can't use a native frame, so clear fp.
5138 } else if (!fp
->script
) {
5143 if (NS_SUCCEEDED(sSecurityManager
->IsSystemPrincipal(principal
, &privileged
)) &&
5145 // Chrome things are allowed to touch us.
5149 // XXX HACK EWW! Allow chrome://global/ access to these things, even
5150 // if they've been cloned into less privileged contexts.
5151 static const char prefix
[] = "chrome://global/";
5152 const char *filename
;
5153 if (fp
&& fp
->script
&&
5154 (filename
= fp
->script
->filename
) &&
5155 !strncmp(filename
, prefix
, NS_ARRAY_LENGTH(prefix
) - 1)) {
5159 // Before we throw, check for UniversalXPConnect.
5160 nsresult rv
= sSecurityManager
->IsCapabilityEnabled("UniversalXPConnect", &privileged
);
5161 if (NS_SUCCEEDED(rv
) && privileged
) {
5168 /* static */ nsresult
5169 nsContentUtils::DispatchXULCommand(nsIContent
* aTarget
,
5171 nsIDOMEvent
* aSourceEvent
,
5172 nsIPresShell
* aShell
,
5178 NS_ENSURE_STATE(aTarget
);
5179 nsIDocument
* doc
= aTarget
->GetOwnerDoc();
5180 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent
= do_QueryInterface(doc
);
5181 NS_ENSURE_STATE(docEvent
);
5182 nsCOMPtr
<nsIDOMEvent
> event
;
5183 docEvent
->CreateEvent(NS_LITERAL_STRING("xulcommandevent"),
5184 getter_AddRefs(event
));
5185 nsCOMPtr
<nsIDOMXULCommandEvent
> xulCommand
= do_QueryInterface(event
);
5186 nsCOMPtr
<nsIPrivateDOMEvent
> pEvent
= do_QueryInterface(xulCommand
);
5187 NS_ENSURE_STATE(pEvent
);
5188 nsCOMPtr
<nsIDOMAbstractView
> view
= do_QueryInterface(doc
->GetWindow());
5189 nsresult rv
= xulCommand
->InitCommandEvent(NS_LITERAL_STRING("command"),
5190 PR_TRUE
, PR_TRUE
, view
,
5191 0, aCtrl
, aAlt
, aShift
, aMeta
,
5193 NS_ENSURE_SUCCESS(rv
, rv
);
5196 nsEventStatus status
= nsEventStatus_eIgnore
;
5197 nsCOMPtr
<nsIPresShell
> kungFuDeathGrip
= aShell
;
5198 return aShell
->HandleDOMEventWithTarget(aTarget
, event
, &status
);
5201 nsCOMPtr
<nsIDOMEventTarget
> target
= do_QueryInterface(aTarget
);
5202 NS_ENSURE_STATE(target
);
5204 return target
->DispatchEvent(event
, &dummy
);
5209 nsContentUtils::WrapNative(JSContext
*cx
, JSObject
*scope
, nsISupports
*native
,
5210 const nsIID
* aIID
, jsval
*vp
,
5211 nsIXPConnectJSObjectHolder
**aHolder
,
5212 PRBool aAllowWrapping
)
5215 NS_ASSERTION(!aHolder
|| !*aHolder
, "*aHolder should be null!");
5222 NS_ENSURE_TRUE(sXPConnect
&& sThreadJSContextStack
, NS_ERROR_UNEXPECTED
);
5224 // Keep sXPConnect and sThreadJSContextStack alive. If we're on the main
5225 // thread then this can be done simply and cheaply by adding a reference to
5226 // nsLayoutStatics. If we're not on the main thread then we need to add a
5227 // more expensive reference sXPConnect directly. We have to use manual
5228 // AddRef and Release calls so don't early-exit from this function after we've
5229 // added the reference!
5230 PRBool isMainThread
= NS_IsMainThread();
5233 nsLayoutStatics::AddRef();
5236 sXPConnect
->AddRef();
5239 JSContext
*topJSContext
;
5240 nsresult rv
= sThreadJSContextStack
->Peek(&topJSContext
);
5241 if (NS_SUCCEEDED(rv
)) {
5242 PRBool push
= topJSContext
!= cx
;
5244 rv
= sThreadJSContextStack
->Push(cx
);
5246 if (NS_SUCCEEDED(rv
)) {
5247 rv
= sXPConnect
->WrapNativeToJSVal(cx
, scope
, native
, aIID
,
5248 aAllowWrapping
, vp
, aHolder
);
5250 sThreadJSContextStack
->Pop(nsnull
);
5256 nsLayoutStatics::Release();
5259 sXPConnect
->Release();
5266 nsContentUtils::StripNullChars(const nsAString
& aInStr
, nsAString
& aOutStr
)
5268 // In common cases where we don't have nulls in the
5269 // string we can simple simply bypass the checking code.
5270 PRInt32 firstNullPos
= aInStr
.FindChar('\0');
5271 if (firstNullPos
== kNotFound
) {
5272 aOutStr
.Assign(aInStr
);
5276 aOutStr
.SetCapacity(aInStr
.Length() - 1);
5277 nsAString::const_iterator start
, end
;
5278 aInStr
.BeginReading(start
);
5279 aInStr
.EndReading(end
);
5280 while (start
!= end
) {
5282 aOutStr
.Append(*start
);
5289 const unsigned int kCloneStackFrameStackSize
= 20;
5291 class CloneStackFrame
5293 friend class CloneStack
;
5296 // These three jsvals must all stick together as they're treated as a jsval
5301 js::AutoIdArray ids
;
5305 // Only let CloneStack access these.
5306 CloneStackFrame(JSContext
* aCx
, jsval aSource
, jsval aClone
, JSIdArray
* aIds
)
5307 : source(aSource
), clone(aClone
), temp(JSVAL_NULL
), ids(aCx
, aIds
), index(0),
5308 prevFrame(nsnull
), tvrVals(aCx
, 3, &source
)
5310 MOZ_COUNT_CTOR(CloneStackFrame
);
5315 MOZ_COUNT_DTOR(CloneStackFrame
);
5318 CloneStackFrame
* prevFrame
;
5319 js::AutoArrayRooter tvrVals
;
5325 CloneStack(JSContext
* cx
)
5326 : mCx(cx
), mLastFrame(nsnull
) {
5331 while (!IsEmpty()) {
5337 Push(jsval source
, jsval clone
, JSIdArray
* ids
) {
5338 NS_ASSERTION(!JSVAL_IS_PRIMITIVE(source
) && !JSVAL_IS_PRIMITIVE(clone
),
5339 "Must be an object!");
5344 CloneStackFrame
* newFrame
;
5345 if (mObjectSet
.Count() < kCloneStackFrameStackSize
) {
5346 // If the object can fit in our stack space then use that.
5347 CloneStackFrame
* buf
= reinterpret_cast<CloneStackFrame
*>(mStackFrames
);
5348 newFrame
= new (buf
+ mObjectSet
.Count())
5349 CloneStackFrame(mCx
, source
, clone
, ids
);
5353 newFrame
= new CloneStackFrame(mCx
, source
, clone
, ids
);
5356 mObjectSet
.PutEntry(JSVAL_TO_OBJECT(source
));
5358 newFrame
->prevFrame
= mLastFrame
;
5359 mLastFrame
= newFrame
;
5372 NS_ERROR("Empty stack!");
5376 CloneStackFrame
* lastFrame
= mLastFrame
;
5378 mObjectSet
.RemoveEntry(JSVAL_TO_OBJECT(lastFrame
->source
));
5379 mLastFrame
= lastFrame
->prevFrame
;
5381 if (mObjectSet
.Count() >= kCloneStackFrameStackSize
) {
5382 // Only delete if this was a heap object.
5386 // Otherwise just run the destructor.
5387 lastFrame
->~CloneStackFrame();
5393 NS_ASSERTION((!mLastFrame
&& !mObjectSet
.Count()) ||
5394 (mLastFrame
&& mObjectSet
.Count()),
5395 "Hashset is out of sync!");
5396 return mObjectSet
.Count() == 0;
5400 Search(JSObject
* obj
) {
5401 return !!mObjectSet
.GetEntry(obj
);
5406 CloneStackFrame
* mLastFrame
;
5407 nsTHashtable
<nsVoidPtrHashKey
> mObjectSet
;
5409 // Use a char array instead of CloneStackFrame array to prevent the JSAuto*
5410 // helpers from running until we're ready for them.
5411 char mStackFrames
[kCloneStackFrameStackSize
* sizeof(CloneStackFrame
)];
5414 struct ReparentObjectData
{
5415 ReparentObjectData(JSContext
* cx
, JSObject
* obj
)
5416 : cx(cx
), obj(obj
), ids(nsnull
), index(0) { }
5418 ~ReparentObjectData() {
5420 JS_DestroyIdArray(cx
, ids
);
5431 SetPropertyOnValueOrObject(JSContext
* cx
,
5437 NS_ASSERTION((rval
&& !obj
) || (!rval
&& obj
), "Can only clone to one dest!");
5442 if (!JS_DefinePropertyById(cx
, obj
, id
, val
, nsnull
, nsnull
,
5443 JSPROP_ENUMERATE
)) {
5444 return NS_ERROR_FAILURE
;
5450 CreateEmptyObjectOrArray(JSContext
* cx
,
5453 if (JS_IsArrayObject(cx
, obj
)) {
5455 if (!JS_GetArrayLength(cx
, obj
, &length
)) {
5456 NS_ERROR("Failed to get array length?!");
5459 return JS_NewArrayObject(cx
, length
, NULL
);
5461 return JS_NewObject(cx
, NULL
, NULL
, NULL
);
5465 CloneSimpleValues(JSContext
* cx
,
5469 JSObject
* robj
= nsnull
,
5470 jsid rid
= INT_TO_JSID(0))
5472 *wasCloned
= PR_TRUE
;
5474 // No cloning necessary for these non-GC'd jsvals.
5475 if (!JSVAL_IS_GCTHING(val
) || JSVAL_IS_NULL(val
)) {
5476 return SetPropertyOnValueOrObject(cx
, val
, rval
, robj
, rid
);
5480 if (JSVAL_IS_DOUBLE(val
)) {
5482 if (!JS_NewDoubleValue(cx
, *JSVAL_TO_DOUBLE(val
), &newVal
)) {
5483 return NS_ERROR_OUT_OF_MEMORY
;
5485 return SetPropertyOnValueOrObject(cx
, newVal
, rval
, robj
, rid
);
5488 // We'll use immutable strings to prevent copying if we can.
5489 if (JSVAL_IS_STRING(val
)) {
5490 if (!JS_MakeStringImmutable(cx
, JSVAL_TO_STRING(val
))) {
5491 return NS_ERROR_FAILURE
;
5493 return SetPropertyOnValueOrObject(cx
, val
, rval
, robj
, rid
);
5496 NS_ASSERTION(!JSVAL_IS_PRIMITIVE(val
), "Not an object!");
5497 JSObject
* obj
= JSVAL_TO_OBJECT(val
);
5499 // Dense arrays of primitives can be cloned quickly.
5501 if (!js_CloneDensePrimitiveArray(cx
, obj
, &newArray
)) {
5502 return NS_ERROR_FAILURE
;
5505 return SetPropertyOnValueOrObject(cx
, OBJECT_TO_JSVAL(newArray
), rval
, robj
,
5510 if (js_DateIsValid(cx
, obj
)) {
5511 jsdouble msec
= js_DateGetMsecSinceEpoch(cx
, obj
);
5513 if (!(msec
&& (newDate
= js_NewDateObjectMsec(cx
, msec
)))) {
5514 return NS_ERROR_OUT_OF_MEMORY
;
5516 return SetPropertyOnValueOrObject(cx
, OBJECT_TO_JSVAL(newDate
), rval
, robj
,
5521 if (js_ObjectIsRegExp(obj
)) {
5523 if (!js_GetClassPrototype(cx
, JS_GetScopeChain(cx
), JSProto_RegExp
,
5525 return NS_ERROR_FAILURE
;
5527 JSObject
* newRegExp
= js_CloneRegExpObject(cx
, obj
, proto
);
5529 return NS_ERROR_FAILURE
;
5531 return SetPropertyOnValueOrObject(cx
, OBJECT_TO_JSVAL(newRegExp
), rval
,
5535 // Typed array objects.
5536 if (js_IsTypedArray(obj
)) {
5537 js::TypedArray
* src
= js::TypedArray::fromJSObject(obj
);
5538 JSObject
* newTypedArray
= js_CreateTypedArrayWithArray(cx
, src
->type
, obj
);
5539 if (!newTypedArray
) {
5540 return NS_ERROR_FAILURE
;
5542 return SetPropertyOnValueOrObject(cx
, OBJECT_TO_JSVAL(newTypedArray
), rval
,
5546 // ArrayBuffer objects.
5547 if (js_IsArrayBuffer(obj
)) {
5548 js::ArrayBuffer
* src
= js::ArrayBuffer::fromJSObject(obj
);
5549 JSObject
* newBuffer
= js_CreateArrayBuffer(cx
, src
->byteLength
);
5551 return NS_ERROR_FAILURE
;
5553 memcpy(js::ArrayBuffer::fromJSObject(newBuffer
)->data
, src
->data
,
5555 return SetPropertyOnValueOrObject(cx
, OBJECT_TO_JSVAL(newBuffer
), rval
,
5559 // Do we support File?
5560 // Do we support Blob?
5561 // Do we support FileList?
5563 // Function objects don't get cloned.
5564 if (JS_ObjectIsFunction(cx
, obj
)) {
5565 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
5568 // Security wrapped objects are not allowed either.
5569 JSClass
* clasp
= JS_GET_CLASS(cx
, obj
);
5570 if ((clasp
->flags
& JSCLASS_IS_EXTENDED
) &&
5571 ((JSExtendedClass
*)clasp
)->wrappedObject
) {
5572 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
5575 // See if this JSObject is backed by some C++ object. If it is then we assume
5576 // that it is inappropriate to clone.
5577 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
5578 nsContentUtils::XPConnect()->
5579 GetWrappedNativeOfJSObject(cx
, obj
, getter_AddRefs(wrapper
));
5581 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
5584 *wasCloned
= PR_FALSE
;
5588 } // anonymous namespace
5592 nsContentUtils::CreateStructuredClone(JSContext
* cx
,
5596 JSAutoRequest
ar(cx
);
5598 nsCOMPtr
<nsIXPConnect
> xpconnect(sXPConnect
);
5599 NS_ENSURE_STATE(xpconnect
);
5602 nsresult rv
= CloneSimpleValues(cx
, val
, rval
, &wasCloned
);
5603 if (NS_FAILED(rv
)) {
5611 NS_ASSERTION(JSVAL_IS_OBJECT(val
), "Not an object?!");
5612 JSObject
* obj
= CreateEmptyObjectOrArray(cx
, JSVAL_TO_OBJECT(val
));
5614 return NS_ERROR_OUT_OF_MEMORY
;
5617 jsval output
= OBJECT_TO_JSVAL(obj
);
5618 js::AutoValueRooter
tvr(cx
, output
);
5620 CloneStack
stack(cx
);
5621 if (!stack
.Push(val
, OBJECT_TO_JSVAL(obj
),
5622 JS_Enumerate(cx
, JSVAL_TO_OBJECT(val
)))) {
5623 return NS_ERROR_OUT_OF_MEMORY
;
5626 while (!stack
.IsEmpty()) {
5627 CloneStackFrame
* frame
= stack
.Peek();
5629 NS_ASSERTION(!!frame
->ids
&&
5630 frame
->ids
.length() >= frame
->index
&&
5631 !JSVAL_IS_PRIMITIVE(frame
->source
) &&
5632 !JSVAL_IS_PRIMITIVE(frame
->clone
),
5633 "Bad frame state!");
5635 if (frame
->index
== frame
->ids
.length()) {
5636 // Done cloning this object, pop the frame.
5641 // Get the current id and increment the index.
5642 jsid id
= frame
->ids
[frame
->index
++];
5644 if (!JS_GetPropertyById(cx
, JSVAL_TO_OBJECT(frame
->source
), id
,
5646 return NS_ERROR_FAILURE
;
5649 if (!JSVAL_IS_PRIMITIVE(frame
->temp
) &&
5650 stack
.Search(JSVAL_TO_OBJECT(frame
->temp
))) {
5651 // Spec says to throw this particular exception for cyclical references.
5652 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
5655 JSObject
* clone
= JSVAL_TO_OBJECT(frame
->clone
);
5658 nsresult rv
= CloneSimpleValues(cx
, frame
->temp
, nsnull
, &wasCloned
, clone
,
5660 if (NS_FAILED(rv
)) {
5665 NS_ASSERTION(JSVAL_IS_OBJECT(frame
->temp
), "Not an object?!");
5666 obj
= CreateEmptyObjectOrArray(cx
, JSVAL_TO_OBJECT(frame
->temp
));
5668 !stack
.Push(frame
->temp
, OBJECT_TO_JSVAL(obj
),
5669 JS_Enumerate(cx
, JSVAL_TO_OBJECT(frame
->temp
)))) {
5670 return NS_ERROR_OUT_OF_MEMORY
;
5672 // Set the new object as a property of the clone. We'll fill it on the
5674 if (!JS_DefinePropertyById(cx
, clone
, id
, OBJECT_TO_JSVAL(obj
), nsnull
,
5675 nsnull
, JSPROP_ENUMERATE
)) {
5676 return NS_ERROR_FAILURE
;
5687 nsContentUtils::ReparentClonedObjectToScope(JSContext
* cx
,
5691 JSAutoRequest
ar(cx
);
5693 scope
= JS_GetGlobalForObject(cx
, scope
);
5695 nsAutoTArray
<ReparentObjectData
, 20> objectData
;
5696 objectData
.AppendElement(ReparentObjectData(cx
, obj
));
5698 while (!objectData
.IsEmpty()) {
5699 ReparentObjectData
& data
= objectData
[objectData
.Length() - 1];
5702 NS_ASSERTION(!data
.index
, "Shouldn't have index here");
5704 // Typed arrays are special and don't need to be enumerated.
5705 if (js_IsTypedArray(data
.obj
)) {
5706 if (!js_ReparentTypedArrayToScope(cx
, data
.obj
, scope
)) {
5707 return NS_ERROR_FAILURE
;
5710 // No need to enumerate anything here.
5711 objectData
.RemoveElementAt(objectData
.Length() - 1);
5715 JSProtoKey key
= JSCLASS_CACHED_PROTO_KEY(JS_GET_CLASS(cx
, data
.obj
));
5717 // We should never be reparenting an object that doesn't have a standard
5719 return NS_ERROR_FAILURE
;
5722 // Fix the prototype and parent first.
5724 if (!js_GetClassPrototype(cx
, scope
, key
, &proto
) ||
5725 !JS_SetPrototype(cx
, data
.obj
, proto
) ||
5726 !JS_SetParent(cx
, data
.obj
, scope
)) {
5727 return NS_ERROR_FAILURE
;
5730 // Primitive arrays don't need to be enumerated either but the proto and
5731 // parent needed to be fixed above. Now we can just move on.
5732 if (js_IsDensePrimitiveArray(data
.obj
)) {
5733 objectData
.RemoveElementAt(objectData
.Length() - 1);
5737 // And now enumerate the object's properties.
5738 if (!(data
.ids
= JS_Enumerate(cx
, data
.obj
))) {
5739 return NS_ERROR_FAILURE
;
5743 // If we've gone through all the object's properties then we're done with
5745 if (data
.index
== data
.ids
->length
) {
5746 objectData
.RemoveElementAt(objectData
.Length() - 1);
5750 // Get the id and increment!
5751 jsid id
= data
.ids
->vector
[data
.index
++];
5754 if (!JS_GetPropertyById(cx
, data
.obj
, id
, &prop
)) {
5755 return NS_ERROR_FAILURE
;
5758 // Push a new frame if this property is an object.
5759 if (!JSVAL_IS_PRIMITIVE(prop
)) {
5760 objectData
.AppendElement(ReparentObjectData(cx
, JSVAL_TO_OBJECT(prop
)));
5767 struct ClassMatchingInfo
{
5768 nsCOMArray
<nsIAtom
> mClasses
;
5769 nsCaseTreatment mCaseTreatment
;
5773 MatchClassNames(nsIContent
* aContent
, PRInt32 aNamespaceID
, nsIAtom
* aAtom
,
5776 // We can't match if there are no class names
5777 const nsAttrValue
* classAttr
= aContent
->GetClasses();
5782 // need to match *all* of the classes
5783 ClassMatchingInfo
* info
= static_cast<ClassMatchingInfo
*>(aData
);
5784 PRInt32 length
= info
->mClasses
.Count();
5786 // If we actually had no classes, don't match.
5790 for (i
= 0; i
< length
; ++i
) {
5791 if (!classAttr
->Contains(info
->mClasses
.ObjectAt(i
),
5792 info
->mCaseTreatment
)) {
5801 DestroyClassNameArray(void* aData
)
5803 ClassMatchingInfo
* info
= static_cast<ClassMatchingInfo
*>(aData
);
5808 AllocClassMatchingInfo(nsINode
* aRootNode
,
5809 const nsString
* aClasses
)
5811 nsAttrValue attrValue
;
5812 attrValue
.ParseAtomArray(*aClasses
);
5813 // nsAttrValue::Equals is sensitive to order, so we'll send an array
5814 ClassMatchingInfo
* info
= new ClassMatchingInfo
;
5815 NS_ENSURE_TRUE(info
, nsnull
);
5817 if (attrValue
.Type() == nsAttrValue::eAtomArray
) {
5818 info
->mClasses
.AppendObjects(*(attrValue
.GetAtomArrayValue()));
5819 } else if (attrValue
.Type() == nsAttrValue::eAtom
) {
5820 info
->mClasses
.AppendObject(attrValue
.GetAtomValue());
5823 info
->mCaseTreatment
=
5824 aRootNode
->GetOwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks
?
5825 eIgnoreCase
: eCaseMatters
;
5832 nsContentUtils::GetElementsByClassName(nsINode
* aRootNode
,
5833 const nsAString
& aClasses
,
5834 nsIDOMNodeList
** aReturn
)
5836 NS_PRECONDITION(aRootNode
, "Must have root node");
5838 nsContentList
* elements
=
5839 NS_GetFuncStringContentList(aRootNode
, MatchClassNames
,
5840 DestroyClassNameArray
,
5841 AllocClassMatchingInfo
,
5843 NS_ENSURE_TRUE(elements
, NS_ERROR_OUT_OF_MEMORY
);
5845 // Transfer ownership
5846 *aReturn
= elements
;
5852 class DebugWrapperTraversalCallback
: public nsCycleCollectionTraversalCallback
5855 DebugWrapperTraversalCallback(void* aWrapper
) : mFound(PR_FALSE
),
5858 mFlags
= WANT_ALL_TRACES
;
5861 NS_IMETHOD_(void) DescribeNode(CCNodeType type
,
5864 const char* objname
)
5867 NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports
*root
)
5870 NS_IMETHOD_(void) NoteRoot(PRUint32 langID
, void* root
,
5871 nsCycleCollectionParticipant
* helper
)
5874 NS_IMETHOD_(void) NoteScriptChild(PRUint32 langID
, void* child
)
5876 if (langID
== nsIProgrammingLanguage::JAVASCRIPT
) {
5877 mFound
= child
== mWrapper
;
5880 NS_IMETHOD_(void) NoteXPCOMChild(nsISupports
*child
)
5883 NS_IMETHOD_(void) NoteNativeChild(void* child
,
5884 nsCycleCollectionParticipant
* helper
)
5888 NS_IMETHOD_(void) NoteNextEdgeName(const char* name
)
5899 DebugWrapperTraceCallback(PRUint32 langID
, void *p
, void *closure
)
5901 DebugWrapperTraversalCallback
* callback
=
5902 static_cast<DebugWrapperTraversalCallback
*>(closure
);
5903 callback
->NoteScriptChild(langID
, p
);
5908 nsContentUtils::CheckCCWrapperTraversal(nsISupports
* aScriptObjectHolder
,
5909 nsWrapperCache
* aCache
)
5911 nsXPCOMCycleCollectionParticipant
* participant
;
5912 CallQueryInterface(aScriptObjectHolder
, &participant
);
5914 DebugWrapperTraversalCallback
callback(aCache
->GetWrapper());
5916 participant
->Traverse(aScriptObjectHolder
, callback
);
5917 NS_ASSERTION(callback
.mFound
,
5918 "Cycle collection participant didn't traverse to preserved "
5919 "wrapper! This will probably crash.");
5921 callback
.mFound
= PR_FALSE
;
5922 participant
->Trace(aScriptObjectHolder
, DebugWrapperTraceCallback
, &callback
);
5923 NS_ASSERTION(callback
.mFound
,
5924 "Cycle collection participant didn't trace preserved wrapper! "
5925 "This will probably crash.");
5929 mozAutoRemovableBlockerRemover::mozAutoRemovableBlockerRemover(nsIDocument
* aDocument MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL
)
5931 MOZILLA_GUARD_OBJECT_NOTIFIER_INIT
;
5932 mNestingLevel
= nsContentUtils::GetRemovableScriptBlockerLevel();
5933 mDocument
= aDocument
;
5934 nsISupports
* sink
= aDocument
? aDocument
->GetCurrentContentSink() : nsnull
;
5935 mObserver
= do_QueryInterface(sink
);
5936 for (PRUint32 i
= 0; i
< mNestingLevel
; ++i
) {
5938 mObserver
->EndUpdate(mDocument
, UPDATE_CONTENT_MODEL
);
5940 nsContentUtils::RemoveRemovableScriptBlocker();
5943 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), "killing mutation events");
5946 mozAutoRemovableBlockerRemover::~mozAutoRemovableBlockerRemover()
5948 NS_ASSERTION(nsContentUtils::GetRemovableScriptBlockerLevel() == 0,
5949 "Should have had none");
5950 for (PRUint32 i
= 0; i
< mNestingLevel
; ++i
) {
5951 nsContentUtils::AddRemovableScriptBlocker();
5953 mObserver
->BeginUpdate(mDocument
, UPDATE_CONTENT_MODEL
);
5960 nsContentUtils::IsFocusedContent(nsIContent
* aContent
)
5962 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
5964 return fm
&& fm
->GetFocusedContent() == aContent
;
5967 void nsContentUtils::RemoveNewlines(nsString
&aString
)
5969 // strip CR/LF and null
5970 static const char badChars
[] = {'\r', '\n', 0};
5971 aString
.StripChars(badChars
);
5975 nsContentUtils::PlatformToDOMLineBreaks(nsString
&aString
)
5977 if (aString
.FindChar(PRUnichar('\r')) != -1) {
5978 // Windows linebreaks: Map CRLF to LF:
5979 aString
.ReplaceSubstring(NS_LITERAL_STRING("\r\n").get(),
5980 NS_LITERAL_STRING("\n").get());
5982 // Mac linebreaks: Map any remaining CR to LF:
5983 aString
.ReplaceSubstring(NS_LITERAL_STRING("\r").get(),
5984 NS_LITERAL_STRING("\n").get());
5988 already_AddRefed
<mozilla::layers::LayerManager
>
5989 nsContentUtils::LayerManagerForDocument(nsIDocument
*aDoc
)
5991 nsIDocument
* doc
= aDoc
;
5992 nsIDocument
* displayDoc
= doc
->GetDisplayDocument();
5997 nsIPresShell
* shell
= doc
->GetPrimaryShell();
5998 nsCOMPtr
<nsISupports
> container
= doc
->GetContainer();
5999 nsCOMPtr
<nsIDocShellTreeItem
> docShellTreeItem
= do_QueryInterface(container
);
6000 while (!shell
&& docShellTreeItem
) {
6001 // We may be in a display:none subdocument, or we may not have a presshell
6003 // Walk the docshell tree to find the nearest container that has a presshell,
6004 // and find the root widget from that.
6005 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(docShellTreeItem
);
6006 nsCOMPtr
<nsIPresShell
> presShell
;
6007 docShell
->GetPresShell(getter_AddRefs(presShell
));
6011 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
6012 docShellTreeItem
->GetParent(getter_AddRefs(parent
));
6013 docShellTreeItem
= parent
;
6018 nsIFrame
* rootFrame
= shell
->FrameManager()->GetRootFrame();
6021 nsLayoutUtils::GetDisplayRootFrame(rootFrame
)->GetWindow();
6023 nsRefPtr
<mozilla::layers::LayerManager
> manager
= widget
->GetLayerManager();
6024 return manager
.forget();
6029 nsRefPtr
<mozilla::layers::LayerManager
> manager
=
6030 new mozilla::layers::BasicLayerManager(nsnull
);
6031 return manager
.forget();
6035 NS_IMPL_ISUPPORTS1(nsIContentUtils
, nsIContentUtils
)
6038 nsIContentUtils::IsSafeToRunScript()
6040 return nsContentUtils::IsSafeToRunScript();