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 "nsCompressedCharMap.h"
150 #include "nsINativeKeyBindings.h"
151 #include "nsIDOMNSUIEvent.h"
152 #include "nsIDOMNSEvent.h"
153 #include "nsIPrivateDOMEvent.h"
154 #include "nsXULPopupManager.h"
155 #include "nsIPermissionManager.h"
156 #include "nsIContentPrefService.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 "nsIAsyncVerifyRedirectCallback.h"
167 #include "nsIInterfaceRequestor.h"
168 #include "nsIOfflineCacheUpdate.h"
169 #include "nsCPrefetchService.h"
170 #include "nsIChromeRegistry.h"
171 #include "nsIMIMEHeaderParam.h"
172 #include "nsIDOMXULCommandEvent.h"
173 #include "nsIDOMAbstractView.h"
174 #include "nsIDOMDragEvent.h"
175 #include "nsDOMDataTransfer.h"
176 #include "nsHtml5Module.h"
177 #include "nsPresContext.h"
178 #include "nsLayoutStatics.h"
179 #include "nsLayoutUtils.h"
180 #include "nsFrameManager.h"
181 #include "BasicLayers.h"
182 #include "nsFocusManager.h"
183 #include "nsTextEditorState.h"
184 #include "nsIPluginHost.h"
185 #include "nsICategoryManager.h"
186 #include "nsAHtml5FragmentParser.h"
189 #include "nsIBidiKeyboard.h"
191 #include "nsCycleCollectionParticipant.h"
193 // for ReportToConsole
194 #include "nsIStringBundle.h"
195 #include "nsIScriptError.h"
196 #include "nsIConsoleService.h"
198 #include "mozAutoDocUpdate.h"
199 #include "imgICache.h"
200 #include "jsinterp.h"
203 #include "jsregexp.h"
204 #include "jstypedarray.h"
205 #include "xpcprivate.h"
206 #include "nsScriptSecurityManager.h"
207 #include "nsIChannelPolicy.h"
208 #include "nsChannelPolicy.h"
209 #include "nsIContentSecurityPolicy.h"
210 #include "nsContentDLF.h"
212 #include "nsHTMLMediaElement.h"
215 using namespace mozilla::dom
;
216 using namespace mozilla::layers
;
218 const char kLoadAsData
[] = "loadAsData";
220 static const char kJSStackContractID
[] = "@mozilla.org/js/xpc/ContextStack;1";
221 static NS_DEFINE_CID(kParserServiceCID
, NS_PARSERSERVICE_CID
);
222 static NS_DEFINE_CID(kCParserCID
, NS_PARSER_CID
);
224 nsIDOMScriptObjectFactory
*nsContentUtils::sDOMScriptObjectFactory
= nsnull
;
225 nsIXPConnect
*nsContentUtils::sXPConnect
;
226 nsIScriptSecurityManager
*nsContentUtils::sSecurityManager
;
227 nsIThreadJSContextStack
*nsContentUtils::sThreadJSContextStack
;
228 nsIParserService
*nsContentUtils::sParserService
= nsnull
;
229 nsINameSpaceManager
*nsContentUtils::sNameSpaceManager
;
230 nsIIOService
*nsContentUtils::sIOService
;
232 nsIXTFService
*nsContentUtils::sXTFService
= nsnull
;
234 nsIPrefBranch2
*nsContentUtils::sPrefBranch
= nsnull
;
235 imgILoader
*nsContentUtils::sImgLoader
;
236 imgICache
*nsContentUtils::sImgCache
;
237 mozilla::IHistory
*nsContentUtils::sHistory
;
238 nsIConsoleService
*nsContentUtils::sConsoleService
;
239 nsDataHashtable
<nsISupportsHashKey
, EventNameMapping
>* nsContentUtils::sAtomEventTable
= nsnull
;
240 nsDataHashtable
<nsStringHashKey
, EventNameMapping
>* nsContentUtils::sStringEventTable
= nsnull
;
241 nsCOMArray
<nsIAtom
>* nsContentUtils::sUserDefinedEvents
= nsnull
;
242 nsIStringBundleService
*nsContentUtils::sStringBundleService
;
243 nsIStringBundle
*nsContentUtils::sStringBundles
[PropertiesFile_COUNT
];
244 nsIContentPolicy
*nsContentUtils::sContentPolicyService
;
245 PRBool
nsContentUtils::sTriedToGetContentPolicy
= PR_FALSE
;
246 nsILineBreaker
*nsContentUtils::sLineBreaker
;
247 nsIWordBreaker
*nsContentUtils::sWordBreaker
;
248 nsIUGenCategory
*nsContentUtils::sGenCat
;
249 nsTArray
<nsISupports
**> *nsContentUtils::sPtrsToPtrsToRelease
;
250 nsIScriptRuntime
*nsContentUtils::sScriptRuntimes
[NS_STID_ARRAY_UBOUND
];
251 PRInt32
nsContentUtils::sScriptRootCount
[NS_STID_ARRAY_UBOUND
];
252 PRUint32
nsContentUtils::sJSGCThingRootCount
;
254 nsIBidiKeyboard
*nsContentUtils::sBidiKeyboard
= nsnull
;
256 PRUint32
nsContentUtils::sScriptBlockerCount
= 0;
257 PRUint32
nsContentUtils::sRemovableScriptBlockerCount
= 0;
258 nsCOMArray
<nsIRunnable
>* nsContentUtils::sBlockedScriptRunners
= nsnull
;
259 PRUint32
nsContentUtils::sRunnersCountAtFirstBlocker
= 0;
260 PRUint32
nsContentUtils::sScriptBlockerCountWhereRunnersPrevented
= 0;
261 nsIInterfaceRequestor
* nsContentUtils::sSameOriginChecker
= nsnull
;
263 PRBool
nsContentUtils::sIsHandlingKeyBoardEvent
= PR_FALSE
;
264 PRBool
nsContentUtils::sAllowXULXBL_for_file
= PR_FALSE
;
266 PRBool
nsContentUtils::sInitialized
= PR_FALSE
;
268 nsRefPtrHashtable
<nsPrefObserverHashKey
, nsPrefOldCallback
>
269 *nsContentUtils::sPrefCallbackTable
= nsnull
;
271 static PLDHashTable sEventListenerManagersHash
;
273 class EventListenerManagerMapEntry
: public PLDHashEntryHdr
276 EventListenerManagerMapEntry(const void *aKey
)
281 ~EventListenerManagerMapEntry()
283 NS_ASSERTION(!mListenerManager
, "caller must release and disconnect ELM");
287 const void *mKey
; // must be first, to look like PLDHashEntryStub
290 nsCOMPtr
<nsIEventListenerManager
> mListenerManager
;
294 EventListenerManagerHashInitEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
,
297 // Initialize the entry with placement new
298 new (entry
) EventListenerManagerMapEntry(key
);
303 EventListenerManagerHashClearEntry(PLDHashTable
*table
, PLDHashEntryHdr
*entry
)
305 EventListenerManagerMapEntry
*lm
=
306 static_cast<EventListenerManagerMapEntry
*>(entry
);
308 // Let the EventListenerManagerMapEntry clean itself up...
309 lm
->~EventListenerManagerMapEntry();
312 class nsSameOriginChecker
: public nsIChannelEventSink
,
313 public nsIInterfaceRequestor
316 NS_DECL_NSICHANNELEVENTSINK
317 NS_DECL_NSIINTERFACEREQUESTOR
320 class nsPrefObserverHashKey
: public PLDHashEntryHdr
{
322 typedef nsPrefObserverHashKey
* KeyType
;
323 typedef const nsPrefObserverHashKey
* KeyTypePointer
;
325 static const nsPrefObserverHashKey
* KeyToPointer(nsPrefObserverHashKey
*aKey
)
330 static PLDHashNumber
HashKey(const nsPrefObserverHashKey
*aKey
)
332 PRUint32 strHash
= nsCRT::HashCode(aKey
->mPref
.BeginReading(),
333 aKey
->mPref
.Length());
334 return PR_ROTATE_LEFT32(strHash
, 4) ^
335 NS_PTR_TO_UINT32(aKey
->mCallback
);
338 nsPrefObserverHashKey(const char *aPref
, PrefChangedFunc aCallback
) :
339 mPref(aPref
), mCallback(aCallback
) { }
341 nsPrefObserverHashKey(const nsPrefObserverHashKey
*aOther
) :
342 mPref(aOther
->mPref
), mCallback(aOther
->mCallback
)
345 PRBool
KeyEquals(const nsPrefObserverHashKey
*aOther
) const
347 return mCallback
== aOther
->mCallback
&&
348 mPref
.Equals(aOther
->mPref
);
351 nsPrefObserverHashKey
*GetKey() const
353 return const_cast<nsPrefObserverHashKey
*>(this);
356 enum { ALLOW_MEMMOVE
= PR_TRUE
};
360 PrefChangedFunc mCallback
;
363 // For nsContentUtils::RegisterPrefCallback/UnregisterPrefCallback
364 class nsPrefOldCallback
: public nsIObserver
,
365 public nsPrefObserverHashKey
372 nsPrefOldCallback(const char *aPref
, PrefChangedFunc aCallback
)
373 : nsPrefObserverHashKey(aPref
, aCallback
) { }
375 ~nsPrefOldCallback() {
376 nsIPrefBranch2
*prefBranch
= nsContentUtils::GetPrefBranch();
378 prefBranch
->RemoveObserver(mPref
.get(), this);
381 void AppendClosure(void *aClosure
) {
382 mClosures
.AppendElement(aClosure
);
385 void RemoveClosure(void *aClosure
) {
386 mClosures
.RemoveElement(aClosure
);
389 PRBool
HasNoClosures() {
390 return mClosures
.Length() == 0;
394 nsTArray
<void *> mClosures
;
397 NS_IMPL_ISUPPORTS1(nsPrefOldCallback
, nsIObserver
)
400 nsPrefOldCallback::Observe(nsISupports
*aSubject
,
402 const PRUnichar
*aData
)
404 NS_ASSERTION(!strcmp(aTopic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
),
406 NS_LossyConvertUTF16toASCII
data(aData
);
407 for (PRUint32 i
= 0; i
< mClosures
.Length(); i
++) {
408 mCallback(data
.get(), mClosures
.ElementAt(i
));
414 struct PrefCacheData
{
417 PRBool defaultValueBool
;
418 PRInt32 defaultValueInt
;
422 nsTArray
<nsAutoPtr
<PrefCacheData
> >* sPrefCacheData
= nsnull
;
426 nsContentUtils::Init()
429 NS_WARNING("Init() called twice");
434 sPrefCacheData
= new nsTArray
<nsAutoPtr
<PrefCacheData
> >();
436 // It's ok to not have a pref service.
437 CallGetService(NS_PREFSERVICE_CONTRACTID
, &sPrefBranch
);
439 nsresult rv
= NS_GetNameSpaceManager(&sNameSpaceManager
);
440 NS_ENSURE_SUCCESS(rv
, rv
);
442 nsXPConnect
* xpconnect
= nsXPConnect::GetXPConnect();
443 NS_ENSURE_TRUE(xpconnect
, NS_ERROR_FAILURE
);
445 sXPConnect
= xpconnect
;
446 sThreadJSContextStack
= xpconnect
;
448 sSecurityManager
= nsScriptSecurityManager::GetScriptSecurityManager();
449 if(!sSecurityManager
)
450 return NS_ERROR_FAILURE
;
451 NS_ADDREF(sSecurityManager
);
453 rv
= CallGetService(NS_IOSERVICE_CONTRACTID
, &sIOService
);
455 // This makes life easier, but we can live without it.
460 rv
= CallGetService(NS_LBRK_CONTRACTID
, &sLineBreaker
);
461 NS_ENSURE_SUCCESS(rv
, rv
);
463 rv
= CallGetService(NS_WBRK_CONTRACTID
, &sWordBreaker
);
464 NS_ENSURE_SUCCESS(rv
, rv
);
466 rv
= CallGetService(NS_UNICHARCATEGORY_CONTRACTID
, &sGenCat
);
467 NS_ENSURE_SUCCESS(rv
, rv
);
469 rv
= CallGetService(NS_IHISTORY_CONTRACTID
, &sHistory
);
471 NS_RUNTIMEABORT("Cannot get the history service");
475 sPtrsToPtrsToRelease
= new nsTArray
<nsISupports
**>();
476 if (!sPtrsToPtrsToRelease
) {
477 return NS_ERROR_OUT_OF_MEMORY
;
480 if (!InitializeEventTable())
481 return NS_ERROR_FAILURE
;
483 if (!sEventListenerManagersHash
.ops
) {
484 static PLDHashTableOps hash_table_ops
=
488 PL_DHashVoidPtrKeyStub
,
489 PL_DHashMatchEntryStub
,
490 PL_DHashMoveEntryStub
,
491 EventListenerManagerHashClearEntry
,
492 PL_DHashFinalizeStub
,
493 EventListenerManagerHashInitEntry
496 if (!PL_DHashTableInit(&sEventListenerManagersHash
, &hash_table_ops
,
497 nsnull
, sizeof(EventListenerManagerMapEntry
), 16)) {
498 sEventListenerManagersHash
.ops
= nsnull
;
500 return NS_ERROR_OUT_OF_MEMORY
;
504 sBlockedScriptRunners
= new nsCOMArray
<nsIRunnable
>;
505 NS_ENSURE_TRUE(sBlockedScriptRunners
, NS_ERROR_OUT_OF_MEMORY
);
507 nsContentUtils::AddBoolPrefVarCache("dom.allow_XUL_XBL_for_file",
508 &sAllowXULXBL_for_file
);
510 sInitialized
= PR_TRUE
;
515 bool nsContentUtils::sImgLoaderInitialized
;
518 nsContentUtils::InitImgLoader()
520 sImgLoaderInitialized
= true;
522 // Ignore failure and just don't load images
523 nsresult rv
= CallGetService("@mozilla.org/image/loader;1", &sImgLoader
);
525 // no image loading for us. Oh, well.
529 if (NS_FAILED(CallGetService("@mozilla.org/image/cache;1", &sImgCache
)))
535 nsContentUtils::InitializeEventTable() {
536 NS_ASSERTION(!sAtomEventTable
, "EventTable already initialized!");
537 NS_ASSERTION(!sStringEventTable
, "EventTable already initialized!");
539 static const EventNameMapping eventArray
[] = {
540 { nsGkAtoms::onmousedown
, NS_MOUSE_BUTTON_DOWN
, EventNameType_All
, NS_MOUSE_EVENT
},
541 { nsGkAtoms::onmouseup
, NS_MOUSE_BUTTON_UP
, EventNameType_All
, NS_MOUSE_EVENT
},
542 { nsGkAtoms::onclick
, NS_MOUSE_CLICK
, EventNameType_All
, NS_MOUSE_EVENT
},
543 { nsGkAtoms::ondblclick
, NS_MOUSE_DOUBLECLICK
, EventNameType_HTMLXUL
, NS_MOUSE_EVENT
},
544 { nsGkAtoms::onmouseover
, NS_MOUSE_ENTER_SYNTH
, EventNameType_All
, NS_MOUSE_EVENT
},
545 { nsGkAtoms::onmouseout
, NS_MOUSE_EXIT_SYNTH
, EventNameType_All
, NS_MOUSE_EVENT
},
546 { nsGkAtoms::onMozMouseHittest
, NS_MOUSE_MOZHITTEST
, EventNameType_None
, NS_MOUSE_EVENT
},
547 { nsGkAtoms::onmousemove
, NS_MOUSE_MOVE
, EventNameType_All
, NS_MOUSE_EVENT
},
548 { nsGkAtoms::oncontextmenu
, NS_CONTEXTMENU
, EventNameType_HTMLXUL
, NS_MOUSE_EVENT
},
550 { nsGkAtoms::onkeydown
, NS_KEY_DOWN
, EventNameType_HTMLXUL
, NS_KEY_EVENT
},
551 { nsGkAtoms::onkeyup
, NS_KEY_UP
, EventNameType_HTMLXUL
, NS_KEY_EVENT
},
552 { nsGkAtoms::onkeypress
, NS_KEY_PRESS
, EventNameType_HTMLXUL
, NS_KEY_EVENT
},
554 { nsGkAtoms::onfocus
, NS_FOCUS_CONTENT
, EventNameType_HTMLXUL
, NS_FOCUS_EVENT
},
555 { nsGkAtoms::onblur
, NS_BLUR_CONTENT
, EventNameType_HTMLXUL
, NS_FOCUS_EVENT
},
557 { nsGkAtoms::onoffline
, NS_OFFLINE
, EventNameType_HTMLXUL
, NS_EVENT
},
558 { nsGkAtoms::ononline
, NS_ONLINE
, EventNameType_HTMLXUL
, NS_EVENT
},
559 { nsGkAtoms::onsubmit
, NS_FORM_SUBMIT
, EventNameType_HTMLXUL
, NS_EVENT
},
560 { nsGkAtoms::onreset
, NS_FORM_RESET
, EventNameType_HTMLXUL
, NS_EVENT
},
561 { nsGkAtoms::onchange
, NS_FORM_CHANGE
, EventNameType_HTMLXUL
, NS_EVENT
},
562 { nsGkAtoms::onselect
, NS_FORM_SELECTED
, EventNameType_HTMLXUL
, NS_EVENT
},
563 { nsGkAtoms::oninvalid
, NS_FORM_INVALID
, EventNameType_HTMLXUL
, NS_EVENT
},
564 { nsGkAtoms::onload
, NS_LOAD
, EventNameType_All
, NS_EVENT
},
565 { nsGkAtoms::onpopstate
, NS_POPSTATE
, EventNameType_HTMLXUL
, NS_EVENT_NULL
},
566 { nsGkAtoms::onunload
, NS_PAGE_UNLOAD
,
567 (EventNameType_HTMLXUL
| EventNameType_SVGSVG
), NS_EVENT
},
568 { nsGkAtoms::onhashchange
, NS_HASHCHANGE
, EventNameType_HTMLXUL
, NS_EVENT
},
569 { nsGkAtoms::onreadystatechange
, NS_READYSTATECHANGE
, EventNameType_HTMLXUL
},
570 { nsGkAtoms::onbeforeunload
, NS_BEFORE_PAGE_UNLOAD
, EventNameType_HTMLXUL
, NS_EVENT
},
571 { nsGkAtoms::onabort
, NS_IMAGE_ABORT
,
572 (EventNameType_HTMLXUL
| EventNameType_SVGSVG
), NS_EVENT
},
573 { nsGkAtoms::onerror
, NS_LOAD_ERROR
,
574 (EventNameType_HTMLXUL
| EventNameType_SVGSVG
), NS_EVENT
},
575 { nsGkAtoms::onbeforescriptexecute
, NS_BEFORE_SCRIPT_EXECUTE
, EventNameType_HTMLXUL
, NS_EVENT
},
576 { nsGkAtoms::onafterscriptexecute
, NS_AFTER_SCRIPT_EXECUTE
, EventNameType_HTMLXUL
, NS_EVENT
},
578 { nsGkAtoms::onDOMAttrModified
, NS_MUTATION_ATTRMODIFIED
, EventNameType_HTMLXUL
, NS_MUTATION_EVENT
},
579 { nsGkAtoms::onDOMCharacterDataModified
, NS_MUTATION_CHARACTERDATAMODIFIED
, EventNameType_HTMLXUL
, NS_MUTATION_EVENT
},
580 { nsGkAtoms::onDOMNodeInserted
, NS_MUTATION_NODEINSERTED
, EventNameType_HTMLXUL
, NS_MUTATION_EVENT
},
581 { nsGkAtoms::onDOMNodeRemoved
, NS_MUTATION_NODEREMOVED
, EventNameType_HTMLXUL
, NS_MUTATION_EVENT
},
582 { nsGkAtoms::onDOMNodeInsertedIntoDocument
, NS_MUTATION_NODEINSERTEDINTODOCUMENT
, EventNameType_HTMLXUL
, NS_MUTATION_EVENT
},
583 { nsGkAtoms::onDOMNodeRemovedFromDocument
, NS_MUTATION_NODEREMOVEDFROMDOCUMENT
, EventNameType_HTMLXUL
, NS_MUTATION_EVENT
},
584 { nsGkAtoms::onDOMSubtreeModified
, NS_MUTATION_SUBTREEMODIFIED
, EventNameType_HTMLXUL
, NS_MUTATION_EVENT
},
586 { nsGkAtoms::onDOMActivate
, NS_UI_ACTIVATE
, EventNameType_HTMLXUL
, NS_UI_EVENT
},
587 { nsGkAtoms::onDOMFocusIn
, NS_UI_FOCUSIN
, EventNameType_HTMLXUL
, NS_UI_EVENT
},
588 { nsGkAtoms::onDOMFocusOut
, NS_UI_FOCUSOUT
, EventNameType_HTMLXUL
, NS_UI_EVENT
},
589 { nsGkAtoms::oninput
, NS_FORM_INPUT
, EventNameType_HTMLXUL
, NS_UI_EVENT
},
591 { nsGkAtoms::onDOMMouseScroll
, NS_MOUSE_SCROLL
, EventNameType_HTMLXUL
, NS_MOUSE_SCROLL_EVENT
},
592 { nsGkAtoms::onMozMousePixelScroll
, NS_MOUSE_PIXEL_SCROLL
, EventNameType_HTMLXUL
, NS_MOUSE_SCROLL_EVENT
},
594 { nsGkAtoms::onpageshow
, NS_PAGE_SHOW
, EventNameType_HTML
, NS_EVENT
},
595 { nsGkAtoms::onpagehide
, NS_PAGE_HIDE
, EventNameType_HTML
, NS_EVENT
},
596 { nsGkAtoms::onMozBeforeResize
, NS_BEFORERESIZE_EVENT
, EventNameType_None
, NS_EVENT
},
597 { nsGkAtoms::onresize
, NS_RESIZE_EVENT
,
598 (EventNameType_HTMLXUL
| EventNameType_SVGSVG
), NS_EVENT
},
599 { nsGkAtoms::onscroll
, NS_SCROLL_EVENT
,
600 (EventNameType_HTMLXUL
| EventNameType_SVGSVG
), NS_EVENT_NULL
},
601 { nsGkAtoms::oncopy
, NS_COPY
, EventNameType_HTMLXUL
, NS_EVENT
},
602 { nsGkAtoms::oncut
, NS_CUT
, EventNameType_HTMLXUL
, NS_EVENT
},
603 { nsGkAtoms::onpaste
, NS_PASTE
, EventNameType_HTMLXUL
, NS_EVENT
},
604 // XUL specific events
605 { nsGkAtoms::ontext
, NS_TEXT_TEXT
, EventNameType_XUL
, NS_EVENT_NULL
},
607 { nsGkAtoms::oncompositionstart
, NS_COMPOSITION_START
, EventNameType_XUL
, NS_COMPOSITION_EVENT
},
608 { nsGkAtoms::oncompositionend
, NS_COMPOSITION_END
, EventNameType_XUL
, NS_COMPOSITION_EVENT
},
610 { nsGkAtoms::oncommand
, NS_XUL_COMMAND
, EventNameType_XUL
, NS_INPUT_EVENT
},
612 { nsGkAtoms::onclose
, NS_XUL_CLOSE
, EventNameType_XUL
, NS_EVENT_NULL
},
613 { nsGkAtoms::onpopupshowing
, NS_XUL_POPUP_SHOWING
, EventNameType_XUL
, NS_EVENT_NULL
},
614 { nsGkAtoms::onpopupshown
, NS_XUL_POPUP_SHOWN
, EventNameType_XUL
, NS_EVENT_NULL
},
615 { nsGkAtoms::onpopuphiding
, NS_XUL_POPUP_HIDING
, EventNameType_XUL
, NS_EVENT_NULL
},
616 { nsGkAtoms::onpopuphidden
, NS_XUL_POPUP_HIDDEN
, EventNameType_XUL
, NS_EVENT_NULL
},
617 { nsGkAtoms::onbroadcast
, NS_XUL_BROADCAST
, EventNameType_XUL
, NS_EVENT_NULL
},
618 { nsGkAtoms::oncommandupdate
, NS_XUL_COMMAND_UPDATE
, EventNameType_XUL
, NS_EVENT_NULL
},
620 { nsGkAtoms::ondragenter
, NS_DRAGDROP_ENTER
, EventNameType_HTMLXUL
, NS_DRAG_EVENT
},
621 { nsGkAtoms::ondragover
, NS_DRAGDROP_OVER_SYNTH
, EventNameType_HTMLXUL
, NS_DRAG_EVENT
},
622 { nsGkAtoms::ondragexit
, NS_DRAGDROP_EXIT_SYNTH
, EventNameType_XUL
, NS_DRAG_EVENT
},
623 { nsGkAtoms::ondragdrop
, NS_DRAGDROP_DRAGDROP
, EventNameType_XUL
, NS_DRAG_EVENT
},
624 { nsGkAtoms::ondraggesture
, NS_DRAGDROP_GESTURE
, EventNameType_XUL
, NS_DRAG_EVENT
},
625 { nsGkAtoms::ondrag
, NS_DRAGDROP_DRAG
, EventNameType_HTMLXUL
, NS_DRAG_EVENT
},
626 { nsGkAtoms::ondragend
, NS_DRAGDROP_END
, EventNameType_HTMLXUL
, NS_DRAG_EVENT
},
627 { nsGkAtoms::ondragstart
, NS_DRAGDROP_START
, EventNameType_HTMLXUL
, NS_DRAG_EVENT
},
628 { nsGkAtoms::ondragleave
, NS_DRAGDROP_LEAVE_SYNTH
, EventNameType_HTMLXUL
, NS_DRAG_EVENT
},
629 { nsGkAtoms::ondrop
, NS_DRAGDROP_DROP
, EventNameType_HTMLXUL
, NS_DRAG_EVENT
},
631 { nsGkAtoms::onoverflow
, NS_SCROLLPORT_OVERFLOW
, EventNameType_XUL
, NS_EVENT_NULL
},
632 { nsGkAtoms::onunderflow
, NS_SCROLLPORT_UNDERFLOW
, EventNameType_XUL
, NS_EVENT_NULL
},
634 { nsGkAtoms::onSVGLoad
, NS_SVG_LOAD
, EventNameType_None
, NS_SVG_EVENT
},
635 { nsGkAtoms::onSVGUnload
, NS_SVG_UNLOAD
, EventNameType_None
, NS_SVG_EVENT
},
636 { nsGkAtoms::onSVGAbort
, NS_SVG_ABORT
, EventNameType_None
, NS_SVG_EVENT
},
637 { nsGkAtoms::onSVGError
, NS_SVG_ERROR
, EventNameType_None
, NS_SVG_EVENT
},
638 { nsGkAtoms::onSVGResize
, NS_SVG_RESIZE
, EventNameType_None
, NS_SVG_EVENT
},
639 { nsGkAtoms::onSVGScroll
, NS_SVG_SCROLL
, EventNameType_None
, NS_SVG_EVENT
},
641 { nsGkAtoms::onSVGZoom
, NS_SVG_ZOOM
, EventNameType_None
, NS_SVGZOOM_EVENT
},
643 // This is a bit hackish, but SVG's event names are weird.
644 { nsGkAtoms::onzoom
, NS_SVG_ZOOM
, EventNameType_SVGSVG
, NS_EVENT_NULL
},
647 { nsGkAtoms::onbegin
, NS_SMIL_BEGIN
, EventNameType_SMIL
, NS_EVENT_NULL
},
648 { nsGkAtoms::onbeginEvent
, NS_SMIL_BEGIN
, EventNameType_None
, NS_SMIL_TIME_EVENT
},
649 { nsGkAtoms::onend
, NS_SMIL_END
, EventNameType_SMIL
, NS_EVENT_NULL
},
650 { nsGkAtoms::onendEvent
, NS_SMIL_END
, EventNameType_None
, NS_SMIL_TIME_EVENT
},
651 { nsGkAtoms::onrepeat
, NS_SMIL_REPEAT
, EventNameType_SMIL
, NS_EVENT_NULL
},
652 { nsGkAtoms::onrepeatEvent
, NS_SMIL_REPEAT
, EventNameType_None
, NS_SMIL_TIME_EVENT
},
655 { nsGkAtoms::onloadstart
, NS_LOADSTART
, EventNameType_HTML
, NS_EVENT_NULL
},
656 { nsGkAtoms::onprogress
, NS_PROGRESS
, EventNameType_HTML
, NS_EVENT_NULL
},
657 { nsGkAtoms::onsuspend
, NS_SUSPEND
, EventNameType_HTML
, NS_EVENT_NULL
},
658 { nsGkAtoms::onemptied
, NS_EMPTIED
, EventNameType_HTML
, NS_EVENT_NULL
},
659 { nsGkAtoms::onstalled
, NS_STALLED
, EventNameType_HTML
, NS_EVENT_NULL
},
660 { nsGkAtoms::onplay
, NS_PLAY
, EventNameType_HTML
, NS_EVENT_NULL
},
661 { nsGkAtoms::onpause
, NS_PAUSE
, EventNameType_HTML
, NS_EVENT_NULL
},
662 { nsGkAtoms::onloadedmetadata
, NS_LOADEDMETADATA
, EventNameType_HTML
, NS_EVENT_NULL
},
663 { nsGkAtoms::onloadeddata
, NS_LOADEDDATA
, EventNameType_HTML
, NS_EVENT_NULL
},
664 { nsGkAtoms::onwaiting
, NS_WAITING
, EventNameType_HTML
, NS_EVENT_NULL
},
665 { nsGkAtoms::onplaying
, NS_PLAYING
, EventNameType_HTML
, NS_EVENT_NULL
},
666 { nsGkAtoms::oncanplay
, NS_CANPLAY
, EventNameType_HTML
, NS_EVENT_NULL
},
667 { nsGkAtoms::oncanplaythrough
, NS_CANPLAYTHROUGH
, EventNameType_HTML
, NS_EVENT_NULL
},
668 { nsGkAtoms::onseeking
, NS_SEEKING
, EventNameType_HTML
, NS_EVENT_NULL
},
669 { nsGkAtoms::onseeked
, NS_SEEKED
, EventNameType_HTML
, NS_EVENT_NULL
},
670 { nsGkAtoms::ontimeupdate
, NS_TIMEUPDATE
, EventNameType_HTML
, NS_EVENT_NULL
},
671 { nsGkAtoms::onended
, NS_ENDED
, EventNameType_HTML
, NS_EVENT_NULL
},
672 { nsGkAtoms::onratechange
, NS_RATECHANGE
, EventNameType_HTML
, NS_EVENT_NULL
},
673 { nsGkAtoms::ondurationchange
, NS_DURATIONCHANGE
, EventNameType_HTML
, NS_EVENT_NULL
},
674 { nsGkAtoms::onvolumechange
, NS_VOLUMECHANGE
, EventNameType_HTML
, NS_EVENT_NULL
},
675 { nsGkAtoms::onMozAudioAvailable
, NS_MOZAUDIOAVAILABLE
, EventNameType_None
, NS_EVENT_NULL
},
677 { nsGkAtoms::onMozAfterPaint
, NS_AFTERPAINT
, EventNameType_None
, NS_EVENT
},
678 { nsGkAtoms::onMozBeforePaint
, NS_BEFOREPAINT
, EventNameType_None
, NS_EVENT_NULL
},
680 { nsGkAtoms::onMozScrolledAreaChanged
, NS_SCROLLEDAREACHANGED
, EventNameType_None
, NS_SCROLLAREA_EVENT
},
682 // Simple gesture events
683 { nsGkAtoms::onMozSwipeGesture
, NS_SIMPLE_GESTURE_SWIPE
, EventNameType_None
, NS_SIMPLE_GESTURE_EVENT
},
684 { nsGkAtoms::onMozMagnifyGestureStart
, NS_SIMPLE_GESTURE_MAGNIFY_START
, EventNameType_None
, NS_SIMPLE_GESTURE_EVENT
},
685 { nsGkAtoms::onMozMagnifyGestureUpdate
, NS_SIMPLE_GESTURE_MAGNIFY_UPDATE
, EventNameType_None
, NS_SIMPLE_GESTURE_EVENT
},
686 { nsGkAtoms::onMozMagnifyGesture
, NS_SIMPLE_GESTURE_MAGNIFY
, EventNameType_None
, NS_SIMPLE_GESTURE_EVENT
},
687 { nsGkAtoms::onMozRotateGestureStart
, NS_SIMPLE_GESTURE_ROTATE_START
, EventNameType_None
, NS_SIMPLE_GESTURE_EVENT
},
688 { nsGkAtoms::onMozRotateGestureUpdate
, NS_SIMPLE_GESTURE_ROTATE_UPDATE
, EventNameType_None
, NS_SIMPLE_GESTURE_EVENT
},
689 { nsGkAtoms::onMozRotateGesture
, NS_SIMPLE_GESTURE_ROTATE
, EventNameType_None
, NS_SIMPLE_GESTURE_EVENT
},
690 { nsGkAtoms::onMozTapGesture
, NS_SIMPLE_GESTURE_TAP
, EventNameType_None
, NS_SIMPLE_GESTURE_EVENT
},
691 { nsGkAtoms::onMozPressTapGesture
, NS_SIMPLE_GESTURE_PRESSTAP
, EventNameType_None
, NS_SIMPLE_GESTURE_EVENT
},
693 { nsGkAtoms::onMozTouchDown
, NS_MOZTOUCH_DOWN
, EventNameType_None
, NS_MOZTOUCH_EVENT
},
694 { nsGkAtoms::onMozTouchMove
, NS_MOZTOUCH_MOVE
, EventNameType_None
, NS_MOZTOUCH_EVENT
},
695 { nsGkAtoms::onMozTouchUp
, NS_MOZTOUCH_UP
, EventNameType_None
, NS_MOZTOUCH_EVENT
},
697 { nsGkAtoms::ontransitionend
, NS_TRANSITION_END
, EventNameType_None
, NS_TRANSITION_EVENT
}
700 sAtomEventTable
= new nsDataHashtable
<nsISupportsHashKey
, EventNameMapping
>;
701 sStringEventTable
= new nsDataHashtable
<nsStringHashKey
, EventNameMapping
>;
702 sUserDefinedEvents
= new nsCOMArray
<nsIAtom
>(64);
704 if (!sAtomEventTable
|| !sStringEventTable
|| !sUserDefinedEvents
||
705 !sAtomEventTable
->Init(int(NS_ARRAY_LENGTH(eventArray
) / 0.75) + 1) ||
706 !sStringEventTable
->Init(int(NS_ARRAY_LENGTH(eventArray
) / 0.75) + 1)) {
707 delete sAtomEventTable
;
708 sAtomEventTable
= nsnull
;
709 delete sStringEventTable
;
710 sStringEventTable
= nsnull
;
711 delete sUserDefinedEvents
;
712 sUserDefinedEvents
= nsnull
;
716 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(eventArray
); ++i
) {
717 if (!sAtomEventTable
->Put(eventArray
[i
].mAtom
, eventArray
[i
]) ||
718 !sStringEventTable
->Put(Substring(nsDependentAtomString(eventArray
[i
].mAtom
), 2),
720 delete sAtomEventTable
;
721 sAtomEventTable
= nsnull
;
722 delete sStringEventTable
;
723 sStringEventTable
= nsnull
;
732 * Access a cached parser service. Don't addref. We need only one
733 * reference to it and this class has that one.
737 nsContentUtils::GetParserService()
739 // XXX: This isn't accessed from several threads, is it?
740 if (!sParserService
) {
741 // Lock, recheck sCachedParserService and aquire if this should be
742 // safe for multiple threads.
743 nsresult rv
= CallGetService(kParserServiceCID
, &sParserService
);
745 sParserService
= nsnull
;
749 return sParserService
;
754 nsContentUtils::GetXTFService()
757 nsresult rv
= CallGetService(kXTFServiceCID
, &sXTFService
);
759 sXTFService
= nsnull
;
769 nsContentUtils::GetBidiKeyboard()
771 if (!sBidiKeyboard
) {
772 nsresult rv
= CallGetService("@mozilla.org/widget/bidikeyboard;1", &sBidiKeyboard
);
774 sBidiKeyboard
= nsnull
;
777 return sBidiKeyboard
;
781 template <class OutputIterator
>
782 struct NormalizeNewlinesCharTraits
{
784 typedef typename
OutputIterator::value_type value_type
;
787 NormalizeNewlinesCharTraits(OutputIterator
& aIterator
) : mIterator(aIterator
) { }
788 void writechar(typename
OutputIterator::value_type aChar
) {
789 *mIterator
++ = aChar
;
793 OutputIterator mIterator
;
796 #ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
798 template <class CharT
>
799 struct NormalizeNewlinesCharTraits
<CharT
*> {
801 typedef CharT value_type
;
804 NormalizeNewlinesCharTraits(CharT
* aCharPtr
) : mCharPtr(aCharPtr
) { }
805 void writechar(CharT aChar
) {
815 NS_SPECIALIZE_TEMPLATE
816 struct NormalizeNewlinesCharTraits
<char*> {
818 typedef char value_type
;
821 NormalizeNewlinesCharTraits(char* aCharPtr
) : mCharPtr(aCharPtr
) { }
822 void writechar(char aChar
) {
830 NS_SPECIALIZE_TEMPLATE
831 struct NormalizeNewlinesCharTraits
<PRUnichar
*> {
833 typedef PRUnichar value_type
;
836 NormalizeNewlinesCharTraits(PRUnichar
* aCharPtr
) : mCharPtr(aCharPtr
) { }
837 void writechar(PRUnichar aChar
) {
847 template <class OutputIterator
>
848 class CopyNormalizeNewlines
851 typedef typename
OutputIterator::value_type value_type
;
854 CopyNormalizeNewlines(OutputIterator
* aDestination
,
855 PRBool aLastCharCR
=PR_FALSE
) :
856 mLastCharCR(aLastCharCR
),
857 mDestination(aDestination
),
861 PRUint32
GetCharsWritten() {
865 PRBool
IsLastCharCR() {
869 void write(const typename
OutputIterator::value_type
* aSource
, PRUint32 aSourceLength
) {
871 const typename
OutputIterator::value_type
* done_writing
= aSource
+ aSourceLength
;
873 // If the last source buffer ended with a CR...
875 // ..and if the next one is a LF, then skip it since
876 // we've already written out a newline
877 if (aSourceLength
&& (*aSource
== value_type('\n'))) {
880 mLastCharCR
= PR_FALSE
;
883 PRUint32 num_written
= 0;
884 while ( aSource
< done_writing
) {
885 if (*aSource
== value_type('\r')) {
886 mDestination
->writechar('\n');
888 // If we've reached the end of the buffer, record
889 // that we wrote out a CR
890 if (aSource
== done_writing
) {
891 mLastCharCR
= PR_TRUE
;
893 // If the next character is a LF, skip it
894 else if (*aSource
== value_type('\n')) {
899 mDestination
->writechar(*aSource
++);
904 mWritten
+= num_written
;
909 OutputIterator
* mDestination
;
915 nsContentUtils::CopyNewlineNormalizedUnicodeTo(const nsAString
& aSource
,
921 typedef NormalizeNewlinesCharTraits
<PRUnichar
*> sink_traits
;
923 sink_traits
dest_traits(aDest
);
924 CopyNormalizeNewlines
<sink_traits
> normalizer(&dest_traits
,aLastCharCR
);
925 nsReadingIterator
<PRUnichar
> fromBegin
, fromEnd
;
926 copy_string(aSource
.BeginReading(fromBegin
).advance( PRInt32(aSrcOffset
) ),
927 aSource
.BeginReading(fromEnd
).advance( PRInt32(aSrcOffset
+aLength
) ),
929 aLastCharCR
= normalizer
.IsLastCharCR();
930 return normalizer
.GetCharsWritten();
935 nsContentUtils::CopyNewlineNormalizedUnicodeTo(nsReadingIterator
<PRUnichar
>& aSrcStart
, const nsReadingIterator
<PRUnichar
>& aSrcEnd
, nsAString
& aDest
)
937 typedef nsWritingIterator
<PRUnichar
> WritingIterator
;
938 typedef NormalizeNewlinesCharTraits
<WritingIterator
> sink_traits
;
940 WritingIterator iter
;
941 aDest
.BeginWriting(iter
);
942 sink_traits
dest_traits(iter
);
943 CopyNormalizeNewlines
<sink_traits
> normalizer(&dest_traits
);
944 copy_string(aSrcStart
, aSrcEnd
, normalizer
);
945 return normalizer
.GetCharsWritten();
948 // Replaced by precompiled CCMap (see bug 180266). To update the list
949 // of characters, see one of files included below. As for the way
950 // the original list of characters was obtained by Frank Tang, see bug 54467.
951 // Updated to fix the regression (bug 263411). The list contains
952 // characters of the following Unicode character classes : Ps, Pi, Po, Pf, Pe.
953 // (ref.: http://www.w3.org/TR/2004/CR-CSS21-20040225/selector.html#first-letter)
954 #include "punct_marks.x-ccmap"
955 DEFINE_X_CCMAP(gPuncCharsCCMapExt
, const);
959 nsContentUtils::IsPunctuationMark(PRUint32 aChar
)
961 return CCMAP_HAS_CHAR_EXT(gPuncCharsCCMapExt
, aChar
);
966 nsContentUtils::IsPunctuationMarkAt(const nsTextFragment
* aFrag
, PRUint32 aOffset
)
968 PRUnichar h
= aFrag
->CharAt(aOffset
);
969 if (!IS_SURROGATE(h
)) {
970 return IsPunctuationMark(h
);
972 if (NS_IS_HIGH_SURROGATE(h
) && aOffset
+ 1 < aFrag
->GetLength()) {
973 PRUnichar l
= aFrag
->CharAt(aOffset
+ 1);
974 if (NS_IS_LOW_SURROGATE(l
)) {
975 return IsPunctuationMark(SURROGATE_TO_UCS4(h
, l
));
982 PRBool
nsContentUtils::IsAlphanumeric(PRUint32 aChar
)
984 nsIUGenCategory::nsUGenCategory cat
= sGenCat
->Get(aChar
);
986 return (cat
== nsIUGenCategory::kLetter
|| cat
== nsIUGenCategory::kNumber
);
990 PRBool
nsContentUtils::IsAlphanumericAt(const nsTextFragment
* aFrag
, PRUint32 aOffset
)
992 PRUnichar h
= aFrag
->CharAt(aOffset
);
993 if (!IS_SURROGATE(h
)) {
994 return IsAlphanumeric(h
);
996 if (NS_IS_HIGH_SURROGATE(h
) && aOffset
+ 1 < aFrag
->GetLength()) {
997 PRUnichar l
= aFrag
->CharAt(aOffset
+ 1);
998 if (NS_IS_LOW_SURROGATE(l
)) {
999 return IsAlphanumeric(SURROGATE_TO_UCS4(h
, l
));
1007 nsContentUtils::IsHTMLWhitespace(PRUnichar aChar
)
1009 return aChar
== PRUnichar(0x0009) ||
1010 aChar
== PRUnichar(0x000A) ||
1011 aChar
== PRUnichar(0x000C) ||
1012 aChar
== PRUnichar(0x000D) ||
1013 aChar
== PRUnichar(0x0020);
1018 nsContentUtils::ParseIntMarginValue(const nsAString
& aString
, nsIntMargin
& result
)
1020 nsAutoString
marginStr(aString
);
1021 marginStr
.CompressWhitespace(PR_TRUE
, PR_TRUE
);
1022 if (marginStr
.IsEmpty()) {
1026 PRInt32 start
= 0, end
= 0;
1027 for (int count
= 0; count
< 4; count
++) {
1028 if ((PRUint32
)end
>= marginStr
.Length())
1031 // top, right, bottom, left
1033 end
= Substring(marginStr
, start
).FindChar(',');
1035 end
= Substring(marginStr
, start
).Length();
1041 nsString(Substring(marginStr
, start
, end
)).ToInteger(&ec
);
1053 result
.bottom
= val
;
1066 nsContentUtils::GetOfflineAppManifest(nsIDocument
*aDocument
, nsIURI
**aURI
)
1068 Element
* docElement
= aDocument
->GetRootElement();
1073 nsAutoString manifestSpec
;
1074 docElement
->GetAttr(kNameSpaceID_None
, nsGkAtoms::manifest
, manifestSpec
);
1076 // Manifest URIs can't have fragment identifiers.
1077 if (manifestSpec
.IsEmpty() ||
1078 manifestSpec
.FindChar('#') != kNotFound
) {
1082 nsContentUtils::NewURIWithDocumentCharset(aURI
, manifestSpec
,
1084 aDocument
->GetDocBaseURI());
1089 nsContentUtils::OfflineAppAllowed(nsIURI
*aURI
)
1091 nsCOMPtr
<nsIOfflineCacheUpdateService
> updateService
=
1092 do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID
);
1093 if (!updateService
) {
1098 nsresult rv
= updateService
->OfflineAppAllowedForURI(aURI
,
1101 return NS_SUCCEEDED(rv
) && allowed
;
1106 nsContentUtils::OfflineAppAllowed(nsIPrincipal
*aPrincipal
)
1108 nsCOMPtr
<nsIOfflineCacheUpdateService
> updateService
=
1109 do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID
);
1110 if (!updateService
) {
1115 nsresult rv
= updateService
->OfflineAppAllowed(aPrincipal
,
1118 return NS_SUCCEEDED(rv
) && allowed
;
1123 nsContentUtils::Shutdown()
1125 sInitialized
= PR_FALSE
;
1127 NS_HTMLParanoidFragmentSinkShutdown();
1128 NS_XHTMLParanoidFragmentSinkShutdown();
1130 NS_IF_RELEASE(sContentPolicyService
);
1131 sTriedToGetContentPolicy
= PR_FALSE
;
1133 for (i
= 0; i
< PropertiesFile_COUNT
; ++i
)
1134 NS_IF_RELEASE(sStringBundles
[i
]);
1136 // Clean up c-style's observer
1137 if (sPrefCallbackTable
) {
1138 delete sPrefCallbackTable
;
1139 sPrefCallbackTable
= nsnull
;
1142 delete sPrefCacheData
;
1143 sPrefCacheData
= nsnull
;
1145 NS_IF_RELEASE(sStringBundleService
);
1146 NS_IF_RELEASE(sConsoleService
);
1147 NS_IF_RELEASE(sDOMScriptObjectFactory
);
1148 sXPConnect
= nsnull
;
1149 sThreadJSContextStack
= nsnull
;
1150 NS_IF_RELEASE(sSecurityManager
);
1151 NS_IF_RELEASE(sNameSpaceManager
);
1152 NS_IF_RELEASE(sParserService
);
1153 NS_IF_RELEASE(sIOService
);
1154 NS_IF_RELEASE(sLineBreaker
);
1155 NS_IF_RELEASE(sWordBreaker
);
1156 NS_IF_RELEASE(sGenCat
);
1158 NS_IF_RELEASE(sXTFService
);
1160 NS_IF_RELEASE(sImgLoader
);
1161 NS_IF_RELEASE(sImgCache
);
1162 NS_IF_RELEASE(sHistory
);
1163 NS_IF_RELEASE(sPrefBranch
);
1165 NS_IF_RELEASE(sBidiKeyboard
);
1168 delete sAtomEventTable
;
1169 sAtomEventTable
= nsnull
;
1170 delete sStringEventTable
;
1171 sStringEventTable
= nsnull
;
1172 delete sUserDefinedEvents
;
1173 sUserDefinedEvents
= nsnull
;
1175 if (sPtrsToPtrsToRelease
) {
1176 for (i
= 0; i
< sPtrsToPtrsToRelease
->Length(); ++i
) {
1177 nsISupports
** ptrToPtr
= sPtrsToPtrsToRelease
->ElementAt(i
);
1178 NS_RELEASE(*ptrToPtr
);
1180 delete sPtrsToPtrsToRelease
;
1181 sPtrsToPtrsToRelease
= nsnull
;
1184 if (sEventListenerManagersHash
.ops
) {
1185 NS_ASSERTION(sEventListenerManagersHash
.entryCount
== 0,
1186 "Event listener manager hash not empty at shutdown!");
1188 // See comment above.
1190 // However, we have to handle this table differently. If it still
1191 // has entries, we want to leak it too, so that we can keep it alive
1192 // in case any elements are destroyed. Because if they are, we need
1193 // their event listener managers to be destroyed too, or otherwise
1194 // it could leave dangling references in DOMClassInfo's preserved
1197 if (sEventListenerManagersHash
.entryCount
== 0) {
1198 PL_DHashTableFinish(&sEventListenerManagersHash
);
1199 sEventListenerManagersHash
.ops
= nsnull
;
1203 NS_ASSERTION(!sBlockedScriptRunners
||
1204 sBlockedScriptRunners
->Count() == 0,
1205 "How'd this happen?");
1206 delete sBlockedScriptRunners
;
1207 sBlockedScriptRunners
= nsnull
;
1209 NS_IF_RELEASE(sSameOriginChecker
);
1211 nsTextEditorState::ShutDown();
1216 nsContentUtils::IsCallerTrustedForCapability(const char* aCapability
)
1218 // The secman really should handle UniversalXPConnect case, since that
1219 // should include UniversalBrowserRead... doesn't right now, though.
1221 if (NS_FAILED(sSecurityManager
->IsCapabilityEnabled(aCapability
, &hasCap
)))
1226 if (NS_FAILED(sSecurityManager
->IsCapabilityEnabled("UniversalXPConnect",
1233 * Checks whether two nodes come from the same origin. aTrustedNode is
1234 * considered 'safe' in that a user can operate on it and that it isn't
1235 * a js-object that implements nsIDOMNode.
1236 * Never call this function with the first node provided by script, it
1237 * must always be known to be a 'real' node!
1241 nsContentUtils::CheckSameOrigin(nsINode
*aTrustedNode
,
1242 nsIDOMNode
*aUnTrustedNode
)
1244 NS_PRECONDITION(aTrustedNode
, "There must be a trusted node");
1246 PRBool isSystem
= PR_FALSE
;
1247 sSecurityManager
->SubjectPrincipalIsSystem(&isSystem
);
1249 // we're running as system, grant access to the node.
1255 * Get hold of each node's principal
1257 nsCOMPtr
<nsINode
> unTrustedNode
= do_QueryInterface(aUnTrustedNode
);
1259 // Make sure these are both real nodes
1260 NS_ENSURE_TRUE(aTrustedNode
&& unTrustedNode
, NS_ERROR_UNEXPECTED
);
1262 nsIPrincipal
* trustedPrincipal
= aTrustedNode
->NodePrincipal();
1263 nsIPrincipal
* unTrustedPrincipal
= unTrustedNode
->NodePrincipal();
1265 if (trustedPrincipal
== unTrustedPrincipal
) {
1270 // XXXbz should we actually have a Subsumes() check here instead? Or perhaps
1271 // a separate method for that, with callers using one or the other?
1272 if (NS_FAILED(trustedPrincipal
->Equals(unTrustedPrincipal
, &equal
)) ||
1274 return NS_ERROR_DOM_PROP_ACCESS_DENIED
;
1282 nsContentUtils::CanCallerAccess(nsIPrincipal
* aSubjectPrincipal
,
1283 nsIPrincipal
* aPrincipal
)
1286 nsresult rv
= aSubjectPrincipal
->Subsumes(aPrincipal
, &subsumes
);
1287 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
1293 // The subject doesn't subsume aPrincipal. Allow access only if the subject
1294 // has either "UniversalXPConnect" (if aPrincipal is system principal) or
1295 // "UniversalBrowserRead" (in all other cases).
1297 rv
= sSecurityManager
->IsSystemPrincipal(aPrincipal
, &isSystem
);
1298 isSystem
= NS_FAILED(rv
) || isSystem
;
1299 const char* capability
=
1300 NS_FAILED(rv
) || isSystem
? "UniversalXPConnect" : "UniversalBrowserRead";
1302 return IsCallerTrustedForCapability(capability
);
1307 nsContentUtils::CanCallerAccess(nsIDOMNode
*aNode
)
1309 // XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
1310 // with the system principal games? But really, there should be a simpler
1311 // API here, dammit.
1312 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
1313 sSecurityManager
->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
1315 if (!subjectPrincipal
) {
1316 // we're running as system, grant access to the node.
1321 nsCOMPtr
<nsINode
> node
= do_QueryInterface(aNode
);
1322 NS_ENSURE_TRUE(node
, PR_FALSE
);
1324 return CanCallerAccess(subjectPrincipal
, node
->NodePrincipal());
1329 nsContentUtils::CanCallerAccess(nsPIDOMWindow
* aWindow
)
1331 // XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
1332 // with the system principal games? But really, there should be a simpler
1333 // API here, dammit.
1334 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
1335 sSecurityManager
->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
1337 if (!subjectPrincipal
) {
1338 // we're running as system, grant access to the node.
1343 nsCOMPtr
<nsIScriptObjectPrincipal
> scriptObject
=
1344 do_QueryInterface(aWindow
->IsOuterWindow() ?
1345 aWindow
->GetCurrentInnerWindow() : aWindow
);
1346 NS_ENSURE_TRUE(scriptObject
, PR_FALSE
);
1348 return CanCallerAccess(subjectPrincipal
, scriptObject
->GetPrincipal());
1353 nsContentUtils::InProlog(nsINode
*aNode
)
1355 NS_PRECONDITION(aNode
, "missing node to nsContentUtils::InProlog");
1357 nsINode
* parent
= aNode
->GetNodeParent();
1358 if (!parent
|| !parent
->IsNodeOfType(nsINode::eDOCUMENT
)) {
1362 nsIDocument
* doc
= static_cast<nsIDocument
*>(parent
);
1363 nsIContent
* root
= doc
->GetRootElement();
1365 return !root
|| doc
->IndexOf(aNode
) < doc
->IndexOf(root
);
1369 GetContextFromDocument(nsIDocument
*aDocument
)
1371 nsIScriptGlobalObject
*sgo
= aDocument
->GetScopeObject();
1373 // No script global, no context.
1377 nsIScriptContext
*scx
= sgo
->GetContext();
1379 // No context left in the scope...
1384 return (JSContext
*)scx
->GetNativeContext();
1389 nsContentUtils::GetContextAndScope(nsIDocument
*aOldDocument
,
1390 nsIDocument
*aNewDocument
, JSContext
**aCx
,
1391 JSObject
**aNewScope
)
1394 *aNewScope
= nsnull
;
1396 JSObject
*newScope
= aNewDocument
->GetWrapper();
1399 nsIScriptGlobalObject
*newSGO
= aNewDocument
->GetScopeObject();
1400 if (!newSGO
|| !(global
= newSGO
->GetGlobalJSObject())) {
1405 NS_ENSURE_TRUE(sXPConnect
, NS_ERROR_NOT_INITIALIZED
);
1407 JSContext
*cx
= aOldDocument
? GetContextFromDocument(aOldDocument
) : nsnull
;
1409 cx
= GetContextFromDocument(aNewDocument
);
1412 // No context reachable from the old or new document, use the
1413 // calling context, or the safe context if no caller can be
1416 sThreadJSContextStack
->Peek(&cx
);
1419 sThreadJSContextStack
->GetSafeJSContext(&cx
);
1422 // No safe context reachable, bail.
1423 NS_WARNING("No context reachable in GetContextAndScopes()!");
1425 return NS_ERROR_NOT_AVAILABLE
;
1431 if (!newScope
&& cx
) {
1433 nsresult rv
= WrapNative(cx
, global
, aNewDocument
, aNewDocument
, &v
);
1434 NS_ENSURE_SUCCESS(rv
, rv
);
1436 newScope
= JSVAL_TO_OBJECT(v
);
1440 *aNewScope
= newScope
;
1446 nsContentUtils::ReparentContentWrappersInScope(nsIScriptGlobalObject
*aOldScope
,
1447 nsIScriptGlobalObject
*aNewScope
)
1449 JSContext
*cx
= nsnull
;
1451 // Try really hard to find a context to work on.
1452 nsIScriptContext
*context
= aOldScope
->GetContext();
1454 cx
= static_cast<JSContext
*>(context
->GetNativeContext());
1458 context
= aNewScope
->GetContext();
1460 cx
= static_cast<JSContext
*>(context
->GetNativeContext());
1464 sThreadJSContextStack
->Peek(&cx
);
1467 sThreadJSContextStack
->GetSafeJSContext(&cx
);
1470 // Wow, this is really bad!
1471 NS_WARNING("No context reachable in ReparentContentWrappers()!");
1473 return NS_ERROR_NOT_AVAILABLE
;
1479 // Now that we have a context, let's get the global objects from the two
1480 // scopes and ask XPConnect to do the rest of the work.
1482 JSObject
*oldScopeObj
= aOldScope
->GetGlobalJSObject();
1483 JSObject
*newScopeObj
= aNewScope
->GetGlobalJSObject();
1485 if (!newScopeObj
|| !oldScopeObj
) {
1486 // We can't really do anything without the JSObjects.
1488 return NS_ERROR_NOT_AVAILABLE
;
1491 return sXPConnect
->MoveWrappers(cx
, oldScopeObj
, newScopeObj
);
1495 nsContentUtils::GetDocShellFromCaller()
1497 JSContext
*cx
= nsnull
;
1498 sThreadJSContextStack
->Peek(&cx
);
1501 nsIScriptGlobalObject
*sgo
= nsJSUtils::GetDynamicScriptGlobal(cx
);
1502 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(sgo
));
1505 return win
->GetDocShell();
1513 nsContentUtils::GetWindowFromCaller()
1515 JSContext
*cx
= nsnull
;
1516 sThreadJSContextStack
->Peek(&cx
);
1519 nsCOMPtr
<nsPIDOMWindow
> win
=
1520 do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx
));
1528 nsContentUtils::GetDocumentFromCaller()
1530 JSContext
*cx
= nsnull
;
1531 JSObject
*obj
= nsnull
;
1532 sXPConnect
->GetCaller(&cx
, &obj
);
1533 NS_ASSERTION(cx
&& obj
, "Caller ensures something is running");
1535 nsCOMPtr
<nsPIDOMWindow
> win
=
1536 do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx
, obj
));
1541 return win
->GetExtantDocument();
1545 nsContentUtils::GetDocumentFromContext()
1547 JSContext
*cx
= nsnull
;
1548 sThreadJSContextStack
->Peek(&cx
);
1551 nsIScriptGlobalObject
*sgo
= nsJSUtils::GetDynamicScriptGlobal(cx
);
1554 nsCOMPtr
<nsPIDOMWindow
> pwin
= do_QueryInterface(sgo
);
1556 return pwin
->GetExtantDocument();
1565 nsContentUtils::IsCallerChrome()
1567 PRBool is_caller_chrome
= PR_FALSE
;
1568 nsresult rv
= sSecurityManager
->SubjectPrincipalIsSystem(&is_caller_chrome
);
1569 if (NS_FAILED(rv
)) {
1573 return is_caller_chrome
;
1577 nsContentUtils::IsCallerTrustedForRead()
1579 return IsCallerTrustedForCapability("UniversalBrowserRead");
1583 nsContentUtils::IsCallerTrustedForWrite()
1585 return IsCallerTrustedForCapability("UniversalBrowserWrite");
1590 nsContentUtils::GetCrossDocParentNode(nsINode
* aChild
)
1592 NS_PRECONDITION(aChild
, "The child is null!");
1594 nsINode
* parent
= aChild
->GetNodeParent();
1595 if (parent
|| !aChild
->IsNodeOfType(nsINode::eDOCUMENT
))
1598 nsIDocument
* doc
= static_cast<nsIDocument
*>(aChild
);
1599 nsIDocument
* parentDoc
= doc
->GetParentDocument();
1600 return parentDoc
? parentDoc
->FindContentForSubDocument(doc
) : nsnull
;
1605 nsContentUtils::ContentIsDescendantOf(const nsINode
* aPossibleDescendant
,
1606 const nsINode
* aPossibleAncestor
)
1608 NS_PRECONDITION(aPossibleDescendant
, "The possible descendant is null!");
1609 NS_PRECONDITION(aPossibleAncestor
, "The possible ancestor is null!");
1612 if (aPossibleDescendant
== aPossibleAncestor
)
1614 aPossibleDescendant
= aPossibleDescendant
->GetNodeParent();
1615 } while (aPossibleDescendant
);
1622 nsContentUtils::ContentIsCrossDocDescendantOf(nsINode
* aPossibleDescendant
,
1623 nsINode
* aPossibleAncestor
)
1625 NS_PRECONDITION(aPossibleDescendant
, "The possible descendant is null!");
1626 NS_PRECONDITION(aPossibleAncestor
, "The possible ancestor is null!");
1629 if (aPossibleDescendant
== aPossibleAncestor
)
1631 aPossibleDescendant
= GetCrossDocParentNode(aPossibleDescendant
);
1632 } while (aPossibleDescendant
);
1640 nsContentUtils::GetAncestors(nsINode
* aNode
,
1641 nsTArray
<nsINode
*>& aArray
)
1644 aArray
.AppendElement(aNode
);
1645 aNode
= aNode
->GetNodeParent();
1652 nsContentUtils::GetAncestorsAndOffsets(nsIDOMNode
* aNode
,
1654 nsTArray
<nsIContent
*>* aAncestorNodes
,
1655 nsTArray
<PRInt32
>* aAncestorOffsets
)
1657 NS_ENSURE_ARG_POINTER(aNode
);
1659 nsCOMPtr
<nsIContent
> content(do_QueryInterface(aNode
));
1662 return NS_ERROR_FAILURE
;
1665 if (!aAncestorNodes
->IsEmpty()) {
1666 NS_WARNING("aAncestorNodes is not empty");
1667 aAncestorNodes
->Clear();
1670 if (!aAncestorOffsets
->IsEmpty()) {
1671 NS_WARNING("aAncestorOffsets is not empty");
1672 aAncestorOffsets
->Clear();
1675 // insert the node itself
1676 aAncestorNodes
->AppendElement(content
.get());
1677 aAncestorOffsets
->AppendElement(aOffset
);
1679 // insert all the ancestors
1680 nsIContent
* child
= content
;
1681 nsIContent
* parent
= child
->GetParent();
1683 aAncestorNodes
->AppendElement(parent
);
1684 aAncestorOffsets
->AppendElement(parent
->IndexOf(child
));
1686 parent
= parent
->GetParent();
1694 nsContentUtils::GetCommonAncestor(nsIDOMNode
*aNode
,
1696 nsIDOMNode
** aCommonAncestor
)
1698 *aCommonAncestor
= nsnull
;
1700 nsCOMPtr
<nsINode
> node1
= do_QueryInterface(aNode
);
1701 nsCOMPtr
<nsINode
> node2
= do_QueryInterface(aOther
);
1703 NS_ENSURE_TRUE(node1
&& node2
, NS_ERROR_UNEXPECTED
);
1705 nsINode
* common
= GetCommonAncestor(node1
, node2
);
1706 NS_ENSURE_TRUE(common
, NS_ERROR_NOT_AVAILABLE
);
1708 return CallQueryInterface(common
, aCommonAncestor
);
1713 nsContentUtils::GetCommonAncestor(nsINode
* aNode1
,
1716 if (aNode1
== aNode2
) {
1720 // Build the chain of parents
1721 nsAutoTPtrArray
<nsINode
, 30> parents1
, parents2
;
1723 parents1
.AppendElement(aNode1
);
1724 aNode1
= aNode1
->GetNodeParent();
1727 parents2
.AppendElement(aNode2
);
1728 aNode2
= aNode2
->GetNodeParent();
1731 // Find where the parent chain differs
1732 PRUint32 pos1
= parents1
.Length();
1733 PRUint32 pos2
= parents2
.Length();
1734 nsINode
* parent
= nsnull
;
1736 for (len
= NS_MIN(pos1
, pos2
); len
> 0; --len
) {
1737 nsINode
* child1
= parents1
.ElementAt(--pos1
);
1738 nsINode
* child2
= parents2
.ElementAt(--pos2
);
1739 if (child1
!= child2
) {
1750 nsContentUtils::ComparePoints(nsINode
* aParent1
, PRInt32 aOffset1
,
1751 nsINode
* aParent2
, PRInt32 aOffset2
,
1752 PRBool
* aDisconnected
)
1754 if (aParent1
== aParent2
) {
1755 return aOffset1
< aOffset2
? -1 :
1756 aOffset1
> aOffset2
? 1 :
1760 nsAutoTArray
<nsINode
*, 32> parents1
, parents2
;
1761 nsINode
* node1
= aParent1
;
1762 nsINode
* node2
= aParent2
;
1764 parents1
.AppendElement(node1
);
1765 node1
= node1
->GetNodeParent();
1768 parents2
.AppendElement(node2
);
1769 node2
= node2
->GetNodeParent();
1772 PRUint32 pos1
= parents1
.Length() - 1;
1773 PRUint32 pos2
= parents2
.Length() - 1;
1775 PRBool disconnected
= parents1
.ElementAt(pos1
) != parents2
.ElementAt(pos2
);
1776 if (aDisconnected
) {
1777 *aDisconnected
= disconnected
;
1780 NS_ASSERTION(aDisconnected
, "unexpected disconnected nodes");
1784 // Find where the parent chains differ
1785 nsINode
* parent
= parents1
.ElementAt(pos1
);
1787 for (len
= NS_MIN(pos1
, pos2
); len
> 0; --len
) {
1788 nsINode
* child1
= parents1
.ElementAt(--pos1
);
1789 nsINode
* child2
= parents2
.ElementAt(--pos2
);
1790 if (child1
!= child2
) {
1791 return parent
->IndexOf(child1
) < parent
->IndexOf(child2
) ? -1 : 1;
1797 // The parent chains never differed, so one of the nodes is an ancestor of
1800 NS_ASSERTION(!pos1
|| !pos2
,
1801 "should have run out of parent chain for one of the nodes");
1804 nsINode
* child2
= parents2
.ElementAt(--pos2
);
1805 return aOffset1
<= parent
->IndexOf(child2
) ? -1 : 1;
1808 nsINode
* child1
= parents1
.ElementAt(--pos1
);
1809 return parent
->IndexOf(child1
) < aOffset2
? -1 : 1;
1813 nsContentUtils::FindFirstChildWithResolvedTag(nsIContent
* aParent
,
1818 if (!aParent
|| !(doc
= aParent
->GetOwnerDoc())) {
1822 nsBindingManager
* bindingManager
= doc
->BindingManager();
1824 PRInt32 namespaceID
;
1825 PRUint32 count
= aParent
->GetChildCount();
1829 for (i
= 0; i
< count
; i
++) {
1830 nsIContent
*child
= aParent
->GetChildAt(i
);
1831 nsIAtom
* tag
= bindingManager
->ResolveTag(child
, &namespaceID
);
1832 if (tag
== aTag
&& namespaceID
== aNamespace
) {
1837 // now look for children in XBL
1838 nsCOMPtr
<nsIDOMNodeList
> children
;
1839 bindingManager
->GetXBLChildNodesFor(aParent
, getter_AddRefs(children
));
1845 children
->GetLength(&length
);
1846 for (i
= 0; i
< length
; i
++) {
1847 nsCOMPtr
<nsIDOMNode
> childNode
;
1848 children
->Item(i
, getter_AddRefs(childNode
));
1849 nsCOMPtr
<nsIContent
> childContent
= do_QueryInterface(childNode
);
1850 nsIAtom
* tag
= bindingManager
->ResolveTag(childContent
, &namespaceID
);
1851 if (tag
== aTag
&& namespaceID
== aNamespace
) {
1852 return childContent
;
1860 IsCharInSet(const char* aSet
,
1861 const PRUnichar aChar
)
1864 while ((ch
= *aSet
)) {
1865 if (aChar
== PRUnichar(ch
)) {
1874 * This method strips leading/trailing chars, in given set, from string.
1878 const nsDependentSubstring
1879 nsContentUtils::TrimCharsInSet(const char* aSet
,
1880 const nsAString
& aValue
)
1882 nsAString::const_iterator valueCurrent
, valueEnd
;
1884 aValue
.BeginReading(valueCurrent
);
1885 aValue
.EndReading(valueEnd
);
1887 // Skip characters in the beginning
1888 while (valueCurrent
!= valueEnd
) {
1889 if (!IsCharInSet(aSet
, *valueCurrent
)) {
1895 if (valueCurrent
!= valueEnd
) {
1898 if (!IsCharInSet(aSet
, *valueEnd
)) {
1902 ++valueEnd
; // Step beyond the last character we want in the value.
1905 // valueEnd should point to the char after the last to copy
1906 return Substring(valueCurrent
, valueEnd
);
1910 * This method strips leading and trailing whitespace from a string.
1914 template<PRBool
IsWhitespace(PRUnichar
)>
1915 const nsDependentSubstring
1916 nsContentUtils::TrimWhitespace(const nsAString
& aStr
, PRBool aTrimTrailing
)
1918 nsAString::const_iterator start
, end
;
1920 aStr
.BeginReading(start
);
1921 aStr
.EndReading(end
);
1923 // Skip whitespace characters in the beginning
1924 while (start
!= end
&& IsWhitespace(*start
)) {
1928 if (aTrimTrailing
) {
1929 // Skip whitespace characters in the end.
1930 while (end
!= start
) {
1933 if (!IsWhitespace(*end
)) {
1934 // Step back to the last non-whitespace character.
1942 // Return a substring for the string w/o leading and/or trailing
1945 return Substring(start
, end
);
1948 // Declaring the templates we are going to use avoid linking issues without
1949 // inlining the method. Considering there is not so much spaces checking
1950 // methods we can consider this to be better than inlining.
1952 const nsDependentSubstring
1953 nsContentUtils::TrimWhitespace
<nsCRT::IsAsciiSpace
>(const nsAString
&, PRBool
);
1955 const nsDependentSubstring
1956 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(const nsAString
&, PRBool
);
1958 static inline void KeyAppendSep(nsACString
& aKey
)
1960 if (!aKey
.IsEmpty()) {
1965 static inline void KeyAppendString(const nsAString
& aString
, nsACString
& aKey
)
1969 // Could escape separator here if collisions happen. > is not a legal char
1970 // for a name or type attribute, so we should be safe avoiding that extra work.
1972 AppendUTF16toUTF8(aString
, aKey
);
1975 static inline void KeyAppendString(const nsACString
& aString
, nsACString
& aKey
)
1979 // Could escape separator here if collisions happen. > is not a legal char
1980 // for a name or type attribute, so we should be safe avoiding that extra work.
1982 aKey
.Append(aString
);
1985 static inline void KeyAppendInt(PRInt32 aInt
, nsACString
& aKey
)
1989 aKey
.Append(nsPrintfCString("%d", aInt
));
1992 static inline void KeyAppendAtom(nsIAtom
* aAtom
, nsACString
& aKey
)
1994 NS_PRECONDITION(aAtom
, "KeyAppendAtom: aAtom can not be null!\n");
1996 KeyAppendString(nsAtomCString(aAtom
), aKey
);
1999 static inline PRBool
IsAutocompleteOff(const nsIContent
* aElement
)
2001 return aElement
->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::autocomplete
,
2002 NS_LITERAL_STRING("off"), eIgnoreCase
);
2006 nsContentUtils::GenerateStateKey(nsIContent
* aContent
,
2007 const nsIDocument
* aDocument
,
2008 nsIStatefulFrame::SpecialStateID aID
,
2013 PRUint32 partID
= aDocument
? aDocument
->GetPartID() : 0;
2015 // SpecialStateID case - e.g. scrollbars around the content window
2016 // The key in this case is a special state id
2017 if (nsIStatefulFrame::eNoID
!= aID
) {
2018 KeyAppendInt(partID
, aKey
); // first append a partID
2019 KeyAppendInt(aID
, aKey
);
2023 // We must have content if we're not using a special state id
2024 NS_ENSURE_TRUE(aContent
, NS_ERROR_FAILURE
);
2026 // Don't capture state for anonymous content
2027 if (aContent
->IsInAnonymousSubtree()) {
2031 if (IsAutocompleteOff(aContent
)) {
2035 nsCOMPtr
<nsIHTMLDocument
> htmlDocument(do_QueryInterface(aContent
->GetCurrentDoc()));
2037 KeyAppendInt(partID
, aKey
); // first append a partID
2038 // Make sure we can't possibly collide with an nsIStatefulFrame
2039 // special id of some sort
2040 KeyAppendInt(nsIStatefulFrame::eNoID
, aKey
);
2041 PRBool generatedUniqueKey
= PR_FALSE
;
2044 // Flush our content model so it'll be up to date
2045 // If this becomes unnecessary and the following line is removed,
2046 // please also remove the corresponding flush operation from
2047 // nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
2048 aContent
->GetCurrentDoc()->FlushPendingNotifications(Flush_Content
);
2050 nsContentList
*htmlForms
= htmlDocument
->GetForms();
2051 nsContentList
*htmlFormControls
= htmlDocument
->GetFormControls();
2053 NS_ENSURE_TRUE(htmlForms
&& htmlFormControls
, NS_ERROR_OUT_OF_MEMORY
);
2055 // If we have a form control and can calculate form information, use that
2056 // as the key - it is more reliable than just recording position in the
2058 // XXXbz Is it, really? We have bugs on this, I think...
2059 // Important to have a unique key, and tag/type/name may not be.
2061 // If the control has a form, the format of the key is:
2062 // f>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
2064 // d>type>IndOfControlInDoc>name
2066 // XXX We don't need to use index if name is there
2067 // XXXbz We don't? Why not? I don't follow.
2069 nsCOMPtr
<nsIFormControl
> control(do_QueryInterface(aContent
));
2070 if (control
&& htmlFormControls
&& htmlForms
) {
2072 // Append the control type
2073 KeyAppendInt(control
->GetType(), aKey
);
2075 // If in a form, add form name / index of form / index in form
2077 Element
*formElement
= control
->GetFormElement();
2079 if (IsAutocompleteOff(formElement
)) {
2084 KeyAppendString(NS_LITERAL_CSTRING("f"), aKey
);
2086 // Append the index of the form in the document
2087 index
= htmlForms
->IndexOf(formElement
, PR_FALSE
);
2090 // XXX HACK this uses some state that was dumped into the document
2091 // specifically to fix bug 138892. What we are trying to do is *guess*
2092 // which form this control's state is found in, with the highly likely
2093 // guess that the highest form parsed so far is the one.
2094 // This code should not be on trunk, only branch.
2096 index
= htmlDocument
->GetNumFormsSynchronous() - 1;
2099 KeyAppendInt(index
, aKey
);
2101 // Append the index of the control in the form
2102 nsCOMPtr
<nsIForm
> form(do_QueryInterface(formElement
));
2103 index
= form
->IndexOfControl(control
);
2106 KeyAppendInt(index
, aKey
);
2107 generatedUniqueKey
= PR_TRUE
;
2111 // Append the form name
2112 nsAutoString formName
;
2113 formElement
->GetAttr(kNameSpaceID_None
, nsGkAtoms::name
, formName
);
2114 KeyAppendString(formName
, aKey
);
2118 KeyAppendString(NS_LITERAL_CSTRING("d"), aKey
);
2120 // If not in a form, add index of control in document
2121 // Less desirable than indexing by form info.
2123 // Hash by index of control in doc (we are not in a form)
2124 // These are important as they are unique, and type/name may not be.
2126 // We have to flush sink notifications at this point to make
2127 // sure that htmlFormControls is up to date.
2128 index
= htmlFormControls
->IndexOf(aContent
, PR_TRUE
);
2130 KeyAppendInt(index
, aKey
);
2131 generatedUniqueKey
= PR_TRUE
;
2135 // Append the control name
2137 aContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::name
, name
);
2138 KeyAppendString(name
, aKey
);
2142 if (!generatedUniqueKey
) {
2143 // Either we didn't have a form control or we aren't in an HTML document so
2144 // we can't figure out form info. First append a character that is not "d"
2145 // or "f" to disambiguate from the case when we were a form control in an
2147 KeyAppendString(NS_LITERAL_CSTRING("o"), aKey
);
2149 // Now start at aContent and append the indices of it and all its ancestors
2150 // in their containers. That should at least pin down its position in the
2152 nsINode
* parent
= aContent
->GetNodeParent();
2153 nsINode
* content
= aContent
;
2155 KeyAppendInt(parent
->IndexOf(content
), aKey
);
2157 parent
= content
->GetNodeParent();
2166 nsContentUtils::NewURIWithDocumentCharset(nsIURI
** aResult
,
2167 const nsAString
& aSpec
,
2168 nsIDocument
* aDocument
,
2171 return NS_NewURI(aResult
, aSpec
,
2172 aDocument
? aDocument
->GetDocumentCharacterSet().get() : nsnull
,
2173 aBaseURI
, sIOService
);
2178 nsContentUtils::BelongsInForm(nsIDOMHTMLFormElement
*aForm
,
2179 nsIContent
*aContent
)
2181 NS_PRECONDITION(aForm
, "Must have a form");
2182 NS_PRECONDITION(aContent
, "Must have a content node");
2184 nsCOMPtr
<nsIContent
> form(do_QueryInterface(aForm
));
2187 NS_ERROR("This should not happen, form is not an nsIContent!");
2192 if (form
== aContent
) {
2193 // A form does not belong inside itself, so we return false here
2198 nsIContent
* content
= aContent
->GetParent();
2201 if (content
== form
) {
2202 // aContent is contained within the form so we return true.
2207 if (content
->Tag() == nsGkAtoms::form
&&
2208 content
->IsHTML()) {
2209 // The child is contained within a form, but not the right form
2215 content
= content
->GetParent();
2218 if (form
->GetChildCount() > 0) {
2219 // The form is a container but aContent wasn't inside the form,
2225 // The form is a leaf and aContent wasn't inside any other form so
2226 // we check whether the content comes after the form. If it does,
2227 // return true. If it does not, then it couldn't have been inside
2228 // the form in the HTML.
2229 if (PositionIsBefore(form
, aContent
)) {
2230 // We could be in this form!
2231 // In the future, we may want to get document.forms, look at the
2232 // form after aForm, and if aContent is after that form after
2233 // aForm return false here....
2242 nsContentUtils::CheckQName(const nsAString
& aQualifiedName
,
2243 PRBool aNamespaceAware
)
2245 nsIParserService
*parserService
= GetParserService();
2246 NS_ENSURE_TRUE(parserService
, NS_ERROR_FAILURE
);
2248 const PRUnichar
*colon
;
2249 return parserService
->CheckQName(PromiseFlatString(aQualifiedName
),
2250 aNamespaceAware
, &colon
);
2255 nsContentUtils::SplitQName(const nsIContent
* aNamespaceResolver
,
2256 const nsAFlatString
& aQName
,
2257 PRInt32
*aNamespace
, nsIAtom
**aLocalName
)
2259 nsIParserService
* parserService
= GetParserService();
2260 NS_ENSURE_TRUE(parserService
, NS_ERROR_FAILURE
);
2262 const PRUnichar
* colon
;
2263 nsresult rv
= parserService
->CheckQName(aQName
, PR_TRUE
, &colon
);
2264 NS_ENSURE_SUCCESS(rv
, rv
);
2267 const PRUnichar
* end
;
2268 aQName
.EndReading(end
);
2269 nsAutoString nameSpace
;
2270 rv
= aNamespaceResolver
->LookupNamespaceURI(Substring(aQName
.get(), colon
),
2272 NS_ENSURE_SUCCESS(rv
, rv
);
2274 *aNamespace
= NameSpaceManager()->GetNameSpaceID(nameSpace
);
2275 if (*aNamespace
== kNameSpaceID_Unknown
)
2276 return NS_ERROR_FAILURE
;
2278 *aLocalName
= NS_NewAtom(Substring(colon
+ 1, end
));
2281 *aNamespace
= kNameSpaceID_None
;
2282 *aLocalName
= NS_NewAtom(aQName
);
2284 NS_ENSURE_TRUE(aLocalName
, NS_ERROR_OUT_OF_MEMORY
);
2290 nsContentUtils::GetNodeInfoFromQName(const nsAString
& aNamespaceURI
,
2291 const nsAString
& aQualifiedName
,
2292 nsNodeInfoManager
* aNodeInfoManager
,
2293 nsINodeInfo
** aNodeInfo
)
2295 nsIParserService
* parserService
= GetParserService();
2296 NS_ENSURE_TRUE(parserService
, NS_ERROR_FAILURE
);
2298 const nsAFlatString
& qName
= PromiseFlatString(aQualifiedName
);
2299 const PRUnichar
* colon
;
2300 nsresult rv
= parserService
->CheckQName(qName
, PR_TRUE
, &colon
);
2301 NS_ENSURE_SUCCESS(rv
, rv
);
2304 sNameSpaceManager
->RegisterNameSpace(aNamespaceURI
, nsID
);
2306 const PRUnichar
* end
;
2307 qName
.EndReading(end
);
2309 nsCOMPtr
<nsIAtom
> prefix
= do_GetAtom(Substring(qName
.get(), colon
));
2311 rv
= aNodeInfoManager
->GetNodeInfo(Substring(colon
+ 1, end
), prefix
,
2315 rv
= aNodeInfoManager
->GetNodeInfo(aQualifiedName
, nsnull
, nsID
,
2318 NS_ENSURE_SUCCESS(rv
, rv
);
2320 return nsContentUtils::IsValidNodeName((*aNodeInfo
)->NameAtom(),
2321 (*aNodeInfo
)->GetPrefixAtom(),
2322 (*aNodeInfo
)->NamespaceID()) ?
2323 NS_OK
: NS_ERROR_DOM_NAMESPACE_ERR
;
2328 nsContentUtils::SplitExpatName(const PRUnichar
*aExpatName
, nsIAtom
**aPrefix
,
2329 nsIAtom
**aLocalName
, PRInt32
* aNameSpaceID
)
2332 * Expat can send the following:
2334 * namespaceURI<separator>localName
2335 * namespaceURI<separator>localName<separator>prefix
2337 * and we use 0xFFFF for the <separator>.
2341 const PRUnichar
*uriEnd
= nsnull
;
2342 const PRUnichar
*nameEnd
= nsnull
;
2343 const PRUnichar
*pos
;
2344 for (pos
= aExpatName
; *pos
; ++pos
) {
2345 if (*pos
== 0xFFFF) {
2355 const PRUnichar
*nameStart
;
2357 if (sNameSpaceManager
) {
2358 sNameSpaceManager
->RegisterNameSpace(nsDependentSubstring(aExpatName
,
2363 *aNameSpaceID
= kNameSpaceID_Unknown
;
2366 nameStart
= (uriEnd
+ 1);
2368 const PRUnichar
*prefixStart
= nameEnd
+ 1;
2369 *aPrefix
= NS_NewAtom(Substring(prefixStart
, pos
));
2377 *aNameSpaceID
= kNameSpaceID_None
;
2378 nameStart
= aExpatName
;
2382 *aLocalName
= NS_NewAtom(Substring(nameStart
, nameEnd
));
2387 nsContentUtils::GetContextForContent(const nsIContent
* aContent
)
2389 nsIDocument
* doc
= aContent
->GetCurrentDoc();
2391 nsIPresShell
*presShell
= doc
->GetShell();
2393 return presShell
->GetPresContext();
2401 nsContentUtils::CanLoadImage(nsIURI
* aURI
, nsISupports
* aContext
,
2402 nsIDocument
* aLoadingDocument
,
2403 nsIPrincipal
* aLoadingPrincipal
,
2404 PRInt16
* aImageBlockingStatus
)
2406 NS_PRECONDITION(aURI
, "Must have a URI");
2407 NS_PRECONDITION(aLoadingDocument
, "Must have a document");
2408 NS_PRECONDITION(aLoadingPrincipal
, "Must have a loading principal");
2412 PRUint32 appType
= nsIDocShell::APP_TYPE_UNKNOWN
;
2415 nsCOMPtr
<nsISupports
> container
= aLoadingDocument
->GetContainer();
2416 nsCOMPtr
<nsIDocShellTreeItem
> docShellTreeItem
=
2417 do_QueryInterface(container
);
2419 if (docShellTreeItem
) {
2420 nsCOMPtr
<nsIDocShellTreeItem
> root
;
2421 docShellTreeItem
->GetRootTreeItem(getter_AddRefs(root
));
2423 nsCOMPtr
<nsIDocShell
> docShell(do_QueryInterface(root
));
2425 if (!docShell
|| NS_FAILED(docShell
->GetAppType(&appType
))) {
2426 appType
= nsIDocShell::APP_TYPE_UNKNOWN
;
2431 if (appType
!= nsIDocShell::APP_TYPE_EDITOR
) {
2432 // Editor apps get special treatment here, editors can load images
2433 // from anywhere. This allows editor to insert images from file://
2434 // into documents that are being edited.
2435 rv
= sSecurityManager
->
2436 CheckLoadURIWithPrincipal(aLoadingPrincipal
, aURI
,
2437 nsIScriptSecurityManager::ALLOW_CHROME
);
2438 if (NS_FAILED(rv
)) {
2439 if (aImageBlockingStatus
) {
2440 // Reject the request itself, not all requests to the relevant
2442 *aImageBlockingStatus
= nsIContentPolicy::REJECT_REQUEST
;
2448 PRInt16 decision
= nsIContentPolicy::ACCEPT
;
2450 rv
= NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_IMAGE
,
2454 EmptyCString(), //mime guess
2460 if (aImageBlockingStatus
) {
2461 *aImageBlockingStatus
=
2462 NS_FAILED(rv
) ? nsIContentPolicy::REJECT_REQUEST
: decision
;
2464 return NS_FAILED(rv
) ? PR_FALSE
: NS_CP_ACCEPTED(decision
);
2469 nsContentUtils::IsImageInCache(nsIURI
* aURI
)
2471 if (!sImgLoaderInitialized
)
2474 if (!sImgCache
) return PR_FALSE
;
2476 // If something unexpected happened we return false, otherwise if props
2477 // is set, the image is cached and we return true
2478 nsCOMPtr
<nsIProperties
> props
;
2479 nsresult rv
= sImgCache
->FindEntryProperties(aURI
, getter_AddRefs(props
));
2480 return (NS_SUCCEEDED(rv
) && props
);
2485 nsContentUtils::LoadImage(nsIURI
* aURI
, nsIDocument
* aLoadingDocument
,
2486 nsIPrincipal
* aLoadingPrincipal
, nsIURI
* aReferrer
,
2487 imgIDecoderObserver
* aObserver
, PRInt32 aLoadFlags
,
2488 imgIRequest
** aRequest
)
2490 NS_PRECONDITION(aURI
, "Must have a URI");
2491 NS_PRECONDITION(aLoadingDocument
, "Must have a document");
2492 NS_PRECONDITION(aLoadingPrincipal
, "Must have a principal");
2493 NS_PRECONDITION(aRequest
, "Null out param");
2495 imgILoader
* imgLoader
= GetImgLoader();
2497 // nothing we can do here
2501 nsCOMPtr
<nsILoadGroup
> loadGroup
= aLoadingDocument
->GetDocumentLoadGroup();
2502 NS_ASSERTION(loadGroup
, "Could not get loadgroup; onload may fire too early");
2504 nsIURI
*documentURI
= aLoadingDocument
->GetDocumentURI();
2506 // check for a Content Security Policy to pass down to the channel that
2507 // will get created to load the image
2508 nsCOMPtr
<nsIChannelPolicy
> channelPolicy
;
2509 nsCOMPtr
<nsIContentSecurityPolicy
> csp
;
2510 if (aLoadingPrincipal
) {
2511 nsresult rv
= aLoadingPrincipal
->GetCsp(getter_AddRefs(csp
));
2512 NS_ENSURE_SUCCESS(rv
, rv
);
2514 channelPolicy
= do_CreateInstance("@mozilla.org/nschannelpolicy;1");
2515 channelPolicy
->SetContentSecurityPolicy(csp
);
2516 channelPolicy
->SetLoadType(nsIContentPolicy::TYPE_IMAGE
);
2520 // Make the URI immutable so people won't change it under us
2521 NS_TryToSetImmutable(aURI
);
2523 // XXXbz using "documentURI" for the initialDocumentURI is not quite
2524 // right, but the best we can do here...
2525 return imgLoader
->LoadImage(aURI
, /* uri to load */
2526 documentURI
, /* initialDocumentURI */
2527 aReferrer
, /* referrer */
2528 loadGroup
, /* loadgroup */
2529 aObserver
, /* imgIDecoderObserver */
2530 aLoadingDocument
, /* uniquification key */
2531 aLoadFlags
, /* load flags */
2532 nsnull
, /* cache key */
2533 nsnull
, /* existing request*/
2534 channelPolicy
, /* CSP info */
2539 already_AddRefed
<imgIContainer
>
2540 nsContentUtils::GetImageFromContent(nsIImageLoadingContent
* aContent
,
2541 imgIRequest
**aRequest
)
2547 NS_ENSURE_TRUE(aContent
, nsnull
);
2549 nsCOMPtr
<imgIRequest
> imgRequest
;
2550 aContent
->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST
,
2551 getter_AddRefs(imgRequest
));
2556 nsCOMPtr
<imgIContainer
> imgContainer
;
2557 imgRequest
->GetImage(getter_AddRefs(imgContainer
));
2559 if (!imgContainer
) {
2564 imgRequest
.swap(*aRequest
);
2567 return imgContainer
.forget();
2571 already_AddRefed
<imgIRequest
>
2572 nsContentUtils::GetStaticRequest(imgIRequest
* aRequest
)
2574 NS_ENSURE_TRUE(aRequest
, nsnull
);
2575 nsCOMPtr
<imgIRequest
> retval
;
2576 aRequest
->GetStaticRequest(getter_AddRefs(retval
));
2577 return retval
.forget();
2582 nsContentUtils::ContentIsDraggable(nsIContent
* aContent
)
2584 nsCOMPtr
<nsIDOMNSHTMLElement
> htmlElement
= do_QueryInterface(aContent
);
2586 PRBool draggable
= PR_FALSE
;
2587 htmlElement
->GetDraggable(&draggable
);
2591 if (aContent
->AttrValueIs(kNameSpaceID_None
, nsGkAtoms::draggable
,
2592 nsGkAtoms::_false
, eIgnoreCase
))
2596 // special handling for content area image and link dragging
2597 return IsDraggableImage(aContent
) || IsDraggableLink(aContent
);
2602 nsContentUtils::IsDraggableImage(nsIContent
* aContent
)
2604 NS_PRECONDITION(aContent
, "Must have content node to test");
2606 nsCOMPtr
<nsIImageLoadingContent
> imageContent(do_QueryInterface(aContent
));
2607 if (!imageContent
) {
2611 nsCOMPtr
<imgIRequest
> imgRequest
;
2612 imageContent
->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST
,
2613 getter_AddRefs(imgRequest
));
2615 // XXXbz It may be draggable even if the request resulted in an error. Why?
2616 // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
2617 return imgRequest
!= nsnull
;
2622 nsContentUtils::IsDraggableLink(const nsIContent
* aContent
) {
2623 nsCOMPtr
<nsIURI
> absURI
;
2624 return aContent
->IsLink(getter_AddRefs(absURI
));
2629 nsContentUtils::GetCharPref(const char *aPref
)
2631 nsAdoptingCString result
;
2634 sPrefBranch
->GetCharPref(aPref
, getter_Copies(result
));
2642 nsContentUtils::GetBoolPref(const char *aPref
, PRBool aDefault
)
2647 NS_FAILED(sPrefBranch
->GetBoolPref(aPref
, &result
))) {
2651 return (PRPackedBool
)result
;
2656 nsContentUtils::GetIntPref(const char *aPref
, PRInt32 aDefault
)
2661 NS_FAILED(sPrefBranch
->GetIntPref(aPref
, &result
))) {
2670 nsContentUtils::GetLocalizedStringPref(const char *aPref
)
2672 nsAdoptingString result
;
2675 nsCOMPtr
<nsIPrefLocalizedString
> prefLocalString
;
2676 sPrefBranch
->GetComplexValue(aPref
, NS_GET_IID(nsIPrefLocalizedString
),
2677 getter_AddRefs(prefLocalString
));
2678 if (prefLocalString
) {
2679 prefLocalString
->GetData(getter_Copies(result
));
2688 nsContentUtils::GetStringPref(const char *aPref
)
2690 nsAdoptingString result
;
2693 nsCOMPtr
<nsISupportsString
> theString
;
2694 sPrefBranch
->GetComplexValue(aPref
, NS_GET_IID(nsISupportsString
),
2695 getter_AddRefs(theString
));
2697 theString
->ToString(getter_Copies(result
));
2704 // RegisterPrefCallback/UnregisterPrefCallback are for backward compatiblity
2705 // with c-style observers.
2709 nsContentUtils::RegisterPrefCallback(const char *aPref
,
2710 PrefChangedFunc aCallback
,
2714 if (!sPrefCallbackTable
) {
2715 sPrefCallbackTable
=
2716 new nsRefPtrHashtable
<nsPrefObserverHashKey
, nsPrefOldCallback
>();
2717 sPrefCallbackTable
->Init();
2720 nsPrefObserverHashKey
hashKey(aPref
, aCallback
);
2721 nsRefPtr
<nsPrefOldCallback
> callback
;
2722 sPrefCallbackTable
->Get(&hashKey
, getter_AddRefs(callback
));
2724 callback
->AppendClosure(aClosure
);
2728 callback
= new nsPrefOldCallback(aPref
, aCallback
);
2729 callback
->AppendClosure(aClosure
);
2730 if (NS_SUCCEEDED(sPrefBranch
->AddObserver(aPref
, callback
, PR_FALSE
))) {
2731 sPrefCallbackTable
->Put(callback
, callback
);
2738 nsContentUtils::UnregisterPrefCallback(const char *aPref
,
2739 PrefChangedFunc aCallback
,
2743 if (!sPrefCallbackTable
) {
2747 nsPrefObserverHashKey
hashKey(aPref
, aCallback
);
2748 nsRefPtr
<nsPrefOldCallback
> callback
;
2749 sPrefCallbackTable
->Get(&hashKey
, getter_AddRefs(callback
));
2752 callback
->RemoveClosure(aClosure
);
2753 if (callback
->HasNoClosures()) {
2754 // Delete the callback since its list of closures is empty.
2755 sPrefCallbackTable
->Remove(callback
);
2762 BoolVarChanged(const char *aPref
, void *aClosure
)
2764 PrefCacheData
* cache
= static_cast<PrefCacheData
*>(aClosure
);
2765 *((PRBool
*)cache
->cacheLocation
) =
2766 nsContentUtils::GetBoolPref(aPref
, cache
->defaultValueBool
);
2772 nsContentUtils::AddBoolPrefVarCache(const char *aPref
,
2776 *aCache
= GetBoolPref(aPref
, aDefault
);
2777 PrefCacheData
* data
= new PrefCacheData
;
2778 data
->cacheLocation
= aCache
;
2779 data
->defaultValueBool
= aDefault
;
2780 sPrefCacheData
->AppendElement(data
);
2781 RegisterPrefCallback(aPref
, BoolVarChanged
, data
);
2785 IntVarChanged(const char *aPref
, void *aClosure
)
2787 PrefCacheData
* cache
= static_cast<PrefCacheData
*>(aClosure
);
2788 *((PRInt32
*)cache
->cacheLocation
) =
2789 nsContentUtils::GetIntPref(aPref
, cache
->defaultValueInt
);
2795 nsContentUtils::AddIntPrefVarCache(const char *aPref
,
2799 *aCache
= GetIntPref(aPref
, aDefault
);
2800 PrefCacheData
* data
= new PrefCacheData
;
2801 data
->cacheLocation
= aCache
;
2802 data
->defaultValueInt
= aDefault
;
2803 sPrefCacheData
->AppendElement(data
);
2804 RegisterPrefCallback(aPref
, IntVarChanged
, data
);
2808 nsContentUtils::IsSitePermAllow(nsIURI
* aURI
, const char* aType
)
2810 nsCOMPtr
<nsIPermissionManager
> permMgr
=
2811 do_GetService("@mozilla.org/permissionmanager;1");
2812 NS_ENSURE_TRUE(permMgr
, PR_FALSE
);
2815 nsresult rv
= permMgr
->TestPermission(aURI
, aType
, &perm
);
2816 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
2818 return perm
== nsIPermissionManager::ALLOW_ACTION
;
2821 static const char *gEventNames
[] = {"event"};
2822 static const char *gSVGEventNames
[] = {"evt"};
2823 // for b/w compat, the first name to onerror is still 'event', even though it
2824 // is actually the error message. (pre this code, the other 2 were not avail.)
2825 // XXXmarkh - a quick lxr shows no affected code - should we correct this?
2826 static const char *gOnErrorNames
[] = {"event", "source", "lineno"};
2830 nsContentUtils::GetEventArgNames(PRInt32 aNameSpaceID
,
2831 nsIAtom
*aEventName
,
2832 PRUint32
*aArgCount
,
2833 const char*** aArgArray
)
2835 #define SET_EVENT_ARG_NAMES(names) \
2836 *aArgCount = sizeof(names)/sizeof(names[0]); \
2839 // nsJSEventListener is what does the arg magic for onerror, and it does
2840 // not seem to take the namespace into account. So we let onerror in all
2841 // namespaces get the 3 arg names.
2842 if (aEventName
== nsGkAtoms::onerror
) {
2843 SET_EVENT_ARG_NAMES(gOnErrorNames
);
2844 } else if (aNameSpaceID
== kNameSpaceID_SVG
) {
2845 SET_EVENT_ARG_NAMES(gSVGEventNames
);
2847 SET_EVENT_ARG_NAMES(gEventNames
);
2851 nsCxPusher::nsCxPusher()
2852 : mScriptIsRunning(PR_FALSE
),
2853 mPushedSomething(PR_FALSE
)
2857 nsCxPusher::~nsCxPusher()
2863 IsContextOnStack(nsIJSContextStack
*aStack
, JSContext
*aContext
)
2865 JSContext
*ctx
= nsnull
;
2869 if (ctx
== aContext
)
2872 nsCOMPtr
<nsIJSContextStackIterator
>
2873 iterator(do_CreateInstance("@mozilla.org/js/xpc/ContextStackIterator;1"));
2874 NS_ENSURE_TRUE(iterator
, PR_FALSE
);
2876 nsresult rv
= iterator
->Reset(aStack
);
2877 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
2880 while (NS_SUCCEEDED(iterator
->Done(&done
)) && !done
) {
2881 rv
= iterator
->Prev(&ctx
);
2882 NS_ASSERTION(NS_SUCCEEDED(rv
), "Broken iterator implementation");
2888 if (nsJSUtils::GetDynamicScriptContext(ctx
) && ctx
== aContext
)
2896 nsCxPusher::Push(nsPIDOMEventTarget
*aCurrentTarget
)
2898 if (mPushedSomething
) {
2899 NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
2904 NS_ENSURE_TRUE(aCurrentTarget
, PR_FALSE
);
2906 nsIScriptContext
* scx
=
2907 aCurrentTarget
->GetContextForEventHandlers(&rv
);
2908 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
2911 // The target may have a special JS context for event handlers.
2912 JSContext
* cx
= aCurrentTarget
->GetJSContextForEventHandlers();
2917 // Nothing to do here, I guess. Have to return true so that event firing
2918 // will still work correctly even if there is no associated JSContext
2922 JSContext
* cx
= nsnull
;
2925 cx
= static_cast<JSContext
*>(scx
->GetNativeContext());
2926 // Bad, no JSContext from script context!
2927 NS_ENSURE_TRUE(cx
, PR_FALSE
);
2930 // If there's no native context in the script context it must be
2931 // in the process or being torn down. We don't want to notify the
2932 // script context about scripts having been evaluated in such a
2933 // case, calling with a null cx is fine in that case.
2938 nsCxPusher::RePush(nsPIDOMEventTarget
*aCurrentTarget
)
2940 if (!mPushedSomething
) {
2941 return Push(aCurrentTarget
);
2944 if (aCurrentTarget
) {
2946 nsIScriptContext
* scx
=
2947 aCurrentTarget
->GetContextForEventHandlers(&rv
);
2948 if (NS_FAILED(rv
)) {
2953 // If we have the same script context and native context is still
2954 // alive, no need to Pop/Push.
2955 if (scx
&& scx
== mScx
&&
2956 scx
->GetNativeContext()) {
2962 return Push(aCurrentTarget
);
2966 nsCxPusher::Push(JSContext
*cx
, PRBool aRequiresScriptContext
)
2968 if (mPushedSomething
) {
2969 NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
2978 // Hold a strong ref to the nsIScriptContext, just in case
2979 // XXXbz do we really need to? If we don't get one of these in Pop(), is
2980 // that really a problem? Or do we need to do this to effectively root |cx|?
2981 mScx
= GetScriptContextFromJSContext(cx
);
2982 if (!mScx
&& aRequiresScriptContext
) {
2983 // Should probably return PR_FALSE. See bug 416916.
2991 nsCxPusher::DoPush(JSContext
* cx
)
2993 nsIThreadJSContextStack
* stack
= nsContentUtils::ThreadJSContextStack();
2998 if (cx
&& IsContextOnStack(stack
, cx
)) {
2999 // If the context is on the stack, that means that a script
3000 // is running at the moment in the context.
3001 mScriptIsRunning
= PR_TRUE
;
3004 if (NS_FAILED(stack
->Push(cx
))) {
3005 mScriptIsRunning
= PR_FALSE
;
3010 mPushedSomething
= PR_TRUE
;
3012 mPushedContext
= cx
;
3018 nsCxPusher::PushNull()
3020 return DoPush(nsnull
);
3026 nsIThreadJSContextStack
* stack
= nsContentUtils::ThreadJSContextStack();
3027 if (!mPushedSomething
|| !stack
) {
3029 mPushedSomething
= PR_FALSE
;
3031 NS_ASSERTION(!mScriptIsRunning
, "Huh, this can't be happening, "
3032 "mScriptIsRunning can't be set here!");
3038 stack
->Pop(&unused
);
3040 NS_ASSERTION(unused
== mPushedContext
, "Unexpected context popped");
3042 if (!mScriptIsRunning
&& mScx
) {
3043 // No JS is running in the context, but executing the event handler might have
3044 // caused some JS to run. Tell the script context that it's done.
3046 mScx
->ScriptEvaluated(PR_TRUE
);
3050 mScriptIsRunning
= PR_FALSE
;
3051 mPushedSomething
= PR_FALSE
;
3054 static const char gPropertiesFiles
[nsContentUtils::PropertiesFile_COUNT
][56] = {
3055 // Must line up with the enum values in |PropertiesFile| enum.
3056 "chrome://global/locale/css.properties",
3057 "chrome://global/locale/xbl.properties",
3058 "chrome://global/locale/xul.properties",
3059 "chrome://global/locale/layout_errors.properties",
3060 "chrome://global/locale/layout/HtmlForm.properties",
3061 "chrome://global/locale/printing.properties",
3062 "chrome://global/locale/dom/dom.properties",
3064 "chrome://global/locale/svg/svg.properties",
3066 "chrome://branding/locale/brand.properties",
3067 "chrome://global/locale/commonDialogs.properties"
3070 /* static */ nsresult
3071 nsContentUtils::EnsureStringBundle(PropertiesFile aFile
)
3073 if (!sStringBundles
[aFile
]) {
3074 if (!sStringBundleService
) {
3076 CallGetService(NS_STRINGBUNDLE_CONTRACTID
, &sStringBundleService
);
3077 NS_ENSURE_SUCCESS(rv
, rv
);
3079 nsIStringBundle
*bundle
;
3081 sStringBundleService
->CreateBundle(gPropertiesFiles
[aFile
], &bundle
);
3082 NS_ENSURE_SUCCESS(rv
, rv
);
3083 sStringBundles
[aFile
] = bundle
; // transfer ownership
3089 nsresult
nsContentUtils::GetLocalizedString(PropertiesFile aFile
,
3091 nsXPIDLString
& aResult
)
3093 nsresult rv
= EnsureStringBundle(aFile
);
3094 NS_ENSURE_SUCCESS(rv
, rv
);
3095 nsIStringBundle
*bundle
= sStringBundles
[aFile
];
3097 return bundle
->GetStringFromName(NS_ConvertASCIItoUTF16(aKey
).get(),
3098 getter_Copies(aResult
));
3102 nsresult
nsContentUtils::FormatLocalizedString(PropertiesFile aFile
,
3104 const PRUnichar
**aParams
,
3105 PRUint32 aParamsLength
,
3106 nsXPIDLString
& aResult
)
3108 nsresult rv
= EnsureStringBundle(aFile
);
3109 NS_ENSURE_SUCCESS(rv
, rv
);
3110 nsIStringBundle
*bundle
= sStringBundles
[aFile
];
3112 return bundle
->FormatStringFromName(NS_ConvertASCIItoUTF16(aKey
).get(),
3113 aParams
, aParamsLength
,
3114 getter_Copies(aResult
));
3117 /* static */ nsresult
3118 nsContentUtils::ReportToConsole(PropertiesFile aFile
,
3119 const char *aMessageName
,
3120 const PRUnichar
**aParams
,
3121 PRUint32 aParamsLength
,
3123 const nsAFlatString
& aSourceLine
,
3124 PRUint32 aLineNumber
,
3125 PRUint32 aColumnNumber
,
3126 PRUint32 aErrorFlags
,
3127 const char *aCategory
)
3129 NS_ASSERTION((aParams
&& aParamsLength
) || (!aParams
&& !aParamsLength
),
3130 "Supply either both parameters and their number or no"
3131 "parameters and 0.");
3134 if (!sConsoleService
) { // only need to bother null-checking here
3135 rv
= CallGetService(NS_CONSOLESERVICE_CONTRACTID
, &sConsoleService
);
3136 NS_ENSURE_SUCCESS(rv
, rv
);
3139 nsXPIDLString errorText
;
3141 rv
= FormatLocalizedString(aFile
, aMessageName
, aParams
, aParamsLength
,
3145 rv
= GetLocalizedString(aFile
, aMessageName
, errorText
);
3147 NS_ENSURE_SUCCESS(rv
, rv
);
3151 aURI
->GetSpec(spec
);
3153 nsCOMPtr
<nsIScriptError
> errorObject
=
3154 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID
, &rv
);
3155 NS_ENSURE_SUCCESS(rv
, rv
);
3156 rv
= errorObject
->Init(errorText
.get(),
3157 NS_ConvertUTF8toUTF16(spec
).get(), // file name
3159 aLineNumber
, aColumnNumber
,
3160 aErrorFlags
, aCategory
);
3161 NS_ENSURE_SUCCESS(rv
, rv
);
3163 return sConsoleService
->LogMessage(errorObject
);
3167 nsContentUtils::IsChromeDoc(nsIDocument
*aDocument
)
3173 nsCOMPtr
<nsIPrincipal
> systemPrincipal
;
3174 sSecurityManager
->GetSystemPrincipal(getter_AddRefs(systemPrincipal
));
3176 return aDocument
->NodePrincipal() == systemPrincipal
;
3180 nsContentUtils::IsChildOfSameType(nsIDocument
* aDoc
)
3182 nsCOMPtr
<nsISupports
> container
= aDoc
->GetContainer();
3183 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(container
));
3184 nsCOMPtr
<nsIDocShellTreeItem
> sameTypeParent
;
3185 if (docShellAsItem
) {
3186 docShellAsItem
->GetSameTypeParent(getter_AddRefs(sameTypeParent
));
3188 return sameTypeParent
!= nsnull
;
3192 nsContentUtils::GetWrapperSafeScriptFilename(nsIDocument
*aDocument
,
3194 nsACString
& aScriptURI
)
3196 PRBool scriptFileNameModified
= PR_FALSE
;
3197 aURI
->GetSpec(aScriptURI
);
3199 if (IsChromeDoc(aDocument
)) {
3200 nsCOMPtr
<nsIChromeRegistry
> chromeReg
=
3201 mozilla::services::GetChromeRegistryService();
3204 // If we're running w/o a chrome registry we won't modify any
3205 // script file names.
3207 return scriptFileNameModified
;
3210 PRBool docWrappersEnabled
=
3211 chromeReg
->WrappersEnabled(aDocument
->GetDocumentURI());
3213 PRBool uriWrappersEnabled
= chromeReg
->WrappersEnabled(aURI
);
3215 nsIURI
*docURI
= aDocument
->GetDocumentURI();
3217 if (docURI
&& docWrappersEnabled
&& !uriWrappersEnabled
) {
3218 // aURI is a script from a URL that doesn't get wrapper
3219 // automation. aDocument is a chrome document that does get
3220 // wrapper automation. Prepend the chrome document's URI
3221 // followed by the string " -> " to the URI of the script we're
3222 // loading here so that script in that URI gets the same wrapper
3223 // automation that the chrome document expects.
3225 docURI
->GetSpec(spec
);
3226 spec
.AppendASCII(" -> ");
3227 spec
.Append(aScriptURI
);
3231 scriptFileNameModified
= PR_TRUE
;
3235 return scriptFileNameModified
;
3240 nsContentUtils::IsInChromeDocshell(nsIDocument
*aDocument
)
3246 if (aDocument
->GetDisplayDocument()) {
3247 return IsInChromeDocshell(aDocument
->GetDisplayDocument());
3250 nsCOMPtr
<nsISupports
> docContainer
= aDocument
->GetContainer();
3251 nsCOMPtr
<nsIDocShellTreeItem
> docShell(do_QueryInterface(docContainer
));
3252 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
3254 docShell
->GetItemType(&itemType
);
3257 return itemType
== nsIDocShellTreeItem::typeChrome
;
3262 nsContentUtils::GetContentPolicy()
3264 if (!sTriedToGetContentPolicy
) {
3265 CallGetService(NS_CONTENTPOLICY_CONTRACTID
, &sContentPolicyService
);
3266 // It's OK to not have a content policy service
3267 sTriedToGetContentPolicy
= PR_TRUE
;
3270 return sContentPolicyService
;
3275 nsContentUtils::IsEventAttributeName(nsIAtom
* aName
, PRInt32 aType
)
3277 const PRUnichar
* name
= aName
->GetUTF16String();
3278 if (name
[0] != 'o' || name
[1] != 'n')
3281 EventNameMapping mapping
;
3282 return (sAtomEventTable
->Get(aName
, &mapping
) && mapping
.mType
& aType
);
3287 nsContentUtils::GetEventId(nsIAtom
* aName
)
3289 EventNameMapping mapping
;
3290 if (sAtomEventTable
->Get(aName
, &mapping
))
3293 return NS_USER_DEFINED_EVENT
;
3297 nsContentUtils::GetEventIdAndAtom(const nsAString
& aName
,
3298 PRUint32 aEventStruct
,
3301 EventNameMapping mapping
;
3302 if (sStringEventTable
->Get(aName
, &mapping
)) {
3304 mapping
.mStructType
== aEventStruct
? mapping
.mId
: NS_USER_DEFINED_EVENT
;
3305 return mapping
.mAtom
;
3308 // If we have cached lots of user defined event names, clear some of them.
3309 if (sUserDefinedEvents
->Count() > 127) {
3310 while (sUserDefinedEvents
->Count() > 64) {
3311 nsIAtom
* first
= sUserDefinedEvents
->ObjectAt(0);
3312 sStringEventTable
->Remove(Substring(nsDependentAtomString(first
), 2));
3313 sUserDefinedEvents
->RemoveObjectAt(0);
3317 *aEventID
= NS_USER_DEFINED_EVENT
;
3318 nsCOMPtr
<nsIAtom
> atom
= do_GetAtom(NS_LITERAL_STRING("on") + aName
);
3319 sUserDefinedEvents
->AppendObject(atom
);
3320 mapping
.mAtom
= atom
;
3321 mapping
.mId
= NS_USER_DEFINED_EVENT
;
3322 mapping
.mType
= EventNameType_None
;
3323 mapping
.mStructType
= NS_EVENT_NULL
;
3324 sStringEventTable
->Put(aName
, mapping
);
3325 return mapping
.mAtom
;
3329 nsresult
GetEventAndTarget(nsIDocument
* aDoc
, nsISupports
* aTarget
,
3330 const nsAString
& aEventName
,
3331 PRBool aCanBubble
, PRBool aCancelable
,
3332 nsIDOMEvent
** aEvent
,
3333 nsIDOMEventTarget
** aTargetOut
)
3335 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent(do_QueryInterface(aDoc
));
3336 nsCOMPtr
<nsIDOMEventTarget
> target(do_QueryInterface(aTarget
));
3337 NS_ENSURE_TRUE(docEvent
&& target
, NS_ERROR_INVALID_ARG
);
3339 nsCOMPtr
<nsIDOMEvent
> event
;
3341 docEvent
->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event
));
3342 NS_ENSURE_SUCCESS(rv
, rv
);
3344 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(event
));
3345 NS_ENSURE_TRUE(privateEvent
, NS_ERROR_FAILURE
);
3347 rv
= event
->InitEvent(aEventName
, aCanBubble
, aCancelable
);
3348 NS_ENSURE_SUCCESS(rv
, rv
);
3350 rv
= privateEvent
->SetTrusted(PR_TRUE
);
3351 NS_ENSURE_SUCCESS(rv
, rv
);
3353 rv
= privateEvent
->SetTarget(target
);
3354 NS_ENSURE_SUCCESS(rv
, rv
);
3356 event
.forget(aEvent
);
3357 target
.forget(aTargetOut
);
3363 nsContentUtils::DispatchTrustedEvent(nsIDocument
* aDoc
, nsISupports
* aTarget
,
3364 const nsAString
& aEventName
,
3365 PRBool aCanBubble
, PRBool aCancelable
,
3366 PRBool
*aDefaultAction
)
3368 nsCOMPtr
<nsIDOMEvent
> event
;
3369 nsCOMPtr
<nsIDOMEventTarget
> target
;
3370 nsresult rv
= GetEventAndTarget(aDoc
, aTarget
, aEventName
, aCanBubble
,
3371 aCancelable
, getter_AddRefs(event
),
3372 getter_AddRefs(target
));
3373 NS_ENSURE_SUCCESS(rv
, rv
);
3376 return target
->DispatchEvent(event
, aDefaultAction
? aDefaultAction
: &dummy
);
3380 nsContentUtils::DispatchChromeEvent(nsIDocument
*aDoc
,
3381 nsISupports
*aTarget
,
3382 const nsAString
& aEventName
,
3383 PRBool aCanBubble
, PRBool aCancelable
,
3384 PRBool
*aDefaultAction
)
3387 nsCOMPtr
<nsIDOMEvent
> event
;
3388 nsCOMPtr
<nsIDOMEventTarget
> target
;
3389 nsresult rv
= GetEventAndTarget(aDoc
, aTarget
, aEventName
, aCanBubble
,
3390 aCancelable
, getter_AddRefs(event
),
3391 getter_AddRefs(target
));
3392 NS_ENSURE_SUCCESS(rv
, rv
);
3394 NS_ASSERTION(aDoc
, "GetEventAndTarget lied?");
3395 if (!aDoc
->GetWindow())
3396 return NS_ERROR_INVALID_ARG
;
3398 nsPIDOMEventTarget
* piTarget
= aDoc
->GetWindow()->GetChromeEventHandler();
3400 return NS_ERROR_INVALID_ARG
;
3402 nsCOMPtr
<nsIFrameLoaderOwner
> flo
= do_QueryInterface(piTarget
);
3404 nsRefPtr
<nsFrameLoader
> fl
= flo
->GetFrameLoader();
3406 nsPIDOMEventTarget
* t
= fl
->GetTabChildGlobalAsEventTarget();
3407 piTarget
= t
? t
: piTarget
;
3411 nsEventStatus status
= nsEventStatus_eIgnore
;
3412 rv
= piTarget
->DispatchDOMEvent(nsnull
, event
, nsnull
, &status
);
3413 if (aDefaultAction
) {
3414 *aDefaultAction
= (status
!= nsEventStatus_eConsumeNoDefault
);
3421 nsContentUtils::MatchElementId(nsIContent
*aContent
, const nsIAtom
* aId
)
3423 for (nsIContent
* cur
= aContent
;
3425 cur
= cur
->GetNextNode(aContent
)) {
3426 if (aId
== cur
->GetID()) {
3427 return cur
->AsElement();
3436 nsContentUtils::MatchElementId(nsIContent
*aContent
, const nsAString
& aId
)
3438 NS_PRECONDITION(!aId
.IsEmpty(), "Will match random elements");
3440 // ID attrs are generally stored as atoms, so just atomize this up front
3441 nsCOMPtr
<nsIAtom
> id(do_GetAtom(aId
));
3443 // OOM, so just bail
3447 return MatchElementId(aContent
, id
);
3450 // Convert the string from the given charset to Unicode.
3453 nsContentUtils::ConvertStringFromCharset(const nsACString
& aCharset
,
3454 const nsACString
& aInput
,
3457 if (aCharset
.IsEmpty()) {
3458 // Treat the string as UTF8
3459 CopyUTF8toUTF16(aInput
, aOutput
);
3464 nsCOMPtr
<nsICharsetConverterManager
> ccm
=
3465 do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID
, &rv
);
3469 nsCOMPtr
<nsIUnicodeDecoder
> decoder
;
3470 rv
= ccm
->GetUnicodeDecoder(PromiseFlatCString(aCharset
).get(),
3471 getter_AddRefs(decoder
));
3475 nsPromiseFlatCString
flatInput(aInput
);
3476 PRInt32 srcLen
= flatInput
.Length();
3478 rv
= decoder
->GetMaxLength(flatInput
.get(), srcLen
, &dstLen
);
3482 PRUnichar
*ustr
= (PRUnichar
*)nsMemory::Alloc((dstLen
+ 1) *
3485 return NS_ERROR_OUT_OF_MEMORY
;
3487 rv
= decoder
->Convert(flatInput
.get(), &srcLen
, ustr
, &dstLen
);
3488 if (NS_SUCCEEDED(rv
)) {
3490 aOutput
.Assign(ustr
, dstLen
);
3493 nsMemory::Free(ustr
);
3499 nsContentUtils::CheckForBOM(const unsigned char* aBuffer
, PRUint32 aLength
,
3500 nsACString
& aCharset
, PRBool
*bigEndian
)
3502 PRBool found
= PR_TRUE
;
3503 aCharset
.Truncate();
3505 aBuffer
[0] == 0xEF &&
3506 aBuffer
[1] == 0xBB &&
3507 aBuffer
[2] == 0xBF) {
3510 else if (aLength
>= 4 &&
3511 aBuffer
[0] == 0x00 &&
3512 aBuffer
[1] == 0x00 &&
3513 aBuffer
[2] == 0xFE &&
3514 aBuffer
[3] == 0xFF) {
3515 aCharset
= "UTF-32";
3517 *bigEndian
= PR_TRUE
;
3519 else if (aLength
>= 4 &&
3520 aBuffer
[0] == 0xFF &&
3521 aBuffer
[1] == 0xFE &&
3522 aBuffer
[2] == 0x00 &&
3523 aBuffer
[3] == 0x00) {
3524 aCharset
= "UTF-32";
3526 *bigEndian
= PR_FALSE
;
3528 else if (aLength
>= 2 &&
3529 aBuffer
[0] == 0xFE && aBuffer
[1] == 0xFF) {
3530 aCharset
= "UTF-16";
3532 *bigEndian
= PR_TRUE
;
3534 else if (aLength
>= 2 &&
3535 aBuffer
[0] == 0xFF && aBuffer
[1] == 0xFE) {
3536 aCharset
= "UTF-16";
3538 *bigEndian
= PR_FALSE
;
3548 nsContentUtils::GetReferencedElement(nsIURI
* aURI
, nsIContent
*aFromContent
)
3550 nsReferencedElement ref
;
3551 ref
.Reset(aFromContent
, aURI
);
3557 nsContentUtils::RegisterShutdownObserver(nsIObserver
* aObserver
)
3559 nsCOMPtr
<nsIObserverService
> observerService
=
3560 mozilla::services::GetObserverService();
3561 if (observerService
) {
3562 observerService
->AddObserver(aObserver
,
3563 NS_XPCOM_SHUTDOWN_OBSERVER_ID
,
3570 nsContentUtils::UnregisterShutdownObserver(nsIObserver
* aObserver
)
3572 nsCOMPtr
<nsIObserverService
> observerService
=
3573 mozilla::services::GetObserverService();
3574 if (observerService
) {
3575 observerService
->RemoveObserver(aObserver
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
);
3581 nsContentUtils::HasNonEmptyAttr(const nsIContent
* aContent
, PRInt32 aNameSpaceID
,
3584 static nsIContent::AttrValuesArray strings
[] = {&nsGkAtoms::_empty
, nsnull
};
3585 return aContent
->FindAttrValueIn(aNameSpaceID
, aName
, strings
, eCaseMatters
)
3586 == nsIContent::ATTR_VALUE_NO_MATCH
;
3591 nsContentUtils::HasMutationListeners(nsINode
* aNode
,
3593 nsINode
* aTargetForSubtreeModified
)
3595 nsIDocument
* doc
= aNode
->GetOwnerDoc();
3600 NS_ASSERTION((aNode
->IsNodeOfType(nsINode::eCONTENT
) &&
3601 static_cast<nsIContent
*>(aNode
)->
3602 IsInNativeAnonymousSubtree()) ||
3603 sScriptBlockerCount
== sRemovableScriptBlockerCount
,
3604 "Want to fire mutation events, but it's not safe");
3606 // global object will be null for documents that don't have windows.
3607 nsPIDOMWindow
* window
= doc
->GetInnerWindow();
3608 // This relies on nsEventListenerManager::AddEventListener, which sets
3609 // all mutation bits when there is a listener for DOMSubtreeModified event.
3610 if (window
&& !window
->HasMutationListeners(aType
)) {
3614 if (aNode
->IsNodeOfType(nsINode::eCONTENT
) &&
3615 static_cast<nsIContent
*>(aNode
)->IsInNativeAnonymousSubtree()) {
3619 doc
->MayDispatchMutationEvent(aTargetForSubtreeModified
);
3621 // If we have a window, we can check it for mutation listeners now.
3622 if (aNode
->IsInDoc()) {
3623 nsCOMPtr
<nsPIDOMEventTarget
> piTarget(do_QueryInterface(window
));
3625 nsIEventListenerManager
* manager
= piTarget
->GetListenerManager(PR_FALSE
);
3627 PRBool hasListeners
= PR_FALSE
;
3628 manager
->HasMutationListeners(&hasListeners
);
3636 // If we have a window, we know a mutation listener is registered, but it
3637 // might not be in our chain. If we don't have a window, we might have a
3638 // mutation listener. Check quickly to see.
3640 nsIEventListenerManager
* manager
= aNode
->GetListenerManager(PR_FALSE
);
3642 PRBool hasListeners
= PR_FALSE
;
3643 manager
->HasMutationListeners(&hasListeners
);
3649 if (aNode
->IsNodeOfType(nsINode::eCONTENT
)) {
3650 nsIContent
* content
= static_cast<nsIContent
*>(aNode
);
3651 nsIContent
* insertionParent
=
3652 doc
->BindingManager()->GetInsertionParent(content
);
3653 if (insertionParent
) {
3654 aNode
= insertionParent
;
3658 aNode
= aNode
->GetNodeParent();
3666 nsContentUtils::TraverseListenerManager(nsINode
*aNode
,
3667 nsCycleCollectionTraversalCallback
&cb
)
3669 if (!sEventListenerManagersHash
.ops
) {
3670 // We're already shut down, just return.
3674 EventListenerManagerMapEntry
*entry
=
3675 static_cast<EventListenerManagerMapEntry
*>
3676 (PL_DHashTableOperate(&sEventListenerManagersHash
, aNode
,
3678 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
3679 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "[via hash] mListenerManager");
3680 cb
.NoteXPCOMChild(entry
->mListenerManager
);
3684 nsIEventListenerManager
*
3685 nsContentUtils::GetListenerManager(nsINode
*aNode
,
3686 PRBool aCreateIfNotFound
)
3688 if (!aCreateIfNotFound
&& !aNode
->HasFlag(NODE_HAS_LISTENERMANAGER
)) {
3692 if (!sEventListenerManagersHash
.ops
) {
3693 // We're already shut down, don't bother creating an event listener
3699 if (!aCreateIfNotFound
) {
3700 EventListenerManagerMapEntry
*entry
=
3701 static_cast<EventListenerManagerMapEntry
*>
3702 (PL_DHashTableOperate(&sEventListenerManagersHash
, aNode
,
3704 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
3705 return entry
->mListenerManager
;
3710 EventListenerManagerMapEntry
*entry
=
3711 static_cast<EventListenerManagerMapEntry
*>
3712 (PL_DHashTableOperate(&sEventListenerManagersHash
, aNode
,
3719 if (!entry
->mListenerManager
) {
3721 NS_NewEventListenerManager(getter_AddRefs(entry
->mListenerManager
));
3723 if (NS_FAILED(rv
)) {
3724 PL_DHashTableRawRemove(&sEventListenerManagersHash
, entry
);
3729 entry
->mListenerManager
->SetListenerTarget(aNode
);
3731 aNode
->SetFlags(NODE_HAS_LISTENERMANAGER
);
3734 return entry
->mListenerManager
;
3739 nsContentUtils::RemoveListenerManager(nsINode
*aNode
)
3741 if (sEventListenerManagersHash
.ops
) {
3742 EventListenerManagerMapEntry
*entry
=
3743 static_cast<EventListenerManagerMapEntry
*>
3744 (PL_DHashTableOperate(&sEventListenerManagersHash
, aNode
,
3746 if (PL_DHASH_ENTRY_IS_BUSY(entry
)) {
3747 nsCOMPtr
<nsIEventListenerManager
> listenerManager
;
3748 listenerManager
.swap(entry
->mListenerManager
);
3749 // Remove the entry and *then* do operations that could cause further
3750 // modification of sEventListenerManagersHash. See bug 334177.
3751 PL_DHashTableRawRemove(&sEventListenerManagersHash
, entry
);
3752 if (listenerManager
) {
3753 listenerManager
->Disconnect();
3761 nsContentUtils::IsValidNodeName(nsIAtom
*aLocalName
, nsIAtom
*aPrefix
,
3762 PRInt32 aNamespaceID
)
3764 if (aNamespaceID
== kNameSpaceID_Unknown
) {
3769 // If the prefix is null, then either the QName must be xmlns or the
3770 // namespace must not be XMLNS.
3771 return (aLocalName
== nsGkAtoms::xmlns
) ==
3772 (aNamespaceID
== kNameSpaceID_XMLNS
);
3775 // If the prefix is non-null then the namespace must not be null.
3776 if (aNamespaceID
== kNameSpaceID_None
) {
3780 // If the namespace is the XMLNS namespace then the prefix must be xmlns,
3781 // but the localname must not be xmlns.
3782 if (aNamespaceID
== kNameSpaceID_XMLNS
) {
3783 return aPrefix
== nsGkAtoms::xmlns
&& aLocalName
!= nsGkAtoms::xmlns
;
3786 // If the namespace is not the XMLNS namespace then the prefix must not be
3788 // If the namespace is the XML namespace then the prefix can be anything.
3789 // If the namespace is not the XML namespace then the prefix must not be xml.
3790 return aPrefix
!= nsGkAtoms::xmlns
&&
3791 (aNamespaceID
== kNameSpaceID_XML
|| aPrefix
!= nsGkAtoms::xml
);
3796 nsContentUtils::CreateContextualFragment(nsINode
* aContextNode
,
3797 const nsAString
& aFragment
,
3798 PRBool aWillOwnFragment
,
3799 nsIDOMDocumentFragment
** aReturn
)
3802 NS_ENSURE_ARG(aContextNode
);
3806 // If we don't have a document here, we can't get the right security context
3807 // for compiling event handlers... so just bail out.
3808 nsCOMPtr
<nsIDocument
> document
= aContextNode
->GetOwnerDoc();
3809 NS_ENSURE_TRUE(document
, NS_ERROR_NOT_AVAILABLE
);
3811 PRBool isHTML
= document
->IsHTML();
3813 nsCOMPtr
<nsIHTMLDocument
> htmlDoc
= do_QueryInterface(document
);
3814 NS_ASSERTION(!isHTML
|| htmlDoc
, "Should have HTMLDocument here!");
3817 if (isHTML
&& nsHtml5Module::sEnabled
) {
3818 // See if the document has a cached fragment parser. nsHTMLDocument is the
3819 // only one that should really have one at the moment.
3820 nsCOMPtr
<nsIParser
> parser
= document
->GetFragmentParser();
3822 // Get the parser ready to use.
3826 // Create a new parser for this operation.
3827 parser
= nsHtml5Module::NewHtml5Parser();
3829 return NS_ERROR_OUT_OF_MEMORY
;
3832 nsCOMPtr
<nsIDOMDocumentFragment
> frag
;
3833 rv
= NS_NewDocumentFragment(getter_AddRefs(frag
), document
->NodeInfoManager());
3834 NS_ENSURE_SUCCESS(rv
, rv
);
3836 nsCOMPtr
<nsIContent
> contextAsContent
= do_QueryInterface(aContextNode
);
3837 if (contextAsContent
&& !contextAsContent
->IsElement()) {
3838 contextAsContent
= contextAsContent
->GetParent();
3839 if (contextAsContent
&& !contextAsContent
->IsElement()) {
3840 // can this even happen?
3841 contextAsContent
= nsnull
;
3845 nsAHtml5FragmentParser
* asFragmentParser
=
3846 static_cast<nsAHtml5FragmentParser
*> (parser
.get());
3847 nsCOMPtr
<nsIContent
> fragment
= do_QueryInterface(frag
);
3848 if (contextAsContent
&&
3849 !(nsGkAtoms::html
== contextAsContent
->Tag() &&
3850 contextAsContent
->IsHTML())) {
3851 asFragmentParser
->ParseHtml5Fragment(aFragment
,
3853 contextAsContent
->Tag(),
3854 contextAsContent
->GetNameSpaceID(),
3855 (document
->GetCompatibilityMode() ==
3856 eCompatibility_NavQuirks
),
3859 asFragmentParser
->ParseHtml5Fragment(aFragment
,
3863 (document
->GetCompatibilityMode() ==
3864 eCompatibility_NavQuirks
),
3868 frag
.swap(*aReturn
);
3869 document
->SetFragmentParser(parser
);
3873 nsAutoTArray
<nsString
, 32> tagStack
;
3874 nsAutoString uriStr
, nameStr
;
3875 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(aContextNode
);
3876 // just in case we have a text node
3877 if (content
&& !content
->IsElement())
3878 content
= content
->GetParent();
3880 while (content
&& content
->IsElement()) {
3881 nsString
& tagName
= *tagStack
.AppendElement();
3882 NS_ENSURE_TRUE(&tagName
, NS_ERROR_OUT_OF_MEMORY
);
3884 content
->NodeInfo()->GetQualifiedName(tagName
);
3886 // see if we need to add xmlns declarations
3887 PRUint32 count
= content
->GetAttrCount();
3888 PRBool setDefaultNamespace
= PR_FALSE
;
3892 for (index
= 0; index
< count
; index
++) {
3893 const nsAttrName
* name
= content
->GetAttrNameAt(index
);
3894 if (name
->NamespaceEquals(kNameSpaceID_XMLNS
)) {
3895 content
->GetAttr(kNameSpaceID_XMLNS
, name
->LocalName(), uriStr
);
3897 // really want something like nsXMLContentSerializer::SerializeAttr
3898 tagName
.Append(NS_LITERAL_STRING(" xmlns")); // space important
3899 if (name
->GetPrefix()) {
3900 tagName
.Append(PRUnichar(':'));
3901 name
->LocalName()->ToString(nameStr
);
3902 tagName
.Append(nameStr
);
3904 setDefaultNamespace
= PR_TRUE
;
3906 tagName
.Append(NS_LITERAL_STRING("=\"") + uriStr
+
3907 NS_LITERAL_STRING("\""));
3912 if (!setDefaultNamespace
) {
3913 nsINodeInfo
* info
= content
->NodeInfo();
3914 if (!info
->GetPrefixAtom() &&
3915 info
->NamespaceID() != kNameSpaceID_None
) {
3916 // We have no namespace prefix, but have a namespace ID. Push
3917 // default namespace attr in, so that our kids will be in our
3919 info
->GetNamespaceURI(uriStr
);
3920 tagName
.Append(NS_LITERAL_STRING(" xmlns=\"") + uriStr
+
3921 NS_LITERAL_STRING("\""));
3925 content
= content
->GetParent();
3928 nsCAutoString contentType
;
3930 document
->GetContentType(buf
);
3931 LossyCopyUTF16toASCII(buf
, contentType
);
3933 // See if the document has a cached fragment parser. nsHTMLDocument is the
3934 // only one that should really have one at the moment.
3935 nsCOMPtr
<nsIParser
> parser
= document
->GetFragmentParser();
3937 // Get the parser ready to use.
3941 // Create a new parser for this operation.
3942 parser
= do_CreateInstance(kCParserCID
, &rv
);
3943 NS_ENSURE_SUCCESS(rv
, rv
);
3946 // See if the parser already has a content sink that we can reuse.
3947 nsCOMPtr
<nsIFragmentContentSink
> sink
;
3948 nsCOMPtr
<nsIContentSink
> contentsink
= parser
->GetContentSink();
3950 // Make sure it's the correct type.
3952 nsCOMPtr
<nsIHTMLContentSink
> htmlsink
= do_QueryInterface(contentsink
);
3953 sink
= do_QueryInterface(htmlsink
);
3956 nsCOMPtr
<nsIXMLContentSink
> xmlsink
= do_QueryInterface(contentsink
);
3957 sink
= do_QueryInterface(xmlsink
);
3962 // Either there was no cached content sink or it was the wrong type. Make a
3965 rv
= NS_NewHTMLFragmentContentSink(getter_AddRefs(sink
));
3967 rv
= NS_NewXMLFragmentContentSink(getter_AddRefs(sink
));
3969 NS_ENSURE_SUCCESS(rv
, rv
);
3971 contentsink
= do_QueryInterface(sink
);
3972 NS_ASSERTION(contentsink
, "Sink doesn't QI to nsIContentSink!");
3974 parser
->SetContentSink(contentsink
);
3977 sink
->SetTargetDocument(document
);
3979 nsDTDMode mode
= eDTDMode_autodetect
;
3980 switch (document
->GetCompatibilityMode()) {
3981 case eCompatibility_NavQuirks
:
3982 mode
= eDTDMode_quirks
;
3984 case eCompatibility_AlmostStandards
:
3985 mode
= eDTDMode_almost_standards
;
3987 case eCompatibility_FullStandards
:
3988 mode
= eDTDMode_full_standards
;
3991 NS_NOTREACHED("unknown mode");
3995 rv
= parser
->ParseFragment(aFragment
, nsnull
, tagStack
,
3996 !isHTML
, contentType
, mode
);
3997 if (NS_SUCCEEDED(rv
)) {
3998 rv
= sink
->GetFragment(aWillOwnFragment
, aReturn
);
4001 document
->SetFragmentParser(parser
);
4008 nsContentUtils::CreateDocument(const nsAString
& aNamespaceURI
,
4009 const nsAString
& aQualifiedName
,
4010 nsIDOMDocumentType
* aDoctype
,
4011 nsIURI
* aDocumentURI
, nsIURI
* aBaseURI
,
4012 nsIPrincipal
* aPrincipal
,
4013 nsIScriptGlobalObject
* aEventObject
,
4014 nsIDOMDocument
** aResult
)
4016 nsresult rv
= NS_NewDOMDocument(aResult
, aNamespaceURI
, aQualifiedName
,
4017 aDoctype
, aDocumentURI
, aBaseURI
, aPrincipal
,
4019 NS_ENSURE_SUCCESS(rv
, rv
);
4021 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(*aResult
);
4022 document
->SetScriptHandlingObject(aEventObject
);
4024 // created documents are immediately "complete" (ready to use)
4025 document
->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE
);
4031 nsContentUtils::SetNodeTextContent(nsIContent
* aContent
,
4032 const nsAString
& aValue
,
4035 // Might as well stick a batch around this since we're performing several
4037 mozAutoDocUpdate
updateBatch(aContent
->GetCurrentDoc(),
4038 UPDATE_CONTENT_MODEL
, PR_TRUE
);
4040 PRUint32 childCount
= aContent
->GetChildCount();
4042 if (aTryReuse
&& !aValue
.IsEmpty()) {
4043 PRUint32 removeIndex
= 0;
4045 // i is unsigned, so i >= is always true
4046 for (PRUint32 i
= 0; i
< childCount
; ++i
) {
4047 nsIContent
* child
= aContent
->GetChildAt(removeIndex
);
4048 if (removeIndex
== 0 && child
&& child
->IsNodeOfType(nsINode::eTEXT
)) {
4049 nsresult rv
= child
->SetText(aValue
, PR_TRUE
);
4050 NS_ENSURE_SUCCESS(rv
, rv
);
4055 aContent
->RemoveChildAt(removeIndex
, PR_TRUE
);
4059 if (removeIndex
== 1) {
4064 // i is unsigned, so i >= is always true
4065 for (PRUint32 i
= childCount
; i
-- != 0; ) {
4066 aContent
->RemoveChildAt(i
, PR_TRUE
);
4070 if (aValue
.IsEmpty()) {
4074 nsCOMPtr
<nsIContent
> textContent
;
4075 nsresult rv
= NS_NewTextNode(getter_AddRefs(textContent
),
4076 aContent
->NodeInfo()->NodeInfoManager());
4077 NS_ENSURE_SUCCESS(rv
, rv
);
4079 textContent
->SetText(aValue
, PR_TRUE
);
4081 return aContent
->AppendChildTo(textContent
, PR_TRUE
);
4084 static void AppendNodeTextContentsRecurse(nsINode
* aNode
, nsAString
& aResult
)
4088 for (i
= 0; (child
= aNode
->GetChildAt(i
)); ++i
) {
4089 if (child
->IsElement()) {
4090 AppendNodeTextContentsRecurse(child
, aResult
);
4092 else if (child
->IsNodeOfType(nsINode::eTEXT
)) {
4093 child
->AppendTextTo(aResult
);
4100 nsContentUtils::AppendNodeTextContent(nsINode
* aNode
, PRBool aDeep
,
4103 if (aNode
->IsNodeOfType(nsINode::eTEXT
)) {
4104 static_cast<nsIContent
*>(aNode
)->AppendTextTo(aResult
);
4107 AppendNodeTextContentsRecurse(aNode
, aResult
);
4112 for (i
= 0; (child
= aNode
->GetChildAt(i
)); ++i
) {
4113 if (child
->IsNodeOfType(nsINode::eTEXT
)) {
4114 child
->AppendTextTo(aResult
);
4121 nsContentUtils::HasNonEmptyTextContent(nsINode
* aNode
)
4125 for (i
= 0; (child
= aNode
->GetChildAt(i
)); ++i
) {
4126 if (child
->IsNodeOfType(nsINode::eTEXT
) &&
4127 child
->TextLength() > 0) {
4137 nsContentUtils::IsInSameAnonymousTree(const nsINode
* aNode
,
4138 const nsIContent
* aContent
)
4140 NS_PRECONDITION(aNode
,
4141 "Must have a node to work with");
4142 NS_PRECONDITION(aContent
,
4143 "Must have a content to work with");
4145 if (!aNode
->IsNodeOfType(nsINode::eCONTENT
)) {
4147 * The root isn't an nsIContent, so it's a document or attribute. The only
4148 * nodes in the same anonymous subtree as it will have a null
4151 * XXXbz strictly speaking, that's not true for attribute nodes.
4153 return aContent
->GetBindingParent() == nsnull
;
4156 return static_cast<const nsIContent
*>(aNode
)->GetBindingParent() ==
4157 aContent
->GetBindingParent();
4161 class AnonymousContentDestroyer
: public nsRunnable
{
4163 AnonymousContentDestroyer(nsCOMPtr
<nsIContent
>* aContent
) {
4164 mContent
.swap(*aContent
);
4165 mParent
= mContent
->GetParent();
4166 mDoc
= mContent
->GetOwnerDoc();
4169 mContent
->UnbindFromTree();
4173 nsCOMPtr
<nsIContent
> mContent
;
4174 // Hold strong refs to the parent content and document so that they
4175 // don't die unexpectedly
4176 nsCOMPtr
<nsIDocument
> mDoc
;
4177 nsCOMPtr
<nsIContent
> mParent
;
4182 nsContentUtils::DestroyAnonymousContent(nsCOMPtr
<nsIContent
>* aContent
)
4185 AddScriptRunner(new AnonymousContentDestroyer(aContent
));
4190 nsIDOMScriptObjectFactory
*
4191 nsContentUtils::GetDOMScriptObjectFactory()
4193 if (!sDOMScriptObjectFactory
) {
4194 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID
,
4195 NS_DOM_SCRIPT_OBJECT_FACTORY_CID
);
4197 CallGetService(kDOMScriptObjectFactoryCID
, &sDOMScriptObjectFactory
);
4200 return sDOMScriptObjectFactory
;
4205 nsContentUtils::HoldScriptObject(PRUint32 aLangID
, void *aObject
)
4207 NS_ASSERTION(aObject
, "unexpected null object");
4208 NS_ASSERTION(aLangID
!= nsIProgrammingLanguage::JAVASCRIPT
,
4209 "Should use HoldJSObjects.");
4212 PRUint32 langIndex
= NS_STID_INDEX(aLangID
);
4213 nsIScriptRuntime
*runtime
= sScriptRuntimes
[langIndex
];
4215 nsIDOMScriptObjectFactory
*factory
= GetDOMScriptObjectFactory();
4216 NS_ENSURE_TRUE(factory
, NS_ERROR_FAILURE
);
4218 rv
= factory
->GetScriptRuntimeByID(aLangID
, &runtime
);
4219 NS_ENSURE_SUCCESS(rv
, rv
);
4221 // This makes sScriptRuntimes hold a strong ref.
4222 sScriptRuntimes
[langIndex
] = runtime
;
4225 rv
= runtime
->HoldScriptObject(aObject
);
4226 NS_ENSURE_SUCCESS(rv
, rv
);
4228 ++sScriptRootCount
[langIndex
];
4229 NS_LOG_ADDREF(sScriptRuntimes
[langIndex
], sScriptRootCount
[langIndex
],
4230 "HoldScriptObject", sizeof(void*));
4237 nsContentUtils::DropScriptObject(PRUint32 aLangID
, void *aObject
,
4240 NS_ASSERTION(aObject
, "unexpected null object");
4241 NS_ASSERTION(aLangID
!= nsIProgrammingLanguage::JAVASCRIPT
,
4242 "Should use DropJSObjects.");
4243 PRUint32 langIndex
= NS_STID_INDEX(aLangID
);
4244 NS_LOG_RELEASE(sScriptRuntimes
[langIndex
], sScriptRootCount
[langIndex
] - 1,
4245 "HoldScriptObject");
4246 sScriptRuntimes
[langIndex
]->DropScriptObject(aObject
);
4247 if (--sScriptRootCount
[langIndex
] == 0) {
4248 NS_RELEASE(sScriptRuntimes
[langIndex
]);
4254 nsContentUtils::HoldJSObjects(void* aScriptObjectHolder
,
4255 nsScriptObjectTracer
* aTracer
)
4257 NS_ENSURE_TRUE(sXPConnect
, NS_ERROR_UNEXPECTED
);
4259 nsresult rv
= sXPConnect
->AddJSHolder(aScriptObjectHolder
, aTracer
);
4260 NS_ENSURE_SUCCESS(rv
, rv
);
4262 if (sJSGCThingRootCount
++ == 0) {
4263 nsLayoutStatics::AddRef();
4265 NS_LOG_ADDREF(sXPConnect
, sJSGCThingRootCount
, "HoldJSObjects",
4273 nsContentUtils::DropJSObjects(void* aScriptObjectHolder
)
4275 NS_LOG_RELEASE(sXPConnect
, sJSGCThingRootCount
- 1, "HoldJSObjects");
4276 nsresult rv
= sXPConnect
->RemoveJSHolder(aScriptObjectHolder
);
4277 if (--sJSGCThingRootCount
== 0) {
4278 nsLayoutStatics::Release();
4285 nsContentUtils::GetWidgetStatusFromIMEStatus(PRUint32 aState
)
4287 switch (aState
& nsIContent::IME_STATUS_MASK_ENABLED
) {
4288 case nsIContent::IME_STATUS_DISABLE
:
4289 return nsIWidget::IME_STATUS_DISABLED
;
4290 case nsIContent::IME_STATUS_ENABLE
:
4291 return nsIWidget::IME_STATUS_ENABLED
;
4292 case nsIContent::IME_STATUS_PASSWORD
:
4293 return nsIWidget::IME_STATUS_PASSWORD
;
4294 case nsIContent::IME_STATUS_PLUGIN
:
4295 return nsIWidget::IME_STATUS_PLUGIN
;
4297 NS_ERROR("The given state doesn't have valid enable state");
4298 return nsIWidget::IME_STATUS_ENABLED
;
4304 nsContentUtils::NotifyInstalledMenuKeyboardListener(PRBool aInstalling
)
4306 nsIMEStateManager::OnInstalledMenuKeyboardListener(aInstalling
);
4309 static PRBool
SchemeIs(nsIURI
* aURI
, const char* aScheme
)
4311 nsCOMPtr
<nsIURI
> baseURI
= NS_GetInnermostURI(aURI
);
4312 NS_ENSURE_TRUE(baseURI
, PR_FALSE
);
4314 PRBool isScheme
= PR_FALSE
;
4315 return NS_SUCCEEDED(baseURI
->SchemeIs(aScheme
, &isScheme
)) && isScheme
;
4320 nsContentUtils::CheckSecurityBeforeLoad(nsIURI
* aURIToLoad
,
4321 nsIPrincipal
* aLoadingPrincipal
,
4322 PRUint32 aCheckLoadFlags
,
4324 PRUint32 aContentPolicyType
,
4325 nsISupports
* aContext
,
4326 const nsACString
& aMimeGuess
,
4327 nsISupports
* aExtra
)
4329 NS_PRECONDITION(aLoadingPrincipal
, "Must have a loading principal here");
4331 PRBool isSystemPrin
= PR_FALSE
;
4332 if (NS_SUCCEEDED(sSecurityManager
->IsSystemPrincipal(aLoadingPrincipal
,
4338 // XXXbz do we want to fast-path skin stylesheets loading XBL here somehow?
4339 // CheckLoadURIWithPrincipal
4340 nsresult rv
= sSecurityManager
->
4341 CheckLoadURIWithPrincipal(aLoadingPrincipal
, aURIToLoad
, aCheckLoadFlags
);
4342 NS_ENSURE_SUCCESS(rv
, rv
);
4345 PRInt16 shouldLoad
= nsIContentPolicy::ACCEPT
;
4346 rv
= NS_CheckContentLoadPolicy(aContentPolicyType
,
4355 NS_ENSURE_SUCCESS(rv
, rv
);
4356 if (NS_CP_REJECTED(shouldLoad
)) {
4357 return NS_ERROR_CONTENT_BLOCKED
;
4361 if ((aAllowData
&& SchemeIs(aURIToLoad
, "data")) ||
4362 ((aCheckLoadFlags
& nsIScriptSecurityManager::ALLOW_CHROME
) &&
4363 SchemeIs(aURIToLoad
, "chrome"))) {
4367 return aLoadingPrincipal
->CheckMayLoad(aURIToLoad
, PR_TRUE
);
4371 nsContentUtils::IsSystemPrincipal(nsIPrincipal
* aPrincipal
)
4374 nsresult rv
= sSecurityManager
->IsSystemPrincipal(aPrincipal
, &isSystem
);
4375 return NS_SUCCEEDED(rv
) && isSystem
;
4380 nsContentUtils::TriggerLink(nsIContent
*aContent
, nsPresContext
*aPresContext
,
4381 nsIURI
*aLinkURI
, const nsString
&aTargetSpec
,
4382 PRBool aClick
, PRBool aIsUserTriggered
)
4384 NS_ASSERTION(aPresContext
, "Need a nsPresContext");
4385 NS_PRECONDITION(aLinkURI
, "No link URI");
4387 if (aContent
->IsEditable()) {
4391 nsILinkHandler
*handler
= aPresContext
->GetLinkHandler();
4397 handler
->OnOverLink(aContent
, aLinkURI
, aTargetSpec
.get());
4402 // Check that this page is allowed to load this URI.
4403 nsresult proceed
= NS_OK
;
4405 if (sSecurityManager
) {
4408 (PRUint32
)nsIScriptSecurityManager::STANDARD
:
4409 (PRUint32
)nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT
;
4411 sSecurityManager
->CheckLoadURIWithPrincipal(aContent
->NodePrincipal(),
4415 // Only pass off the click event if the script security manager says it's ok.
4416 if (NS_SUCCEEDED(proceed
)) {
4417 handler
->OnLinkClick(aContent
, aLinkURI
, aTargetSpec
.get());
4423 nsContentUtils::GetTopLevelWidget(nsIWidget
* aWidget
)
4428 return aWidget
->GetTopLevelWidget();
4432 const nsDependentString
4433 nsContentUtils::GetLocalizedEllipsis()
4435 static PRUnichar sBuf
[4] = { 0, 0, 0, 0 };
4437 nsAutoString
tmp(GetLocalizedStringPref("intl.ellipsis"));
4438 PRUint32 len
= NS_MIN(PRUint32(tmp
.Length()),
4439 PRUint32(NS_ARRAY_LENGTH(sBuf
) - 1));
4440 CopyUnicodeTo(tmp
, 0, sBuf
, len
);
4442 sBuf
[0] = PRUnichar(0x2026);
4444 return nsDependentString(sBuf
);
4449 nsContentUtils::GetNativeEvent(nsIDOMEvent
* aDOMEvent
)
4451 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aDOMEvent
));
4454 return privateEvent
->GetInternalNSEvent();
4459 nsContentUtils::DOMEventToNativeKeyEvent(nsIDOMKeyEvent
* aKeyEvent
,
4460 nsNativeKeyEvent
* aNativeEvent
,
4461 PRBool aGetCharCode
)
4463 nsCOMPtr
<nsIDOMNSUIEvent
> uievent
= do_QueryInterface(aKeyEvent
);
4464 PRBool defaultPrevented
;
4465 uievent
->GetPreventDefault(&defaultPrevented
);
4466 if (defaultPrevented
)
4469 nsCOMPtr
<nsIDOMNSEvent
> nsevent
= do_QueryInterface(aKeyEvent
);
4470 PRBool trusted
= PR_FALSE
;
4471 nsevent
->GetIsTrusted(&trusted
);
4476 aKeyEvent
->GetCharCode(&aNativeEvent
->charCode
);
4478 aNativeEvent
->charCode
= 0;
4480 aKeyEvent
->GetKeyCode(&aNativeEvent
->keyCode
);
4481 aKeyEvent
->GetAltKey(&aNativeEvent
->altKey
);
4482 aKeyEvent
->GetCtrlKey(&aNativeEvent
->ctrlKey
);
4483 aKeyEvent
->GetShiftKey(&aNativeEvent
->shiftKey
);
4484 aKeyEvent
->GetMetaKey(&aNativeEvent
->metaKey
);
4486 aNativeEvent
->nativeEvent
= GetNativeEvent(aKeyEvent
);
4492 HasASCIIDigit(const nsTArray
<nsShortcutCandidate
>& aCandidates
)
4494 for (PRUint32 i
= 0; i
< aCandidates
.Length(); ++i
) {
4495 PRUint32 ch
= aCandidates
[i
].mCharCode
;
4496 if (ch
>= '0' && ch
<= '9')
4503 CharsCaseInsensitiveEqual(PRUint32 aChar1
, PRUint32 aChar2
)
4505 return aChar1
== aChar2
||
4506 (IS_IN_BMP(aChar1
) && IS_IN_BMP(aChar2
) &&
4507 ToLowerCase(PRUnichar(aChar1
)) == ToLowerCase(PRUnichar(aChar2
)));
4511 IsCaseChangeableChar(PRUint32 aChar
)
4513 return IS_IN_BMP(aChar
) &&
4514 ToLowerCase(PRUnichar(aChar
)) != ToUpperCase(PRUnichar(aChar
));
4519 nsContentUtils::GetAccelKeyCandidates(nsIDOMKeyEvent
* aDOMKeyEvent
,
4520 nsTArray
<nsShortcutCandidate
>& aCandidates
)
4522 NS_PRECONDITION(aCandidates
.IsEmpty(), "aCandidates must be empty");
4524 nsAutoString eventType
;
4525 aDOMKeyEvent
->GetType(eventType
);
4526 // Don't process if aDOMKeyEvent is not a keypress event.
4527 if (!eventType
.EqualsLiteral("keypress"))
4530 nsKeyEvent
* nativeKeyEvent
=
4531 static_cast<nsKeyEvent
*>(GetNativeEvent(aDOMKeyEvent
));
4532 if (nativeKeyEvent
) {
4533 NS_ASSERTION(nativeKeyEvent
->eventStructType
== NS_KEY_EVENT
,
4534 "wrong type of native event");
4535 // nsShortcutCandidate::mCharCode is a candidate charCode.
4536 // nsShoftcutCandidate::mIgnoreShift means the mCharCode should be tried to
4537 // execute a command with/without shift key state. If this is TRUE, the
4538 // shifted key state should be ignored. Otherwise, don't ignore the state.
4539 // the priority of the charCodes are (shift key is not pressed):
4540 // 0: charCode/PR_FALSE,
4541 // 1: unshiftedCharCodes[0]/PR_FALSE, 2: unshiftedCharCodes[1]/PR_FALSE...
4542 // the priority of the charCodes are (shift key is pressed):
4543 // 0: charCode/PR_FALSE,
4544 // 1: shiftedCharCodes[0]/PR_FALSE, 2: shiftedCharCodes[0]/PR_TRUE,
4545 // 3: shiftedCharCodes[1]/PR_FALSE, 4: shiftedCharCodes[1]/PR_TRUE...
4546 if (nativeKeyEvent
->charCode
) {
4547 nsShortcutCandidate
key(nativeKeyEvent
->charCode
, PR_FALSE
);
4548 aCandidates
.AppendElement(key
);
4551 PRUint32 len
= nativeKeyEvent
->alternativeCharCodes
.Length();
4552 if (!nativeKeyEvent
->isShift
) {
4553 for (PRUint32 i
= 0; i
< len
; ++i
) {
4555 nativeKeyEvent
->alternativeCharCodes
[i
].mUnshiftedCharCode
;
4556 if (!ch
|| ch
== nativeKeyEvent
->charCode
)
4559 nsShortcutCandidate
key(ch
, PR_FALSE
);
4560 aCandidates
.AppendElement(key
);
4562 // If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
4563 // this keyboard layout is AZERTY or similar layout, probably.
4564 // In this case, Accel+[0-9] should be accessible without shift key.
4565 // However, the priority should be lowest.
4566 if (!HasASCIIDigit(aCandidates
)) {
4567 for (PRUint32 i
= 0; i
< len
; ++i
) {
4569 nativeKeyEvent
->alternativeCharCodes
[i
].mShiftedCharCode
;
4570 if (ch
>= '0' && ch
<= '9') {
4571 nsShortcutCandidate
key(ch
, PR_FALSE
);
4572 aCandidates
.AppendElement(key
);
4578 for (PRUint32 i
= 0; i
< len
; ++i
) {
4579 PRUint32 ch
= nativeKeyEvent
->alternativeCharCodes
[i
].mShiftedCharCode
;
4583 if (ch
!= nativeKeyEvent
->charCode
) {
4584 nsShortcutCandidate
key(ch
, PR_FALSE
);
4585 aCandidates
.AppendElement(key
);
4588 // If the char is an alphabet, the shift key state should not be
4589 // ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
4591 // And checking the charCode is same as unshiftedCharCode too.
4592 // E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
4593 PRUint32 unshiftCh
=
4594 nativeKeyEvent
->alternativeCharCodes
[i
].mUnshiftedCharCode
;
4595 if (CharsCaseInsensitiveEqual(ch
, unshiftCh
))
4598 // On the Hebrew keyboard layout on Windows, the unshifted char is a
4599 // localized character but the shifted char is a Latin alphabet,
4600 // then, we should not execute without the shift state. See bug 433192.
4601 if (IsCaseChangeableChar(ch
))
4604 // Setting the alternative charCode candidates for retry without shift
4605 // key state only when the shift key is pressed.
4606 nsShortcutCandidate
key(ch
, PR_TRUE
);
4607 aCandidates
.AppendElement(key
);
4612 aDOMKeyEvent
->GetCharCode(&charCode
);
4614 nsShortcutCandidate
key(charCode
, PR_FALSE
);
4615 aCandidates
.AppendElement(key
);
4622 nsContentUtils::GetAccessKeyCandidates(nsKeyEvent
* aNativeKeyEvent
,
4623 nsTArray
<PRUint32
>& aCandidates
)
4625 NS_PRECONDITION(aCandidates
.IsEmpty(), "aCandidates must be empty");
4627 // return the lower cased charCode candidates for access keys.
4628 // the priority of the charCodes are:
4629 // 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
4630 // 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
4631 if (aNativeKeyEvent
->charCode
) {
4632 PRUint32 ch
= aNativeKeyEvent
->charCode
;
4634 ch
= ToLowerCase(PRUnichar(ch
));
4635 aCandidates
.AppendElement(ch
);
4637 for (PRUint32 i
= 0;
4638 i
< aNativeKeyEvent
->alternativeCharCodes
.Length(); ++i
) {
4640 { aNativeKeyEvent
->alternativeCharCodes
[i
].mUnshiftedCharCode
,
4641 aNativeKeyEvent
->alternativeCharCodes
[i
].mShiftedCharCode
};
4642 for (PRUint32 j
= 0; j
< 2; ++j
) {
4645 if (IS_IN_BMP(ch
[j
]))
4646 ch
[j
] = ToLowerCase(PRUnichar(ch
[j
]));
4647 // Don't append the charCode that was already appended.
4648 if (aCandidates
.IndexOf(ch
[j
]) == aCandidates
.NoIndex
)
4649 aCandidates
.AppendElement(ch
[j
]);
4657 nsContentUtils::AddScriptBlocker()
4659 if (!sScriptBlockerCount
) {
4660 NS_ASSERTION(sRunnersCountAtFirstBlocker
== 0,
4661 "Should not already have a count");
4662 sRunnersCountAtFirstBlocker
= sBlockedScriptRunners
->Count();
4664 ++sScriptBlockerCount
;
4669 nsContentUtils::AddScriptBlockerAndPreventAddingRunners()
4672 if (sScriptBlockerCountWhereRunnersPrevented
== 0) {
4673 sScriptBlockerCountWhereRunnersPrevented
= sScriptBlockerCount
;
4679 nsContentUtils::RemoveScriptBlocker()
4681 NS_ASSERTION(sScriptBlockerCount
!= 0, "Negative script blockers");
4682 --sScriptBlockerCount
;
4683 if (sScriptBlockerCount
< sScriptBlockerCountWhereRunnersPrevented
) {
4684 sScriptBlockerCountWhereRunnersPrevented
= 0;
4686 if (sScriptBlockerCount
) {
4690 PRUint32 firstBlocker
= sRunnersCountAtFirstBlocker
;
4691 PRUint32 lastBlocker
= (PRUint32
)sBlockedScriptRunners
->Count();
4692 sRunnersCountAtFirstBlocker
= 0;
4693 NS_ASSERTION(firstBlocker
<= lastBlocker
,
4694 "bad sRunnersCountAtFirstBlocker");
4696 while (firstBlocker
< lastBlocker
) {
4697 nsCOMPtr
<nsIRunnable
> runnable
= (*sBlockedScriptRunners
)[firstBlocker
];
4698 sBlockedScriptRunners
->RemoveObjectAt(firstBlocker
);
4702 NS_ASSERTION(lastBlocker
== (PRUint32
)sBlockedScriptRunners
->Count() &&
4703 sRunnersCountAtFirstBlocker
== 0,
4705 NS_ASSERTION(!sScriptBlockerCount
, "This is really bad");
4711 nsContentUtils::AddScriptRunner(nsIRunnable
* aRunnable
)
4717 if (sScriptBlockerCount
) {
4718 if (sScriptBlockerCountWhereRunnersPrevented
> 0) {
4719 NS_ERROR("Adding a script runner when that is prevented!");
4722 return sBlockedScriptRunners
->AppendObject(aRunnable
);
4725 nsCOMPtr
<nsIRunnable
> run
= aRunnable
;
4732 * Helper function for nsContentUtils::ProcessViewportInfo.
4734 * Handles a single key=value pair. If it corresponds to a valid viewport
4735 * attribute, add it to the document header data. No validation is done on the
4736 * value itself (this is done at display time).
4738 static void ProcessViewportToken(nsIDocument
*aDocument
,
4739 const nsAString
&token
) {
4742 nsAString::const_iterator tip
, tail
, end
;
4743 token
.BeginReading(tip
);
4745 token
.EndReading(end
);
4747 /* Move tip to the '='. */
4748 while ((tip
!= end
) && (*tip
!= '='))
4751 /* If we didn't find an '=', punt. */
4755 /* Extract the key and value. */
4756 const nsAString
&key
=
4757 nsContentUtils::TrimWhitespace
<nsCRT::IsAsciiSpace
>(Substring(tail
, tip
),
4759 const nsAString
&value
=
4760 nsContentUtils::TrimWhitespace
<nsCRT::IsAsciiSpace
>(Substring(++tip
, end
),
4763 /* Check for known keys. If we find a match, insert the appropriate
4764 * information into the document header. */
4765 nsCOMPtr
<nsIAtom
> key_atom
= do_GetAtom(key
);
4766 if (key_atom
== nsGkAtoms::height
)
4767 aDocument
->SetHeaderData(nsGkAtoms::viewport_height
, value
);
4768 else if (key_atom
== nsGkAtoms::width
)
4769 aDocument
->SetHeaderData(nsGkAtoms::viewport_width
, value
);
4770 else if (key_atom
== nsGkAtoms::initial_scale
)
4771 aDocument
->SetHeaderData(nsGkAtoms::viewport_initial_scale
, value
);
4772 else if (key_atom
== nsGkAtoms::minimum_scale
)
4773 aDocument
->SetHeaderData(nsGkAtoms::viewport_minimum_scale
, value
);
4774 else if (key_atom
== nsGkAtoms::maximum_scale
)
4775 aDocument
->SetHeaderData(nsGkAtoms::viewport_maximum_scale
, value
);
4776 else if (key_atom
== nsGkAtoms::user_scalable
)
4777 aDocument
->SetHeaderData(nsGkAtoms::viewport_user_scalable
, value
);
4780 #define IS_SEPARATOR(c) ((c == '=') || (c == ',') || (c == ';') || \
4781 (c == '\t') || (c == '\n') || (c == '\r'))
4785 nsContentUtils::ProcessViewportInfo(nsIDocument
*aDocument
,
4786 const nsAString
&viewportInfo
) {
4788 /* We never fail. */
4789 nsresult rv
= NS_OK
;
4792 nsAString::const_iterator tip
, tail
, end
;
4793 viewportInfo
.BeginReading(tip
);
4795 viewportInfo
.EndReading(end
);
4797 /* Read the tip to the first non-separator character. */
4798 while ((tip
!= end
) && (IS_SEPARATOR(*tip
) || nsCRT::IsAsciiSpace(*tip
)))
4801 /* Read through and find tokens separated by separators. */
4802 while (tip
!= end
) {
4804 /* Synchronize tip and tail. */
4807 /* Advance tip past non-separator characters. */
4808 while ((tip
!= end
) && !IS_SEPARATOR(*tip
))
4811 /* Allow white spaces that surround the '=' character */
4812 if ((tip
!= end
) && (*tip
== '=')) {
4815 while ((tip
!= end
) && nsCRT::IsAsciiSpace(*tip
))
4818 while ((tip
!= end
) && !(IS_SEPARATOR(*tip
) || nsCRT::IsAsciiSpace(*tip
)))
4822 /* Our token consists of the characters between tail and tip. */
4823 ProcessViewportToken(aDocument
, Substring(tail
, tip
));
4825 /* Skip separators. */
4826 while ((tip
!= end
) && (IS_SEPARATOR(*tip
) || nsCRT::IsAsciiSpace(*tip
)))
4838 nsContentUtils::HidePopupsInDocument(nsIDocument
* aDocument
)
4841 nsXULPopupManager
* pm
= nsXULPopupManager::GetInstance();
4842 if (pm
&& aDocument
) {
4843 nsCOMPtr
<nsISupports
> container
= aDocument
->GetContainer();
4844 nsCOMPtr
<nsIDocShellTreeItem
> docShellToHide
= do_QueryInterface(container
);
4846 pm
->HidePopupsInDocShell(docShellToHide
);
4852 already_AddRefed
<nsIDragSession
>
4853 nsContentUtils::GetDragSession()
4855 nsIDragSession
* dragSession
= nsnull
;
4856 nsCOMPtr
<nsIDragService
> dragService
=
4857 do_GetService("@mozilla.org/widget/dragservice;1");
4859 dragService
->GetCurrentSession(&dragSession
);
4865 nsContentUtils::SetDataTransferInEvent(nsDragEvent
* aDragEvent
)
4867 if (aDragEvent
->dataTransfer
|| !NS_IS_TRUSTED_EVENT(aDragEvent
))
4870 // For draggesture and dragstart events, the data transfer object is
4871 // created before the event fires, so it should already be set. For other
4872 // drag events, get the object from the drag session.
4873 NS_ASSERTION(aDragEvent
->message
!= NS_DRAGDROP_GESTURE
&&
4874 aDragEvent
->message
!= NS_DRAGDROP_START
,
4875 "draggesture event created without a dataTransfer");
4877 nsCOMPtr
<nsIDragSession
> dragSession
= GetDragSession();
4878 NS_ENSURE_TRUE(dragSession
, NS_OK
); // no drag in progress
4880 nsCOMPtr
<nsIDOMDataTransfer
> initialDataTransfer
;
4881 dragSession
->GetDataTransfer(getter_AddRefs(initialDataTransfer
));
4882 if (!initialDataTransfer
) {
4883 // A dataTransfer won't exist when a drag was started by some other
4884 // means, for instance calling the drag service directly, or a drag
4885 // from another application. In either case, a new dataTransfer should
4886 // be created that reflects the data.
4887 initialDataTransfer
=
4888 new nsDOMDataTransfer(aDragEvent
->message
);
4889 NS_ENSURE_TRUE(initialDataTransfer
, NS_ERROR_OUT_OF_MEMORY
);
4891 // now set it in the drag session so we don't need to create it again
4892 dragSession
->SetDataTransfer(initialDataTransfer
);
4895 // each event should use a clone of the original dataTransfer.
4896 nsCOMPtr
<nsIDOMNSDataTransfer
> initialDataTransferNS
=
4897 do_QueryInterface(initialDataTransfer
);
4898 NS_ENSURE_TRUE(initialDataTransferNS
, NS_ERROR_FAILURE
);
4899 initialDataTransferNS
->Clone(aDragEvent
->message
, aDragEvent
->userCancelled
,
4900 getter_AddRefs(aDragEvent
->dataTransfer
));
4901 NS_ENSURE_TRUE(aDragEvent
->dataTransfer
, NS_ERROR_OUT_OF_MEMORY
);
4903 // for the dragenter and dragover events, initialize the drop effect
4904 // from the drop action, which platform specific widget code sets before
4905 // the event is fired based on the keyboard state.
4906 if (aDragEvent
->message
== NS_DRAGDROP_ENTER
||
4907 aDragEvent
->message
== NS_DRAGDROP_OVER
) {
4908 nsCOMPtr
<nsIDOMNSDataTransfer
> newDataTransfer
=
4909 do_QueryInterface(aDragEvent
->dataTransfer
);
4910 NS_ENSURE_TRUE(newDataTransfer
, NS_ERROR_FAILURE
);
4912 PRUint32 action
, effectAllowed
;
4913 dragSession
->GetDragAction(&action
);
4914 newDataTransfer
->GetEffectAllowedInt(&effectAllowed
);
4915 newDataTransfer
->SetDropEffectInt(FilterDropEffect(action
, effectAllowed
));
4917 else if (aDragEvent
->message
== NS_DRAGDROP_DROP
||
4918 aDragEvent
->message
== NS_DRAGDROP_DRAGDROP
||
4919 aDragEvent
->message
== NS_DRAGDROP_END
) {
4920 // For the drop and dragend events, set the drop effect based on the
4921 // last value that the dropEffect had. This will have been set in
4922 // nsEventStateManager::PostHandleEvent for the last dragenter or
4924 nsCOMPtr
<nsIDOMNSDataTransfer
> newDataTransfer
=
4925 do_QueryInterface(aDragEvent
->dataTransfer
);
4926 NS_ENSURE_TRUE(newDataTransfer
, NS_ERROR_FAILURE
);
4928 PRUint32 dropEffect
;
4929 initialDataTransferNS
->GetDropEffectInt(&dropEffect
);
4930 newDataTransfer
->SetDropEffectInt(dropEffect
);
4938 nsContentUtils::FilterDropEffect(PRUint32 aAction
, PRUint32 aEffectAllowed
)
4940 // It is possible for the drag action to include more than one action, but
4941 // the widget code which sets the action from the keyboard state should only
4942 // be including one. If multiple actions were set, we just consider them in
4943 // the following order:
4945 if (aAction
& nsIDragService::DRAGDROP_ACTION_COPY
)
4946 aAction
= nsIDragService::DRAGDROP_ACTION_COPY
;
4947 else if (aAction
& nsIDragService::DRAGDROP_ACTION_LINK
)
4948 aAction
= nsIDragService::DRAGDROP_ACTION_LINK
;
4949 else if (aAction
& nsIDragService::DRAGDROP_ACTION_MOVE
)
4950 aAction
= nsIDragService::DRAGDROP_ACTION_MOVE
;
4952 // Filter the action based on the effectAllowed. If the effectAllowed
4953 // doesn't include the action, then that action cannot be done, so adjust
4954 // the action to something that is allowed. For a copy, adjust to move or
4955 // link. For a move, adjust to copy or link. For a link, adjust to move or
4956 // link. Otherwise, use none.
4957 if (aAction
& aEffectAllowed
||
4958 aEffectAllowed
== nsIDragService::DRAGDROP_ACTION_UNINITIALIZED
)
4960 if (aEffectAllowed
& nsIDragService::DRAGDROP_ACTION_MOVE
)
4961 return nsIDragService::DRAGDROP_ACTION_MOVE
;
4962 if (aEffectAllowed
& nsIDragService::DRAGDROP_ACTION_COPY
)
4963 return nsIDragService::DRAGDROP_ACTION_COPY
;
4964 if (aEffectAllowed
& nsIDragService::DRAGDROP_ACTION_LINK
)
4965 return nsIDragService::DRAGDROP_ACTION_LINK
;
4966 return nsIDragService::DRAGDROP_ACTION_NONE
;
4971 nsContentUtils::URIIsLocalFile(nsIURI
*aURI
)
4974 nsCOMPtr
<nsINetUtil
> util
= do_QueryInterface(sIOService
);
4976 return util
&& NS_SUCCEEDED(util
->ProtocolHasFlags(aURI
,
4977 nsIProtocolHandler::URI_IS_LOCAL_FILE
,
4984 nsContentUtils::GetContextForEventHandlers(nsINode
* aNode
,
4988 nsIDocument
* ownerDoc
= aNode
->GetOwnerDoc();
4990 *aRv
= NS_ERROR_UNEXPECTED
;
4994 PRBool hasHadScriptObject
= PR_TRUE
;
4995 nsIScriptGlobalObject
* sgo
=
4996 ownerDoc
->GetScriptHandlingObject(hasHadScriptObject
);
4997 // It is bad if the document doesn't have event handling context,
4998 // but it used to have one.
4999 if (!sgo
&& hasHadScriptObject
) {
5000 *aRv
= NS_ERROR_UNEXPECTED
;
5005 nsIScriptContext
* scx
= sgo
->GetContext();
5006 // Bad, no context from script global object!
5008 *aRv
= NS_ERROR_UNEXPECTED
;
5019 nsContentUtils::GetCurrentJSContext()
5021 JSContext
*cx
= nsnull
;
5023 sThreadJSContextStack
->Peek(&cx
);
5030 nsContentUtils::ASCIIToLower(nsAString
& aStr
)
5032 PRUnichar
* iter
= aStr
.BeginWriting();
5033 PRUnichar
* end
= aStr
.EndWriting();
5034 while (iter
!= end
) {
5035 PRUnichar c
= *iter
;
5036 if (c
>= 'A' && c
<= 'Z') {
5037 *iter
= c
+ ('a' - 'A');
5045 nsContentUtils::ASCIIToLower(const nsAString
& aSource
, nsAString
& aDest
)
5047 PRUint32 len
= aSource
.Length();
5048 aDest
.SetLength(len
);
5049 if (aDest
.Length() == len
) {
5050 PRUnichar
* dest
= aDest
.BeginWriting();
5051 const PRUnichar
* iter
= aSource
.BeginReading();
5052 const PRUnichar
* end
= aSource
.EndReading();
5053 while (iter
!= end
) {
5054 PRUnichar c
= *iter
;
5055 *dest
= (c
>= 'A' && c
<= 'Z') ?
5056 c
+ ('a' - 'A') : c
;
5065 nsContentUtils::ASCIIToUpper(nsAString
& aStr
)
5067 PRUnichar
* iter
= aStr
.BeginWriting();
5068 PRUnichar
* end
= aStr
.EndWriting();
5069 while (iter
!= end
) {
5070 PRUnichar c
= *iter
;
5071 if (c
>= 'a' && c
<= 'z') {
5072 *iter
= c
+ ('A' - 'a');
5080 nsContentUtils::ASCIIToUpper(const nsAString
& aSource
, nsAString
& aDest
)
5082 PRUint32 len
= aSource
.Length();
5083 aDest
.SetLength(len
);
5084 if (aDest
.Length() == len
) {
5085 PRUnichar
* dest
= aDest
.BeginWriting();
5086 const PRUnichar
* iter
= aSource
.BeginReading();
5087 const PRUnichar
* end
= aSource
.EndReading();
5088 while (iter
!= end
) {
5089 PRUnichar c
= *iter
;
5090 *dest
= (c
>= 'a' && c
<= 'z') ?
5091 c
+ ('A' - 'a') : c
;
5099 nsContentUtils::EqualsIgnoreASCIICase(const nsAString
& aStr1
,
5100 const nsAString
& aStr2
)
5102 PRUint32 len
= aStr1
.Length();
5103 if (len
!= aStr2
.Length()) {
5107 const PRUnichar
* str1
= aStr1
.BeginReading();
5108 const PRUnichar
* str2
= aStr2
.BeginReading();
5109 const PRUnichar
* end
= str1
+ len
;
5111 while (str1
< end
) {
5112 PRUnichar c1
= *str1
++;
5113 PRUnichar c2
= *str2
++;
5115 // First check if any bits other than the 0x0020 differs
5116 if ((c1
^ c2
) & 0xffdf) {
5120 // We know they only differ in the 0x0020 bit.
5121 // Likely the two chars are the same, so check that first
5123 // They do differ, but since it's only in the 0x0020 bit, check if it's
5124 // the same ascii char, but just differing in case
5125 PRUnichar c1Upper
= c1
& 0xffdf;
5126 if (!('A' <= c1Upper
&& c1Upper
<= 'Z')) {
5136 nsIInterfaceRequestor
*
5137 nsContentUtils::GetSameOriginChecker()
5139 if (!sSameOriginChecker
) {
5140 sSameOriginChecker
= new nsSameOriginChecker();
5141 NS_IF_ADDREF(sSameOriginChecker
);
5143 return sSameOriginChecker
;
5148 nsContentUtils::CheckSameOrigin(nsIChannel
*aOldChannel
, nsIChannel
*aNewChannel
)
5150 if (!nsContentUtils::GetSecurityManager())
5151 return NS_ERROR_NOT_AVAILABLE
;
5153 nsCOMPtr
<nsIPrincipal
> oldPrincipal
;
5154 nsContentUtils::GetSecurityManager()->
5155 GetChannelPrincipal(aOldChannel
, getter_AddRefs(oldPrincipal
));
5157 nsCOMPtr
<nsIURI
> newURI
;
5158 aNewChannel
->GetURI(getter_AddRefs(newURI
));
5159 nsCOMPtr
<nsIURI
> newOriginalURI
;
5160 aNewChannel
->GetOriginalURI(getter_AddRefs(newOriginalURI
));
5162 NS_ENSURE_STATE(oldPrincipal
&& newURI
&& newOriginalURI
);
5164 nsresult rv
= oldPrincipal
->CheckMayLoad(newURI
, PR_FALSE
);
5165 if (NS_SUCCEEDED(rv
) && newOriginalURI
!= newURI
) {
5166 rv
= oldPrincipal
->CheckMayLoad(newOriginalURI
, PR_FALSE
);
5172 NS_IMPL_ISUPPORTS2(nsSameOriginChecker
,
5173 nsIChannelEventSink
,
5174 nsIInterfaceRequestor
)
5177 nsSameOriginChecker::AsyncOnChannelRedirect(nsIChannel
*aOldChannel
,
5178 nsIChannel
*aNewChannel
,
5180 nsIAsyncVerifyRedirectCallback
*cb
)
5182 NS_PRECONDITION(aNewChannel
, "Redirecting to null channel?");
5184 nsresult rv
= nsContentUtils::CheckSameOrigin(aOldChannel
, aNewChannel
);
5185 if (NS_SUCCEEDED(rv
)) {
5186 cb
->OnRedirectVerifyCallback(NS_OK
);
5193 nsSameOriginChecker::GetInterface(const nsIID
& aIID
, void **aResult
)
5195 return QueryInterface(aIID
, aResult
);
5200 nsContentUtils::GetASCIIOrigin(nsIPrincipal
* aPrincipal
, nsCString
& aOrigin
)
5202 NS_PRECONDITION(aPrincipal
, "missing principal");
5206 nsCOMPtr
<nsIURI
> uri
;
5207 nsresult rv
= aPrincipal
->GetURI(getter_AddRefs(uri
));
5208 NS_ENSURE_SUCCESS(rv
, rv
);
5211 return GetASCIIOrigin(uri
, aOrigin
);
5214 aOrigin
.AssignLiteral("null");
5221 nsContentUtils::GetASCIIOrigin(nsIURI
* aURI
, nsCString
& aOrigin
)
5223 NS_PRECONDITION(aURI
, "missing uri");
5227 nsCOMPtr
<nsIURI
> uri
= NS_GetInnermostURI(aURI
);
5228 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
5231 nsresult rv
= uri
->GetAsciiHost(host
);
5233 if (NS_SUCCEEDED(rv
) && !host
.IsEmpty()) {
5235 rv
= uri
->GetScheme(scheme
);
5236 NS_ENSURE_SUCCESS(rv
, rv
);
5238 aOrigin
= scheme
+ NS_LITERAL_CSTRING("://") + host
;
5240 // If needed, append the port
5242 uri
->GetPort(&port
);
5244 PRInt32 defaultPort
= NS_GetDefaultPort(scheme
.get());
5245 if (port
!= defaultPort
) {
5246 aOrigin
.Append(':');
5247 aOrigin
.AppendInt(port
);
5252 aOrigin
.AssignLiteral("null");
5260 nsContentUtils::GetUTFOrigin(nsIPrincipal
* aPrincipal
, nsString
& aOrigin
)
5262 NS_PRECONDITION(aPrincipal
, "missing principal");
5266 nsCOMPtr
<nsIURI
> uri
;
5267 nsresult rv
= aPrincipal
->GetURI(getter_AddRefs(uri
));
5268 NS_ENSURE_SUCCESS(rv
, rv
);
5271 return GetUTFOrigin(uri
, aOrigin
);
5274 aOrigin
.AssignLiteral("null");
5281 nsContentUtils::GetUTFOrigin(nsIURI
* aURI
, nsString
& aOrigin
)
5283 NS_PRECONDITION(aURI
, "missing uri");
5287 nsCOMPtr
<nsIURI
> uri
= NS_GetInnermostURI(aURI
);
5288 NS_ENSURE_TRUE(uri
, NS_ERROR_UNEXPECTED
);
5291 nsresult rv
= uri
->GetHost(host
);
5293 if (NS_SUCCEEDED(rv
) && !host
.IsEmpty()) {
5295 rv
= uri
->GetScheme(scheme
);
5296 NS_ENSURE_SUCCESS(rv
, rv
);
5298 aOrigin
= NS_ConvertUTF8toUTF16(scheme
+ NS_LITERAL_CSTRING("://") + host
);
5300 // If needed, append the port
5302 uri
->GetPort(&port
);
5304 PRInt32 defaultPort
= NS_GetDefaultPort(scheme
.get());
5305 if (port
!= defaultPort
) {
5306 aOrigin
.Append(':');
5307 aOrigin
.AppendInt(port
);
5312 aOrigin
.AssignLiteral("null");
5319 already_AddRefed
<nsIDocument
>
5320 nsContentUtils::GetDocumentFromScriptContext(nsIScriptContext
*aScriptContext
)
5322 if (!aScriptContext
)
5325 nsCOMPtr
<nsIDOMWindow
> window
=
5326 do_QueryInterface(aScriptContext
->GetGlobalObject());
5327 nsIDocument
*doc
= nsnull
;
5329 nsCOMPtr
<nsIDOMDocument
> domdoc
;
5330 window
->GetDocument(getter_AddRefs(domdoc
));
5332 CallQueryInterface(domdoc
, &doc
);
5340 nsContentUtils::CheckMayLoad(nsIPrincipal
* aPrincipal
, nsIChannel
* aChannel
)
5342 nsCOMPtr
<nsIURI
> channelURI
;
5343 nsresult rv
= NS_GetFinalChannelURI(aChannel
, getter_AddRefs(channelURI
));
5344 NS_ENSURE_SUCCESS(rv
, PR_FALSE
);
5346 return NS_SUCCEEDED(aPrincipal
->CheckMayLoad(channelURI
, PR_FALSE
));
5349 nsContentTypeParser::nsContentTypeParser(const nsAString
& aString
)
5350 : mString(aString
), mService(nsnull
)
5352 CallGetService("@mozilla.org/network/mime-hdrparam;1", &mService
);
5355 nsContentTypeParser::~nsContentTypeParser()
5357 NS_IF_RELEASE(mService
);
5361 nsContentTypeParser::GetParameter(const char* aParameterName
, nsAString
& aResult
)
5363 NS_ENSURE_TRUE(mService
, NS_ERROR_FAILURE
);
5364 return mService
->GetParameter(mString
, aParameterName
,
5365 EmptyCString(), PR_FALSE
, nsnull
,
5371 // If you change this code, change also AllowedToAct() in
5372 // XPCSystemOnlyWrapper.cpp!
5374 nsContentUtils::CanAccessNativeAnon()
5376 JSContext
* cx
= nsnull
;
5377 sThreadJSContextStack
->Peek(&cx
);
5382 nsIPrincipal
* principal
=
5383 sSecurityManager
->GetCxSubjectPrincipalAndFrame(cx
, &fp
);
5384 NS_ENSURE_TRUE(principal
, PR_FALSE
);
5387 if (!JS_FrameIterator(cx
, &fp
)) {
5388 // No code at all is running. So we must be arriving here as the result
5389 // of C++ code asking us to do something. Allow access.
5393 // Some code is running, we can't make the assumption, as above, but we
5394 // can't use a native frame, so clear fp.
5396 } else if (!JS_IsScriptFrame(cx
, fp
)) {
5401 if (NS_SUCCEEDED(sSecurityManager
->IsSystemPrincipal(principal
, &privileged
)) &&
5403 // Chrome things are allowed to touch us.
5407 // XXX HACK EWW! Allow chrome://global/ access to these things, even
5408 // if they've been cloned into less privileged contexts.
5409 static const char prefix
[] = "chrome://global/";
5410 const char *filename
;
5411 if (fp
&& JS_IsScriptFrame(cx
, fp
) &&
5412 (filename
= JS_GetFrameScript(cx
, fp
)->filename
) &&
5413 !strncmp(filename
, prefix
, NS_ARRAY_LENGTH(prefix
) - 1)) {
5417 // Before we throw, check for UniversalXPConnect.
5418 nsresult rv
= sSecurityManager
->IsCapabilityEnabled("UniversalXPConnect", &privileged
);
5419 if (NS_SUCCEEDED(rv
) && privileged
) {
5426 /* static */ nsresult
5427 nsContentUtils::DispatchXULCommand(nsIContent
* aTarget
,
5429 nsIDOMEvent
* aSourceEvent
,
5430 nsIPresShell
* aShell
,
5436 NS_ENSURE_STATE(aTarget
);
5437 nsIDocument
* doc
= aTarget
->GetOwnerDoc();
5438 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent
= do_QueryInterface(doc
);
5439 NS_ENSURE_STATE(docEvent
);
5440 nsCOMPtr
<nsIDOMEvent
> event
;
5441 docEvent
->CreateEvent(NS_LITERAL_STRING("xulcommandevent"),
5442 getter_AddRefs(event
));
5443 nsCOMPtr
<nsIDOMXULCommandEvent
> xulCommand
= do_QueryInterface(event
);
5444 nsCOMPtr
<nsIPrivateDOMEvent
> pEvent
= do_QueryInterface(xulCommand
);
5445 NS_ENSURE_STATE(pEvent
);
5446 nsCOMPtr
<nsIDOMAbstractView
> view
= do_QueryInterface(doc
->GetWindow());
5447 nsresult rv
= xulCommand
->InitCommandEvent(NS_LITERAL_STRING("command"),
5448 PR_TRUE
, PR_TRUE
, view
,
5449 0, aCtrl
, aAlt
, aShift
, aMeta
,
5451 NS_ENSURE_SUCCESS(rv
, rv
);
5454 nsEventStatus status
= nsEventStatus_eIgnore
;
5455 nsCOMPtr
<nsIPresShell
> kungFuDeathGrip
= aShell
;
5456 return aShell
->HandleDOMEventWithTarget(aTarget
, event
, &status
);
5459 nsCOMPtr
<nsIDOMEventTarget
> target
= do_QueryInterface(aTarget
);
5460 NS_ENSURE_STATE(target
);
5462 return target
->DispatchEvent(event
, &dummy
);
5467 nsContentUtils::WrapNative(JSContext
*cx
, JSObject
*scope
, nsISupports
*native
,
5468 nsWrapperCache
*cache
, const nsIID
* aIID
, jsval
*vp
,
5469 nsIXPConnectJSObjectHolder
**aHolder
,
5470 PRBool aAllowWrapping
)
5473 NS_ASSERTION(!aHolder
|| !*aHolder
, "*aHolder should be null!");
5480 JSObject
*wrapper
= xpc_GetCachedSlimWrapper(cache
, scope
, vp
);
5485 NS_ENSURE_TRUE(sXPConnect
&& sThreadJSContextStack
, NS_ERROR_UNEXPECTED
);
5487 // Keep sXPConnect and sThreadJSContextStack alive. If we're on the main
5488 // thread then this can be done simply and cheaply by adding a reference to
5489 // nsLayoutStatics. If we're not on the main thread then we need to add a
5490 // more expensive reference sXPConnect directly. We have to use manual
5491 // AddRef and Release calls so don't early-exit from this function after we've
5492 // added the reference!
5493 PRBool isMainThread
= NS_IsMainThread();
5496 nsLayoutStatics::AddRef();
5499 sXPConnect
->AddRef();
5502 JSContext
*topJSContext
;
5503 nsresult rv
= sThreadJSContextStack
->Peek(&topJSContext
);
5504 if (NS_SUCCEEDED(rv
)) {
5505 PRBool push
= topJSContext
!= cx
;
5507 rv
= sThreadJSContextStack
->Push(cx
);
5509 if (NS_SUCCEEDED(rv
)) {
5510 rv
= sXPConnect
->WrapNativeToJSVal(cx
, scope
, native
, cache
, aIID
,
5511 aAllowWrapping
, vp
, aHolder
);
5513 sThreadJSContextStack
->Pop(nsnull
);
5519 nsLayoutStatics::Release();
5522 sXPConnect
->Release();
5529 nsContentUtils::StripNullChars(const nsAString
& aInStr
, nsAString
& aOutStr
)
5531 // In common cases where we don't have nulls in the
5532 // string we can simple simply bypass the checking code.
5533 PRInt32 firstNullPos
= aInStr
.FindChar('\0');
5534 if (firstNullPos
== kNotFound
) {
5535 aOutStr
.Assign(aInStr
);
5539 aOutStr
.SetCapacity(aInStr
.Length() - 1);
5540 nsAString::const_iterator start
, end
;
5541 aInStr
.BeginReading(start
);
5542 aInStr
.EndReading(end
);
5543 while (start
!= end
) {
5545 aOutStr
.Append(*start
);
5552 const unsigned int kCloneStackFrameStackSize
= 20;
5554 class CloneStackFrame
5556 friend class CloneStack
;
5559 // These three jsvals must all stick together as they're treated as a jsval
5564 js::AutoIdArray ids
;
5568 // Only let CloneStack access these.
5569 CloneStackFrame(JSContext
* aCx
, jsval aSource
, jsval aClone
, JSIdArray
* aIds
)
5570 : source(aSource
), clone(aClone
), temp(JSVAL_NULL
), ids(aCx
, aIds
), index(0),
5571 prevFrame(nsnull
), tvrVals(aCx
, 3, &source
)
5573 MOZ_COUNT_CTOR(CloneStackFrame
);
5578 MOZ_COUNT_DTOR(CloneStackFrame
);
5581 CloneStackFrame
* prevFrame
;
5582 js::AutoArrayRooter tvrVals
;
5588 CloneStack(JSContext
* cx
)
5589 : mCx(cx
), mLastFrame(nsnull
) {
5594 while (!IsEmpty()) {
5600 Push(jsval source
, jsval clone
, JSIdArray
* ids
) {
5601 NS_ASSERTION(!JSVAL_IS_PRIMITIVE(source
) && !JSVAL_IS_PRIMITIVE(clone
),
5602 "Must be an object!");
5607 CloneStackFrame
* newFrame
;
5608 if (mObjectSet
.Count() < kCloneStackFrameStackSize
) {
5609 // If the object can fit in our stack space then use that.
5610 CloneStackFrame
* buf
= reinterpret_cast<CloneStackFrame
*>(mStackFrames
);
5611 newFrame
= new (buf
+ mObjectSet
.Count())
5612 CloneStackFrame(mCx
, source
, clone
, ids
);
5616 newFrame
= new CloneStackFrame(mCx
, source
, clone
, ids
);
5619 mObjectSet
.PutEntry(JSVAL_TO_OBJECT(source
));
5621 newFrame
->prevFrame
= mLastFrame
;
5622 mLastFrame
= newFrame
;
5635 NS_ERROR("Empty stack!");
5639 CloneStackFrame
* lastFrame
= mLastFrame
;
5641 mObjectSet
.RemoveEntry(JSVAL_TO_OBJECT(lastFrame
->source
));
5642 mLastFrame
= lastFrame
->prevFrame
;
5644 if (mObjectSet
.Count() >= kCloneStackFrameStackSize
) {
5645 // Only delete if this was a heap object.
5649 // Otherwise just run the destructor.
5650 lastFrame
->~CloneStackFrame();
5656 NS_ASSERTION((!mLastFrame
&& !mObjectSet
.Count()) ||
5657 (mLastFrame
&& mObjectSet
.Count()),
5658 "Hashset is out of sync!");
5659 return mObjectSet
.Count() == 0;
5663 Search(JSObject
* obj
) {
5664 return !!mObjectSet
.GetEntry(obj
);
5669 CloneStackFrame
* mLastFrame
;
5670 nsTHashtable
<nsVoidPtrHashKey
> mObjectSet
;
5672 // Use a char array instead of CloneStackFrame array to prevent the JSAuto*
5673 // helpers from running until we're ready for them.
5674 char mStackFrames
[kCloneStackFrameStackSize
* sizeof(CloneStackFrame
)];
5677 struct ReparentObjectData
{
5678 ReparentObjectData(JSContext
* cx
, JSObject
* obj
)
5679 : cx(cx
), obj(obj
), ids(nsnull
), index(0) { }
5681 ~ReparentObjectData() {
5683 JS_DestroyIdArray(cx
, ids
);
5694 SetPropertyOnValueOrObject(JSContext
* cx
,
5700 NS_ASSERTION((rval
&& !obj
) || (!rval
&& obj
), "Can only clone to one dest!");
5705 if (!JS_DefinePropertyById(cx
, obj
, id
, val
, nsnull
, nsnull
,
5706 JSPROP_ENUMERATE
)) {
5707 return NS_ERROR_FAILURE
;
5713 CreateEmptyObjectOrArray(JSContext
* cx
,
5716 if (JS_IsArrayObject(cx
, obj
)) {
5718 if (!JS_GetArrayLength(cx
, obj
, &length
)) {
5719 NS_ERROR("Failed to get array length?!");
5722 return JS_NewArrayObject(cx
, length
, NULL
);
5724 return JS_NewObject(cx
, NULL
, NULL
, NULL
);
5728 CloneSimpleValues(JSContext
* cx
,
5732 JSObject
* robj
= nsnull
,
5733 jsid rid
= INT_TO_JSID(0))
5735 *wasCloned
= PR_TRUE
;
5737 // No cloning necessary for these non-GC'd jsvals.
5738 if (!JSVAL_IS_GCTHING(val
) || JSVAL_IS_NULL(val
)) {
5739 return SetPropertyOnValueOrObject(cx
, val
, rval
, robj
, rid
);
5742 // We'll use immutable strings to prevent copying if we can.
5743 if (JSVAL_IS_STRING(val
)) {
5744 if (!JS_MakeStringImmutable(cx
, JSVAL_TO_STRING(val
))) {
5745 return NS_ERROR_FAILURE
;
5747 return SetPropertyOnValueOrObject(cx
, val
, rval
, robj
, rid
);
5750 NS_ASSERTION(!JSVAL_IS_PRIMITIVE(val
), "Not an object!");
5751 JSObject
* obj
= JSVAL_TO_OBJECT(val
);
5753 // Dense arrays of primitives can be cloned quickly.
5755 if (!js_CloneDensePrimitiveArray(cx
, obj
, &newArray
)) {
5756 return NS_ERROR_FAILURE
;
5759 return SetPropertyOnValueOrObject(cx
, OBJECT_TO_JSVAL(newArray
), rval
, robj
,
5764 if (js_DateIsValid(cx
, obj
)) {
5765 jsdouble msec
= js_DateGetMsecSinceEpoch(cx
, obj
);
5767 if (!(msec
&& (newDate
= js_NewDateObjectMsec(cx
, msec
)))) {
5768 return NS_ERROR_OUT_OF_MEMORY
;
5770 return SetPropertyOnValueOrObject(cx
, OBJECT_TO_JSVAL(newDate
), rval
, robj
,
5775 if (js_ObjectIsRegExp(obj
)) {
5777 if (!js_GetClassPrototype(cx
, JS_GetScopeChain(cx
), JSProto_RegExp
,
5779 return NS_ERROR_FAILURE
;
5781 JSObject
* newRegExp
= js_CloneRegExpObject(cx
, obj
, proto
);
5783 return NS_ERROR_FAILURE
;
5785 return SetPropertyOnValueOrObject(cx
, OBJECT_TO_JSVAL(newRegExp
), rval
,
5789 // Typed array objects.
5790 if (js_IsTypedArray(obj
)) {
5791 js::TypedArray
* src
= js::TypedArray::fromJSObject(obj
);
5792 JSObject
* newTypedArray
= js_CreateTypedArrayWithArray(cx
, src
->type
, obj
);
5793 if (!newTypedArray
) {
5794 return NS_ERROR_FAILURE
;
5796 return SetPropertyOnValueOrObject(cx
, OBJECT_TO_JSVAL(newTypedArray
), rval
,
5800 // ArrayBuffer objects.
5801 if (js_IsArrayBuffer(obj
)) {
5802 js::ArrayBuffer
* src
= js::ArrayBuffer::fromJSObject(obj
);
5804 return NS_ERROR_FAILURE
;
5807 JSObject
* newBuffer
= js_CreateArrayBuffer(cx
, src
->byteLength
);
5809 return NS_ERROR_FAILURE
;
5811 memcpy(js::ArrayBuffer::fromJSObject(newBuffer
)->data
, src
->data
,
5813 return SetPropertyOnValueOrObject(cx
, OBJECT_TO_JSVAL(newBuffer
), rval
,
5817 // Do we support File?
5818 // Do we support Blob?
5819 // Do we support FileList?
5821 // Function objects don't get cloned.
5822 if (JS_ObjectIsFunction(cx
, obj
)) {
5823 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
5826 // Security wrapped objects are not allowed either.
5827 if (obj
->isWrapper() && !obj
->getClass()->ext
.innerObject
)
5828 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
5830 // See if this JSObject is backed by some C++ object. If it is then we assume
5831 // that it is inappropriate to clone.
5832 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
5833 nsContentUtils::XPConnect()->
5834 GetWrappedNativeOfJSObject(cx
, obj
, getter_AddRefs(wrapper
));
5836 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
5839 *wasCloned
= PR_FALSE
;
5843 } // anonymous namespace
5847 nsContentUtils::CreateStructuredClone(JSContext
* cx
,
5851 JSAutoRequest
ar(cx
);
5853 nsCOMPtr
<nsIXPConnect
> xpconnect(sXPConnect
);
5854 NS_ENSURE_STATE(xpconnect
);
5857 nsresult rv
= CloneSimpleValues(cx
, val
, rval
, &wasCloned
);
5858 if (NS_FAILED(rv
)) {
5866 NS_ASSERTION(JSVAL_IS_OBJECT(val
), "Not an object?!");
5867 JSObject
* obj
= CreateEmptyObjectOrArray(cx
, JSVAL_TO_OBJECT(val
));
5869 return NS_ERROR_OUT_OF_MEMORY
;
5872 jsval output
= OBJECT_TO_JSVAL(obj
);
5873 js::AutoValueRooter
tvr(cx
, output
);
5875 CloneStack
stack(cx
);
5876 if (!stack
.Push(val
, OBJECT_TO_JSVAL(obj
),
5877 JS_Enumerate(cx
, JSVAL_TO_OBJECT(val
)))) {
5878 return NS_ERROR_OUT_OF_MEMORY
;
5881 while (!stack
.IsEmpty()) {
5882 CloneStackFrame
* frame
= stack
.Peek();
5884 NS_ASSERTION(!!frame
->ids
&&
5885 frame
->ids
.length() >= frame
->index
&&
5886 !JSVAL_IS_PRIMITIVE(frame
->source
) &&
5887 !JSVAL_IS_PRIMITIVE(frame
->clone
),
5888 "Bad frame state!");
5890 if (frame
->index
== frame
->ids
.length()) {
5891 // Done cloning this object, pop the frame.
5896 // Get the current id and increment the index.
5897 jsid id
= frame
->ids
[frame
->index
++];
5899 if (!JS_GetPropertyById(cx
, JSVAL_TO_OBJECT(frame
->source
), id
,
5901 return NS_ERROR_FAILURE
;
5904 if (!JSVAL_IS_PRIMITIVE(frame
->temp
) &&
5905 stack
.Search(JSVAL_TO_OBJECT(frame
->temp
))) {
5906 // Spec says to throw this particular exception for cyclical references.
5907 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
5910 JSObject
* clone
= JSVAL_TO_OBJECT(frame
->clone
);
5913 nsresult rv
= CloneSimpleValues(cx
, frame
->temp
, nsnull
, &wasCloned
, clone
,
5915 if (NS_FAILED(rv
)) {
5920 NS_ASSERTION(JSVAL_IS_OBJECT(frame
->temp
), "Not an object?!");
5921 obj
= CreateEmptyObjectOrArray(cx
, JSVAL_TO_OBJECT(frame
->temp
));
5923 !stack
.Push(frame
->temp
, OBJECT_TO_JSVAL(obj
),
5924 JS_Enumerate(cx
, JSVAL_TO_OBJECT(frame
->temp
)))) {
5925 return NS_ERROR_OUT_OF_MEMORY
;
5927 // Set the new object as a property of the clone. We'll fill it on the
5929 if (!JS_DefinePropertyById(cx
, clone
, id
, OBJECT_TO_JSVAL(obj
), nsnull
,
5930 nsnull
, JSPROP_ENUMERATE
)) {
5931 return NS_ERROR_FAILURE
;
5942 nsContentUtils::ReparentClonedObjectToScope(JSContext
* cx
,
5946 JSAutoRequest
ar(cx
);
5948 scope
= JS_GetGlobalForObject(cx
, scope
);
5950 nsAutoTArray
<ReparentObjectData
, 20> objectData
;
5951 objectData
.AppendElement(ReparentObjectData(cx
, obj
));
5953 while (!objectData
.IsEmpty()) {
5954 ReparentObjectData
& data
= objectData
[objectData
.Length() - 1];
5957 NS_ASSERTION(!data
.index
, "Shouldn't have index here");
5959 // Typed arrays are special and don't need to be enumerated.
5960 if (js_IsTypedArray(data
.obj
)) {
5961 if (!js_ReparentTypedArrayToScope(cx
, data
.obj
, scope
)) {
5962 return NS_ERROR_FAILURE
;
5965 // No need to enumerate anything here.
5966 objectData
.RemoveElementAt(objectData
.Length() - 1);
5970 JSProtoKey key
= JSCLASS_CACHED_PROTO_KEY(JS_GET_CLASS(cx
, data
.obj
));
5972 // We should never be reparenting an object that doesn't have a standard
5974 return NS_ERROR_FAILURE
;
5977 // Fix the prototype and parent first.
5979 if (!js_GetClassPrototype(cx
, scope
, key
, &proto
) ||
5980 !JS_SetPrototype(cx
, data
.obj
, proto
) ||
5981 !JS_SetParent(cx
, data
.obj
, scope
)) {
5982 return NS_ERROR_FAILURE
;
5985 // Primitive arrays don't need to be enumerated either but the proto and
5986 // parent needed to be fixed above. Now we can just move on.
5987 if (js_IsDensePrimitiveArray(data
.obj
)) {
5988 objectData
.RemoveElementAt(objectData
.Length() - 1);
5992 // And now enumerate the object's properties.
5993 if (!(data
.ids
= JS_Enumerate(cx
, data
.obj
))) {
5994 return NS_ERROR_FAILURE
;
5998 // If we've gone through all the object's properties then we're done with
6000 if (data
.index
== data
.ids
->length
) {
6001 objectData
.RemoveElementAt(objectData
.Length() - 1);
6005 // Get the id and increment!
6006 jsid id
= data
.ids
->vector
[data
.index
++];
6009 if (!JS_GetPropertyById(cx
, data
.obj
, id
, &prop
)) {
6010 return NS_ERROR_FAILURE
;
6013 // Push a new frame if this property is an object.
6014 if (!JSVAL_IS_PRIMITIVE(prop
)) {
6015 objectData
.AppendElement(ReparentObjectData(cx
, JSVAL_TO_OBJECT(prop
)));
6022 struct ClassMatchingInfo
{
6023 nsAttrValue::AtomArray mClasses
;
6024 nsCaseTreatment mCaseTreatment
;
6028 MatchClassNames(nsIContent
* aContent
, PRInt32 aNamespaceID
, nsIAtom
* aAtom
,
6031 // We can't match if there are no class names
6032 const nsAttrValue
* classAttr
= aContent
->GetClasses();
6037 // need to match *all* of the classes
6038 ClassMatchingInfo
* info
= static_cast<ClassMatchingInfo
*>(aData
);
6039 PRUint32 length
= info
->mClasses
.Length();
6041 // If we actually had no classes, don't match.
6045 for (i
= 0; i
< length
; ++i
) {
6046 if (!classAttr
->Contains(info
->mClasses
[i
],
6047 info
->mCaseTreatment
)) {
6056 DestroyClassNameArray(void* aData
)
6058 ClassMatchingInfo
* info
= static_cast<ClassMatchingInfo
*>(aData
);
6063 AllocClassMatchingInfo(nsINode
* aRootNode
,
6064 const nsString
* aClasses
)
6066 nsAttrValue attrValue
;
6067 attrValue
.ParseAtomArray(*aClasses
);
6068 // nsAttrValue::Equals is sensitive to order, so we'll send an array
6069 ClassMatchingInfo
* info
= new ClassMatchingInfo
;
6070 NS_ENSURE_TRUE(info
, nsnull
);
6072 if (attrValue
.Type() == nsAttrValue::eAtomArray
) {
6073 info
->mClasses
.SwapElements(*(attrValue
.GetAtomArrayValue()));
6074 } else if (attrValue
.Type() == nsAttrValue::eAtom
) {
6075 info
->mClasses
.AppendElement(attrValue
.GetAtomValue());
6078 info
->mCaseTreatment
=
6079 aRootNode
->GetOwnerDoc() &&
6080 aRootNode
->GetOwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks
?
6081 eIgnoreCase
: eCaseMatters
;
6088 nsContentUtils::GetElementsByClassName(nsINode
* aRootNode
,
6089 const nsAString
& aClasses
,
6090 nsIDOMNodeList
** aReturn
)
6092 NS_PRECONDITION(aRootNode
, "Must have root node");
6094 nsContentList
* elements
=
6095 NS_GetFuncStringContentList(aRootNode
, MatchClassNames
,
6096 DestroyClassNameArray
,
6097 AllocClassMatchingInfo
,
6099 NS_ENSURE_TRUE(elements
, NS_ERROR_OUT_OF_MEMORY
);
6101 // Transfer ownership
6102 *aReturn
= elements
;
6108 class DebugWrapperTraversalCallback
: public nsCycleCollectionTraversalCallback
6111 DebugWrapperTraversalCallback(void* aWrapper
) : mFound(PR_FALSE
),
6114 mFlags
= WANT_ALL_TRACES
;
6117 NS_IMETHOD_(void) DescribeNode(CCNodeType type
,
6120 const char* objname
)
6123 NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports
*root
)
6126 NS_IMETHOD_(void) NoteRoot(PRUint32 langID
, void* root
,
6127 nsCycleCollectionParticipant
* helper
)
6130 NS_IMETHOD_(void) NoteScriptChild(PRUint32 langID
, void* child
)
6132 if (langID
== nsIProgrammingLanguage::JAVASCRIPT
) {
6133 mFound
= child
== mWrapper
;
6136 NS_IMETHOD_(void) NoteXPCOMChild(nsISupports
*child
)
6139 NS_IMETHOD_(void) NoteNativeChild(void* child
,
6140 nsCycleCollectionParticipant
* helper
)
6144 NS_IMETHOD_(void) NoteNextEdgeName(const char* name
)
6155 DebugWrapperTraceCallback(PRUint32 langID
, void *p
, void *closure
)
6157 DebugWrapperTraversalCallback
* callback
=
6158 static_cast<DebugWrapperTraversalCallback
*>(closure
);
6159 callback
->NoteScriptChild(langID
, p
);
6164 nsContentUtils::CheckCCWrapperTraversal(nsISupports
* aScriptObjectHolder
,
6165 nsWrapperCache
* aCache
)
6167 nsXPCOMCycleCollectionParticipant
* participant
;
6168 CallQueryInterface(aScriptObjectHolder
, &participant
);
6170 DebugWrapperTraversalCallback
callback(aCache
->GetWrapper());
6172 participant
->Traverse(aScriptObjectHolder
, callback
);
6173 NS_ASSERTION(callback
.mFound
,
6174 "Cycle collection participant didn't traverse to preserved "
6175 "wrapper! This will probably crash.");
6177 callback
.mFound
= PR_FALSE
;
6178 participant
->Trace(aScriptObjectHolder
, DebugWrapperTraceCallback
, &callback
);
6179 NS_ASSERTION(callback
.mFound
,
6180 "Cycle collection participant didn't trace preserved wrapper! "
6181 "This will probably crash.");
6185 mozAutoRemovableBlockerRemover::mozAutoRemovableBlockerRemover(nsIDocument
* aDocument MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL
)
6187 MOZILLA_GUARD_OBJECT_NOTIFIER_INIT
;
6188 mNestingLevel
= nsContentUtils::GetRemovableScriptBlockerLevel();
6189 mDocument
= aDocument
;
6190 nsISupports
* sink
= aDocument
? aDocument
->GetCurrentContentSink() : nsnull
;
6191 mObserver
= do_QueryInterface(sink
);
6192 for (PRUint32 i
= 0; i
< mNestingLevel
; ++i
) {
6194 mObserver
->EndUpdate(mDocument
, UPDATE_CONTENT_MODEL
);
6196 nsContentUtils::RemoveRemovableScriptBlocker();
6199 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(), "killing mutation events");
6202 mozAutoRemovableBlockerRemover::~mozAutoRemovableBlockerRemover()
6204 NS_ASSERTION(nsContentUtils::GetRemovableScriptBlockerLevel() == 0,
6205 "Should have had none");
6206 for (PRUint32 i
= 0; i
< mNestingLevel
; ++i
) {
6207 nsContentUtils::AddRemovableScriptBlocker();
6209 mObserver
->BeginUpdate(mDocument
, UPDATE_CONTENT_MODEL
);
6216 nsContentUtils::IsFocusedContent(const nsIContent
* aContent
)
6218 nsFocusManager
* fm
= nsFocusManager::GetFocusManager();
6220 return fm
&& fm
->GetFocusedContent() == aContent
;
6224 nsContentUtils::IsSubDocumentTabbable(nsIContent
* aContent
)
6226 nsIDocument
* doc
= aContent
->GetCurrentDoc();
6231 // XXXbz should this use GetOwnerDoc() for GetSubDocumentFor?
6233 nsIDocument
* subDoc
= doc
->GetSubDocumentFor(aContent
);
6238 nsCOMPtr
<nsISupports
> container
= subDoc
->GetContainer();
6239 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(container
);
6244 nsCOMPtr
<nsIContentViewer
> contentViewer
;
6245 docShell
->GetContentViewer(getter_AddRefs(contentViewer
));
6246 if (!contentViewer
) {
6250 nsCOMPtr
<nsIContentViewer
> zombieViewer
;
6251 contentViewer
->GetPreviousViewer(getter_AddRefs(zombieViewer
));
6253 // If there are 2 viewers for the current docshell, that
6254 // means the current document is a zombie document.
6255 // Only navigate into the subdocument if it's not a zombie.
6256 return !zombieViewer
;
6260 nsContentUtils::FlushLayoutForTree(nsIDOMWindow
* aWindow
)
6262 nsCOMPtr
<nsPIDOMWindow
> piWin
= do_QueryInterface(aWindow
);
6266 // Note that because FlushPendingNotifications flushes parents, this
6267 // is O(N^2) in docshell tree depth. However, the docshell tree is
6268 // usually pretty shallow.
6270 nsCOMPtr
<nsIDOMDocument
> domDoc
;
6271 aWindow
->GetDocument(getter_AddRefs(domDoc
));
6272 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(domDoc
);
6274 doc
->FlushPendingNotifications(Flush_Layout
);
6277 nsCOMPtr
<nsIDocShellTreeNode
> node
=
6278 do_QueryInterface(piWin
->GetDocShell());
6280 PRInt32 i
= 0, i_end
;
6281 node
->GetChildCount(&i_end
);
6282 for (; i
< i_end
; ++i
) {
6283 nsCOMPtr
<nsIDocShellTreeItem
> item
;
6284 node
->GetChildAt(i
, getter_AddRefs(item
));
6285 nsCOMPtr
<nsIDOMWindow
> win
= do_GetInterface(item
);
6287 FlushLayoutForTree(win
);
6293 void nsContentUtils::RemoveNewlines(nsString
&aString
)
6295 // strip CR/LF and null
6296 static const char badChars
[] = {'\r', '\n', 0};
6297 aString
.StripChars(badChars
);
6301 nsContentUtils::PlatformToDOMLineBreaks(nsString
&aString
)
6303 if (aString
.FindChar(PRUnichar('\r')) != -1) {
6304 // Windows linebreaks: Map CRLF to LF:
6305 aString
.ReplaceSubstring(NS_LITERAL_STRING("\r\n").get(),
6306 NS_LITERAL_STRING("\n").get());
6308 // Mac linebreaks: Map any remaining CR to LF:
6309 aString
.ReplaceSubstring(NS_LITERAL_STRING("\r").get(),
6310 NS_LITERAL_STRING("\n").get());
6314 already_AddRefed
<LayerManager
>
6315 nsContentUtils::LayerManagerForDocument(nsIDocument
*aDoc
)
6317 nsIDocument
* doc
= aDoc
;
6318 nsIDocument
* displayDoc
= doc
->GetDisplayDocument();
6323 nsIPresShell
* shell
= doc
->GetShell();
6324 nsCOMPtr
<nsISupports
> container
= doc
->GetContainer();
6325 nsCOMPtr
<nsIDocShellTreeItem
> docShellTreeItem
= do_QueryInterface(container
);
6326 while (!shell
&& docShellTreeItem
) {
6327 // We may be in a display:none subdocument, or we may not have a presshell
6329 // Walk the docshell tree to find the nearest container that has a presshell,
6330 // and find the root widget from that.
6331 nsCOMPtr
<nsIDocShell
> docShell
= do_QueryInterface(docShellTreeItem
);
6332 nsCOMPtr
<nsIPresShell
> presShell
;
6333 docShell
->GetPresShell(getter_AddRefs(presShell
));
6337 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
6338 docShellTreeItem
->GetParent(getter_AddRefs(parent
));
6339 docShellTreeItem
= parent
;
6344 nsIFrame
* rootFrame
= shell
->FrameManager()->GetRootFrame();
6347 nsLayoutUtils::GetDisplayRootFrame(rootFrame
)->GetNearestWidget();
6349 nsRefPtr
<LayerManager
> manager
= widget
->GetLayerManager();
6350 return manager
.forget();
6355 nsRefPtr
<LayerManager
> manager
= new BasicLayerManager();
6356 return manager
.forget();
6360 nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal
* aPrincipal
)
6362 if (IsSystemPrincipal(aPrincipal
)) {
6366 nsCOMPtr
<nsIURI
> princURI
;
6367 aPrincipal
->GetURI(getter_AddRefs(princURI
));
6370 ((sAllowXULXBL_for_file
&& SchemeIs(princURI
, "file")) ||
6371 IsSitePermAllow(princURI
, "allowXULXBL"));
6374 NS_IMPL_ISUPPORTS1(nsIContentUtils
, nsIContentUtils
)
6377 nsIContentUtils::IsSafeToRunScript()
6379 return nsContentUtils::IsSafeToRunScript();
6383 nsIContentUtils::ParseIntMarginValue(const nsAString
& aString
, nsIntMargin
& result
)
6385 return nsContentUtils::ParseIntMarginValue(aString
, result
);
6388 already_AddRefed
<nsIDocumentLoaderFactory
>
6389 nsIContentUtils::FindInternalContentViewer(const char* aType
,
6390 ContentViewerType
* aLoaderType
)
6393 *aLoaderType
= TYPE_UNSUPPORTED
;
6396 // one helper factory, please
6397 nsCOMPtr
<nsICategoryManager
> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID
));
6401 nsCOMPtr
<nsIDocumentLoaderFactory
> docFactory
;
6403 nsXPIDLCString contractID
;
6404 nsresult rv
= catMan
->GetCategoryEntry("Gecko-Content-Viewers", aType
, getter_Copies(contractID
));
6405 if (NS_SUCCEEDED(rv
)) {
6406 docFactory
= do_GetService(contractID
);
6407 if (docFactory
&& aLoaderType
) {
6408 if (contractID
.EqualsLiteral(CONTENT_DLF_CONTRACTID
))
6409 *aLoaderType
= TYPE_CONTENT
;
6410 else if (contractID
.EqualsLiteral(PLUGIN_DLF_CONTRACTID
))
6411 *aLoaderType
= TYPE_PLUGIN
;
6413 *aLoaderType
= TYPE_UNKNOWN
;
6415 return docFactory
.forget();
6420 if (nsHTMLMediaElement::IsOggEnabled()) {
6421 for (unsigned int i
= 0; i
< NS_ARRAY_LENGTH(nsHTMLMediaElement::gOggTypes
); ++i
) {
6422 const char* type
= nsHTMLMediaElement::gOggTypes
[i
];
6423 if (!strcmp(aType
, type
)) {
6424 docFactory
= do_GetService("@mozilla.org/content/document-loader-factory;1");
6425 if (docFactory
&& aLoaderType
) {
6426 *aLoaderType
= TYPE_CONTENT
;
6428 return docFactory
.forget();
6435 if (nsHTMLMediaElement::IsWebMEnabled()) {
6436 for (unsigned int i
= 0; i
< NS_ARRAY_LENGTH(nsHTMLMediaElement::gWebMTypes
); ++i
) {
6437 const char* type
= nsHTMLMediaElement::gWebMTypes
[i
];
6438 if (!strcmp(aType
, type
)) {
6439 docFactory
= do_GetService("@mozilla.org/content/document-loader-factory;1");
6440 if (docFactory
&& aLoaderType
) {
6441 *aLoaderType
= TYPE_CONTENT
;
6443 return docFactory
.forget();
6453 NS_IMPL_ISUPPORTS1(nsIContentUtils2
, nsIContentUtils2
)
6455 nsIInterfaceRequestor
*
6456 nsIContentUtils2::GetSameOriginChecker()
6458 return nsContentUtils::GetSameOriginChecker();
6462 nsIContentUtils2::CheckSameOrigin(nsIChannel
*aOldChannel
, nsIChannel
*aNewChannel
)
6464 return nsContentUtils::CheckSameOrigin(aOldChannel
, aNewChannel
);