LCOV - code coverage report
Current view: directory - content/base/src - nsContentUtils.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 2767 819 29.6 %
Date: 2012-06-02 Functions: 267 87 32.6 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=78: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code, released
      17                 :  * March 31, 1998.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Netscape Communications Corporation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *   Johnny Stenback <jst@netscape.com>
      26                 :  *   Christopher A. Aillon <christopher@aillon.com>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : /* A namespace class for static layout utilities. */
      43                 : 
      44                 : #include "mozilla/Util.h"
      45                 : 
      46                 : #include "jsapi.h"
      47                 : #include "jsdbgapi.h"
      48                 : #include "jstypedarray.h"
      49                 : 
      50                 : #include "nsJSUtils.h"
      51                 : #include "nsCOMPtr.h"
      52                 : #include "nsAString.h"
      53                 : #include "nsPrintfCString.h"
      54                 : #include "nsUnicharUtils.h"
      55                 : #include "nsServiceManagerUtils.h"
      56                 : #include "nsIScriptGlobalObject.h"
      57                 : #include "nsIScriptContext.h"
      58                 : #include "nsIDOMScriptObjectFactory.h"
      59                 : #include "nsDOMCID.h"
      60                 : #include "nsContentUtils.h"
      61                 : #include "nsIXPConnect.h"
      62                 : #include "nsIContent.h"
      63                 : #include "mozilla/dom/Element.h"
      64                 : #include "nsIDocument.h"
      65                 : #include "nsINodeInfo.h"
      66                 : #include "nsReadableUtils.h"
      67                 : #include "nsIDOMDocument.h"
      68                 : #include "nsIDOMNodeList.h"
      69                 : #include "nsIDOMNode.h"
      70                 : #include "nsIIOService.h"
      71                 : #include "nsNetCID.h"
      72                 : #include "nsNetUtil.h"
      73                 : #include "nsIScriptSecurityManager.h"
      74                 : #include "nsDOMError.h"
      75                 : #include "nsPIDOMWindow.h"
      76                 : #include "nsIJSContextStack.h"
      77                 : #include "nsIDocShell.h"
      78                 : #include "nsIDocShellTreeItem.h"
      79                 : #include "nsParserCIID.h"
      80                 : #include "nsIParser.h"
      81                 : #include "nsIFragmentContentSink.h"
      82                 : #include "nsIContentSink.h"
      83                 : #include "nsIHTMLContentSink.h"
      84                 : #include "nsIXMLContentSink.h"
      85                 : #include "nsHTMLParts.h"
      86                 : #include "nsIParserService.h"
      87                 : #include "nsIServiceManager.h"
      88                 : #include "nsIAttribute.h"
      89                 : #include "nsContentList.h"
      90                 : #include "nsIHTMLDocument.h"
      91                 : #include "nsIDOMHTMLDocument.h"
      92                 : #include "nsIDOMHTMLCollection.h"
      93                 : #include "nsIDOMHTMLFormElement.h"
      94                 : #include "nsIDOMHTMLElement.h"
      95                 : #include "nsIForm.h"
      96                 : #include "nsIFormControl.h"
      97                 : #include "nsGkAtoms.h"
      98                 : #include "nsISupportsPrimitives.h"
      99                 : #include "imgIDecoderObserver.h"
     100                 : #include "imgIRequest.h"
     101                 : #include "imgIContainer.h"
     102                 : #include "imgILoader.h"
     103                 : #include "nsDocShellCID.h"
     104                 : #include "nsIImageLoadingContent.h"
     105                 : #include "nsIInterfaceRequestor.h"
     106                 : #include "nsIInterfaceRequestorUtils.h"
     107                 : #include "nsILoadGroup.h"
     108                 : #include "nsIObserver.h"
     109                 : #include "nsIObserverService.h"
     110                 : #include "nsContentPolicyUtils.h"
     111                 : #include "nsNodeInfoManager.h"
     112                 : #include "nsIXBLService.h"
     113                 : #include "nsCRT.h"
     114                 : #include "nsIDOMEvent.h"
     115                 : #include "nsIDOMEventTarget.h"
     116                 : #include "nsIPrivateDOMEvent.h"
     117                 : #ifdef MOZ_XTF
     118                 : #include "nsIXTFService.h"
     119                 : static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
     120                 : #endif
     121                 : #include "nsIMIMEService.h"
     122                 : #include "nsLWBrkCIID.h"
     123                 : #include "nsILineBreaker.h"
     124                 : #include "nsIWordBreaker.h"
     125                 : #include "nsUnicodeProperties.h"
     126                 : #include "harfbuzz/hb-common.h"
     127                 : #include "jsdbgapi.h"
     128                 : #include "nsIJSRuntimeService.h"
     129                 : #include "nsIDOMDocumentXBL.h"
     130                 : #include "nsBindingManager.h"
     131                 : #include "nsIURI.h"
     132                 : #include "nsIURL.h"
     133                 : #include "nsXBLBinding.h"
     134                 : #include "nsXBLPrototypeBinding.h"
     135                 : #include "nsEscape.h"
     136                 : #include "nsICharsetConverterManager.h"
     137                 : #include "nsEventListenerManager.h"
     138                 : #include "nsAttrName.h"
     139                 : #include "nsIDOMUserDataHandler.h"
     140                 : #include "nsContentCreatorFunctions.h"
     141                 : #include "nsGUIEvent.h"
     142                 : #include "nsMutationEvent.h"
     143                 : #include "nsIMEStateManager.h"
     144                 : #include "nsContentErrors.h"
     145                 : #include "nsUnicharUtilCIID.h"
     146                 : #include "nsCompressedCharMap.h"
     147                 : #include "nsINativeKeyBindings.h"
     148                 : #include "nsIDOMNSEvent.h"
     149                 : #include "nsIPrivateDOMEvent.h"
     150                 : #include "nsXULPopupManager.h"
     151                 : #include "nsIPermissionManager.h"
     152                 : #include "nsIContentPrefService.h"
     153                 : #include "nsIScriptObjectPrincipal.h"
     154                 : #include "nsIRunnable.h"
     155                 : #include "nsDOMJSUtils.h"
     156                 : #include "nsGenericHTMLElement.h"
     157                 : #include "nsAttrValue.h"
     158                 : #include "nsReferencedElement.h"
     159                 : #include "nsIDragService.h"
     160                 : #include "nsIChannelEventSink.h"
     161                 : #include "nsIAsyncVerifyRedirectCallback.h"
     162                 : #include "nsIInterfaceRequestor.h"
     163                 : #include "nsIOfflineCacheUpdate.h"
     164                 : #include "nsCPrefetchService.h"
     165                 : #include "nsIChromeRegistry.h"
     166                 : #include "nsEventDispatcher.h"
     167                 : #include "nsIMIMEHeaderParam.h"
     168                 : #include "nsIDOMXULCommandEvent.h"
     169                 : #include "nsIDOMDragEvent.h"
     170                 : #include "nsDOMDataTransfer.h"
     171                 : #include "nsHtml5Module.h"
     172                 : #include "nsPresContext.h"
     173                 : #include "nsLayoutStatics.h"
     174                 : #include "nsLayoutUtils.h"
     175                 : #include "nsFrameManager.h"
     176                 : #include "BasicLayers.h"
     177                 : #include "nsFocusManager.h"
     178                 : #include "nsTextEditorState.h"
     179                 : #include "nsIPluginHost.h"
     180                 : #include "nsICategoryManager.h"
     181                 : #include "nsIViewManager.h"
     182                 : #include "nsEventStateManager.h"
     183                 : #include "nsIDOMHTMLInputElement.h"
     184                 : #include "nsParserConstants.h"
     185                 : 
     186                 : #ifdef IBMBIDI
     187                 : #include "nsIBidiKeyboard.h"
     188                 : #endif
     189                 : #include "nsCycleCollectionParticipant.h"
     190                 : 
     191                 : // for ReportToConsole
     192                 : #include "nsIStringBundle.h"
     193                 : #include "nsIScriptError.h"
     194                 : #include "nsIConsoleService.h"
     195                 : 
     196                 : #include "mozAutoDocUpdate.h"
     197                 : #include "imgICache.h"
     198                 : #include "xpcprivate.h" // nsXPConnect
     199                 : #include "nsScriptSecurityManager.h"
     200                 : #include "nsIChannelPolicy.h"
     201                 : #include "nsChannelPolicy.h"
     202                 : #include "nsIContentSecurityPolicy.h"
     203                 : #include "nsContentDLF.h"
     204                 : #ifdef MOZ_MEDIA
     205                 : #include "nsHTMLMediaElement.h"
     206                 : #endif
     207                 : #include "nsDOMTouchEvent.h"
     208                 : #include "nsIScriptElement.h"
     209                 : #include "nsIContentViewer.h"
     210                 : #include "nsIObjectLoadingContent.h"
     211                 : #include "nsCCUncollectableMarker.h"
     212                 : #include "mozilla/Base64.h"
     213                 : #include "mozilla/Preferences.h"
     214                 : 
     215                 : #include "nsWrapperCacheInlines.h"
     216                 : #include "nsIDOMDocumentType.h"
     217                 : #include "nsIDOMWindowUtils.h"
     218                 : #include "nsCharSeparatedTokenizer.h"
     219                 : #include "nsUnicharUtils.h"
     220                 : 
     221                 : using namespace mozilla::dom;
     222                 : using namespace mozilla::layers;
     223                 : using namespace mozilla::widget;
     224                 : using namespace mozilla;
     225                 : 
     226                 : const char kLoadAsData[] = "loadAsData";
     227                 : 
     228                 : /**
     229                 :  * Default values for the ViewportInfo structure.
     230                 :  */
     231                 : static const float    kViewportMinScale = 0.0;
     232                 : static const float    kViewportMaxScale = 10.0;
     233                 : static const PRUint32 kViewportMinWidth = 200;
     234                 : static const PRUint32 kViewportMaxWidth = 10000;
     235                 : static const PRUint32 kViewportMinHeight = 223;
     236                 : static const PRUint32 kViewportMaxHeight = 10000;
     237                 : static const PRInt32  kViewportDefaultScreenWidth = 980;
     238                 : 
     239                 : static const char kJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
     240                 : static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
     241                 : static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
     242                 : 
     243                 : nsIDOMScriptObjectFactory *nsContentUtils::sDOMScriptObjectFactory = nsnull;
     244                 : nsIXPConnect *nsContentUtils::sXPConnect;
     245                 : nsIScriptSecurityManager *nsContentUtils::sSecurityManager;
     246                 : nsIThreadJSContextStack *nsContentUtils::sThreadJSContextStack;
     247                 : nsIParserService *nsContentUtils::sParserService = nsnull;
     248                 : nsINameSpaceManager *nsContentUtils::sNameSpaceManager;
     249                 : nsIIOService *nsContentUtils::sIOService;
     250                 : #ifdef MOZ_XTF
     251                 : nsIXTFService *nsContentUtils::sXTFService = nsnull;
     252                 : #endif
     253                 : imgILoader *nsContentUtils::sImgLoader;
     254                 : imgICache *nsContentUtils::sImgCache;
     255                 : nsIConsoleService *nsContentUtils::sConsoleService;
     256                 : nsDataHashtable<nsISupportsHashKey, EventNameMapping>* nsContentUtils::sAtomEventTable = nsnull;
     257                 : nsDataHashtable<nsStringHashKey, EventNameMapping>* nsContentUtils::sStringEventTable = nsnull;
     258                 : nsCOMArray<nsIAtom>* nsContentUtils::sUserDefinedEvents = nsnull;
     259                 : nsIStringBundleService *nsContentUtils::sStringBundleService;
     260                 : nsIStringBundle *nsContentUtils::sStringBundles[PropertiesFile_COUNT];
     261                 : nsIContentPolicy *nsContentUtils::sContentPolicyService;
     262                 : bool nsContentUtils::sTriedToGetContentPolicy = false;
     263                 : nsILineBreaker *nsContentUtils::sLineBreaker;
     264                 : nsIWordBreaker *nsContentUtils::sWordBreaker;
     265                 : nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND];
     266                 : PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND];
     267                 : PRUint32 nsContentUtils::sJSGCThingRootCount;
     268                 : #ifdef IBMBIDI
     269                 : nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull;
     270                 : #endif
     271                 : PRUint32 nsContentUtils::sScriptBlockerCount = 0;
     272                 : #ifdef DEBUG
     273                 : PRUint32 nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
     274                 : #endif
     275                 : nsTArray< nsCOMPtr<nsIRunnable> >* nsContentUtils::sBlockedScriptRunners = nsnull;
     276                 : PRUint32 nsContentUtils::sRunnersCountAtFirstBlocker = 0;
     277                 : nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nsnull;
     278                 : 
     279                 : bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
     280                 : bool nsContentUtils::sAllowXULXBL_for_file = false;
     281                 : 
     282                 : nsString* nsContentUtils::sShiftText = nsnull;
     283                 : nsString* nsContentUtils::sControlText = nsnull;
     284                 : nsString* nsContentUtils::sMetaText = nsnull;
     285                 : nsString* nsContentUtils::sAltText = nsnull;
     286                 : nsString* nsContentUtils::sModifierSeparator = nsnull;
     287                 : 
     288                 : bool nsContentUtils::sInitialized = false;
     289                 : bool nsContentUtils::sIsFullScreenApiEnabled = false;
     290                 : bool nsContentUtils::sTrustedFullScreenOnly = true;
     291                 : bool nsContentUtils::sFullScreenKeyInputRestricted = true;
     292                 : 
     293                 : PRUint32 nsContentUtils::sHandlingInputTimeout = 1000;
     294                 : 
     295                 : nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nsnull;
     296                 : nsIParser* nsContentUtils::sXMLFragmentParser = nsnull;
     297                 : nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nsnull;
     298                 : bool nsContentUtils::sFragmentParsingActive = false;
     299                 : 
     300                 : static PLDHashTable sEventListenerManagersHash;
     301                 : 
     302                 : class EventListenerManagerMapEntry : public PLDHashEntryHdr
     303                 : {
     304                 : public:
     305               2 :   EventListenerManagerMapEntry(const void *aKey)
     306               2 :     : mKey(aKey)
     307                 :   {
     308               2 :   }
     309                 : 
     310               0 :   ~EventListenerManagerMapEntry()
     311               0 :   {
     312               0 :     NS_ASSERTION(!mListenerManager, "caller must release and disconnect ELM");
     313               0 :   }
     314                 : 
     315                 : private:
     316                 :   const void *mKey; // must be first, to look like PLDHashEntryStub
     317                 : 
     318                 : public:
     319                 :   nsRefPtr<nsEventListenerManager> mListenerManager;
     320                 : };
     321                 : 
     322                 : static bool
     323               2 : EventListenerManagerHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
     324                 :                                   const void *key)
     325                 : {
     326                 :   // Initialize the entry with placement new
     327               2 :   new (entry) EventListenerManagerMapEntry(key);
     328               2 :   return true;
     329                 : }
     330                 : 
     331                 : static void
     332               0 : EventListenerManagerHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
     333                 : {
     334                 :   EventListenerManagerMapEntry *lm =
     335               0 :     static_cast<EventListenerManagerMapEntry *>(entry);
     336                 : 
     337                 :   // Let the EventListenerManagerMapEntry clean itself up...
     338               0 :   lm->~EventListenerManagerMapEntry();
     339               0 : }
     340                 : 
     341                 : class nsSameOriginChecker : public nsIChannelEventSink,
     342                 :                             public nsIInterfaceRequestor
     343               0 : {
     344                 :   NS_DECL_ISUPPORTS
     345                 :   NS_DECL_NSICHANNELEVENTSINK
     346                 :   NS_DECL_NSIINTERFACEREQUESTOR
     347                 : };
     348                 : 
     349                 : /* static */
     350                 : TimeDuration
     351               0 : nsContentUtils::HandlingUserInputTimeout()
     352                 : {
     353               0 :   return TimeDuration::FromMilliseconds(sHandlingInputTimeout);
     354                 : }
     355                 : 
     356                 : // static
     357                 : nsresult
     358            1404 : nsContentUtils::Init()
     359                 : {
     360            1404 :   if (sInitialized) {
     361               0 :     NS_WARNING("Init() called twice");
     362                 : 
     363               0 :     return NS_OK;
     364                 :   }
     365                 : 
     366            1404 :   nsresult rv = NS_GetNameSpaceManager(&sNameSpaceManager);
     367            1404 :   NS_ENSURE_SUCCESS(rv, rv);
     368                 : 
     369            1404 :   nsXPConnect* xpconnect = nsXPConnect::GetXPConnect();
     370            1404 :   NS_ENSURE_TRUE(xpconnect, NS_ERROR_FAILURE);
     371                 : 
     372            1404 :   sXPConnect = xpconnect;
     373            1404 :   sThreadJSContextStack = xpconnect;
     374                 : 
     375            1404 :   sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
     376            1404 :   if(!sSecurityManager)
     377               0 :     return NS_ERROR_FAILURE;
     378            1404 :   NS_ADDREF(sSecurityManager);
     379                 : 
     380            1404 :   rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
     381            1404 :   if (NS_FAILED(rv)) {
     382                 :     // This makes life easier, but we can live without it.
     383                 : 
     384               0 :     sIOService = nsnull;
     385                 :   }
     386                 : 
     387            1404 :   rv = CallGetService(NS_LBRK_CONTRACTID, &sLineBreaker);
     388            1404 :   NS_ENSURE_SUCCESS(rv, rv);
     389                 :   
     390            1404 :   rv = CallGetService(NS_WBRK_CONTRACTID, &sWordBreaker);
     391            1404 :   NS_ENSURE_SUCCESS(rv, rv);
     392                 : 
     393            1404 :   if (!InitializeEventTable())
     394               0 :     return NS_ERROR_FAILURE;
     395                 : 
     396            1404 :   if (!sEventListenerManagersHash.ops) {
     397                 :     static PLDHashTableOps hash_table_ops =
     398                 :     {
     399                 :       PL_DHashAllocTable,
     400                 :       PL_DHashFreeTable,
     401                 :       PL_DHashVoidPtrKeyStub,
     402                 :       PL_DHashMatchEntryStub,
     403                 :       PL_DHashMoveEntryStub,
     404                 :       EventListenerManagerHashClearEntry,
     405                 :       PL_DHashFinalizeStub,
     406                 :       EventListenerManagerHashInitEntry
     407                 :     };
     408                 : 
     409            1404 :     if (!PL_DHashTableInit(&sEventListenerManagersHash, &hash_table_ops,
     410            1404 :                            nsnull, sizeof(EventListenerManagerMapEntry), 16)) {
     411               0 :       sEventListenerManagersHash.ops = nsnull;
     412                 : 
     413               0 :       return NS_ERROR_OUT_OF_MEMORY;
     414                 :     }
     415                 :   }
     416                 : 
     417            1404 :   sBlockedScriptRunners = new nsTArray< nsCOMPtr<nsIRunnable> >;
     418                 : 
     419                 :   Preferences::AddBoolVarCache(&sAllowXULXBL_for_file,
     420            1404 :                                "dom.allow_XUL_XBL_for_file");
     421                 : 
     422                 :   Preferences::AddBoolVarCache(&sIsFullScreenApiEnabled,
     423            1404 :                                "full-screen-api.enabled");
     424                 : 
     425                 :   Preferences::AddBoolVarCache(&sTrustedFullScreenOnly,
     426            1404 :                                "full-screen-api.allow-trusted-requests-only");
     427                 : 
     428                 :   Preferences::AddBoolVarCache(&sFullScreenKeyInputRestricted,
     429            1404 :                                "full-screen-api.key-input-restricted");
     430                 : 
     431                 :   Preferences::AddUintVarCache(&sHandlingInputTimeout,
     432                 :                                "dom.event.handling-user-input-time-limit",
     433            1404 :                                1000);
     434                 : 
     435            1404 :   nsGenericElement::InitCCCallbacks();
     436                 : 
     437            1404 :   sInitialized = true;
     438                 : 
     439            1404 :   return NS_OK;
     440                 : }
     441                 : 
     442                 : void
     443               0 : nsContentUtils::GetShiftText(nsAString& text)
     444                 : {
     445               0 :   if (!sShiftText)
     446               0 :     InitializeModifierStrings();
     447               0 :   text.Assign(*sShiftText);
     448               0 : }
     449                 : 
     450                 : void
     451               0 : nsContentUtils::GetControlText(nsAString& text)
     452                 : {
     453               0 :   if (!sControlText)
     454               0 :     InitializeModifierStrings();
     455               0 :   text.Assign(*sControlText);
     456               0 : }
     457                 : 
     458                 : void
     459               0 : nsContentUtils::GetMetaText(nsAString& text)
     460                 : {
     461               0 :   if (!sMetaText)
     462               0 :     InitializeModifierStrings();
     463               0 :   text.Assign(*sMetaText);
     464               0 : }
     465                 : 
     466                 : void
     467               0 : nsContentUtils::GetAltText(nsAString& text)
     468                 : {
     469               0 :   if (!sAltText)
     470               0 :     InitializeModifierStrings();
     471               0 :   text.Assign(*sAltText);
     472               0 : }
     473                 : 
     474                 : void
     475               0 : nsContentUtils::GetModifierSeparatorText(nsAString& text)
     476                 : {
     477               0 :   if (!sModifierSeparator)
     478               0 :     InitializeModifierStrings();
     479               0 :   text.Assign(*sModifierSeparator);
     480               0 : }
     481                 : 
     482                 : void
     483               0 : nsContentUtils::InitializeModifierStrings()
     484                 : {
     485                 :   //load the display strings for the keyboard accelerators
     486                 :   nsCOMPtr<nsIStringBundleService> bundleService =
     487               0 :     mozilla::services::GetStringBundleService();
     488               0 :   nsCOMPtr<nsIStringBundle> bundle;
     489               0 :   nsresult rv = NS_OK;
     490               0 :   if (bundleService) {
     491               0 :     rv = bundleService->CreateBundle( "chrome://global-platform/locale/platformKeys.properties",
     492               0 :                                       getter_AddRefs(bundle));
     493                 :   }
     494                 :   
     495               0 :   NS_ASSERTION(NS_SUCCEEDED(rv) && bundle, "chrome://global/locale/platformKeys.properties could not be loaded");
     496               0 :   nsXPIDLString shiftModifier;
     497               0 :   nsXPIDLString metaModifier;
     498               0 :   nsXPIDLString altModifier;
     499               0 :   nsXPIDLString controlModifier;
     500               0 :   nsXPIDLString modifierSeparator;
     501               0 :   if (bundle) {
     502                 :     //macs use symbols for each modifier key, so fetch each from the bundle, which also covers i18n
     503               0 :     bundle->GetStringFromName(NS_LITERAL_STRING("VK_SHIFT").get(), getter_Copies(shiftModifier));
     504               0 :     bundle->GetStringFromName(NS_LITERAL_STRING("VK_META").get(), getter_Copies(metaModifier));
     505               0 :     bundle->GetStringFromName(NS_LITERAL_STRING("VK_ALT").get(), getter_Copies(altModifier));
     506               0 :     bundle->GetStringFromName(NS_LITERAL_STRING("VK_CONTROL").get(), getter_Copies(controlModifier));
     507               0 :     bundle->GetStringFromName(NS_LITERAL_STRING("MODIFIER_SEPARATOR").get(), getter_Copies(modifierSeparator));
     508                 :   }
     509                 :   //if any of these don't exist, we get  an empty string
     510               0 :   sShiftText = new nsString(shiftModifier);
     511               0 :   sMetaText = new nsString(metaModifier);
     512               0 :   sAltText = new nsString(altModifier);
     513               0 :   sControlText = new nsString(controlModifier);
     514               0 :   sModifierSeparator = new nsString(modifierSeparator);  
     515               0 : }
     516                 : 
     517                 : bool nsContentUtils::sImgLoaderInitialized;
     518                 : 
     519                 : void
     520               1 : nsContentUtils::InitImgLoader()
     521                 : {
     522               1 :   sImgLoaderInitialized = true;
     523                 : 
     524                 :   // Ignore failure and just don't load images
     525               1 :   nsresult rv = CallGetService("@mozilla.org/image/loader;1", &sImgLoader);
     526               1 :   if (NS_FAILED(rv)) {
     527                 :     // no image loading for us.  Oh, well.
     528               0 :     sImgLoader = nsnull;
     529               0 :     sImgCache = nsnull;
     530                 :   } else {
     531               1 :     if (NS_FAILED(CallGetService("@mozilla.org/image/cache;1", &sImgCache )))
     532               0 :       sImgCache = nsnull;
     533                 :   }
     534               1 : }
     535                 : 
     536                 : bool
     537            1404 : nsContentUtils::InitializeEventTable() {
     538            1404 :   NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!");
     539            1404 :   NS_ASSERTION(!sStringEventTable, "EventTable already initialized!");
     540                 : 
     541                 :   static const EventNameMapping eventArray[] = {
     542                 : #define EVENT(name_,  _id, _type, _struct)          \
     543                 :     { nsGkAtoms::on##name_, _id, _type, _struct },
     544                 : #define WINDOW_ONLY_EVENT EVENT
     545                 : #define NON_IDL_EVENT EVENT
     546                 : #include "nsEventNameList.h"
     547                 : #undef WINDOW_ONLY_EVENT
     548                 : #undef EVENT
     549                 :     { nsnull }
     550            1404 :   };
     551                 : 
     552            1404 :   sAtomEventTable = new nsDataHashtable<nsISupportsHashKey, EventNameMapping>;
     553            1404 :   sStringEventTable = new nsDataHashtable<nsStringHashKey, EventNameMapping>;
     554            1404 :   sUserDefinedEvents = new nsCOMArray<nsIAtom>(64);
     555                 : 
     556            4212 :   if (!sAtomEventTable || !sStringEventTable || !sUserDefinedEvents ||
     557            1404 :       !sAtomEventTable->Init(int(ArrayLength(eventArray) / 0.75) + 1) ||
     558            1404 :       !sStringEventTable->Init(int(ArrayLength(eventArray) / 0.75) + 1)) {
     559               0 :     delete sAtomEventTable;
     560               0 :     sAtomEventTable = nsnull;
     561               0 :     delete sStringEventTable;
     562               0 :     sStringEventTable = nsnull;
     563               0 :     delete sUserDefinedEvents;
     564               0 :     sUserDefinedEvents = nsnull;
     565               0 :     return false;
     566                 :   }
     567                 : 
     568                 :   // Subtract one from the length because of the trailing null
     569          196560 :   for (PRUint32 i = 0; i < ArrayLength(eventArray) - 1; ++i) {
     570          780624 :     if (!sAtomEventTable->Put(eventArray[i].mAtom, eventArray[i]) ||
     571          390312 :         !sStringEventTable->Put(Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
     572          780624 :                                 eventArray[i])) {
     573               0 :       delete sAtomEventTable;
     574               0 :       sAtomEventTable = nsnull;
     575               0 :       delete sStringEventTable;
     576               0 :       sStringEventTable = nsnull;
     577               0 :       return false;
     578                 :     }
     579                 :   }
     580                 : 
     581            1404 :   return true;
     582                 : }
     583                 : 
     584                 : void
     585               0 : nsContentUtils::InitializeTouchEventTable()
     586                 : {
     587                 :   static bool sEventTableInitialized = false;
     588               0 :   if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
     589               0 :     sEventTableInitialized = true;
     590                 :     static const EventNameMapping touchEventArray[] = {
     591                 : #define EVENT(name_,  _id, _type, _struct)
     592                 : #define TOUCH_EVENT(name_,  _id, _type, _struct)      \
     593                 :       { nsGkAtoms::on##name_, _id, _type, _struct },
     594                 : #include "nsEventNameList.h"
     595                 : #undef TOUCH_EVENT
     596                 : #undef EVENT
     597                 :       { nsnull }
     598               0 :     };
     599                 :     // Subtract one from the length because of the trailing null
     600               0 :     for (PRUint32 i = 0; i < ArrayLength(touchEventArray) - 1; ++i) {
     601               0 :       if (!sAtomEventTable->Put(touchEventArray[i].mAtom, touchEventArray[i]) ||
     602               0 :           !sStringEventTable->Put(Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
     603               0 :                                   touchEventArray[i])) {
     604               0 :         delete sAtomEventTable;
     605               0 :         sAtomEventTable = nsnull;
     606               0 :         delete sStringEventTable;
     607               0 :         sStringEventTable = nsnull;
     608               0 :         return;
     609                 :       }
     610                 :     }
     611                 :   }
     612                 : }
     613                 : 
     614                 : static bool
     615               0 : Is8bit(const nsAString& aString)
     616                 : {
     617                 :   static const PRUnichar EIGHT_BIT = PRUnichar(~0x00FF);
     618                 : 
     619               0 :   nsAString::const_iterator done_reading;
     620               0 :   aString.EndReading(done_reading);
     621                 : 
     622                 :   // for each chunk of |aString|...
     623               0 :   PRUint32 fragmentLength = 0;
     624               0 :   nsAString::const_iterator iter;
     625               0 :   for (aString.BeginReading(iter); iter != done_reading;
     626               0 :        iter.advance(PRInt32(fragmentLength))) {
     627               0 :     fragmentLength = PRUint32(iter.size_forward());
     628               0 :     const PRUnichar* c = iter.get();
     629               0 :     const PRUnichar* fragmentEnd = c + fragmentLength;
     630                 : 
     631                 :     // for each character in this chunk...
     632               0 :     while (c < fragmentEnd) {
     633               0 :       if (*c++ & EIGHT_BIT) {
     634               0 :         return false;
     635                 :       }
     636                 :     }
     637                 :   }
     638                 : 
     639               0 :   return true;
     640                 : }
     641                 : 
     642                 : nsresult
     643               0 : nsContentUtils::Btoa(const nsAString& aBinaryData,
     644                 :                      nsAString& aAsciiBase64String)
     645                 : {
     646               0 :   if (!Is8bit(aBinaryData)) {
     647               0 :     aAsciiBase64String.Truncate();
     648               0 :     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
     649                 :   }
     650                 : 
     651               0 :   return Base64Encode(aBinaryData, aAsciiBase64String);
     652                 : }
     653                 : 
     654                 : nsresult
     655               0 : nsContentUtils::Atob(const nsAString& aAsciiBase64String,
     656                 :                      nsAString& aBinaryData)
     657                 : {
     658               0 :   if (!Is8bit(aAsciiBase64String)) {
     659               0 :     aBinaryData.Truncate();
     660               0 :     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
     661                 :   }
     662                 : 
     663               0 :   nsresult rv = Base64Decode(aAsciiBase64String, aBinaryData);
     664               0 :   if (NS_FAILED(rv) && rv == NS_ERROR_INVALID_ARG) {
     665               0 :     return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
     666                 :   }
     667               0 :   return rv;
     668                 : }
     669                 : 
     670                 : bool
     671               0 : nsContentUtils::IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput)
     672                 : {
     673               0 :   NS_PRECONDITION(aInput, "aInput should not be null!");
     674                 : 
     675               0 :   nsAutoString autocomplete;
     676               0 :   aInput->GetAutocomplete(autocomplete);
     677                 : 
     678               0 :   if (autocomplete.IsEmpty()) {
     679               0 :     nsCOMPtr<nsIDOMHTMLFormElement> form;
     680               0 :     aInput->GetForm(getter_AddRefs(form));
     681               0 :     if (!form) {
     682               0 :       return true;
     683                 :     }
     684                 : 
     685               0 :     form->GetAutocomplete(autocomplete);
     686                 :   }
     687                 : 
     688               0 :   return autocomplete.EqualsLiteral("on");
     689                 : }
     690                 : 
     691                 : bool
     692               0 : nsContentUtils::URIIsChromeOrInPref(nsIURI *aURI, const char *aPref)
     693                 : {
     694               0 :   if (!aURI) {
     695               0 :     return false;
     696                 :   }
     697                 : 
     698               0 :   nsCAutoString scheme;
     699               0 :   aURI->GetScheme(scheme);
     700               0 :   if (scheme.EqualsLiteral("chrome")) {
     701               0 :     return true;
     702                 :   }
     703                 : 
     704               0 :   nsCAutoString prePathUTF8;
     705               0 :   aURI->GetPrePath(prePathUTF8);
     706               0 :   NS_ConvertUTF8toUTF16 prePath(prePathUTF8);
     707                 : 
     708               0 :   const nsAdoptingString& whitelist = Preferences::GetString(aPref);
     709                 : 
     710                 :   // This tokenizer also strips off whitespace around tokens, as desired.
     711                 :   nsCharSeparatedTokenizer tokenizer(whitelist, ',',
     712               0 :     nsCharSeparatedTokenizerTemplate<>::SEPARATOR_OPTIONAL);
     713                 : 
     714               0 :   while (tokenizer.hasMoreTokens()) {
     715               0 :     const nsSubstring& whitelistItem = tokenizer.nextToken();
     716                 : 
     717               0 :     if (whitelistItem.Equals(prePath, nsCaseInsensitiveStringComparator())) {
     718               0 :       return true;
     719                 :     }
     720                 :   }
     721                 : 
     722               0 :   return false;
     723                 : }
     724                 : 
     725                 : #define SKIP_WHITESPACE(iter, end_iter, end_res)                 \
     726                 :   while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
     727                 :     ++(iter);                                                    \
     728                 :   }                                                              \
     729                 :   if ((iter) == (end_iter)) {                                    \
     730                 :     return (end_res);                                            \
     731                 :   }
     732                 : 
     733                 : #define SKIP_ATTR_NAME(iter, end_iter)                            \
     734                 :   while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
     735                 :          *(iter) != '=') {                                        \
     736                 :     ++(iter);                                                     \
     737                 :   }
     738                 : 
     739                 : bool
     740             112 : nsContentUtils::GetPseudoAttributeValue(const nsString& aSource, nsIAtom *aName,
     741                 :                                         nsAString& aValue)
     742                 : {
     743             112 :   aValue.Truncate();
     744                 : 
     745             112 :   const PRUnichar *start = aSource.get();
     746             112 :   const PRUnichar *end = start + aSource.Length();
     747                 :   const PRUnichar *iter;
     748                 : 
     749             286 :   while (start != end) {
     750             154 :     SKIP_WHITESPACE(start, end, false)
     751             154 :     iter = start;
     752             154 :     SKIP_ATTR_NAME(iter, end)
     753                 : 
     754             154 :     if (start == iter) {
     755               0 :       return false;
     756                 :     }
     757                 : 
     758                 :     // Remember the attr name.
     759             308 :     const nsDependentSubstring & attrName = Substring(start, iter);
     760                 : 
     761                 :     // Now check whether this is a valid name="value" pair.
     762             154 :     start = iter;
     763             154 :     SKIP_WHITESPACE(start, end, false)
     764             130 :     if (*start != '=') {
     765                 :       // No '=', so this is not a name="value" pair.  We don't know
     766                 :       // what it is, and we have no way to handle it.
     767               6 :       return false;
     768                 :     }
     769                 : 
     770                 :     // Have to skip the value.
     771             124 :     ++start;
     772             124 :     SKIP_WHITESPACE(start, end, false)
     773             124 :     PRUnichar q = *start;
     774             124 :     if (q != kQuote && q != kApostrophe) {
     775                 :       // Not a valid quoted value, so bail.
     776               0 :       return false;
     777                 :     }
     778                 : 
     779             124 :     ++start;  // Point to the first char of the value.
     780             124 :     iter = start;
     781                 : 
     782            2666 :     while (iter != end && *iter != q) {
     783            2418 :       ++iter;
     784                 :     }
     785                 : 
     786             124 :     if (iter == end) {
     787                 :       // Oops, unterminated quoted string.
     788               0 :       return false;
     789                 :     }
     790                 : 
     791                 :     // At this point attrName holds the name of the "attribute" and
     792                 :     // the value is between start and iter.
     793                 : 
     794             124 :     if (aName->Equals(attrName)) {
     795              62 :       nsIParserService* parserService = nsContentUtils::GetParserService();
     796              62 :       NS_ENSURE_TRUE(parserService, false);
     797                 : 
     798                 :       // We'll accumulate as many characters as possible (until we hit either
     799                 :       // the end of the string or the beginning of an entity). Chunks will be
     800                 :       // delimited by start and chunkEnd.
     801              62 :       const PRUnichar *chunkEnd = start;
     802             620 :       while (chunkEnd != iter) {
     803             496 :         if (*chunkEnd == kLessThan) {
     804               0 :           aValue.Truncate();
     805                 : 
     806               0 :           return false;
     807                 :         }
     808                 : 
     809             496 :         if (*chunkEnd == kAmpersand) {
     810               0 :           aValue.Append(start, chunkEnd - start);
     811                 : 
     812                 :           // Point to first character after the ampersand.
     813               0 :           ++chunkEnd;
     814                 : 
     815                 :           const PRUnichar *afterEntity;
     816                 :           PRUnichar result[2];
     817                 :           PRUint32 count =
     818               0 :             parserService->DecodeEntity(chunkEnd, iter, &afterEntity, result);
     819               0 :           if (count == 0) {
     820               0 :             aValue.Truncate();
     821                 : 
     822               0 :             return false;
     823                 :           }
     824                 : 
     825               0 :           aValue.Append(result, count);
     826                 : 
     827                 :           // Advance to after the entity and begin a new chunk.
     828               0 :           start = chunkEnd = afterEntity;
     829                 :         }
     830                 :         else {
     831             496 :           ++chunkEnd;
     832                 :         }
     833                 :       }
     834                 : 
     835                 :       // Append remainder.
     836              62 :       aValue.Append(start, iter - start);
     837                 : 
     838              62 :       return true;
     839                 :     }
     840                 : 
     841                 :     // Resume scanning after the end of the attribute value (past the quote
     842                 :     // char).
     843             216 :     start = iter + 1;
     844                 :   }
     845                 : 
     846              20 :   return false;
     847                 : }
     848                 : 
     849                 : bool
     850               0 : nsContentUtils::IsJavaScriptLanguage(const nsString& aName, PRUint32 *aFlags)
     851                 : {
     852               0 :   JSVersion version = JSVERSION_UNKNOWN;
     853                 : 
     854               0 :   if (aName.LowerCaseEqualsLiteral("javascript") ||
     855               0 :       aName.LowerCaseEqualsLiteral("livescript") ||
     856               0 :       aName.LowerCaseEqualsLiteral("mocha")) {
     857               0 :     version = JSVERSION_DEFAULT;
     858               0 :   } else if (aName.LowerCaseEqualsLiteral("javascript1.0")) {
     859               0 :     version = JSVERSION_1_0;
     860               0 :   } else if (aName.LowerCaseEqualsLiteral("javascript1.1")) {
     861               0 :     version = JSVERSION_1_1;
     862               0 :   } else if (aName.LowerCaseEqualsLiteral("javascript1.2")) {
     863               0 :     version = JSVERSION_1_2;
     864               0 :   } else if (aName.LowerCaseEqualsLiteral("javascript1.3")) {
     865               0 :     version = JSVERSION_1_3;
     866               0 :   } else if (aName.LowerCaseEqualsLiteral("javascript1.4")) {
     867               0 :     version = JSVERSION_1_4;
     868               0 :   } else if (aName.LowerCaseEqualsLiteral("javascript1.5")) {
     869               0 :     version = JSVERSION_1_5;
     870               0 :   } else if (aName.LowerCaseEqualsLiteral("javascript1.6")) {
     871               0 :     version = JSVERSION_1_6;
     872               0 :   } else if (aName.LowerCaseEqualsLiteral("javascript1.7")) {
     873               0 :     version = JSVERSION_1_7;
     874               0 :   } else if (aName.LowerCaseEqualsLiteral("javascript1.8")) {
     875               0 :     version = JSVERSION_1_8;
     876                 :   }
     877                 : 
     878               0 :   if (version == JSVERSION_UNKNOWN) {
     879               0 :     return false;
     880                 :   }
     881               0 :   *aFlags = version;
     882               0 :   return true;
     883                 : }
     884                 : 
     885                 : void
     886               0 : nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
     887                 :                               nsString& aParams)
     888                 : {
     889               0 :   aType.Truncate();
     890               0 :   aParams.Truncate();
     891               0 :   PRInt32 semiIndex = aValue.FindChar(PRUnichar(';'));
     892               0 :   if (-1 != semiIndex) {
     893               0 :     aType = Substring(aValue, 0, semiIndex);
     894                 :     aParams = Substring(aValue, semiIndex + 1,
     895               0 :                        aValue.Length() - (semiIndex + 1));
     896               0 :     aParams.StripWhitespace();
     897                 :   }
     898                 :   else {
     899               0 :     aType = aValue;
     900                 :   }
     901               0 :   aType.StripWhitespace();
     902               0 : }
     903                 : 
     904                 : /**
     905                 :  * Access a cached parser service. Don't addref. We need only one
     906                 :  * reference to it and this class has that one.
     907                 :  */
     908                 : /* static */
     909                 : nsIParserService*
     910            2966 : nsContentUtils::GetParserService()
     911                 : {
     912                 :   // XXX: This isn't accessed from several threads, is it?
     913            2966 :   if (!sParserService) {
     914                 :     // Lock, recheck sCachedParserService and aquire if this should be
     915                 :     // safe for multiple threads.
     916              36 :     nsresult rv = CallGetService(kParserServiceCID, &sParserService);
     917              36 :     if (NS_FAILED(rv)) {
     918               0 :       sParserService = nsnull;
     919                 :     }
     920                 :   }
     921                 : 
     922            2966 :   return sParserService;
     923                 : }
     924                 : 
     925                 : #ifdef MOZ_XTF
     926                 : nsIXTFService*
     927           19537 : nsContentUtils::GetXTFService()
     928                 : {
     929           19537 :   if (!sXTFService) {
     930             236 :     nsresult rv = CallGetService(kXTFServiceCID, &sXTFService);
     931             236 :     if (NS_FAILED(rv)) {
     932               0 :       sXTFService = nsnull;
     933                 :     }
     934                 :   }
     935                 : 
     936           19537 :   return sXTFService;
     937                 : }
     938                 : #endif
     939                 : 
     940                 : #ifdef IBMBIDI
     941                 : nsIBidiKeyboard*
     942               0 : nsContentUtils::GetBidiKeyboard()
     943                 : {
     944               0 :   if (!sBidiKeyboard) {
     945               0 :     nsresult rv = CallGetService("@mozilla.org/widget/bidikeyboard;1", &sBidiKeyboard);
     946               0 :     if (NS_FAILED(rv)) {
     947               0 :       sBidiKeyboard = nsnull;
     948                 :     }
     949                 :   }
     950               0 :   return sBidiKeyboard;
     951                 : }
     952                 : #endif
     953                 : 
     954                 : template <class OutputIterator>
     955                 : struct NormalizeNewlinesCharTraits {
     956                 :   public:
     957                 :     typedef typename OutputIterator::value_type value_type;
     958                 : 
     959                 :   public:
     960               0 :     NormalizeNewlinesCharTraits(OutputIterator& aIterator) : mIterator(aIterator) { }
     961               0 :     void writechar(typename OutputIterator::value_type aChar) {
     962               0 :       *mIterator++ = aChar;
     963               0 :     }
     964                 : 
     965                 :   private:
     966                 :     OutputIterator mIterator;
     967                 : };
     968                 : 
     969                 : #ifdef HAVE_CPP_PARTIAL_SPECIALIZATION
     970                 : 
     971                 : template <class CharT>
     972                 : struct NormalizeNewlinesCharTraits<CharT*> {
     973                 :   public:
     974                 :     typedef CharT value_type;
     975                 : 
     976                 :   public:
     977               0 :     NormalizeNewlinesCharTraits(CharT* aCharPtr) : mCharPtr(aCharPtr) { }
     978               0 :     void writechar(CharT aChar) {
     979               0 :       *mCharPtr++ = aChar;
     980               0 :     }
     981                 : 
     982                 :   private:
     983                 :     CharT* mCharPtr;
     984                 : };
     985                 : 
     986                 : #else
     987                 : 
     988                 : template <>
     989                 : struct NormalizeNewlinesCharTraits<char*> {
     990                 :   public:
     991                 :     typedef char value_type;
     992                 : 
     993                 :   public:
     994                 :     NormalizeNewlinesCharTraits(char* aCharPtr) : mCharPtr(aCharPtr) { }
     995                 :     void writechar(char aChar) {
     996                 :       *mCharPtr++ = aChar;
     997                 :     }
     998                 : 
     999                 :   private:
    1000                 :     char* mCharPtr;
    1001                 : };
    1002                 : 
    1003                 : template <>
    1004                 : struct NormalizeNewlinesCharTraits<PRUnichar*> {
    1005                 :   public:
    1006                 :     typedef PRUnichar value_type;
    1007                 : 
    1008                 :   public:
    1009                 :     NormalizeNewlinesCharTraits(PRUnichar* aCharPtr) : mCharPtr(aCharPtr) { }
    1010                 :     void writechar(PRUnichar aChar) {
    1011                 :       *mCharPtr++ = aChar;
    1012                 :     }
    1013                 : 
    1014                 :   private:
    1015                 :     PRUnichar* mCharPtr;
    1016                 : };
    1017                 : 
    1018                 : #endif
    1019                 : 
    1020                 : template <class OutputIterator>
    1021                 : class CopyNormalizeNewlines
    1022                 : {
    1023                 :   public:
    1024                 :     typedef typename OutputIterator::value_type value_type;
    1025                 : 
    1026                 :   public:
    1027               0 :     CopyNormalizeNewlines(OutputIterator* aDestination,
    1028                 :                           bool aLastCharCR=false) :
    1029                 :       mLastCharCR(aLastCharCR),
    1030                 :       mDestination(aDestination),
    1031               0 :       mWritten(0)
    1032               0 :     { }
    1033                 : 
    1034               0 :     PRUint32 GetCharsWritten() {
    1035               0 :       return mWritten;
    1036                 :     }
    1037                 : 
    1038               0 :     bool IsLastCharCR() {
    1039               0 :       return mLastCharCR;
    1040                 :     }
    1041                 : 
    1042               0 :     void write(const typename OutputIterator::value_type* aSource, PRUint32 aSourceLength) {
    1043                 : 
    1044               0 :       const typename OutputIterator::value_type* done_writing = aSource + aSourceLength;
    1045                 : 
    1046                 :       // If the last source buffer ended with a CR...
    1047               0 :       if (mLastCharCR) {
    1048                 :         // ..and if the next one is a LF, then skip it since
    1049                 :         // we've already written out a newline
    1050               0 :         if (aSourceLength && (*aSource == value_type('\n'))) {
    1051               0 :           ++aSource;
    1052                 :         }
    1053               0 :         mLastCharCR = false;
    1054                 :       }
    1055                 : 
    1056               0 :       PRUint32 num_written = 0;
    1057               0 :       while ( aSource < done_writing ) {
    1058               0 :         if (*aSource == value_type('\r')) {
    1059               0 :           mDestination->writechar('\n');
    1060               0 :           ++aSource;
    1061                 :           // If we've reached the end of the buffer, record
    1062                 :           // that we wrote out a CR
    1063               0 :           if (aSource == done_writing) {
    1064               0 :             mLastCharCR = true;
    1065                 :           }
    1066                 :           // If the next character is a LF, skip it
    1067               0 :           else if (*aSource == value_type('\n')) {
    1068               0 :             ++aSource;
    1069                 :           }
    1070                 :         }
    1071                 :         else {
    1072               0 :           mDestination->writechar(*aSource++);
    1073                 :         }
    1074               0 :         ++num_written;
    1075                 :       }
    1076                 : 
    1077               0 :       mWritten += num_written;
    1078               0 :     }
    1079                 : 
    1080                 :   private:
    1081                 :     bool mLastCharCR;
    1082                 :     OutputIterator* mDestination;
    1083                 :     PRUint32 mWritten;
    1084                 : };
    1085                 : 
    1086                 : // static
    1087                 : PRUint32
    1088               0 : nsContentUtils::CopyNewlineNormalizedUnicodeTo(const nsAString& aSource,
    1089                 :                                                PRUint32 aSrcOffset,
    1090                 :                                                PRUnichar* aDest,
    1091                 :                                                PRUint32 aLength,
    1092                 :                                                bool& aLastCharCR)
    1093                 : {
    1094                 :   typedef NormalizeNewlinesCharTraits<PRUnichar*> sink_traits;
    1095                 : 
    1096               0 :   sink_traits dest_traits(aDest);
    1097               0 :   CopyNormalizeNewlines<sink_traits> normalizer(&dest_traits,aLastCharCR);
    1098               0 :   nsReadingIterator<PRUnichar> fromBegin, fromEnd;
    1099               0 :   copy_string(aSource.BeginReading(fromBegin).advance( PRInt32(aSrcOffset) ),
    1100               0 :               aSource.BeginReading(fromEnd).advance( PRInt32(aSrcOffset+aLength) ),
    1101               0 :               normalizer);
    1102               0 :   aLastCharCR = normalizer.IsLastCharCR();
    1103               0 :   return normalizer.GetCharsWritten();
    1104                 : }
    1105                 : 
    1106                 : // static
    1107                 : PRUint32
    1108               0 : nsContentUtils::CopyNewlineNormalizedUnicodeTo(nsReadingIterator<PRUnichar>& aSrcStart, const nsReadingIterator<PRUnichar>& aSrcEnd, nsAString& aDest)
    1109                 : {
    1110                 :   typedef nsWritingIterator<PRUnichar> WritingIterator;
    1111                 :   typedef NormalizeNewlinesCharTraits<WritingIterator> sink_traits;
    1112                 : 
    1113               0 :   WritingIterator iter;
    1114               0 :   aDest.BeginWriting(iter);
    1115               0 :   sink_traits dest_traits(iter);
    1116               0 :   CopyNormalizeNewlines<sink_traits> normalizer(&dest_traits);
    1117               0 :   copy_string(aSrcStart, aSrcEnd, normalizer);
    1118               0 :   return normalizer.GetCharsWritten();
    1119                 : }
    1120                 : 
    1121                 : /**
    1122                 :  * This is used to determine whether a character is in one of the punctuation
    1123                 :  * mark classes which CSS says should be part of the first-letter.
    1124                 :  * See http://www.w3.org/TR/CSS2/selector.html#first-letter and
    1125                 :  *     http://www.w3.org/TR/selectors/#first-letter
    1126                 :  */
    1127                 : 
    1128                 : // static
    1129                 : bool
    1130               0 : nsContentUtils::IsFirstLetterPunctuation(PRUint32 aChar)
    1131                 : {
    1132               0 :   PRUint8 cat = mozilla::unicode::GetGeneralCategory(aChar);
    1133                 : 
    1134                 :   return (cat == HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION ||     // Ps
    1135                 :           cat == HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION ||    // Pe
    1136                 :           cat == HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION ||  // Pi
    1137                 :           cat == HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION ||    // Pf
    1138               0 :           cat == HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION);     // Po
    1139                 : }
    1140                 : 
    1141                 : // static
    1142                 : bool
    1143               0 : nsContentUtils::IsFirstLetterPunctuationAt(const nsTextFragment* aFrag, PRUint32 aOffset)
    1144                 : {
    1145               0 :   PRUnichar h = aFrag->CharAt(aOffset);
    1146               0 :   if (!IS_SURROGATE(h)) {
    1147               0 :     return IsFirstLetterPunctuation(h);
    1148                 :   }
    1149               0 :   if (NS_IS_HIGH_SURROGATE(h) && aOffset + 1 < aFrag->GetLength()) {
    1150               0 :     PRUnichar l = aFrag->CharAt(aOffset + 1);
    1151               0 :     if (NS_IS_LOW_SURROGATE(l)) {
    1152               0 :       return IsFirstLetterPunctuation(SURROGATE_TO_UCS4(h, l));
    1153                 :     }
    1154                 :   }
    1155               0 :   return false;
    1156                 : }
    1157                 : 
    1158                 : // static
    1159               0 : bool nsContentUtils::IsAlphanumeric(PRUint32 aChar)
    1160                 : {
    1161               0 :   nsIUGenCategory::nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
    1162                 : 
    1163               0 :   return (cat == nsIUGenCategory::kLetter || cat == nsIUGenCategory::kNumber);
    1164                 : }
    1165                 :  
    1166                 : // static
    1167               0 : bool nsContentUtils::IsAlphanumericAt(const nsTextFragment* aFrag, PRUint32 aOffset)
    1168                 : {
    1169               0 :   PRUnichar h = aFrag->CharAt(aOffset);
    1170               0 :   if (!IS_SURROGATE(h)) {
    1171               0 :     return IsAlphanumeric(h);
    1172                 :   }
    1173               0 :   if (NS_IS_HIGH_SURROGATE(h) && aOffset + 1 < aFrag->GetLength()) {
    1174               0 :     PRUnichar l = aFrag->CharAt(aOffset + 1);
    1175               0 :     if (NS_IS_LOW_SURROGATE(l)) {
    1176               0 :       return IsAlphanumeric(SURROGATE_TO_UCS4(h, l));
    1177                 :     }
    1178                 :   }
    1179               0 :   return false;
    1180                 : }
    1181                 : 
    1182                 : /* static */
    1183                 : bool
    1184               0 : nsContentUtils::IsHTMLWhitespace(PRUnichar aChar)
    1185                 : {
    1186                 :   return aChar == PRUnichar(0x0009) ||
    1187                 :          aChar == PRUnichar(0x000A) ||
    1188                 :          aChar == PRUnichar(0x000C) ||
    1189                 :          aChar == PRUnichar(0x000D) ||
    1190               0 :          aChar == PRUnichar(0x0020);
    1191                 : }
    1192                 : 
    1193                 : /* static */
    1194                 : bool
    1195            1059 : nsContentUtils::IsHTMLBlock(nsIAtom* aLocalName)
    1196                 : {
    1197                 :   return
    1198                 :     (aLocalName == nsGkAtoms::address) ||
    1199                 :     (aLocalName == nsGkAtoms::article) ||
    1200                 :     (aLocalName == nsGkAtoms::aside) ||
    1201                 :     (aLocalName == nsGkAtoms::blockquote) ||
    1202                 :     (aLocalName == nsGkAtoms::center) ||
    1203                 :     (aLocalName == nsGkAtoms::dir) ||
    1204                 :     (aLocalName == nsGkAtoms::div) ||
    1205                 :     (aLocalName == nsGkAtoms::dl) || // XXX why not dt and dd?
    1206                 :     (aLocalName == nsGkAtoms::fieldset) ||
    1207                 :     (aLocalName == nsGkAtoms::figure) || // XXX shouldn't figcaption be on this list
    1208                 :     (aLocalName == nsGkAtoms::footer) ||
    1209                 :     (aLocalName == nsGkAtoms::form) ||
    1210                 :     (aLocalName == nsGkAtoms::h1) ||
    1211                 :     (aLocalName == nsGkAtoms::h2) ||
    1212                 :     (aLocalName == nsGkAtoms::h3) ||
    1213                 :     (aLocalName == nsGkAtoms::h4) ||
    1214                 :     (aLocalName == nsGkAtoms::h5) ||
    1215                 :     (aLocalName == nsGkAtoms::h6) ||
    1216                 :     (aLocalName == nsGkAtoms::header) ||
    1217                 :     (aLocalName == nsGkAtoms::hgroup) ||
    1218                 :     (aLocalName == nsGkAtoms::hr) ||
    1219                 :     (aLocalName == nsGkAtoms::li) ||
    1220                 :     (aLocalName == nsGkAtoms::listing) ||
    1221                 :     (aLocalName == nsGkAtoms::menu) ||
    1222                 :     (aLocalName == nsGkAtoms::multicol) || // XXX get rid of this one?
    1223                 :     (aLocalName == nsGkAtoms::nav) ||
    1224                 :     (aLocalName == nsGkAtoms::ol) ||
    1225                 :     (aLocalName == nsGkAtoms::p) ||
    1226                 :     (aLocalName == nsGkAtoms::pre) ||
    1227                 :     (aLocalName == nsGkAtoms::section) ||
    1228                 :     (aLocalName == nsGkAtoms::table) ||
    1229                 :     (aLocalName == nsGkAtoms::ul) ||
    1230            1059 :     (aLocalName == nsGkAtoms::xmp);
    1231                 : }
    1232                 : 
    1233                 : /* static */
    1234                 : bool
    1235            1560 : nsContentUtils::IsHTMLVoid(nsIAtom* aLocalName)
    1236                 : {
    1237                 :   return
    1238                 :     (aLocalName == nsGkAtoms::area) ||
    1239                 :     (aLocalName == nsGkAtoms::base) ||
    1240                 :     (aLocalName == nsGkAtoms::basefont) ||
    1241                 :     (aLocalName == nsGkAtoms::bgsound) ||
    1242                 :     (aLocalName == nsGkAtoms::br) ||
    1243                 :     (aLocalName == nsGkAtoms::col) ||
    1244                 :     (aLocalName == nsGkAtoms::command) ||
    1245                 :     (aLocalName == nsGkAtoms::embed) ||
    1246                 :     (aLocalName == nsGkAtoms::frame) ||
    1247                 :     (aLocalName == nsGkAtoms::hr) ||
    1248                 :     (aLocalName == nsGkAtoms::img) ||
    1249                 :     (aLocalName == nsGkAtoms::input) ||
    1250                 :     (aLocalName == nsGkAtoms::keygen) ||
    1251                 :     (aLocalName == nsGkAtoms::link) ||
    1252                 :     (aLocalName == nsGkAtoms::meta) ||
    1253                 :     (aLocalName == nsGkAtoms::param) ||
    1254                 :     (aLocalName == nsGkAtoms::source) ||
    1255                 :     (aLocalName == nsGkAtoms::track) ||
    1256            1560 :     (aLocalName == nsGkAtoms::wbr);
    1257                 : }
    1258                 : 
    1259                 : /* static */
    1260                 : bool
    1261               0 : nsContentUtils::ParseIntMarginValue(const nsAString& aString, nsIntMargin& result)
    1262                 : {
    1263               0 :   nsAutoString marginStr(aString);
    1264               0 :   marginStr.CompressWhitespace(true, true);
    1265               0 :   if (marginStr.IsEmpty()) {
    1266               0 :     return false;
    1267                 :   }
    1268                 : 
    1269               0 :   PRInt32 start = 0, end = 0;
    1270               0 :   for (int count = 0; count < 4; count++) {
    1271               0 :     if ((PRUint32)end >= marginStr.Length())
    1272               0 :       return false;
    1273                 : 
    1274                 :     // top, right, bottom, left
    1275               0 :     if (count < 3)
    1276               0 :       end = Substring(marginStr, start).FindChar(',');
    1277                 :     else
    1278               0 :       end = Substring(marginStr, start).Length();
    1279                 : 
    1280               0 :     if (end <= 0)
    1281               0 :       return false;
    1282                 : 
    1283                 :     PRInt32 ec, val = 
    1284               0 :       nsString(Substring(marginStr, start, end)).ToInteger(&ec);
    1285               0 :     if (NS_FAILED(ec))
    1286               0 :       return false;
    1287                 : 
    1288               0 :     switch(count) {
    1289                 :       case 0:
    1290               0 :         result.top = val;
    1291               0 :       break;
    1292                 :       case 1:
    1293               0 :         result.right = val;
    1294               0 :       break;
    1295                 :       case 2:
    1296               0 :         result.bottom = val;
    1297               0 :       break;
    1298                 :       case 3:
    1299               0 :         result.left = val;
    1300               0 :       break;
    1301                 :     }
    1302               0 :     start += end + 1;
    1303                 :   }
    1304               0 :   return true;
    1305                 : }
    1306                 : 
    1307                 : /* static */
    1308                 : void
    1309               0 : nsContentUtils::GetOfflineAppManifest(nsIDocument *aDocument, nsIURI **aURI)
    1310                 : {
    1311               0 :   Element* docElement = aDocument->GetRootElement();
    1312               0 :   if (!docElement) {
    1313               0 :     return;
    1314                 :   }
    1315                 : 
    1316               0 :   nsAutoString manifestSpec;
    1317               0 :   docElement->GetAttr(kNameSpaceID_None, nsGkAtoms::manifest, manifestSpec);
    1318                 : 
    1319                 :   // Manifest URIs can't have fragment identifiers.
    1320               0 :   if (manifestSpec.IsEmpty() ||
    1321               0 :       manifestSpec.FindChar('#') != kNotFound) {
    1322                 :     return;
    1323                 :   }
    1324                 : 
    1325                 :   nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec,
    1326                 :                                             aDocument,
    1327               0 :                                             aDocument->GetDocBaseURI());
    1328                 : }
    1329                 : 
    1330                 : /* static */
    1331                 : bool
    1332               0 : nsContentUtils::OfflineAppAllowed(nsIURI *aURI)
    1333                 : {
    1334                 :   nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
    1335               0 :     do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
    1336               0 :   if (!updateService) {
    1337               0 :     return false;
    1338                 :   }
    1339                 : 
    1340                 :   bool allowed;
    1341                 :   nsresult rv =
    1342               0 :     updateService->OfflineAppAllowedForURI(aURI,
    1343                 :                                            Preferences::GetRootBranch(),
    1344               0 :                                            &allowed);
    1345               0 :   return NS_SUCCEEDED(rv) && allowed;
    1346                 : }
    1347                 : 
    1348                 : /* static */
    1349                 : bool
    1350               0 : nsContentUtils::OfflineAppAllowed(nsIPrincipal *aPrincipal)
    1351                 : {
    1352                 :   nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
    1353               0 :     do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
    1354               0 :   if (!updateService) {
    1355               0 :     return false;
    1356                 :   }
    1357                 : 
    1358                 :   bool allowed;
    1359               0 :   nsresult rv = updateService->OfflineAppAllowed(aPrincipal,
    1360                 :                                                  Preferences::GetRootBranch(),
    1361               0 :                                                  &allowed);
    1362               0 :   return NS_SUCCEEDED(rv) && allowed;
    1363                 : }
    1364                 : 
    1365                 : // static
    1366                 : void
    1367            1403 : nsContentUtils::Shutdown()
    1368                 : {
    1369            1403 :   sInitialized = false;
    1370                 : 
    1371            1403 :   NS_IF_RELEASE(sContentPolicyService);
    1372            1403 :   sTriedToGetContentPolicy = false;
    1373                 :   PRUint32 i;
    1374           16836 :   for (i = 0; i < PropertiesFile_COUNT; ++i)
    1375           15433 :     NS_IF_RELEASE(sStringBundles[i]);
    1376                 : 
    1377            1403 :   NS_IF_RELEASE(sStringBundleService);
    1378            1403 :   NS_IF_RELEASE(sConsoleService);
    1379            1403 :   NS_IF_RELEASE(sDOMScriptObjectFactory);
    1380            1403 :   sXPConnect = nsnull;
    1381            1403 :   sThreadJSContextStack = nsnull;
    1382            1403 :   NS_IF_RELEASE(sSecurityManager);
    1383            1403 :   NS_IF_RELEASE(sNameSpaceManager);
    1384            1403 :   NS_IF_RELEASE(sParserService);
    1385            1403 :   NS_IF_RELEASE(sIOService);
    1386            1403 :   NS_IF_RELEASE(sLineBreaker);
    1387            1403 :   NS_IF_RELEASE(sWordBreaker);
    1388                 : #ifdef MOZ_XTF
    1389            1403 :   NS_IF_RELEASE(sXTFService);
    1390                 : #endif
    1391            1403 :   NS_IF_RELEASE(sImgLoader);
    1392            1403 :   NS_IF_RELEASE(sImgCache);
    1393                 : #ifdef IBMBIDI
    1394            1403 :   NS_IF_RELEASE(sBidiKeyboard);
    1395                 : #endif
    1396                 : 
    1397            1403 :   delete sAtomEventTable;
    1398            1403 :   sAtomEventTable = nsnull;
    1399            1403 :   delete sStringEventTable;
    1400            1403 :   sStringEventTable = nsnull;
    1401            1403 :   delete sUserDefinedEvents;
    1402            1403 :   sUserDefinedEvents = nsnull;
    1403                 : 
    1404            1403 :   if (sEventListenerManagersHash.ops) {
    1405            1403 :     NS_ASSERTION(sEventListenerManagersHash.entryCount == 0,
    1406                 :                  "Event listener manager hash not empty at shutdown!");
    1407                 : 
    1408                 :     // See comment above.
    1409                 : 
    1410                 :     // However, we have to handle this table differently.  If it still
    1411                 :     // has entries, we want to leak it too, so that we can keep it alive
    1412                 :     // in case any elements are destroyed.  Because if they are, we need
    1413                 :     // their event listener managers to be destroyed too, or otherwise
    1414                 :     // it could leave dangling references in DOMClassInfo's preserved
    1415                 :     // wrapper table.
    1416                 : 
    1417            1403 :     if (sEventListenerManagersHash.entryCount == 0) {
    1418            1403 :       PL_DHashTableFinish(&sEventListenerManagersHash);
    1419            1403 :       sEventListenerManagersHash.ops = nsnull;
    1420                 :     }
    1421                 :   }
    1422                 : 
    1423            1403 :   NS_ASSERTION(!sBlockedScriptRunners ||
    1424                 :                sBlockedScriptRunners->Length() == 0,
    1425                 :                "How'd this happen?");
    1426            1403 :   delete sBlockedScriptRunners;
    1427            1403 :   sBlockedScriptRunners = nsnull;
    1428                 : 
    1429            1403 :   delete sShiftText;
    1430            1403 :   sShiftText = nsnull;
    1431            1403 :   delete sControlText;  
    1432            1403 :   sControlText = nsnull;
    1433            1403 :   delete sMetaText;  
    1434            1403 :   sMetaText = nsnull;
    1435            1403 :   delete sAltText;  
    1436            1403 :   sAltText = nsnull;
    1437            1403 :   delete sModifierSeparator;
    1438            1403 :   sModifierSeparator = nsnull;
    1439                 : 
    1440            1403 :   NS_IF_RELEASE(sSameOriginChecker);
    1441                 :   
    1442            1403 :   nsTextEditorState::ShutDown();
    1443            1403 : }
    1444                 : 
    1445                 : // static
    1446                 : bool
    1447               0 : nsContentUtils::CallerHasUniversalXPConnect()
    1448                 : {
    1449                 :   bool hasCap;
    1450               0 :   if (NS_FAILED(sSecurityManager->IsCapabilityEnabled("UniversalXPConnect",
    1451                 :                                                       &hasCap)))
    1452               0 :     return false;
    1453               0 :   return hasCap;
    1454                 : }
    1455                 : 
    1456                 : /**
    1457                 :  * Checks whether two nodes come from the same origin. aTrustedNode is
    1458                 :  * considered 'safe' in that a user can operate on it and that it isn't
    1459                 :  * a js-object that implements nsIDOMNode.
    1460                 :  * Never call this function with the first node provided by script, it
    1461                 :  * must always be known to be a 'real' node!
    1462                 :  */
    1463                 : // static
    1464                 : nsresult
    1465             176 : nsContentUtils::CheckSameOrigin(nsINode *aTrustedNode,
    1466                 :                                 nsIDOMNode *aUnTrustedNode)
    1467                 : {
    1468             176 :   NS_PRECONDITION(aTrustedNode, "There must be a trusted node");
    1469                 : 
    1470             176 :   bool isSystem = false;
    1471             176 :   nsresult rv = sSecurityManager->SubjectPrincipalIsSystem(&isSystem);
    1472             176 :   NS_ENSURE_SUCCESS(rv, rv);
    1473                 : 
    1474             176 :   if (isSystem) {
    1475                 :     // we're running as system, grant access to the node.
    1476                 : 
    1477             176 :     return NS_OK;
    1478                 :   }
    1479                 : 
    1480                 :   /*
    1481                 :    * Get hold of each node's principal
    1482                 :    */
    1483               0 :   nsCOMPtr<nsINode> unTrustedNode = do_QueryInterface(aUnTrustedNode);
    1484                 : 
    1485                 :   // Make sure these are both real nodes
    1486               0 :   NS_ENSURE_TRUE(aTrustedNode && unTrustedNode, NS_ERROR_UNEXPECTED);
    1487                 : 
    1488               0 :   nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
    1489               0 :   nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();
    1490                 : 
    1491               0 :   if (trustedPrincipal == unTrustedPrincipal) {
    1492               0 :     return NS_OK;
    1493                 :   }
    1494                 : 
    1495                 :   bool equal;
    1496                 :   // XXXbz should we actually have a Subsumes() check here instead?  Or perhaps
    1497                 :   // a separate method for that, with callers using one or the other?
    1498               0 :   if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal)) ||
    1499               0 :       !equal) {
    1500               0 :     return NS_ERROR_DOM_PROP_ACCESS_DENIED;
    1501                 :   }
    1502                 : 
    1503               0 :   return NS_OK;
    1504                 : }
    1505                 : 
    1506                 : // static
    1507                 : bool
    1508             326 : nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
    1509                 :                                 nsIPrincipal* aPrincipal)
    1510                 : {
    1511                 :   bool subsumes;
    1512             326 :   nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes);
    1513             326 :   NS_ENSURE_SUCCESS(rv, false);
    1514                 : 
    1515             326 :   if (subsumes) {
    1516             326 :     return true;
    1517                 :   }
    1518                 : 
    1519                 :   // The subject doesn't subsume aPrincipal. Allow access only if the subject
    1520                 :   // has UniversalXPConnect.
    1521               0 :   return CallerHasUniversalXPConnect();
    1522                 : }
    1523                 : 
    1524                 : // static
    1525                 : bool
    1526             327 : nsContentUtils::CanCallerAccess(nsIDOMNode *aNode)
    1527                 : {
    1528                 :   // XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
    1529                 :   // with the system principal games?  But really, there should be a simpler
    1530                 :   // API here, dammit.
    1531             654 :   nsCOMPtr<nsIPrincipal> subjectPrincipal;
    1532             327 :   nsresult rv = sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
    1533             327 :   NS_ENSURE_SUCCESS(rv, false);
    1534                 : 
    1535             327 :   if (!subjectPrincipal) {
    1536                 :     // we're running as system, grant access to the node.
    1537                 : 
    1538               0 :     return true;
    1539                 :   }
    1540                 : 
    1541             654 :   nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
    1542             327 :   NS_ENSURE_TRUE(node, false);
    1543                 : 
    1544             326 :   return CanCallerAccess(subjectPrincipal, node->NodePrincipal());
    1545                 : }
    1546                 : 
    1547                 : // static
    1548                 : bool
    1549               0 : nsContentUtils::CanCallerAccess(nsPIDOMWindow* aWindow)
    1550                 : {
    1551                 :   // XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
    1552                 :   // with the system principal games?  But really, there should be a simpler
    1553                 :   // API here, dammit.
    1554               0 :   nsCOMPtr<nsIPrincipal> subjectPrincipal;
    1555               0 :   nsresult rv = sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
    1556               0 :   NS_ENSURE_SUCCESS(rv, false);
    1557                 : 
    1558               0 :   if (!subjectPrincipal) {
    1559                 :     // we're running as system, grant access to the node.
    1560                 : 
    1561               0 :     return true;
    1562                 :   }
    1563                 : 
    1564                 :   nsCOMPtr<nsIScriptObjectPrincipal> scriptObject =
    1565               0 :     do_QueryInterface(aWindow->IsOuterWindow() ?
    1566               0 :                       aWindow->GetCurrentInnerWindow() : aWindow);
    1567               0 :   NS_ENSURE_TRUE(scriptObject, false);
    1568                 : 
    1569               0 :   return CanCallerAccess(subjectPrincipal, scriptObject->GetPrincipal());
    1570                 : }
    1571                 : 
    1572                 : //static
    1573                 : bool
    1574               0 : nsContentUtils::InProlog(nsINode *aNode)
    1575                 : {
    1576               0 :   NS_PRECONDITION(aNode, "missing node to nsContentUtils::InProlog");
    1577                 : 
    1578               0 :   nsINode* parent = aNode->GetNodeParent();
    1579               0 :   if (!parent || !parent->IsNodeOfType(nsINode::eDOCUMENT)) {
    1580               0 :     return false;
    1581                 :   }
    1582                 : 
    1583               0 :   nsIDocument* doc = static_cast<nsIDocument*>(parent);
    1584               0 :   nsIContent* root = doc->GetRootElement();
    1585                 : 
    1586               0 :   return !root || doc->IndexOf(aNode) < doc->IndexOf(root);
    1587                 : }
    1588                 : 
    1589                 : JSContext *
    1590               0 : nsContentUtils::GetContextFromDocument(nsIDocument *aDocument)
    1591                 : {
    1592               0 :   nsIScriptGlobalObject *sgo = aDocument->GetScopeObject();
    1593               0 :   if (!sgo) {
    1594                 :     // No script global, no context.
    1595               0 :     return nsnull;
    1596                 :   }
    1597                 : 
    1598               0 :   nsIScriptContext *scx = sgo->GetContext();
    1599               0 :   if (!scx) {
    1600                 :     // No context left in the scope...
    1601               0 :     return nsnull;
    1602                 :   }
    1603                 : 
    1604               0 :   return scx->GetNativeContext();
    1605                 : }
    1606                 : 
    1607                 : // static
    1608                 : nsresult
    1609               0 : nsContentUtils::GetContextAndScope(nsIDocument *aOldDocument,
    1610                 :                                    nsIDocument *aNewDocument, JSContext **aCx,
    1611                 :                                    JSObject **aNewScope)
    1612                 : {
    1613               0 :   *aCx = nsnull;
    1614               0 :   *aNewScope = nsnull;
    1615                 : 
    1616               0 :   JSObject *newScope = aNewDocument->GetWrapper();
    1617                 :   JSObject *global;
    1618               0 :   if (!newScope) {
    1619               0 :     nsIScriptGlobalObject *newSGO = aNewDocument->GetScopeObject();
    1620               0 :     if (!newSGO || !(global = newSGO->GetGlobalJSObject())) {
    1621               0 :       return NS_OK;
    1622                 :     }
    1623                 :   }
    1624                 : 
    1625               0 :   NS_ENSURE_TRUE(sXPConnect, NS_ERROR_NOT_INITIALIZED);
    1626                 : 
    1627               0 :   JSContext *cx = aOldDocument ? GetContextFromDocument(aOldDocument) : nsnull;
    1628               0 :   if (!cx) {
    1629               0 :     cx = GetContextFromDocument(aNewDocument);
    1630                 : 
    1631               0 :     if (!cx) {
    1632                 :       // No context reachable from the old or new document, use the
    1633                 :       // calling context, or the safe context if no caller can be
    1634                 :       // found.
    1635                 : 
    1636               0 :       sThreadJSContextStack->Peek(&cx);
    1637                 : 
    1638               0 :       if (!cx) {
    1639               0 :         sThreadJSContextStack->GetSafeJSContext(&cx);
    1640                 : 
    1641               0 :         if (!cx) {
    1642                 :           // No safe context reachable, bail.
    1643               0 :           NS_WARNING("No context reachable in GetContextAndScopes()!");
    1644                 : 
    1645               0 :           return NS_ERROR_NOT_AVAILABLE;
    1646                 :         }
    1647                 :       }
    1648                 :     }
    1649                 :   }
    1650                 : 
    1651               0 :   if (!newScope && cx) {
    1652                 :     jsval v;
    1653               0 :     nsresult rv = WrapNative(cx, global, aNewDocument, aNewDocument, &v);
    1654               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1655                 : 
    1656               0 :     newScope = JSVAL_TO_OBJECT(v);
    1657                 :   }
    1658                 : 
    1659               0 :   *aCx = cx;
    1660               0 :   *aNewScope = newScope;
    1661                 : 
    1662               0 :   return NS_OK;
    1663                 : }
    1664                 : 
    1665                 : nsresult
    1666               0 : nsContentUtils::ReparentContentWrappersInScope(JSContext *cx,
    1667                 :                                                nsIScriptGlobalObject *aOldScope,
    1668                 :                                                nsIScriptGlobalObject *aNewScope)
    1669                 : {
    1670               0 :   JSObject *oldScopeObj = aOldScope->GetGlobalJSObject();
    1671               0 :   JSObject *newScopeObj = aNewScope->GetGlobalJSObject();
    1672                 : 
    1673               0 :   if (!newScopeObj || !oldScopeObj) {
    1674                 :     // We can't really do anything without the JSObjects.
    1675                 : 
    1676               0 :     return NS_ERROR_NOT_AVAILABLE;
    1677                 :   }
    1678                 : 
    1679               0 :   return sXPConnect->MoveWrappers(cx, oldScopeObj, newScopeObj);
    1680                 : }
    1681                 : 
    1682                 : nsPIDOMWindow *
    1683               0 : nsContentUtils::GetWindowFromCaller()
    1684                 : {
    1685               0 :   JSContext *cx = nsnull;
    1686               0 :   sThreadJSContextStack->Peek(&cx);
    1687                 : 
    1688               0 :   if (cx) {
    1689                 :     nsCOMPtr<nsPIDOMWindow> win =
    1690               0 :       do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
    1691               0 :     return win;
    1692                 :   }
    1693                 : 
    1694               0 :   return nsnull;
    1695                 : }
    1696                 : 
    1697                 : nsIDOMDocument *
    1698               0 : nsContentUtils::GetDocumentFromCaller()
    1699                 : {
    1700               0 :   JSContext *cx = nsnull;
    1701               0 :   JSObject *obj = nsnull;
    1702               0 :   sXPConnect->GetCaller(&cx, &obj);
    1703               0 :   NS_ASSERTION(cx && obj, "Caller ensures something is running");
    1704                 : 
    1705               0 :   JSAutoEnterCompartment ac;
    1706               0 :   if (!ac.enter(cx, obj)) {
    1707               0 :     return nsnull;
    1708                 :   }
    1709                 : 
    1710                 :   nsCOMPtr<nsPIDOMWindow> win =
    1711               0 :     do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx, obj));
    1712               0 :   if (!win) {
    1713               0 :     return nsnull;
    1714                 :   }
    1715                 : 
    1716               0 :   return win->GetExtantDocument();
    1717                 : }
    1718                 : 
    1719                 : nsIDOMDocument *
    1720               0 : nsContentUtils::GetDocumentFromContext()
    1721                 : {
    1722               0 :   JSContext *cx = nsnull;
    1723               0 :   sThreadJSContextStack->Peek(&cx);
    1724                 : 
    1725               0 :   if (cx) {
    1726               0 :     nsIScriptGlobalObject *sgo = nsJSUtils::GetDynamicScriptGlobal(cx);
    1727                 : 
    1728               0 :     if (sgo) {
    1729               0 :       nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(sgo);
    1730               0 :       if (pwin) {
    1731               0 :         return pwin->GetExtantDocument();
    1732                 :       }
    1733                 :     }
    1734                 :   }
    1735                 : 
    1736               0 :   return nsnull;
    1737                 : }
    1738                 : 
    1739                 : bool
    1740             309 : nsContentUtils::IsCallerChrome()
    1741                 : {
    1742             309 :   bool is_caller_chrome = false;
    1743             309 :   nsresult rv = sSecurityManager->SubjectPrincipalIsSystem(&is_caller_chrome);
    1744             309 :   if (NS_FAILED(rv)) {
    1745               0 :     return false;
    1746                 :   }
    1747                 : 
    1748             309 :   return is_caller_chrome;
    1749                 : }
    1750                 : 
    1751                 : bool
    1752               0 : nsContentUtils::IsCallerTrustedForRead()
    1753                 : {
    1754               0 :   return CallerHasUniversalXPConnect();
    1755                 : }
    1756                 : 
    1757                 : bool
    1758               0 : nsContentUtils::IsCallerTrustedForWrite()
    1759                 : {
    1760               0 :   return CallerHasUniversalXPConnect();
    1761                 : }
    1762                 : 
    1763                 : bool
    1764               0 : nsContentUtils::IsImageSrcSetDisabled()
    1765                 : {
    1766               0 :   return Preferences::GetBool("dom.disable_image_src_set") &&
    1767               0 :          !IsCallerChrome();
    1768                 : }
    1769                 : 
    1770                 : // static
    1771                 : nsINode*
    1772               0 : nsContentUtils::GetCrossDocParentNode(nsINode* aChild)
    1773                 : {
    1774               0 :   NS_PRECONDITION(aChild, "The child is null!");
    1775                 : 
    1776               0 :   nsINode* parent = aChild->GetNodeParent();
    1777               0 :   if (parent || !aChild->IsNodeOfType(nsINode::eDOCUMENT))
    1778               0 :     return parent;
    1779                 : 
    1780               0 :   nsIDocument* doc = static_cast<nsIDocument*>(aChild);
    1781               0 :   nsIDocument* parentDoc = doc->GetParentDocument();
    1782               0 :   return parentDoc ? parentDoc->FindContentForSubDocument(doc) : nsnull;
    1783                 : }
    1784                 : 
    1785                 : // static
    1786                 : bool
    1787             691 : nsContentUtils::ContentIsDescendantOf(const nsINode* aPossibleDescendant,
    1788                 :                                       const nsINode* aPossibleAncestor)
    1789                 : {
    1790             691 :   NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
    1791             691 :   NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
    1792                 : 
    1793             912 :   do {
    1794            1174 :     if (aPossibleDescendant == aPossibleAncestor)
    1795             262 :       return true;
    1796             912 :     aPossibleDescendant = aPossibleDescendant->GetNodeParent();
    1797                 :   } while (aPossibleDescendant);
    1798                 : 
    1799             429 :   return false;
    1800                 : }
    1801                 : 
    1802                 : // static
    1803                 : bool
    1804               0 : nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant,
    1805                 :                                               nsINode* aPossibleAncestor)
    1806                 : {
    1807               0 :   NS_PRECONDITION(aPossibleDescendant, "The possible descendant is null!");
    1808               0 :   NS_PRECONDITION(aPossibleAncestor, "The possible ancestor is null!");
    1809                 : 
    1810               0 :   do {
    1811               0 :     if (aPossibleDescendant == aPossibleAncestor)
    1812               0 :       return true;
    1813               0 :     aPossibleDescendant = GetCrossDocParentNode(aPossibleDescendant);
    1814                 :   } while (aPossibleDescendant);
    1815                 : 
    1816               0 :   return false;
    1817                 : }
    1818                 : 
    1819                 : 
    1820                 : // static
    1821                 : nsresult
    1822               0 : nsContentUtils::GetAncestors(nsINode* aNode,
    1823                 :                              nsTArray<nsINode*>& aArray)
    1824                 : {
    1825               0 :   while (aNode) {
    1826               0 :     aArray.AppendElement(aNode);
    1827               0 :     aNode = aNode->GetNodeParent();
    1828                 :   }
    1829               0 :   return NS_OK;
    1830                 : }
    1831                 : 
    1832                 : // static
    1833                 : nsresult
    1834               6 : nsContentUtils::GetAncestorsAndOffsets(nsIDOMNode* aNode,
    1835                 :                                        PRInt32 aOffset,
    1836                 :                                        nsTArray<nsIContent*>* aAncestorNodes,
    1837                 :                                        nsTArray<PRInt32>* aAncestorOffsets)
    1838                 : {
    1839               6 :   NS_ENSURE_ARG_POINTER(aNode);
    1840                 : 
    1841              12 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
    1842                 : 
    1843               6 :   if (!content) {
    1844               0 :     return NS_ERROR_FAILURE;
    1845                 :   }
    1846                 : 
    1847               6 :   if (!aAncestorNodes->IsEmpty()) {
    1848               0 :     NS_WARNING("aAncestorNodes is not empty");
    1849               0 :     aAncestorNodes->Clear();
    1850                 :   }
    1851                 : 
    1852               6 :   if (!aAncestorOffsets->IsEmpty()) {
    1853               0 :     NS_WARNING("aAncestorOffsets is not empty");
    1854               0 :     aAncestorOffsets->Clear();
    1855                 :   }
    1856                 : 
    1857                 :   // insert the node itself
    1858               6 :   aAncestorNodes->AppendElement(content.get());
    1859               6 :   aAncestorOffsets->AppendElement(aOffset);
    1860                 : 
    1861                 :   // insert all the ancestors
    1862               6 :   nsIContent* child = content;
    1863               6 :   nsIContent* parent = child->GetParent();
    1864              14 :   while (parent) {
    1865               2 :     aAncestorNodes->AppendElement(parent);
    1866               2 :     aAncestorOffsets->AppendElement(parent->IndexOf(child));
    1867               2 :     child = parent;
    1868               2 :     parent = parent->GetParent();
    1869                 :   }
    1870                 : 
    1871               6 :   return NS_OK;
    1872                 : }
    1873                 : 
    1874                 : // static
    1875                 : nsresult
    1876               4 : nsContentUtils::GetCommonAncestor(nsIDOMNode *aNode,
    1877                 :                                   nsIDOMNode *aOther,
    1878                 :                                   nsIDOMNode** aCommonAncestor)
    1879                 : {
    1880               4 :   *aCommonAncestor = nsnull;
    1881                 : 
    1882               8 :   nsCOMPtr<nsINode> node1 = do_QueryInterface(aNode);
    1883               8 :   nsCOMPtr<nsINode> node2 = do_QueryInterface(aOther);
    1884                 : 
    1885               4 :   NS_ENSURE_TRUE(node1 && node2, NS_ERROR_UNEXPECTED);
    1886                 : 
    1887               4 :   nsINode* common = GetCommonAncestor(node1, node2);
    1888               4 :   NS_ENSURE_TRUE(common, NS_ERROR_NOT_AVAILABLE);
    1889                 : 
    1890               4 :   return CallQueryInterface(common, aCommonAncestor);
    1891                 : }
    1892                 : 
    1893                 : // static
    1894                 : nsINode*
    1895             105 : nsContentUtils::GetCommonAncestor(nsINode* aNode1,
    1896                 :                                   nsINode* aNode2)
    1897                 : {
    1898             105 :   if (aNode1 == aNode2) {
    1899              38 :     return aNode1;
    1900                 :   }
    1901                 : 
    1902                 :   // Build the chain of parents
    1903             134 :   nsAutoTArray<nsINode*, 30> parents1, parents2;
    1904             135 :   do {
    1905             135 :     parents1.AppendElement(aNode1);
    1906             135 :     aNode1 = aNode1->GetNodeParent();
    1907                 :   } while (aNode1);
    1908             118 :   do {
    1909             118 :     parents2.AppendElement(aNode2);
    1910             118 :     aNode2 = aNode2->GetNodeParent();
    1911                 :   } while (aNode2);
    1912                 : 
    1913                 :   // Find where the parent chain differs
    1914              67 :   PRUint32 pos1 = parents1.Length();
    1915              67 :   PRUint32 pos2 = parents2.Length();
    1916              67 :   nsINode* parent = nsnull;
    1917                 :   PRUint32 len;
    1918             133 :   for (len = NS_MIN(pos1, pos2); len > 0; --len) {
    1919             101 :     nsINode* child1 = parents1.ElementAt(--pos1);
    1920             101 :     nsINode* child2 = parents2.ElementAt(--pos2);
    1921             101 :     if (child1 != child2) {
    1922              35 :       break;
    1923                 :     }
    1924              66 :     parent = child1;
    1925                 :   }
    1926                 : 
    1927              67 :   return parent;
    1928                 : }
    1929                 : 
    1930                 : /* static */
    1931                 : PRInt32
    1932             161 : nsContentUtils::ComparePoints(nsINode* aParent1, PRInt32 aOffset1,
    1933                 :                               nsINode* aParent2, PRInt32 aOffset2,
    1934                 :                               bool* aDisconnected)
    1935                 : {
    1936             161 :   if (aParent1 == aParent2) {
    1937                 :     return aOffset1 < aOffset2 ? -1 :
    1938                 :            aOffset1 > aOffset2 ? 1 :
    1939             125 :            0;
    1940                 :   }
    1941                 : 
    1942              72 :   nsAutoTArray<nsINode*, 32> parents1, parents2;
    1943              36 :   nsINode* node1 = aParent1;
    1944              36 :   nsINode* node2 = aParent2;
    1945              72 :   do {
    1946              72 :     parents1.AppendElement(node1);
    1947              72 :     node1 = node1->GetNodeParent();
    1948                 :   } while (node1);
    1949              55 :   do {
    1950              55 :     parents2.AppendElement(node2);
    1951              55 :     node2 = node2->GetNodeParent();
    1952                 :   } while (node2);
    1953                 : 
    1954              36 :   PRUint32 pos1 = parents1.Length() - 1;
    1955              36 :   PRUint32 pos2 = parents2.Length() - 1;
    1956                 :   
    1957              36 :   bool disconnected = parents1.ElementAt(pos1) != parents2.ElementAt(pos2);
    1958              36 :   if (aDisconnected) {
    1959              32 :     *aDisconnected = disconnected;
    1960                 :   }
    1961              36 :   if (disconnected) {
    1962               0 :     NS_ASSERTION(aDisconnected, "unexpected disconnected nodes");
    1963               0 :     return 1;
    1964                 :   }
    1965                 : 
    1966                 :   // Find where the parent chains differ
    1967              36 :   nsINode* parent = parents1.ElementAt(pos1);
    1968                 :   PRUint32 len;
    1969              36 :   for (len = NS_MIN(pos1, pos2); len > 0; --len) {
    1970              19 :     nsINode* child1 = parents1.ElementAt(--pos1);
    1971              19 :     nsINode* child2 = parents2.ElementAt(--pos2);
    1972              19 :     if (child1 != child2) {
    1973              19 :       return parent->IndexOf(child1) < parent->IndexOf(child2) ? -1 : 1;
    1974                 :     }
    1975               0 :     parent = child1;
    1976                 :   }
    1977                 : 
    1978                 :   
    1979                 :   // The parent chains never differed, so one of the nodes is an ancestor of
    1980                 :   // the other
    1981                 : 
    1982              17 :   NS_ASSERTION(!pos1 || !pos2,
    1983                 :                "should have run out of parent chain for one of the nodes");
    1984                 : 
    1985              17 :   if (!pos1) {
    1986               0 :     nsINode* child2 = parents2.ElementAt(--pos2);
    1987               0 :     return aOffset1 <= parent->IndexOf(child2) ? -1 : 1;
    1988                 :   }
    1989                 : 
    1990              17 :   nsINode* child1 = parents1.ElementAt(--pos1);
    1991              17 :   return parent->IndexOf(child1) < aOffset2 ? -1 : 1;
    1992                 : }
    1993                 : 
    1994                 : /* static */
    1995                 : PRInt32
    1996               0 : nsContentUtils::ComparePoints(nsIDOMNode* aParent1, PRInt32 aOffset1,
    1997                 :                               nsIDOMNode* aParent2, PRInt32 aOffset2,
    1998                 :                               bool* aDisconnected)
    1999                 : {
    2000               0 :   nsCOMPtr<nsINode> parent1 = do_QueryInterface(aParent1);
    2001               0 :   nsCOMPtr<nsINode> parent2 = do_QueryInterface(aParent2);
    2002               0 :   NS_ENSURE_TRUE(parent1 && parent2, -1);
    2003               0 :   return ComparePoints(parent1, aOffset1, parent2, aOffset2);
    2004                 : }
    2005                 : 
    2006                 : inline bool
    2007               0 : IsCharInSet(const char* aSet,
    2008                 :             const PRUnichar aChar)
    2009                 : {
    2010                 :   PRUnichar ch;
    2011               0 :   while ((ch = *aSet)) {
    2012               0 :     if (aChar == PRUnichar(ch)) {
    2013               0 :       return true;
    2014                 :     }
    2015               0 :     ++aSet;
    2016                 :   }
    2017               0 :   return false;
    2018                 : }
    2019                 : 
    2020                 : /**
    2021                 :  * This method strips leading/trailing chars, in given set, from string.
    2022                 :  */
    2023                 : 
    2024                 : // static
    2025                 : const nsDependentSubstring
    2026               0 : nsContentUtils::TrimCharsInSet(const char* aSet,
    2027                 :                                const nsAString& aValue)
    2028                 : {
    2029               0 :   nsAString::const_iterator valueCurrent, valueEnd;
    2030                 : 
    2031               0 :   aValue.BeginReading(valueCurrent);
    2032               0 :   aValue.EndReading(valueEnd);
    2033                 : 
    2034                 :   // Skip characters in the beginning
    2035               0 :   while (valueCurrent != valueEnd) {
    2036               0 :     if (!IsCharInSet(aSet, *valueCurrent)) {
    2037               0 :       break;
    2038                 :     }
    2039               0 :     ++valueCurrent;
    2040                 :   }
    2041                 : 
    2042               0 :   if (valueCurrent != valueEnd) {
    2043               0 :     for (;;) {
    2044               0 :       --valueEnd;
    2045               0 :       if (!IsCharInSet(aSet, *valueEnd)) {
    2046                 :         break;
    2047                 :       }
    2048                 :     }
    2049               0 :     ++valueEnd; // Step beyond the last character we want in the value.
    2050                 :   }
    2051                 : 
    2052                 :   // valueEnd should point to the char after the last to copy
    2053               0 :   return Substring(valueCurrent, valueEnd);
    2054                 : }
    2055                 : 
    2056                 : /**
    2057                 :  * This method strips leading and trailing whitespace from a string.
    2058                 :  */
    2059                 : 
    2060                 : // static
    2061                 : template<bool IsWhitespace(PRUnichar)>
    2062                 : const nsDependentSubstring
    2063               0 : nsContentUtils::TrimWhitespace(const nsAString& aStr, bool aTrimTrailing)
    2064                 : {
    2065               0 :   nsAString::const_iterator start, end;
    2066                 : 
    2067               0 :   aStr.BeginReading(start);
    2068               0 :   aStr.EndReading(end);
    2069                 : 
    2070                 :   // Skip whitespace characters in the beginning
    2071               0 :   while (start != end && IsWhitespace(*start)) {
    2072               0 :     ++start;
    2073                 :   }
    2074                 : 
    2075               0 :   if (aTrimTrailing) {
    2076                 :     // Skip whitespace characters in the end.
    2077               0 :     while (end != start) {
    2078               0 :       --end;
    2079                 : 
    2080               0 :       if (!IsWhitespace(*end)) {
    2081                 :         // Step back to the last non-whitespace character.
    2082               0 :         ++end;
    2083                 : 
    2084               0 :         break;
    2085                 :       }
    2086                 :     }
    2087                 :   }
    2088                 : 
    2089                 :   // Return a substring for the string w/o leading and/or trailing
    2090                 :   // whitespace
    2091                 : 
    2092               0 :   return Substring(start, end);
    2093                 : }
    2094                 : 
    2095                 : // Declaring the templates we are going to use avoid linking issues without
    2096                 : // inlining the method. Considering there is not so much spaces checking
    2097                 : // methods we can consider this to be better than inlining.
    2098                 : template
    2099                 : const nsDependentSubstring
    2100                 : nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, bool);
    2101                 : template
    2102                 : const nsDependentSubstring
    2103                 : nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(const nsAString&, bool);
    2104                 : 
    2105               0 : static inline void KeyAppendSep(nsACString& aKey)
    2106                 : {
    2107               0 :   if (!aKey.IsEmpty()) {
    2108               0 :     aKey.Append('>');
    2109                 :   }
    2110               0 : }
    2111                 : 
    2112               0 : static inline void KeyAppendString(const nsAString& aString, nsACString& aKey)
    2113                 : {
    2114               0 :   KeyAppendSep(aKey);
    2115                 : 
    2116                 :   // Could escape separator here if collisions happen.  > is not a legal char
    2117                 :   // for a name or type attribute, so we should be safe avoiding that extra work.
    2118                 : 
    2119               0 :   AppendUTF16toUTF8(aString, aKey);
    2120               0 : }
    2121                 : 
    2122               0 : static inline void KeyAppendString(const nsACString& aString, nsACString& aKey)
    2123                 : {
    2124               0 :   KeyAppendSep(aKey);
    2125                 : 
    2126                 :   // Could escape separator here if collisions happen.  > is not a legal char
    2127                 :   // for a name or type attribute, so we should be safe avoiding that extra work.
    2128                 : 
    2129               0 :   aKey.Append(aString);
    2130               0 : }
    2131                 : 
    2132               0 : static inline void KeyAppendInt(PRInt32 aInt, nsACString& aKey)
    2133                 : {
    2134               0 :   KeyAppendSep(aKey);
    2135                 : 
    2136               0 :   aKey.Append(nsPrintfCString("%d", aInt));
    2137               0 : }
    2138                 : 
    2139                 : static inline void KeyAppendAtom(nsIAtom* aAtom, nsACString& aKey)
    2140                 : {
    2141                 :   NS_PRECONDITION(aAtom, "KeyAppendAtom: aAtom can not be null!\n");
    2142                 : 
    2143                 :   KeyAppendString(nsAtomCString(aAtom), aKey);
    2144                 : }
    2145                 : 
    2146               0 : static inline bool IsAutocompleteOff(const nsIContent* aElement)
    2147                 : {
    2148                 :   return aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::autocomplete,
    2149               0 :                                NS_LITERAL_STRING("off"), eIgnoreCase);
    2150                 : }
    2151                 : 
    2152                 : /*static*/ nsresult
    2153               0 : nsContentUtils::GenerateStateKey(nsIContent* aContent,
    2154                 :                                  const nsIDocument* aDocument,
    2155                 :                                  nsIStatefulFrame::SpecialStateID aID,
    2156                 :                                  nsACString& aKey)
    2157                 : {
    2158               0 :   aKey.Truncate();
    2159                 : 
    2160               0 :   PRUint32 partID = aDocument ? aDocument->GetPartID() : 0;
    2161                 : 
    2162                 :   // SpecialStateID case - e.g. scrollbars around the content window
    2163                 :   // The key in this case is a special state id
    2164               0 :   if (nsIStatefulFrame::eNoID != aID) {
    2165               0 :     KeyAppendInt(partID, aKey);  // first append a partID
    2166               0 :     KeyAppendInt(aID, aKey);
    2167               0 :     return NS_OK;
    2168                 :   }
    2169                 : 
    2170                 :   // We must have content if we're not using a special state id
    2171               0 :   NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE);
    2172                 : 
    2173                 :   // Don't capture state for anonymous content
    2174               0 :   if (aContent->IsInAnonymousSubtree()) {
    2175               0 :     return NS_OK;
    2176                 :   }
    2177                 : 
    2178               0 :   if (IsAutocompleteOff(aContent)) {
    2179               0 :     return NS_OK;
    2180                 :   }
    2181                 : 
    2182               0 :   nsCOMPtr<nsIHTMLDocument> htmlDocument(do_QueryInterface(aContent->GetCurrentDoc()));
    2183                 : 
    2184               0 :   KeyAppendInt(partID, aKey);  // first append a partID
    2185                 :   // Make sure we can't possibly collide with an nsIStatefulFrame
    2186                 :   // special id of some sort
    2187               0 :   KeyAppendInt(nsIStatefulFrame::eNoID, aKey);
    2188               0 :   bool generatedUniqueKey = false;
    2189                 : 
    2190               0 :   if (htmlDocument) {
    2191                 :     // Flush our content model so it'll be up to date
    2192                 :     // If this becomes unnecessary and the following line is removed,
    2193                 :     // please also remove the corresponding flush operation from
    2194                 :     // nsHtml5TreeBuilderCppSupplement.h. (Look for "See bug 497861." there.)
    2195               0 :     aContent->GetCurrentDoc()->FlushPendingNotifications(Flush_Content);
    2196                 : 
    2197               0 :     nsContentList *htmlForms = htmlDocument->GetForms();
    2198               0 :     nsContentList *htmlFormControls = htmlDocument->GetFormControls();
    2199                 : 
    2200               0 :     NS_ENSURE_TRUE(htmlForms && htmlFormControls, NS_ERROR_OUT_OF_MEMORY);
    2201                 : 
    2202                 :     // If we have a form control and can calculate form information, use that
    2203                 :     // as the key - it is more reliable than just recording position in the
    2204                 :     // DOM.
    2205                 :     // XXXbz Is it, really?  We have bugs on this, I think...
    2206                 :     // Important to have a unique key, and tag/type/name may not be.
    2207                 :     //
    2208                 :     // If the control has a form, the format of the key is:
    2209                 :     // f>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
    2210                 :     // else:
    2211                 :     // d>type>IndOfControlInDoc>name
    2212                 :     //
    2213                 :     // XXX We don't need to use index if name is there
    2214                 :     // XXXbz We don't?  Why not?  I don't follow.
    2215                 :     //
    2216               0 :     nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
    2217               0 :     if (control && htmlFormControls && htmlForms) {
    2218                 : 
    2219                 :       // Append the control type
    2220               0 :       KeyAppendInt(control->GetType(), aKey);
    2221                 : 
    2222                 :       // If in a form, add form name / index of form / index in form
    2223               0 :       PRInt32 index = -1;
    2224               0 :       Element *formElement = control->GetFormElement();
    2225               0 :       if (formElement) {
    2226               0 :         if (IsAutocompleteOff(formElement)) {
    2227               0 :           aKey.Truncate();
    2228               0 :           return NS_OK;
    2229                 :         }
    2230                 : 
    2231               0 :         KeyAppendString(NS_LITERAL_CSTRING("f"), aKey);
    2232                 : 
    2233                 :         // Append the index of the form in the document
    2234               0 :         index = htmlForms->IndexOf(formElement, false);
    2235               0 :         if (index <= -1) {
    2236                 :           //
    2237                 :           // XXX HACK this uses some state that was dumped into the document
    2238                 :           // specifically to fix bug 138892.  What we are trying to do is *guess*
    2239                 :           // which form this control's state is found in, with the highly likely
    2240                 :           // guess that the highest form parsed so far is the one.
    2241                 :           // This code should not be on trunk, only branch.
    2242                 :           //
    2243               0 :           index = htmlDocument->GetNumFormsSynchronous() - 1;
    2244                 :         }
    2245               0 :         if (index > -1) {
    2246               0 :           KeyAppendInt(index, aKey);
    2247                 : 
    2248                 :           // Append the index of the control in the form
    2249               0 :           nsCOMPtr<nsIForm> form(do_QueryInterface(formElement));
    2250               0 :           index = form->IndexOfControl(control);
    2251                 : 
    2252               0 :           if (index > -1) {
    2253               0 :             KeyAppendInt(index, aKey);
    2254               0 :             generatedUniqueKey = true;
    2255                 :           }
    2256                 :         }
    2257                 : 
    2258                 :         // Append the form name
    2259               0 :         nsAutoString formName;
    2260               0 :         formElement->GetAttr(kNameSpaceID_None, nsGkAtoms::name, formName);
    2261               0 :         KeyAppendString(formName, aKey);
    2262                 : 
    2263                 :       } else {
    2264                 : 
    2265               0 :         KeyAppendString(NS_LITERAL_CSTRING("d"), aKey);
    2266                 : 
    2267                 :         // If not in a form, add index of control in document
    2268                 :         // Less desirable than indexing by form info.
    2269                 : 
    2270                 :         // Hash by index of control in doc (we are not in a form)
    2271                 :         // These are important as they are unique, and type/name may not be.
    2272                 : 
    2273                 :         // We have to flush sink notifications at this point to make
    2274                 :         // sure that htmlFormControls is up to date.
    2275               0 :         index = htmlFormControls->IndexOf(aContent, true);
    2276               0 :         if (index > -1) {
    2277               0 :           KeyAppendInt(index, aKey);
    2278               0 :           generatedUniqueKey = true;
    2279                 :         }
    2280                 :       }
    2281                 : 
    2282                 :       // Append the control name
    2283               0 :       nsAutoString name;
    2284               0 :       aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
    2285               0 :       KeyAppendString(name, aKey);
    2286                 :     }
    2287                 :   }
    2288                 : 
    2289               0 :   if (!generatedUniqueKey) {
    2290                 :     // Either we didn't have a form control or we aren't in an HTML document so
    2291                 :     // we can't figure out form info.  Append the tag name if it's an element
    2292                 :     // to avoid restoring state for one type of element on another type.
    2293               0 :     if (aContent->IsElement()) {
    2294               0 :       KeyAppendString(nsDependentAtomString(aContent->Tag()), aKey);
    2295                 :     }
    2296                 :     else {
    2297                 :       // Append a character that is not "d" or "f" to disambiguate from
    2298                 :       // the case when we were a form control in an HTML document.
    2299               0 :       KeyAppendString(NS_LITERAL_CSTRING("o"), aKey);
    2300                 :     }
    2301                 : 
    2302                 :     // Now start at aContent and append the indices of it and all its ancestors
    2303                 :     // in their containers.  That should at least pin down its position in the
    2304                 :     // DOM...
    2305               0 :     nsINode* parent = aContent->GetNodeParent();
    2306               0 :     nsINode* content = aContent;
    2307               0 :     while (parent) {
    2308               0 :       KeyAppendInt(parent->IndexOf(content), aKey);
    2309               0 :       content = parent;
    2310               0 :       parent = content->GetNodeParent();
    2311                 :     }
    2312                 :   }
    2313                 : 
    2314               0 :   return NS_OK;
    2315                 : }
    2316                 : 
    2317                 : // static
    2318                 : nsresult
    2319               0 : nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
    2320                 :                                           const nsAString& aSpec,
    2321                 :                                           nsIDocument* aDocument,
    2322                 :                                           nsIURI* aBaseURI)
    2323                 : {
    2324                 :   return NS_NewURI(aResult, aSpec,
    2325               0 :                    aDocument ? aDocument->GetDocumentCharacterSet().get() : nsnull,
    2326               0 :                    aBaseURI, sIOService);
    2327                 : }
    2328                 : 
    2329                 : // static
    2330                 : bool
    2331               0 : nsContentUtils::BelongsInForm(nsIContent *aForm,
    2332                 :                               nsIContent *aContent)
    2333                 : {
    2334               0 :   NS_PRECONDITION(aForm, "Must have a form");
    2335               0 :   NS_PRECONDITION(aContent, "Must have a content node");
    2336                 : 
    2337               0 :   if (aForm == aContent) {
    2338                 :     // A form does not belong inside itself, so we return false here
    2339                 : 
    2340               0 :     return false;
    2341                 :   }
    2342                 : 
    2343               0 :   nsIContent* content = aContent->GetParent();
    2344                 : 
    2345               0 :   while (content) {
    2346               0 :     if (content == aForm) {
    2347                 :       // aContent is contained within the form so we return true.
    2348                 : 
    2349               0 :       return true;
    2350                 :     }
    2351                 : 
    2352               0 :     if (content->Tag() == nsGkAtoms::form &&
    2353               0 :         content->IsHTML()) {
    2354                 :       // The child is contained within a form, but not the right form
    2355                 :       // so we ignore it.
    2356                 : 
    2357               0 :       return false;
    2358                 :     }
    2359                 : 
    2360               0 :     content = content->GetParent();
    2361                 :   }
    2362                 : 
    2363               0 :   if (aForm->GetChildCount() > 0) {
    2364                 :     // The form is a container but aContent wasn't inside the form,
    2365                 :     // return false
    2366                 : 
    2367               0 :     return false;
    2368                 :   }
    2369                 : 
    2370                 :   // The form is a leaf and aContent wasn't inside any other form so
    2371                 :   // we check whether the content comes after the form.  If it does,
    2372                 :   // return true.  If it does not, then it couldn't have been inside
    2373                 :   // the form in the HTML.
    2374               0 :   if (PositionIsBefore(aForm, aContent)) {
    2375                 :     // We could be in this form!
    2376                 :     // In the future, we may want to get document.forms, look at the
    2377                 :     // form after aForm, and if aContent is after that form after
    2378                 :     // aForm return false here....
    2379               0 :     return true;
    2380                 :   }
    2381                 : 
    2382               0 :   return false;
    2383                 : }
    2384                 : 
    2385                 : // static
    2386                 : nsresult
    2387            1867 : nsContentUtils::CheckQName(const nsAString& aQualifiedName,
    2388                 :                            bool aNamespaceAware)
    2389                 : {
    2390            1867 :   nsIParserService *parserService = GetParserService();
    2391            1867 :   NS_ENSURE_TRUE(parserService, NS_ERROR_FAILURE);
    2392                 : 
    2393                 :   const PRUnichar *colon;
    2394            1867 :   return parserService->CheckQName(PromiseFlatString(aQualifiedName),
    2395            1867 :                                    aNamespaceAware, &colon);
    2396                 : }
    2397                 : 
    2398                 : //static
    2399                 : nsresult
    2400               0 : nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver,
    2401                 :                            const nsAFlatString& aQName,
    2402                 :                            PRInt32 *aNamespace, nsIAtom **aLocalName)
    2403                 : {
    2404               0 :   nsIParserService* parserService = GetParserService();
    2405               0 :   NS_ENSURE_TRUE(parserService, NS_ERROR_FAILURE);
    2406                 : 
    2407                 :   const PRUnichar* colon;
    2408               0 :   nsresult rv = parserService->CheckQName(aQName, true, &colon);
    2409               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2410                 : 
    2411               0 :   if (colon) {
    2412                 :     const PRUnichar* end;
    2413               0 :     aQName.EndReading(end);
    2414               0 :     nsAutoString nameSpace;
    2415                 :     rv = aNamespaceResolver->LookupNamespaceURIInternal(Substring(aQName.get(),
    2416               0 :                                                                   colon),
    2417               0 :                                                         nameSpace);
    2418               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2419                 : 
    2420               0 :     *aNamespace = NameSpaceManager()->GetNameSpaceID(nameSpace);
    2421               0 :     if (*aNamespace == kNameSpaceID_Unknown)
    2422               0 :       return NS_ERROR_FAILURE;
    2423                 : 
    2424               0 :     *aLocalName = NS_NewAtom(Substring(colon + 1, end));
    2425                 :   }
    2426                 :   else {
    2427               0 :     *aNamespace = kNameSpaceID_None;
    2428               0 :     *aLocalName = NS_NewAtom(aQName);
    2429                 :   }
    2430               0 :   NS_ENSURE_TRUE(aLocalName, NS_ERROR_OUT_OF_MEMORY);
    2431               0 :   return NS_OK;
    2432                 : }
    2433                 : 
    2434                 : // static
    2435                 : nsresult
    2436             193 : nsContentUtils::GetNodeInfoFromQName(const nsAString& aNamespaceURI,
    2437                 :                                      const nsAString& aQualifiedName,
    2438                 :                                      nsNodeInfoManager* aNodeInfoManager,
    2439                 :                                      PRUint16 aNodeType,
    2440                 :                                      nsINodeInfo** aNodeInfo)
    2441                 : {
    2442             193 :   nsIParserService* parserService = GetParserService();
    2443             193 :   NS_ENSURE_TRUE(parserService, NS_ERROR_FAILURE);
    2444                 : 
    2445             386 :   const nsAFlatString& qName = PromiseFlatString(aQualifiedName);
    2446                 :   const PRUnichar* colon;
    2447             193 :   nsresult rv = parserService->CheckQName(qName, true, &colon);
    2448             193 :   NS_ENSURE_SUCCESS(rv, rv);
    2449                 : 
    2450                 :   PRInt32 nsID;
    2451             193 :   sNameSpaceManager->RegisterNameSpace(aNamespaceURI, nsID);
    2452             193 :   if (colon) {
    2453                 :     const PRUnichar* end;
    2454              15 :     qName.EndReading(end);
    2455                 : 
    2456              30 :     nsCOMPtr<nsIAtom> prefix = do_GetAtom(Substring(qName.get(), colon));
    2457                 : 
    2458              15 :     rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, end), prefix,
    2459              15 :                                        nsID, aNodeType, aNodeInfo);
    2460                 :   }
    2461                 :   else {
    2462                 :     rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nsnull, nsID,
    2463             178 :                                        aNodeType, aNodeInfo);
    2464                 :   }
    2465             193 :   NS_ENSURE_SUCCESS(rv, rv);
    2466                 : 
    2467                 :   return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(),
    2468                 :                                          (*aNodeInfo)->GetPrefixAtom(),
    2469             193 :                                          (*aNodeInfo)->NamespaceID()) ?
    2470             193 :          NS_OK : NS_ERROR_DOM_NAMESPACE_ERR;
    2471                 : }
    2472                 : 
    2473                 : // static
    2474                 : void
    2475           82909 : nsContentUtils::SplitExpatName(const PRUnichar *aExpatName, nsIAtom **aPrefix,
    2476                 :                                nsIAtom **aLocalName, PRInt32* aNameSpaceID)
    2477                 : {
    2478                 :   /**
    2479                 :    *  Expat can send the following:
    2480                 :    *    localName
    2481                 :    *    namespaceURI<separator>localName
    2482                 :    *    namespaceURI<separator>localName<separator>prefix
    2483                 :    *
    2484                 :    *  and we use 0xFFFF for the <separator>.
    2485                 :    *
    2486                 :    */
    2487                 : 
    2488           82909 :   const PRUnichar *uriEnd = nsnull;
    2489           82909 :   const PRUnichar *nameEnd = nsnull;
    2490                 :   const PRUnichar *pos;
    2491         3240318 :   for (pos = aExpatName; *pos; ++pos) {
    2492         3157409 :     if (*pos == 0xFFFF) {
    2493           93772 :       if (uriEnd) {
    2494           34501 :         nameEnd = pos;
    2495                 :       }
    2496                 :       else {
    2497           59271 :         uriEnd = pos;
    2498                 :       }
    2499                 :     }
    2500                 :   }
    2501                 : 
    2502                 :   const PRUnichar *nameStart;
    2503           82909 :   if (uriEnd) {
    2504           59271 :     if (sNameSpaceManager) {
    2505                 :       sNameSpaceManager->RegisterNameSpace(nsDependentSubstring(aExpatName,
    2506           59271 :                                                                 uriEnd),
    2507           59271 :                                            *aNameSpaceID);
    2508                 :     }
    2509                 :     else {
    2510               0 :       *aNameSpaceID = kNameSpaceID_Unknown;
    2511                 :     }
    2512                 : 
    2513           59271 :     nameStart = (uriEnd + 1);
    2514           59271 :     if (nameEnd)  {
    2515           34501 :       const PRUnichar *prefixStart = nameEnd + 1;
    2516           34501 :       *aPrefix = NS_NewAtom(Substring(prefixStart, pos));
    2517                 :     }
    2518                 :     else {
    2519           24770 :       nameEnd = pos;
    2520           24770 :       *aPrefix = nsnull;
    2521                 :     }
    2522                 :   }
    2523                 :   else {
    2524           23638 :     *aNameSpaceID = kNameSpaceID_None;
    2525           23638 :     nameStart = aExpatName;
    2526           23638 :     nameEnd = pos;
    2527           23638 :     *aPrefix = nsnull;
    2528                 :   }
    2529           82909 :   *aLocalName = NS_NewAtom(Substring(nameStart, nameEnd));
    2530           82909 : }
    2531                 : 
    2532                 : // static
    2533                 : nsPresContext*
    2534               0 : nsContentUtils::GetContextForContent(const nsIContent* aContent)
    2535                 : {
    2536               0 :   nsIDocument* doc = aContent->GetCurrentDoc();
    2537               0 :   if (doc) {
    2538               0 :     nsIPresShell *presShell = doc->GetShell();
    2539               0 :     if (presShell) {
    2540               0 :       return presShell->GetPresContext();
    2541                 :     }
    2542                 :   }
    2543               0 :   return nsnull;
    2544                 : }
    2545                 : 
    2546                 : // static
    2547                 : bool
    2548               0 : nsContentUtils::CanLoadImage(nsIURI* aURI, nsISupports* aContext,
    2549                 :                              nsIDocument* aLoadingDocument,
    2550                 :                              nsIPrincipal* aLoadingPrincipal,
    2551                 :                              PRInt16* aImageBlockingStatus)
    2552                 : {
    2553               0 :   NS_PRECONDITION(aURI, "Must have a URI");
    2554               0 :   NS_PRECONDITION(aLoadingDocument, "Must have a document");
    2555               0 :   NS_PRECONDITION(aLoadingPrincipal, "Must have a loading principal");
    2556                 : 
    2557                 :   nsresult rv;
    2558                 : 
    2559               0 :   PRUint32 appType = nsIDocShell::APP_TYPE_UNKNOWN;
    2560                 : 
    2561                 :   {
    2562               0 :     nsCOMPtr<nsISupports> container = aLoadingDocument->GetContainer();
    2563                 :     nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
    2564               0 :       do_QueryInterface(container);
    2565                 : 
    2566               0 :     if (docShellTreeItem) {
    2567               0 :       nsCOMPtr<nsIDocShellTreeItem> root;
    2568               0 :       docShellTreeItem->GetRootTreeItem(getter_AddRefs(root));
    2569                 : 
    2570               0 :       nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(root));
    2571                 : 
    2572               0 :       if (!docShell || NS_FAILED(docShell->GetAppType(&appType))) {
    2573               0 :         appType = nsIDocShell::APP_TYPE_UNKNOWN;
    2574                 :       }
    2575                 :     }
    2576                 :   }
    2577                 : 
    2578               0 :   if (appType != nsIDocShell::APP_TYPE_EDITOR) {
    2579                 :     // Editor apps get special treatment here, editors can load images
    2580                 :     // from anywhere.  This allows editor to insert images from file://
    2581                 :     // into documents that are being edited.
    2582                 :     rv = sSecurityManager->
    2583                 :       CheckLoadURIWithPrincipal(aLoadingPrincipal, aURI,
    2584               0 :                                 nsIScriptSecurityManager::ALLOW_CHROME);
    2585               0 :     if (NS_FAILED(rv)) {
    2586               0 :       if (aImageBlockingStatus) {
    2587                 :         // Reject the request itself, not all requests to the relevant
    2588                 :         // server...
    2589               0 :         *aImageBlockingStatus = nsIContentPolicy::REJECT_REQUEST;
    2590                 :       }
    2591               0 :       return false;
    2592                 :     }
    2593                 :   }
    2594                 : 
    2595               0 :   PRInt16 decision = nsIContentPolicy::ACCEPT;
    2596                 : 
    2597                 :   rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_IMAGE,
    2598                 :                                  aURI,
    2599                 :                                  aLoadingPrincipal,
    2600                 :                                  aContext,
    2601               0 :                                  EmptyCString(), //mime guess
    2602                 :                                  nsnull,         //extra
    2603                 :                                  &decision,
    2604                 :                                  GetContentPolicy(),
    2605               0 :                                  sSecurityManager);
    2606                 : 
    2607               0 :   if (aImageBlockingStatus) {
    2608                 :     *aImageBlockingStatus =
    2609               0 :       NS_FAILED(rv) ? nsIContentPolicy::REJECT_REQUEST : decision;
    2610                 :   }
    2611               0 :   return NS_FAILED(rv) ? false : NS_CP_ACCEPTED(decision);
    2612                 : }
    2613                 : 
    2614                 : // static
    2615                 : bool
    2616               0 : nsContentUtils::IsImageInCache(nsIURI* aURI)
    2617                 : {
    2618               0 :     if (!sImgLoaderInitialized)
    2619               0 :         InitImgLoader();
    2620                 : 
    2621               0 :     if (!sImgCache) return false;
    2622                 : 
    2623                 :     // If something unexpected happened we return false, otherwise if props
    2624                 :     // is set, the image is cached and we return true
    2625               0 :     nsCOMPtr<nsIProperties> props;
    2626               0 :     nsresult rv = sImgCache->FindEntryProperties(aURI, getter_AddRefs(props));
    2627               0 :     return (NS_SUCCEEDED(rv) && props);
    2628                 : }
    2629                 : 
    2630                 : // static
    2631                 : nsresult
    2632               0 : nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument,
    2633                 :                           nsIPrincipal* aLoadingPrincipal, nsIURI* aReferrer,
    2634                 :                           imgIDecoderObserver* aObserver, PRInt32 aLoadFlags,
    2635                 :                           imgIRequest** aRequest)
    2636                 : {
    2637               0 :   NS_PRECONDITION(aURI, "Must have a URI");
    2638               0 :   NS_PRECONDITION(aLoadingDocument, "Must have a document");
    2639               0 :   NS_PRECONDITION(aLoadingPrincipal, "Must have a principal");
    2640               0 :   NS_PRECONDITION(aRequest, "Null out param");
    2641                 : 
    2642               0 :   imgILoader* imgLoader = GetImgLoader();
    2643               0 :   if (!imgLoader) {
    2644                 :     // nothing we can do here
    2645               0 :     return NS_OK;
    2646                 :   }
    2647                 : 
    2648               0 :   nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
    2649               0 :   NS_ASSERTION(loadGroup, "Could not get loadgroup; onload may fire too early");
    2650                 : 
    2651               0 :   nsIURI *documentURI = aLoadingDocument->GetDocumentURI();
    2652                 : 
    2653                 :   // check for a Content Security Policy to pass down to the channel that
    2654                 :   // will get created to load the image
    2655               0 :   nsCOMPtr<nsIChannelPolicy> channelPolicy;
    2656               0 :   nsCOMPtr<nsIContentSecurityPolicy> csp;
    2657               0 :   if (aLoadingPrincipal) {
    2658               0 :     nsresult rv = aLoadingPrincipal->GetCsp(getter_AddRefs(csp));
    2659               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2660               0 :     if (csp) {
    2661               0 :       channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
    2662               0 :       channelPolicy->SetContentSecurityPolicy(csp);
    2663               0 :       channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
    2664                 :     }
    2665                 :   }
    2666                 :     
    2667                 :   // Make the URI immutable so people won't change it under us
    2668               0 :   NS_TryToSetImmutable(aURI);
    2669                 : 
    2670                 :   // XXXbz using "documentURI" for the initialDocumentURI is not quite
    2671                 :   // right, but the best we can do here...
    2672                 :   return imgLoader->LoadImage(aURI,                 /* uri to load */
    2673                 :                               documentURI,          /* initialDocumentURI */
    2674                 :                               aReferrer,            /* referrer */
    2675                 :                               aLoadingPrincipal,    /* loading principal */
    2676                 :                               loadGroup,            /* loadgroup */
    2677                 :                               aObserver,            /* imgIDecoderObserver */
    2678                 :                               aLoadingDocument,     /* uniquification key */
    2679                 :                               aLoadFlags,           /* load flags */
    2680                 :                               nsnull,               /* cache key */
    2681                 :                               nsnull,               /* existing request*/
    2682                 :                               channelPolicy,        /* CSP info */
    2683               0 :                               aRequest);
    2684                 : }
    2685                 : 
    2686                 : // static
    2687                 : already_AddRefed<imgIContainer>
    2688               0 : nsContentUtils::GetImageFromContent(nsIImageLoadingContent* aContent,
    2689                 :                                     imgIRequest **aRequest)
    2690                 : {
    2691               0 :   if (aRequest) {
    2692               0 :     *aRequest = nsnull;
    2693                 :   }
    2694                 : 
    2695               0 :   NS_ENSURE_TRUE(aContent, nsnull);
    2696                 : 
    2697               0 :   nsCOMPtr<imgIRequest> imgRequest;
    2698                 :   aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
    2699               0 :                       getter_AddRefs(imgRequest));
    2700               0 :   if (!imgRequest) {
    2701               0 :     return nsnull;
    2702                 :   }
    2703                 : 
    2704               0 :   nsCOMPtr<imgIContainer> imgContainer;
    2705               0 :   imgRequest->GetImage(getter_AddRefs(imgContainer));
    2706                 : 
    2707               0 :   if (!imgContainer) {
    2708               0 :     return nsnull;
    2709                 :   }
    2710                 : 
    2711               0 :   if (aRequest) {
    2712               0 :     imgRequest.swap(*aRequest);
    2713                 :   }
    2714                 : 
    2715               0 :   return imgContainer.forget();
    2716                 : }
    2717                 : 
    2718                 : //static
    2719                 : already_AddRefed<imgIRequest>
    2720               0 : nsContentUtils::GetStaticRequest(imgIRequest* aRequest)
    2721                 : {
    2722               0 :   NS_ENSURE_TRUE(aRequest, nsnull);
    2723               0 :   nsCOMPtr<imgIRequest> retval;
    2724               0 :   aRequest->GetStaticRequest(getter_AddRefs(retval));
    2725               0 :   return retval.forget();
    2726                 : }
    2727                 : 
    2728                 : // static
    2729                 : bool
    2730               0 : nsContentUtils::ContentIsDraggable(nsIContent* aContent)
    2731                 : {
    2732               0 :   nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(aContent);
    2733               0 :   if (htmlElement) {
    2734               0 :     bool draggable = false;
    2735               0 :     htmlElement->GetDraggable(&draggable);
    2736               0 :     if (draggable)
    2737               0 :       return true;
    2738                 : 
    2739               0 :     if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
    2740               0 :                               nsGkAtoms::_false, eIgnoreCase))
    2741               0 :       return false;
    2742                 :   }
    2743                 : 
    2744                 :   // special handling for content area image and link dragging
    2745               0 :   return IsDraggableImage(aContent) || IsDraggableLink(aContent);
    2746                 : }
    2747                 : 
    2748                 : // static
    2749                 : bool
    2750               0 : nsContentUtils::IsDraggableImage(nsIContent* aContent)
    2751                 : {
    2752               0 :   NS_PRECONDITION(aContent, "Must have content node to test");
    2753                 : 
    2754               0 :   nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(aContent));
    2755               0 :   if (!imageContent) {
    2756               0 :     return false;
    2757                 :   }
    2758                 : 
    2759               0 :   nsCOMPtr<imgIRequest> imgRequest;
    2760               0 :   imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
    2761               0 :                            getter_AddRefs(imgRequest));
    2762                 : 
    2763                 :   // XXXbz It may be draggable even if the request resulted in an error.  Why?
    2764                 :   // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
    2765               0 :   return imgRequest != nsnull;
    2766                 : }
    2767                 : 
    2768                 : // static
    2769                 : bool
    2770               0 : nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
    2771               0 :   nsCOMPtr<nsIURI> absURI;
    2772               0 :   return aContent->IsLink(getter_AddRefs(absURI));
    2773                 : }
    2774                 : 
    2775                 : bool
    2776               0 : nsContentUtils::IsSitePermAllow(nsIURI* aURI, const char* aType)
    2777                 : {
    2778                 :   nsCOMPtr<nsIPermissionManager> permMgr =
    2779               0 :     do_GetService("@mozilla.org/permissionmanager;1");
    2780               0 :   NS_ENSURE_TRUE(permMgr, false);
    2781                 : 
    2782                 :   PRUint32 perm;
    2783               0 :   nsresult rv = permMgr->TestPermission(aURI, aType, &perm);
    2784               0 :   NS_ENSURE_SUCCESS(rv, false);
    2785                 :   
    2786               0 :   return perm == nsIPermissionManager::ALLOW_ACTION;
    2787                 : }
    2788                 : 
    2789                 : static const char *gEventNames[] = {"event"};
    2790                 : static const char *gSVGEventNames[] = {"evt"};
    2791                 : // for b/w compat, the first name to onerror is still 'event', even though it
    2792                 : // is actually the error message.  (pre this code, the other 2 were not avail.)
    2793                 : // XXXmarkh - a quick lxr shows no affected code - should we correct this?
    2794                 : static const char *gOnErrorNames[] = {"event", "source", "lineno"};
    2795                 : 
    2796                 : // static
    2797                 : void
    2798               0 : nsContentUtils::GetEventArgNames(PRInt32 aNameSpaceID,
    2799                 :                                  nsIAtom *aEventName,
    2800                 :                                  PRUint32 *aArgCount,
    2801                 :                                  const char*** aArgArray)
    2802                 : {
    2803                 : #define SET_EVENT_ARG_NAMES(names) \
    2804                 :     *aArgCount = sizeof(names)/sizeof(names[0]); \
    2805                 :     *aArgArray = names;
    2806                 : 
    2807                 :   // nsJSEventListener is what does the arg magic for onerror, and it does
    2808                 :   // not seem to take the namespace into account.  So we let onerror in all
    2809                 :   // namespaces get the 3 arg names.
    2810               0 :   if (aEventName == nsGkAtoms::onerror) {
    2811               0 :     SET_EVENT_ARG_NAMES(gOnErrorNames);
    2812               0 :   } else if (aNameSpaceID == kNameSpaceID_SVG) {
    2813               0 :     SET_EVENT_ARG_NAMES(gSVGEventNames);
    2814                 :   } else {
    2815               0 :     SET_EVENT_ARG_NAMES(gEventNames);
    2816                 :   }
    2817               0 : }
    2818                 : 
    2819           16904 : nsCxPusher::nsCxPusher()
    2820                 :     : mScriptIsRunning(false),
    2821           16904 :       mPushedSomething(false)
    2822                 : {
    2823           16904 : }
    2824                 : 
    2825           33808 : nsCxPusher::~nsCxPusher()
    2826                 : {
    2827           16904 :   Pop();
    2828           16904 : }
    2829                 : 
    2830                 : static bool
    2831             261 : IsContextOnStack(nsIJSContextStack *aStack, JSContext *aContext)
    2832                 : {
    2833             261 :   JSContext *ctx = nsnull;
    2834             261 :   aStack->Peek(&ctx);
    2835             261 :   if (!ctx)
    2836               0 :     return false;
    2837             261 :   if (ctx == aContext)
    2838             261 :     return true;
    2839                 : 
    2840                 :   nsCOMPtr<nsIJSContextStackIterator>
    2841               0 :     iterator(do_CreateInstance("@mozilla.org/js/xpc/ContextStackIterator;1"));
    2842               0 :   NS_ENSURE_TRUE(iterator, false);
    2843                 : 
    2844               0 :   nsresult rv = iterator->Reset(aStack);
    2845               0 :   NS_ENSURE_SUCCESS(rv, false);
    2846                 : 
    2847                 :   bool done;
    2848               0 :   while (NS_SUCCEEDED(iterator->Done(&done)) && !done) {
    2849               0 :     rv = iterator->Prev(&ctx);
    2850               0 :     NS_ASSERTION(NS_SUCCEEDED(rv), "Broken iterator implementation");
    2851                 : 
    2852               0 :     if (!ctx) {
    2853               0 :       continue;
    2854                 :     }
    2855                 : 
    2856               0 :     if (nsJSUtils::GetDynamicScriptContext(ctx) && ctx == aContext)
    2857               0 :       return true;
    2858                 :   }
    2859                 : 
    2860               0 :   return false;
    2861                 : }
    2862                 : 
    2863                 : bool
    2864            3972 : nsCxPusher::Push(nsIDOMEventTarget *aCurrentTarget)
    2865                 : {
    2866            3972 :   if (mPushedSomething) {
    2867               0 :     NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
    2868                 : 
    2869               0 :     return false;
    2870                 :   }
    2871                 : 
    2872            3972 :   NS_ENSURE_TRUE(aCurrentTarget, false);
    2873                 :   nsresult rv;
    2874                 :   nsIScriptContext* scx =
    2875            3972 :     aCurrentTarget->GetContextForEventHandlers(&rv);
    2876            3972 :   NS_ENSURE_SUCCESS(rv, false);
    2877                 : 
    2878            3972 :   if (!scx) {
    2879                 :     // The target may have a special JS context for event handlers.
    2880            3972 :     JSContext* cx = aCurrentTarget->GetJSContextForEventHandlers();
    2881            3972 :     if (cx) {
    2882               0 :       DoPush(cx);
    2883                 :     }
    2884                 : 
    2885                 :     // Nothing to do here, I guess.  Have to return true so that event firing
    2886                 :     // will still work correctly even if there is no associated JSContext
    2887            3972 :     return true;
    2888                 :   }
    2889                 : 
    2890               0 :   JSContext* cx = nsnull;
    2891                 : 
    2892               0 :   if (scx) {
    2893               0 :     cx = scx->GetNativeContext();
    2894                 :     // Bad, no JSContext from script context!
    2895               0 :     NS_ENSURE_TRUE(cx, false);
    2896                 :   }
    2897                 : 
    2898                 :   // If there's no native context in the script context it must be
    2899                 :   // in the process or being torn down. We don't want to notify the
    2900                 :   // script context about scripts having been evaluated in such a
    2901                 :   // case, calling with a null cx is fine in that case.
    2902               0 :   return Push(cx);
    2903                 : }
    2904                 : 
    2905                 : bool
    2906            3972 : nsCxPusher::RePush(nsIDOMEventTarget *aCurrentTarget)
    2907                 : {
    2908            3972 :   if (!mPushedSomething) {
    2909            3972 :     return Push(aCurrentTarget);
    2910                 :   }
    2911                 : 
    2912               0 :   if (aCurrentTarget) {
    2913                 :     nsresult rv;
    2914                 :     nsIScriptContext* scx =
    2915               0 :       aCurrentTarget->GetContextForEventHandlers(&rv);
    2916               0 :     if (NS_FAILED(rv)) {
    2917               0 :       Pop();
    2918               0 :       return false;
    2919                 :     }
    2920                 : 
    2921                 :     // If we have the same script context and native context is still
    2922                 :     // alive, no need to Pop/Push.
    2923               0 :     if (scx && scx == mScx &&
    2924               0 :         scx->GetNativeContext()) {
    2925               0 :       return true;
    2926                 :     }
    2927                 :   }
    2928                 : 
    2929               0 :   Pop();
    2930               0 :   return Push(aCurrentTarget);
    2931                 : }
    2932                 : 
    2933                 : bool
    2934             261 : nsCxPusher::Push(JSContext *cx, bool aRequiresScriptContext)
    2935                 : {
    2936             261 :   if (mPushedSomething) {
    2937               0 :     NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
    2938                 : 
    2939               0 :     return false;
    2940                 :   }
    2941                 : 
    2942             261 :   if (!cx) {
    2943               0 :     return false;
    2944                 :   }
    2945                 : 
    2946                 :   // Hold a strong ref to the nsIScriptContext, just in case
    2947                 :   // XXXbz do we really need to?  If we don't get one of these in Pop(), is
    2948                 :   // that really a problem?  Or do we need to do this to effectively root |cx|?
    2949             261 :   mScx = GetScriptContextFromJSContext(cx);
    2950             261 :   if (!mScx && aRequiresScriptContext) {
    2951                 :     // Should probably return false. See bug 416916.
    2952               0 :     return true;
    2953                 :   }
    2954                 : 
    2955             261 :   return DoPush(cx);
    2956                 : }
    2957                 : 
    2958                 : bool
    2959             261 : nsCxPusher::DoPush(JSContext* cx)
    2960                 : {
    2961             261 :   nsIThreadJSContextStack* stack = nsContentUtils::ThreadJSContextStack();
    2962             261 :   if (!stack) {
    2963               0 :     return true;
    2964                 :   }
    2965                 : 
    2966             261 :   if (cx && IsContextOnStack(stack, cx)) {
    2967                 :     // If the context is on the stack, that means that a script
    2968                 :     // is running at the moment in the context.
    2969             261 :     mScriptIsRunning = true;
    2970                 :   }
    2971                 : 
    2972             261 :   if (NS_FAILED(stack->Push(cx))) {
    2973               0 :     mScriptIsRunning = false;
    2974               0 :     mScx = nsnull;
    2975               0 :     return false;
    2976                 :   }
    2977                 : 
    2978             261 :   mPushedSomething = true;
    2979                 : #ifdef DEBUG
    2980             261 :   mPushedContext = cx;
    2981                 : #endif
    2982             261 :   return true;
    2983                 : }
    2984                 : 
    2985                 : bool
    2986               0 : nsCxPusher::PushNull()
    2987                 : {
    2988               0 :   return DoPush(nsnull);
    2989                 : }
    2990                 : 
    2991                 : void
    2992           33379 : nsCxPusher::Pop()
    2993                 : {
    2994           33379 :   nsIThreadJSContextStack* stack = nsContentUtils::ThreadJSContextStack();
    2995           33379 :   if (!mPushedSomething || !stack) {
    2996           33118 :     mScx = nsnull;
    2997           33118 :     mPushedSomething = false;
    2998                 : 
    2999           33118 :     NS_ASSERTION(!mScriptIsRunning, "Huh, this can't be happening, "
    3000                 :                  "mScriptIsRunning can't be set here!");
    3001                 : 
    3002           33118 :     return;
    3003                 :   }
    3004                 : 
    3005                 :   JSContext *unused;
    3006             261 :   stack->Pop(&unused);
    3007                 : 
    3008             261 :   NS_ASSERTION(unused == mPushedContext, "Unexpected context popped");
    3009                 : 
    3010             261 :   if (!mScriptIsRunning && mScx) {
    3011                 :     // No JS is running in the context, but executing the event handler might have
    3012                 :     // caused some JS to run. Tell the script context that it's done.
    3013                 : 
    3014               0 :     mScx->ScriptEvaluated(true);
    3015                 :   }
    3016                 : 
    3017             261 :   mScx = nsnull;
    3018             261 :   mScriptIsRunning = false;
    3019             261 :   mPushedSomething = false;
    3020                 : }
    3021                 : 
    3022                 : static const char gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT][56] = {
    3023                 :   // Must line up with the enum values in |PropertiesFile| enum.
    3024                 :   "chrome://global/locale/css.properties",
    3025                 :   "chrome://global/locale/xbl.properties",
    3026                 :   "chrome://global/locale/xul.properties",
    3027                 :   "chrome://global/locale/layout_errors.properties",
    3028                 :   "chrome://global/locale/layout/HtmlForm.properties",
    3029                 :   "chrome://global/locale/printing.properties",
    3030                 :   "chrome://global/locale/dom/dom.properties",
    3031                 :   "chrome://global/locale/layout/htmlparser.properties",
    3032                 :   "chrome://global/locale/svg/svg.properties",
    3033                 :   "chrome://branding/locale/brand.properties",
    3034                 :   "chrome://global/locale/commonDialogs.properties"
    3035                 : };
    3036                 : 
    3037                 : /* static */ nsresult
    3038              28 : nsContentUtils::EnsureStringBundle(PropertiesFile aFile)
    3039                 : {
    3040              28 :   if (!sStringBundles[aFile]) {
    3041               4 :     if (!sStringBundleService) {
    3042                 :       nsresult rv =
    3043               4 :         CallGetService(NS_STRINGBUNDLE_CONTRACTID, &sStringBundleService);
    3044               4 :       NS_ENSURE_SUCCESS(rv, rv);
    3045                 :     }
    3046                 :     nsIStringBundle *bundle;
    3047                 :     nsresult rv =
    3048               4 :       sStringBundleService->CreateBundle(gPropertiesFiles[aFile], &bundle);
    3049               4 :     NS_ENSURE_SUCCESS(rv, rv);
    3050               4 :     sStringBundles[aFile] = bundle; // transfer ownership
    3051                 :   }
    3052              28 :   return NS_OK;
    3053                 : }
    3054                 : 
    3055                 : /* static */
    3056              28 : nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile,
    3057                 :                                             const char* aKey,
    3058                 :                                             nsXPIDLString& aResult)
    3059                 : {
    3060              28 :   nsresult rv = EnsureStringBundle(aFile);
    3061              28 :   NS_ENSURE_SUCCESS(rv, rv);
    3062              28 :   nsIStringBundle *bundle = sStringBundles[aFile];
    3063                 : 
    3064              28 :   return bundle->GetStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
    3065              56 :                                    getter_Copies(aResult));
    3066                 : }
    3067                 : 
    3068                 : /* static */
    3069               0 : nsresult nsContentUtils::FormatLocalizedString(PropertiesFile aFile,
    3070                 :                                                const char* aKey,
    3071                 :                                                const PRUnichar **aParams,
    3072                 :                                                PRUint32 aParamsLength,
    3073                 :                                                nsXPIDLString& aResult)
    3074                 : {
    3075               0 :   nsresult rv = EnsureStringBundle(aFile);
    3076               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3077               0 :   nsIStringBundle *bundle = sStringBundles[aFile];
    3078                 : 
    3079               0 :   return bundle->FormatStringFromName(NS_ConvertASCIItoUTF16(aKey).get(),
    3080                 :                                       aParams, aParamsLength,
    3081               0 :                                       getter_Copies(aResult));
    3082                 : }
    3083                 : 
    3084                 : /* static */ nsresult
    3085              28 : nsContentUtils::ReportToConsole(PRUint32 aErrorFlags,
    3086                 :                                 const char *aCategory,
    3087                 :                                 nsIDocument* aDocument,
    3088                 :                                 PropertiesFile aFile,
    3089                 :                                 const char *aMessageName,
    3090                 :                                 const PRUnichar **aParams,
    3091                 :                                 PRUint32 aParamsLength,
    3092                 :                                 nsIURI* aURI,
    3093                 :                                 const nsAFlatString& aSourceLine,
    3094                 :                                 PRUint32 aLineNumber,
    3095                 :                                 PRUint32 aColumnNumber)
    3096                 : {
    3097              28 :   NS_ASSERTION((aParams && aParamsLength) || (!aParams && !aParamsLength),
    3098                 :                "Supply either both parameters and their number or no"
    3099                 :                "parameters and 0.");
    3100                 : 
    3101              28 :   PRUint64 innerWindowID = 0;
    3102              28 :   if (aDocument) {
    3103               5 :     if (!aURI) {
    3104               5 :       aURI = aDocument->GetDocumentURI();
    3105                 :     }
    3106               5 :     innerWindowID = aDocument->InnerWindowID();
    3107                 :   }
    3108                 : 
    3109                 :   nsresult rv;
    3110              28 :   if (!sConsoleService) { // only need to bother null-checking here
    3111               4 :     rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID, &sConsoleService);
    3112               4 :     NS_ENSURE_SUCCESS(rv, rv);
    3113                 :   }
    3114                 : 
    3115              56 :   nsXPIDLString errorText;
    3116              28 :   if (aParams) {
    3117                 :     rv = FormatLocalizedString(aFile, aMessageName, aParams, aParamsLength,
    3118               0 :                                errorText);
    3119                 :   }
    3120                 :   else {
    3121              28 :     rv = GetLocalizedString(aFile, aMessageName, errorText);
    3122                 :   }
    3123              28 :   NS_ENSURE_SUCCESS(rv, rv);
    3124                 : 
    3125              56 :   nsCAutoString spec;
    3126              28 :   if (aURI)
    3127               5 :     aURI->GetSpec(spec);
    3128                 : 
    3129                 :   nsCOMPtr<nsIScriptError> errorObject =
    3130              56 :       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
    3131              28 :   NS_ENSURE_SUCCESS(rv, rv);
    3132                 : 
    3133              28 :   rv = errorObject->InitWithWindowID(errorText.get(),
    3134              28 :                                      NS_ConvertUTF8toUTF16(spec).get(), // file name
    3135                 :                                      aSourceLine.get(),
    3136                 :                                      aLineNumber, aColumnNumber,
    3137                 :                                      aErrorFlags, aCategory,
    3138              28 :                                      innerWindowID);
    3139              28 :   NS_ENSURE_SUCCESS(rv, rv);
    3140                 : 
    3141              28 :   return sConsoleService->LogMessage(errorObject);
    3142                 : }
    3143                 : 
    3144                 : bool
    3145               2 : nsContentUtils::IsChromeDoc(nsIDocument *aDocument)
    3146                 : {
    3147               2 :   if (!aDocument) {
    3148               0 :     return false;
    3149                 :   }
    3150                 :   
    3151               4 :   nsCOMPtr<nsIPrincipal> systemPrincipal;
    3152               2 :   sSecurityManager->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
    3153                 : 
    3154               2 :   return aDocument->NodePrincipal() == systemPrincipal;
    3155                 : }
    3156                 : 
    3157                 : bool
    3158               0 : nsContentUtils::IsChildOfSameType(nsIDocument* aDoc)
    3159                 : {
    3160               0 :   nsCOMPtr<nsISupports> container = aDoc->GetContainer();
    3161               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(container));
    3162               0 :   nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
    3163               0 :   if (docShellAsItem) {
    3164               0 :     docShellAsItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
    3165                 :   }
    3166               0 :   return sameTypeParent != nsnull;
    3167                 : }
    3168                 : 
    3169                 : bool
    3170               0 : nsContentUtils::GetWrapperSafeScriptFilename(nsIDocument *aDocument,
    3171                 :                                              nsIURI *aURI,
    3172                 :                                              nsACString& aScriptURI)
    3173                 : {
    3174               0 :   bool scriptFileNameModified = false;
    3175               0 :   aURI->GetSpec(aScriptURI);
    3176                 : 
    3177               0 :   if (IsChromeDoc(aDocument)) {
    3178                 :     nsCOMPtr<nsIChromeRegistry> chromeReg =
    3179               0 :       mozilla::services::GetChromeRegistryService();
    3180                 : 
    3181               0 :     if (!chromeReg) {
    3182                 :       // If we're running w/o a chrome registry we won't modify any
    3183                 :       // script file names.
    3184                 : 
    3185               0 :       return scriptFileNameModified;
    3186                 :     }
    3187                 : 
    3188                 :     bool docWrappersEnabled =
    3189               0 :       chromeReg->WrappersEnabled(aDocument->GetDocumentURI());
    3190                 : 
    3191               0 :     bool uriWrappersEnabled = chromeReg->WrappersEnabled(aURI);
    3192                 : 
    3193               0 :     nsIURI *docURI = aDocument->GetDocumentURI();
    3194                 : 
    3195               0 :     if (docURI && docWrappersEnabled && !uriWrappersEnabled) {
    3196                 :       // aURI is a script from a URL that doesn't get wrapper
    3197                 :       // automation. aDocument is a chrome document that does get
    3198                 :       // wrapper automation. Prepend the chrome document's URI
    3199                 :       // followed by the string " -> " to the URI of the script we're
    3200                 :       // loading here so that script in that URI gets the same wrapper
    3201                 :       // automation that the chrome document expects.
    3202               0 :       nsCAutoString spec;
    3203               0 :       docURI->GetSpec(spec);
    3204               0 :       spec.AppendASCII(" -> ");
    3205               0 :       spec.Append(aScriptURI);
    3206                 : 
    3207               0 :       aScriptURI = spec;
    3208                 : 
    3209               0 :       scriptFileNameModified = true;
    3210                 :     }
    3211                 :   }
    3212                 : 
    3213               0 :   return scriptFileNameModified;
    3214                 : }
    3215                 : 
    3216                 : // static
    3217                 : bool
    3218               0 : nsContentUtils::IsInChromeDocshell(nsIDocument *aDocument)
    3219                 : {
    3220               0 :   if (!aDocument) {
    3221               0 :     return false;
    3222                 :   }
    3223                 : 
    3224               0 :   if (aDocument->GetDisplayDocument()) {
    3225               0 :     return IsInChromeDocshell(aDocument->GetDisplayDocument());
    3226                 :   }
    3227                 : 
    3228               0 :   nsCOMPtr<nsISupports> docContainer = aDocument->GetContainer();
    3229               0 :   nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryInterface(docContainer));
    3230               0 :   PRInt32 itemType = nsIDocShellTreeItem::typeContent;
    3231               0 :   if (docShell) {
    3232               0 :     docShell->GetItemType(&itemType);
    3233                 :   }
    3234                 : 
    3235               0 :   return itemType == nsIDocShellTreeItem::typeChrome;
    3236                 : }
    3237                 : 
    3238                 : // static
    3239                 : nsIContentPolicy*
    3240             598 : nsContentUtils::GetContentPolicy()
    3241                 : {
    3242             598 :   if (!sTriedToGetContentPolicy) {
    3243             110 :     CallGetService(NS_CONTENTPOLICY_CONTRACTID, &sContentPolicyService);
    3244                 :     // It's OK to not have a content policy service
    3245             110 :     sTriedToGetContentPolicy = true;
    3246                 :   }
    3247                 : 
    3248             598 :   return sContentPolicyService;
    3249                 : }
    3250                 : 
    3251                 : // static
    3252                 : bool
    3253              72 : nsContentUtils::IsEventAttributeName(nsIAtom* aName, PRInt32 aType)
    3254                 : {
    3255              72 :   const PRUnichar* name = aName->GetUTF16String();
    3256              72 :   if (name[0] != 'o' || name[1] != 'n')
    3257              72 :     return false;
    3258                 : 
    3259                 :   EventNameMapping mapping;
    3260               0 :   return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType);
    3261                 : }
    3262                 : 
    3263                 : // static
    3264                 : PRUint32
    3265            4613 : nsContentUtils::GetEventId(nsIAtom* aName)
    3266                 : {
    3267                 :   EventNameMapping mapping;
    3268            4613 :   if (sAtomEventTable->Get(aName, &mapping))
    3269            2906 :     return mapping.mId;
    3270                 : 
    3271            1707 :   return NS_USER_DEFINED_EVENT;
    3272                 : }
    3273                 : 
    3274                 : // static
    3275                 : PRUint32
    3276               0 : nsContentUtils::GetEventCategory(const nsAString& aName)
    3277                 : {
    3278                 :   EventNameMapping mapping;
    3279               0 :   if (sStringEventTable->Get(aName, &mapping))
    3280               0 :     return mapping.mStructType;
    3281                 : 
    3282               0 :   return NS_EVENT;
    3283                 : }
    3284                 : 
    3285                 : nsIAtom*
    3286           16367 : nsContentUtils::GetEventIdAndAtom(const nsAString& aName,
    3287                 :                                   PRUint32 aEventStruct,
    3288                 :                                   PRUint32* aEventID)
    3289                 : {
    3290                 :   EventNameMapping mapping;
    3291           16367 :   if (sStringEventTable->Get(aName, &mapping)) {
    3292                 :     *aEventID =
    3293           15351 :       mapping.mStructType == aEventStruct ? mapping.mId : NS_USER_DEFINED_EVENT;
    3294           15351 :     return mapping.mAtom;
    3295                 :   }
    3296                 : 
    3297                 :   // If we have cached lots of user defined event names, clear some of them.
    3298            1016 :   if (sUserDefinedEvents->Count() > 127) {
    3299               0 :     while (sUserDefinedEvents->Count() > 64) {
    3300               0 :       nsIAtom* first = sUserDefinedEvents->ObjectAt(0);
    3301               0 :       sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
    3302               0 :       sUserDefinedEvents->RemoveObjectAt(0);
    3303                 :     }
    3304                 :   }
    3305                 : 
    3306            1016 :   *aEventID = NS_USER_DEFINED_EVENT;
    3307            2032 :   nsCOMPtr<nsIAtom> atom = do_GetAtom(NS_LITERAL_STRING("on") + aName);
    3308            1016 :   sUserDefinedEvents->AppendObject(atom);
    3309            1016 :   mapping.mAtom = atom;
    3310            1016 :   mapping.mId = NS_USER_DEFINED_EVENT;
    3311            1016 :   mapping.mType = EventNameType_None;
    3312            1016 :   mapping.mStructType = NS_EVENT_NULL;
    3313            1016 :   sStringEventTable->Put(aName, mapping);
    3314            1016 :   return mapping.mAtom;
    3315                 : }
    3316                 : 
    3317                 : static
    3318            6401 : nsresult GetEventAndTarget(nsIDocument* aDoc, nsISupports* aTarget,
    3319                 :                            const nsAString& aEventName,
    3320                 :                            bool aCanBubble, bool aCancelable,
    3321                 :                            bool aTrusted, nsIDOMEvent** aEvent,
    3322                 :                            nsIDOMEventTarget** aTargetOut)
    3323                 : {
    3324           12802 :   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
    3325           12802 :   nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(aTarget));
    3326            6401 :   NS_ENSURE_TRUE(domDoc && target, NS_ERROR_INVALID_ARG);
    3327                 : 
    3328           12802 :   nsCOMPtr<nsIDOMEvent> event;
    3329                 :   nsresult rv =
    3330            6401 :     domDoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
    3331            6401 :   NS_ENSURE_SUCCESS(rv, rv);
    3332                 : 
    3333           12802 :   nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
    3334            6401 :   NS_ENSURE_TRUE(privateEvent, NS_ERROR_FAILURE);
    3335                 : 
    3336            6401 :   rv = event->InitEvent(aEventName, aCanBubble, aCancelable);
    3337            6401 :   NS_ENSURE_SUCCESS(rv, rv);
    3338                 : 
    3339            6401 :   rv = privateEvent->SetTrusted(aTrusted);
    3340            6401 :   NS_ENSURE_SUCCESS(rv, rv);
    3341                 : 
    3342            6401 :   rv = privateEvent->SetTarget(target);
    3343            6401 :   NS_ENSURE_SUCCESS(rv, rv);
    3344                 : 
    3345            6401 :   event.forget(aEvent);
    3346            6401 :   target.forget(aTargetOut);
    3347            6401 :   return NS_OK;
    3348                 : }
    3349                 : 
    3350                 : // static
    3351                 : nsresult
    3352            5363 : nsContentUtils::DispatchTrustedEvent(nsIDocument* aDoc, nsISupports* aTarget,
    3353                 :                                      const nsAString& aEventName,
    3354                 :                                      bool aCanBubble, bool aCancelable,
    3355                 :                                      bool *aDefaultAction)
    3356                 : {
    3357                 :   return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
    3358            5363 :                        true, aDefaultAction);
    3359                 : }
    3360                 : 
    3361                 : // static
    3362                 : nsresult
    3363               0 : nsContentUtils::DispatchUntrustedEvent(nsIDocument* aDoc, nsISupports* aTarget,
    3364                 :                                        const nsAString& aEventName,
    3365                 :                                        bool aCanBubble, bool aCancelable,
    3366                 :                                        bool *aDefaultAction)
    3367                 : {
    3368                 :   return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
    3369               0 :                        false, aDefaultAction);
    3370                 : }
    3371                 : 
    3372                 : // static
    3373                 : nsresult
    3374            5363 : nsContentUtils::DispatchEvent(nsIDocument* aDoc, nsISupports* aTarget,
    3375                 :                               const nsAString& aEventName,
    3376                 :                               bool aCanBubble, bool aCancelable,
    3377                 :                               bool aTrusted, bool *aDefaultAction)
    3378                 : {
    3379           10726 :   nsCOMPtr<nsIDOMEvent> event;
    3380           10726 :   nsCOMPtr<nsIDOMEventTarget> target;
    3381                 :   nsresult rv = GetEventAndTarget(aDoc, aTarget, aEventName, aCanBubble,
    3382            5363 :                                   aCancelable, aTrusted, getter_AddRefs(event),
    3383           10726 :                                   getter_AddRefs(target));
    3384            5363 :   NS_ENSURE_SUCCESS(rv, rv);
    3385                 : 
    3386                 :   bool dummy;
    3387            5363 :   return target->DispatchEvent(event, aDefaultAction ? aDefaultAction : &dummy);
    3388                 : }
    3389                 : 
    3390                 : nsresult
    3391            1038 : nsContentUtils::DispatchChromeEvent(nsIDocument *aDoc,
    3392                 :                                     nsISupports *aTarget,
    3393                 :                                     const nsAString& aEventName,
    3394                 :                                     bool aCanBubble, bool aCancelable,
    3395                 :                                     bool *aDefaultAction)
    3396                 : {
    3397                 : 
    3398            2076 :   nsCOMPtr<nsIDOMEvent> event;
    3399            2076 :   nsCOMPtr<nsIDOMEventTarget> target;
    3400                 :   nsresult rv = GetEventAndTarget(aDoc, aTarget, aEventName, aCanBubble,
    3401            1038 :                                   aCancelable, true, getter_AddRefs(event),
    3402            2076 :                                   getter_AddRefs(target));
    3403            1038 :   NS_ENSURE_SUCCESS(rv, rv);
    3404                 : 
    3405            1038 :   NS_ASSERTION(aDoc, "GetEventAndTarget lied?");
    3406            1038 :   if (!aDoc->GetWindow())
    3407            1038 :     return NS_ERROR_INVALID_ARG;
    3408                 : 
    3409               0 :   nsIDOMEventTarget* piTarget = aDoc->GetWindow()->GetChromeEventHandler();
    3410               0 :   if (!piTarget)
    3411               0 :     return NS_ERROR_INVALID_ARG;
    3412                 : 
    3413               0 :   nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(piTarget);
    3414               0 :   if (flo) {
    3415               0 :     nsRefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
    3416               0 :     if (fl) {
    3417               0 :       nsIDOMEventTarget* t = fl->GetTabChildGlobalAsEventTarget();
    3418               0 :       piTarget = t ? t : piTarget;
    3419                 :     }
    3420                 :   }
    3421                 : 
    3422               0 :   nsEventStatus status = nsEventStatus_eIgnore;
    3423               0 :   rv = piTarget->DispatchDOMEvent(nsnull, event, nsnull, &status);
    3424               0 :   if (aDefaultAction) {
    3425               0 :     *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
    3426                 :   }
    3427               0 :   return rv;
    3428                 : }
    3429                 : 
    3430                 : /* static */
    3431                 : Element*
    3432               0 : nsContentUtils::MatchElementId(nsIContent *aContent, const nsIAtom* aId)
    3433                 : {
    3434               0 :   for (nsIContent* cur = aContent;
    3435                 :        cur;
    3436               0 :        cur = cur->GetNextNode(aContent)) {
    3437               0 :     if (aId == cur->GetID()) {
    3438               0 :       return cur->AsElement();
    3439                 :     }
    3440                 :   }
    3441                 : 
    3442               0 :   return nsnull;
    3443                 : }
    3444                 : 
    3445                 : /* static */
    3446                 : Element *
    3447               0 : nsContentUtils::MatchElementId(nsIContent *aContent, const nsAString& aId)
    3448                 : {
    3449               0 :   NS_PRECONDITION(!aId.IsEmpty(), "Will match random elements");
    3450                 :   
    3451                 :   // ID attrs are generally stored as atoms, so just atomize this up front
    3452               0 :   nsCOMPtr<nsIAtom> id(do_GetAtom(aId));
    3453               0 :   if (!id) {
    3454                 :     // OOM, so just bail
    3455               0 :     return nsnull;
    3456                 :   }
    3457                 : 
    3458               0 :   return MatchElementId(aContent, id);
    3459                 : }
    3460                 : 
    3461                 : // Convert the string from the given charset to Unicode.
    3462                 : /* static */
    3463                 : nsresult
    3464               0 : nsContentUtils::ConvertStringFromCharset(const nsACString& aCharset,
    3465                 :                                          const nsACString& aInput,
    3466                 :                                          nsAString& aOutput)
    3467                 : {
    3468               0 :   if (aCharset.IsEmpty()) {
    3469                 :     // Treat the string as UTF8
    3470               0 :     CopyUTF8toUTF16(aInput, aOutput);
    3471               0 :     return NS_OK;
    3472                 :   }
    3473                 : 
    3474                 :   nsresult rv;
    3475                 :   nsCOMPtr<nsICharsetConverterManager> ccm =
    3476               0 :     do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
    3477               0 :   if (NS_FAILED(rv))
    3478               0 :     return rv;
    3479                 : 
    3480               0 :   nsCOMPtr<nsIUnicodeDecoder> decoder;
    3481               0 :   rv = ccm->GetUnicodeDecoder(PromiseFlatCString(aCharset).get(),
    3482               0 :                               getter_AddRefs(decoder));
    3483               0 :   if (NS_FAILED(rv))
    3484               0 :     return rv;
    3485                 : 
    3486               0 :   nsPromiseFlatCString flatInput(aInput);
    3487               0 :   PRInt32 srcLen = flatInput.Length();
    3488                 :   PRInt32 dstLen;
    3489               0 :   rv = decoder->GetMaxLength(flatInput.get(), srcLen, &dstLen);
    3490               0 :   if (NS_FAILED(rv))
    3491               0 :     return rv;
    3492                 : 
    3493                 :   PRUnichar *ustr = (PRUnichar *)nsMemory::Alloc((dstLen + 1) *
    3494               0 :                                                  sizeof(PRUnichar));
    3495               0 :   if (!ustr)
    3496               0 :     return NS_ERROR_OUT_OF_MEMORY;
    3497                 : 
    3498               0 :   rv = decoder->Convert(flatInput.get(), &srcLen, ustr, &dstLen);
    3499               0 :   if (NS_SUCCEEDED(rv)) {
    3500               0 :     ustr[dstLen] = 0;
    3501               0 :     aOutput.Assign(ustr, dstLen);
    3502                 :   }
    3503                 : 
    3504               0 :   nsMemory::Free(ustr);
    3505               0 :   return rv;
    3506                 : }
    3507                 : 
    3508                 : /* static */
    3509                 : bool
    3510             286 : nsContentUtils::CheckForBOM(const unsigned char* aBuffer, PRUint32 aLength,
    3511                 :                             nsACString& aCharset, bool *bigEndian)
    3512                 : {
    3513             286 :   bool found = true;
    3514             286 :   aCharset.Truncate();
    3515             571 :   if (aLength >= 3 &&
    3516             285 :       aBuffer[0] == 0xEF &&
    3517               0 :       aBuffer[1] == 0xBB &&
    3518               0 :       aBuffer[2] == 0xBF) {
    3519               0 :     aCharset = "UTF-8";
    3520                 :   }
    3521             572 :   else if (aLength >= 2 &&
    3522             286 :            aBuffer[0] == 0xFE && aBuffer[1] == 0xFF) {
    3523               0 :     aCharset = "UTF-16";
    3524               0 :     if (bigEndian)
    3525               0 :       *bigEndian = true;
    3526                 :   }
    3527             572 :   else if (aLength >= 2 &&
    3528             286 :            aBuffer[0] == 0xFF && aBuffer[1] == 0xFE) {
    3529               0 :     aCharset = "UTF-16";
    3530               0 :     if (bigEndian)
    3531               0 :       *bigEndian = false;
    3532                 :   } else {
    3533             286 :     found = false;
    3534                 :   }
    3535                 : 
    3536             286 :   return found;
    3537                 : }
    3538                 : 
    3539                 : /* static */
    3540                 : void
    3541               0 : nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver)
    3542                 : {
    3543                 :   nsCOMPtr<nsIObserverService> observerService =
    3544               0 :     mozilla::services::GetObserverService();
    3545               0 :   if (observerService) {
    3546               0 :     observerService->AddObserver(aObserver, 
    3547                 :                                  NS_XPCOM_SHUTDOWN_OBSERVER_ID, 
    3548               0 :                                  false);
    3549                 :   }
    3550               0 : }
    3551                 : 
    3552                 : /* static */
    3553                 : void
    3554               0 : nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver)
    3555                 : {
    3556                 :   nsCOMPtr<nsIObserverService> observerService =
    3557               0 :     mozilla::services::GetObserverService();
    3558               0 :   if (observerService) {
    3559               0 :     observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
    3560                 :   }
    3561               0 : }
    3562                 : 
    3563                 : /* static */
    3564                 : bool
    3565               3 : nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent, PRInt32 aNameSpaceID,
    3566                 :                                 nsIAtom* aName)
    3567                 : {
    3568                 :   static nsIContent::AttrValuesArray strings[] = {&nsGkAtoms::_empty, nsnull};
    3569               3 :   return aContent->FindAttrValueIn(aNameSpaceID, aName, strings, eCaseMatters)
    3570               3 :     == nsIContent::ATTR_VALUE_NO_MATCH;
    3571                 : }
    3572                 : 
    3573                 : /* static */
    3574                 : bool
    3575            3616 : nsContentUtils::HasMutationListeners(nsINode* aNode,
    3576                 :                                      PRUint32 aType,
    3577                 :                                      nsINode* aTargetForSubtreeModified)
    3578                 : {
    3579            3616 :   nsIDocument* doc = aNode->OwnerDoc();
    3580                 : 
    3581                 :   // global object will be null for documents that don't have windows.
    3582            3616 :   nsPIDOMWindow* window = doc->GetInnerWindow();
    3583                 :   // This relies on nsEventListenerManager::AddEventListener, which sets
    3584                 :   // all mutation bits when there is a listener for DOMSubtreeModified event.
    3585            3616 :   if (window && !window->HasMutationListeners(aType)) {
    3586               0 :     return false;
    3587                 :   }
    3588                 : 
    3589            7232 :   if (aNode->IsNodeOfType(nsINode::eCONTENT) &&
    3590            3616 :       static_cast<nsIContent*>(aNode)->IsInNativeAnonymousSubtree()) {
    3591               0 :     return false;
    3592                 :   }
    3593                 : 
    3594            3616 :   doc->MayDispatchMutationEvent(aTargetForSubtreeModified);
    3595                 : 
    3596                 :   // If we have a window, we can check it for mutation listeners now.
    3597            3616 :   if (aNode->IsInDoc()) {
    3598            3158 :     nsCOMPtr<nsIDOMEventTarget> piTarget(do_QueryInterface(window));
    3599            1579 :     if (piTarget) {
    3600               0 :       nsEventListenerManager* manager = piTarget->GetListenerManager(false);
    3601               0 :       if (manager && manager->HasMutationListeners()) {
    3602               0 :         return true;
    3603                 :       }
    3604                 :     }
    3605                 :   }
    3606                 : 
    3607                 :   // If we have a window, we know a mutation listener is registered, but it
    3608                 :   // might not be in our chain.  If we don't have a window, we might have a
    3609                 :   // mutation listener.  Check quickly to see.
    3610           13414 :   while (aNode) {
    3611            6184 :     nsEventListenerManager* manager = aNode->GetListenerManager(false);
    3612            6184 :     if (manager && manager->HasMutationListeners()) {
    3613               2 :       return true;
    3614                 :     }
    3615                 : 
    3616            6182 :     if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
    3617            4605 :       nsIContent* content = static_cast<nsIContent*>(aNode);
    3618                 :       nsIContent* insertionParent =
    3619            4605 :         doc->BindingManager()->GetInsertionParent(content);
    3620            4605 :       if (insertionParent) {
    3621               0 :         aNode = insertionParent;
    3622               0 :         continue;
    3623                 :       }
    3624                 :     }
    3625            6182 :     aNode = aNode->GetNodeParent();
    3626                 :   }
    3627                 : 
    3628            3614 :   return false;
    3629                 : }
    3630                 : 
    3631                 : /* static */
    3632                 : bool
    3633              15 : nsContentUtils::HasMutationListeners(nsIDocument* aDocument,
    3634                 :                                      PRUint32 aType)
    3635                 : {
    3636                 :   nsPIDOMWindow* window = aDocument ?
    3637              15 :     aDocument->GetInnerWindow() : nsnull;
    3638                 : 
    3639                 :   // This relies on nsEventListenerManager::AddEventListener, which sets
    3640                 :   // all mutation bits when there is a listener for DOMSubtreeModified event.
    3641              15 :   return !window || window->HasMutationListeners(aType);
    3642                 : }
    3643                 : 
    3644                 : void
    3645             239 : nsContentUtils::MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent,
    3646                 :                                      nsIDocument* aOwnerDoc)
    3647                 : {
    3648             239 :   NS_PRECONDITION(aChild, "Missing child");
    3649             239 :   NS_PRECONDITION(aChild->GetNodeParent() == aParent, "Wrong parent");
    3650             239 :   NS_PRECONDITION(aChild->OwnerDoc() == aOwnerDoc, "Wrong owner-doc");
    3651                 : 
    3652                 :   // This checks that IsSafeToRunScript is true since we don't want to fire
    3653                 :   // events when that is false. We can't rely on nsEventDispatcher to assert
    3654                 :   // this in this situation since most of the time there are no mutation
    3655                 :   // event listeners, in which case we won't even attempt to dispatch events.
    3656                 :   // However this also allows for two exceptions. First off, we don't assert
    3657                 :   // if the mutation happens to native anonymous content since we never fire
    3658                 :   // mutation events on such content anyway.
    3659                 :   // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
    3660                 :   // that is a know case when we'd normally fire a mutation event, but can't
    3661                 :   // make that safe and so we suppress it at this time. Ideally this should
    3662                 :   // go away eventually.
    3663             239 :   NS_ASSERTION(aChild->IsNodeOfType(nsINode::eCONTENT) &&
    3664                 :                static_cast<nsIContent*>(aChild)->
    3665                 :                  IsInNativeAnonymousSubtree() ||
    3666                 :                IsSafeToRunScript() ||
    3667                 :                sDOMNodeRemovedSuppressCount,
    3668                 :                "Want to fire DOMNodeRemoved event, but it's not safe");
    3669                 : 
    3670                 :   // Having an explicit check here since it's an easy mistake to fall into,
    3671                 :   // and there might be existing code with problems. We'd rather be safe
    3672                 :   // than fire DOMNodeRemoved in all corner cases. We also rely on it for
    3673                 :   // nsAutoScriptBlockerSuppressNodeRemoved.
    3674             239 :   if (!IsSafeToRunScript()) {
    3675               0 :     return;
    3676                 :   }
    3677                 : 
    3678             239 :   if (HasMutationListeners(aChild,
    3679                 :         NS_EVENT_BITS_MUTATION_NODEREMOVED, aParent)) {
    3680               0 :     nsMutationEvent mutation(true, NS_MUTATION_NODEREMOVED);
    3681               0 :     mutation.mRelatedNode = do_QueryInterface(aParent);
    3682                 : 
    3683               0 :     mozAutoSubtreeModified subtree(aOwnerDoc, aParent);
    3684               0 :     nsEventDispatcher::Dispatch(aChild, nsnull, &mutation);
    3685                 :   }
    3686                 : }
    3687                 : 
    3688                 : PLDHashOperator
    3689               0 : ListenerEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aEntry,
    3690                 :                    PRUint32 aNumber, void* aArg)
    3691                 : {
    3692                 :   EventListenerManagerMapEntry* entry =
    3693               0 :     static_cast<EventListenerManagerMapEntry*>(aEntry);
    3694               0 :   if (entry) {
    3695               0 :     nsINode* n = static_cast<nsINode*>(entry->mListenerManager->GetTarget());
    3696               0 :     if (n && n->IsInDoc() &&
    3697               0 :         nsCCUncollectableMarker::InGeneration(n->OwnerDoc()->GetMarkedCCGeneration())) {
    3698               0 :       entry->mListenerManager->UnmarkGrayJSListeners();
    3699                 :     }
    3700                 :   }
    3701               0 :   return PL_DHASH_NEXT;
    3702                 : }
    3703                 : 
    3704                 : void
    3705               0 : nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(PRUint32 aGeneration)
    3706                 : {
    3707               0 :   if (sEventListenerManagersHash.ops) {
    3708                 :     PL_DHashTableEnumerate(&sEventListenerManagersHash, ListenerEnumerator,
    3709               0 :                            &aGeneration);
    3710                 :   }
    3711               0 : }
    3712                 : 
    3713                 : /* static */
    3714                 : void
    3715               3 : nsContentUtils::TraverseListenerManager(nsINode *aNode,
    3716                 :                                         nsCycleCollectionTraversalCallback &cb)
    3717                 : {
    3718               3 :   if (!sEventListenerManagersHash.ops) {
    3719                 :     // We're already shut down, just return.
    3720               0 :     return;
    3721                 :   }
    3722                 : 
    3723                 :   EventListenerManagerMapEntry *entry =
    3724                 :     static_cast<EventListenerManagerMapEntry *>
    3725                 :                (PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
    3726               3 :                                         PL_DHASH_LOOKUP));
    3727               3 :   if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
    3728               3 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(entry->mListenerManager,
    3729                 :                                                  nsEventListenerManager,
    3730                 :                                   "[via hash] mListenerManager")
    3731                 :   }
    3732                 : }
    3733                 : 
    3734                 : nsEventListenerManager*
    3735           27262 : nsContentUtils::GetListenerManager(nsINode *aNode,
    3736                 :                                    bool aCreateIfNotFound)
    3737                 : {
    3738           27262 :   if (!aCreateIfNotFound && !aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
    3739           27254 :     return nsnull;
    3740                 :   }
    3741                 :   
    3742               8 :   if (!sEventListenerManagersHash.ops) {
    3743                 :     // We're already shut down, don't bother creating an event listener
    3744                 :     // manager.
    3745                 : 
    3746               0 :     return nsnull;
    3747                 :   }
    3748                 : 
    3749               8 :   if (!aCreateIfNotFound) {
    3750                 :     EventListenerManagerMapEntry *entry =
    3751                 :       static_cast<EventListenerManagerMapEntry *>
    3752                 :                  (PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
    3753               6 :                                           PL_DHASH_LOOKUP));
    3754               6 :     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
    3755               6 :       return entry->mListenerManager;
    3756                 :     }
    3757               0 :     return nsnull;
    3758                 :   }
    3759                 : 
    3760                 :   EventListenerManagerMapEntry *entry =
    3761                 :     static_cast<EventListenerManagerMapEntry *>
    3762                 :                (PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
    3763               2 :                                         PL_DHASH_ADD));
    3764                 : 
    3765               2 :   if (!entry) {
    3766               0 :     return nsnull;
    3767                 :   }
    3768                 : 
    3769               2 :   if (!entry->mListenerManager) {
    3770               2 :     entry->mListenerManager = new nsEventListenerManager(aNode);
    3771                 : 
    3772               2 :     aNode->SetFlags(NODE_HAS_LISTENERMANAGER);
    3773                 :   }
    3774                 : 
    3775               2 :   return entry->mListenerManager;
    3776                 : }
    3777                 : 
    3778                 : /* static */
    3779                 : void
    3780               0 : nsContentUtils::RemoveListenerManager(nsINode *aNode)
    3781                 : {
    3782               0 :   if (sEventListenerManagersHash.ops) {
    3783                 :     EventListenerManagerMapEntry *entry =
    3784                 :       static_cast<EventListenerManagerMapEntry *>
    3785                 :                  (PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
    3786               0 :                                           PL_DHASH_LOOKUP));
    3787               0 :     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
    3788               0 :       nsRefPtr<nsEventListenerManager> listenerManager;
    3789               0 :       listenerManager.swap(entry->mListenerManager);
    3790                 :       // Remove the entry and *then* do operations that could cause further
    3791                 :       // modification of sEventListenerManagersHash.  See bug 334177.
    3792               0 :       PL_DHashTableRawRemove(&sEventListenerManagersHash, entry);
    3793               0 :       if (listenerManager) {
    3794               0 :         listenerManager->Disconnect();
    3795                 :       }
    3796                 :     }
    3797                 :   }
    3798               0 : }
    3799                 : 
    3800                 : /* static */
    3801                 : bool
    3802             193 : nsContentUtils::IsValidNodeName(nsIAtom *aLocalName, nsIAtom *aPrefix,
    3803                 :                                 PRInt32 aNamespaceID)
    3804                 : {
    3805             193 :   if (aNamespaceID == kNameSpaceID_Unknown) {
    3806               0 :     return false;
    3807                 :   }
    3808                 : 
    3809             193 :   if (!aPrefix) {
    3810                 :     // If the prefix is null, then either the QName must be xmlns or the
    3811                 :     // namespace must not be XMLNS.
    3812                 :     return (aLocalName == nsGkAtoms::xmlns) ==
    3813             178 :            (aNamespaceID == kNameSpaceID_XMLNS);
    3814                 :   }
    3815                 : 
    3816                 :   // If the prefix is non-null then the namespace must not be null.
    3817              15 :   if (aNamespaceID == kNameSpaceID_None) {
    3818               0 :     return false;
    3819                 :   }
    3820                 : 
    3821                 :   // If the namespace is the XMLNS namespace then the prefix must be xmlns,
    3822                 :   // but the localname must not be xmlns.
    3823              15 :   if (aNamespaceID == kNameSpaceID_XMLNS) {
    3824               0 :     return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns;
    3825                 :   }
    3826                 : 
    3827                 :   // If the namespace is not the XMLNS namespace then the prefix must not be
    3828                 :   // xmlns.
    3829                 :   // If the namespace is the XML namespace then the prefix can be anything.
    3830                 :   // If the namespace is not the XML namespace then the prefix must not be xml.
    3831                 :   return aPrefix != nsGkAtoms::xmlns &&
    3832              15 :          (aNamespaceID == kNameSpaceID_XML || aPrefix != nsGkAtoms::xml);
    3833                 : }
    3834                 : 
    3835                 : /* static */
    3836                 : nsresult
    3837               0 : nsContentUtils::CreateContextualFragment(nsINode* aContextNode,
    3838                 :                                          const nsAString& aFragment,
    3839                 :                                          bool aPreventScriptExecution,
    3840                 :                                          nsIDOMDocumentFragment** aReturn)
    3841                 : {
    3842               0 :   *aReturn = nsnull;
    3843               0 :   NS_ENSURE_ARG(aContextNode);
    3844                 : 
    3845                 :   // If we don't have a document here, we can't get the right security context
    3846                 :   // for compiling event handlers... so just bail out.
    3847               0 :   nsCOMPtr<nsIDocument> document = aContextNode->OwnerDoc();
    3848               0 :   bool isHTML = document->IsHTML();
    3849                 : #ifdef DEBUG
    3850               0 :   nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(document);
    3851               0 :   NS_ASSERTION(!isHTML || htmlDoc, "Should have HTMLDocument here!");
    3852                 : #endif
    3853                 : 
    3854               0 :   if (isHTML) {
    3855               0 :     nsCOMPtr<nsIDOMDocumentFragment> frag;
    3856               0 :     NS_NewDocumentFragment(getter_AddRefs(frag), document->NodeInfoManager());
    3857                 :     
    3858               0 :     nsCOMPtr<nsIContent> contextAsContent = do_QueryInterface(aContextNode);
    3859               0 :     if (contextAsContent && !contextAsContent->IsElement()) {
    3860               0 :       contextAsContent = contextAsContent->GetParent();
    3861               0 :       if (contextAsContent && !contextAsContent->IsElement()) {
    3862                 :         // can this even happen?
    3863               0 :         contextAsContent = nsnull;
    3864                 :       }
    3865                 :     }
    3866                 :     
    3867                 :     nsresult rv;
    3868               0 :     nsCOMPtr<nsIContent> fragment = do_QueryInterface(frag);
    3869               0 :     if (contextAsContent && !contextAsContent->IsHTML(nsGkAtoms::html)) {
    3870                 :       rv = ParseFragmentHTML(aFragment,
    3871                 :                              fragment,
    3872                 :                              contextAsContent->Tag(),
    3873                 :                              contextAsContent->GetNameSpaceID(),
    3874               0 :                              (document->GetCompatibilityMode() ==
    3875                 :                                eCompatibility_NavQuirks),
    3876               0 :                              aPreventScriptExecution);
    3877                 :     } else {
    3878                 :       rv = ParseFragmentHTML(aFragment,
    3879                 :                              fragment,
    3880                 :                              nsGkAtoms::body,
    3881                 :                              kNameSpaceID_XHTML,
    3882               0 :                              (document->GetCompatibilityMode() ==
    3883                 :                                eCompatibility_NavQuirks),
    3884               0 :                              aPreventScriptExecution);
    3885                 :     }
    3886                 : 
    3887               0 :     frag.forget(aReturn);
    3888               0 :     return rv;
    3889                 :   }
    3890                 : 
    3891               0 :   nsAutoTArray<nsString, 32> tagStack;
    3892               0 :   nsAutoString uriStr, nameStr;
    3893               0 :   nsCOMPtr<nsIContent> content = do_QueryInterface(aContextNode);
    3894                 :   // just in case we have a text node
    3895               0 :   if (content && !content->IsElement())
    3896               0 :     content = content->GetParent();
    3897                 : 
    3898               0 :   while (content && content->IsElement()) {
    3899               0 :     nsString& tagName = *tagStack.AppendElement();
    3900               0 :     NS_ENSURE_TRUE(&tagName, NS_ERROR_OUT_OF_MEMORY);
    3901                 : 
    3902               0 :     tagName = content->NodeInfo()->QualifiedName();
    3903                 : 
    3904                 :     // see if we need to add xmlns declarations
    3905               0 :     PRUint32 count = content->GetAttrCount();
    3906               0 :     bool setDefaultNamespace = false;
    3907               0 :     if (count > 0) {
    3908                 :       PRUint32 index;
    3909                 : 
    3910               0 :       for (index = 0; index < count; index++) {
    3911               0 :         const nsAttrName* name = content->GetAttrNameAt(index);
    3912               0 :         if (name->NamespaceEquals(kNameSpaceID_XMLNS)) {
    3913               0 :           content->GetAttr(kNameSpaceID_XMLNS, name->LocalName(), uriStr);
    3914                 : 
    3915                 :           // really want something like nsXMLContentSerializer::SerializeAttr
    3916               0 :           tagName.Append(NS_LITERAL_STRING(" xmlns")); // space important
    3917               0 :           if (name->GetPrefix()) {
    3918               0 :             tagName.Append(PRUnichar(':'));
    3919               0 :             name->LocalName()->ToString(nameStr);
    3920               0 :             tagName.Append(nameStr);
    3921                 :           } else {
    3922               0 :             setDefaultNamespace = true;
    3923                 :           }
    3924               0 :           tagName.Append(NS_LITERAL_STRING("=\"") + uriStr +
    3925               0 :             NS_LITERAL_STRING("\""));
    3926                 :         }
    3927                 :       }
    3928                 :     }
    3929                 : 
    3930               0 :     if (!setDefaultNamespace) {
    3931               0 :       nsINodeInfo* info = content->NodeInfo();
    3932               0 :       if (!info->GetPrefixAtom() &&
    3933               0 :           info->NamespaceID() != kNameSpaceID_None) {
    3934                 :         // We have no namespace prefix, but have a namespace ID.  Push
    3935                 :         // default namespace attr in, so that our kids will be in our
    3936                 :         // namespace.
    3937               0 :         info->GetNamespaceURI(uriStr);
    3938               0 :         tagName.Append(NS_LITERAL_STRING(" xmlns=\"") + uriStr +
    3939               0 :                        NS_LITERAL_STRING("\""));
    3940                 :       }
    3941                 :     }
    3942                 : 
    3943               0 :     content = content->GetParent();
    3944                 :   }
    3945                 : 
    3946                 :   return ParseFragmentXML(aFragment,
    3947                 :                           document,
    3948                 :                           tagStack,
    3949                 :                           aPreventScriptExecution,
    3950               0 :                           aReturn);
    3951                 : }
    3952                 : 
    3953                 : /* static */
    3954                 : void
    3955            1404 : nsContentUtils::DropFragmentParsers()
    3956                 : {
    3957            1404 :   NS_IF_RELEASE(sHTMLFragmentParser);
    3958            1404 :   NS_IF_RELEASE(sXMLFragmentParser);
    3959            1404 :   NS_IF_RELEASE(sXMLFragmentSink);
    3960            1404 : }
    3961                 : 
    3962                 : /* static */
    3963                 : void
    3964            1404 : nsContentUtils::XPCOMShutdown()
    3965                 : {
    3966            1404 :   nsContentUtils::DropFragmentParsers();
    3967            1404 : }
    3968                 : 
    3969                 : /* static */
    3970                 : nsresult
    3971               0 : nsContentUtils::ParseFragmentHTML(const nsAString& aSourceBuffer,
    3972                 :                                   nsIContent* aTargetNode,
    3973                 :                                   nsIAtom* aContextLocalName,
    3974                 :                                   PRInt32 aContextNamespace,
    3975                 :                                   bool aQuirks,
    3976                 :                                   bool aPreventScriptExecution)
    3977                 : {
    3978               0 :   if (nsContentUtils::sFragmentParsingActive) {
    3979               0 :     NS_NOTREACHED("Re-entrant fragment parsing attempted.");
    3980               0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
    3981                 :   }
    3982               0 :   mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
    3983               0 :   nsContentUtils::sFragmentParsingActive = true;
    3984               0 :   if (!sHTMLFragmentParser) {
    3985               0 :     NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser());
    3986                 :     // Now sHTMLFragmentParser owns the object
    3987                 :   }
    3988                 :   nsresult rv =
    3989                 :     sHTMLFragmentParser->ParseFragment(aSourceBuffer,
    3990                 :                                        aTargetNode,
    3991                 :                                        aContextLocalName,
    3992                 :                                        aContextNamespace,
    3993                 :                                        aQuirks,
    3994               0 :                                        aPreventScriptExecution);
    3995               0 :   return rv;
    3996                 : }
    3997                 : 
    3998                 : /* static */
    3999                 : nsresult
    4000             234 : nsContentUtils::ParseDocumentHTML(const nsAString& aSourceBuffer,
    4001                 :                                   nsIDocument* aTargetDocument,
    4002                 :                                   bool aScriptingEnabledForNoscriptParsing)
    4003                 : {
    4004             234 :   if (nsContentUtils::sFragmentParsingActive) {
    4005               0 :     NS_NOTREACHED("Re-entrant fragment parsing attempted.");
    4006               0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
    4007                 :   }
    4008             468 :   mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
    4009             234 :   nsContentUtils::sFragmentParsingActive = true;
    4010             234 :   if (!sHTMLFragmentParser) {
    4011              12 :     NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser());
    4012                 :     // Now sHTMLFragmentParser owns the object
    4013                 :   }
    4014                 :   nsresult rv =
    4015                 :     sHTMLFragmentParser->ParseDocument(aSourceBuffer,
    4016                 :                                        aTargetDocument,
    4017             234 :                                        aScriptingEnabledForNoscriptParsing);
    4018             234 :   return rv;
    4019                 : }
    4020                 : 
    4021                 : /* static */
    4022                 : nsresult
    4023               1 : nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
    4024                 :                                  nsIDocument* aDocument,
    4025                 :                                  nsTArray<nsString>& aTagStack,
    4026                 :                                  bool aPreventScriptExecution,
    4027                 :                                  nsIDOMDocumentFragment** aReturn)
    4028                 : {
    4029               1 :   if (nsContentUtils::sFragmentParsingActive) {
    4030               0 :     NS_NOTREACHED("Re-entrant fragment parsing attempted.");
    4031               0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
    4032                 :   }
    4033               2 :   mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
    4034               1 :   nsContentUtils::sFragmentParsingActive = true;
    4035               1 :   if (!sXMLFragmentParser) {
    4036               2 :     nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID);
    4037               1 :     parser.forget(&sXMLFragmentParser);
    4038                 :     // sXMLFragmentParser now owns the parser
    4039                 :   }
    4040               1 :   if (!sXMLFragmentSink) {
    4041               1 :     NS_NewXMLFragmentContentSink(&sXMLFragmentSink);
    4042                 :     // sXMLFragmentSink now owns the sink
    4043                 :   }
    4044               2 :   nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink);
    4045               1 :   NS_ABORT_IF_FALSE(contentsink, "Sink doesn't QI to nsIContentSink!");
    4046               1 :   sXMLFragmentParser->SetContentSink(contentsink);
    4047                 : 
    4048               1 :   sXMLFragmentSink->SetTargetDocument(aDocument);
    4049               1 :   sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution);
    4050                 : 
    4051                 :   nsresult rv =
    4052                 :     sXMLFragmentParser->ParseFragment(aSourceBuffer,
    4053               1 :                                       aTagStack);
    4054               1 :   if (NS_FAILED(rv)) {
    4055                 :     // Drop the fragment parser and sink that might be in an inconsistent state
    4056               0 :     NS_IF_RELEASE(sXMLFragmentParser);
    4057               0 :     NS_IF_RELEASE(sXMLFragmentSink);
    4058               0 :     return rv;
    4059                 :   }
    4060                 : 
    4061               1 :   rv = sXMLFragmentSink->FinishFragmentParsing(aReturn);
    4062                 : 
    4063               1 :   sXMLFragmentParser->Reset();
    4064                 : 
    4065               1 :   return rv;
    4066                 : }
    4067                 : 
    4068                 : /* static */
    4069                 : nsresult
    4070             234 : nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
    4071                 :                                    nsAString& aResultBuffer,
    4072                 :                                    PRUint32 aFlags,
    4073                 :                                    PRUint32 aWrapCol)
    4074                 : {
    4075             468 :   nsCOMPtr<nsIURI> uri;
    4076             234 :   NS_NewURI(getter_AddRefs(uri), "about:blank");
    4077                 :   nsCOMPtr<nsIPrincipal> principal =
    4078             468 :     do_CreateInstance("@mozilla.org/nullprincipal;1");
    4079             468 :   nsCOMPtr<nsIDOMDocument> domDocument;
    4080             234 :   nsresult rv = nsContentUtils::CreateDocument(EmptyString(),
    4081             234 :                                                EmptyString(),
    4082                 :                                                nsnull,
    4083                 :                                                uri,
    4084                 :                                                uri,
    4085                 :                                                principal,
    4086                 :                                                nsnull,
    4087                 :                                                DocumentFlavorHTML,
    4088             702 :                                                getter_AddRefs(domDocument));
    4089             234 :   NS_ENSURE_SUCCESS(rv, rv);
    4090                 : 
    4091             468 :   nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
    4092                 :   rv = nsContentUtils::ParseDocumentHTML(aSourceBuffer, document,
    4093             234 :     !(aFlags & nsIDocumentEncoder::OutputNoScriptContent));
    4094             234 :   NS_ENSURE_SUCCESS(rv, rv);
    4095                 : 
    4096                 :   nsCOMPtr<nsIDocumentEncoder> encoder = do_CreateInstance(
    4097             468 :     "@mozilla.org/layout/documentEncoder;1?type=text/plain");
    4098                 : 
    4099             234 :   rv = encoder->Init(domDocument, NS_LITERAL_STRING("text/plain"), aFlags);
    4100             234 :   NS_ENSURE_SUCCESS(rv, rv);
    4101                 : 
    4102             234 :   encoder->SetWrapColumn(aWrapCol);
    4103                 : 
    4104             234 :   return encoder->EncodeToString(aResultBuffer);
    4105                 : }
    4106                 : 
    4107                 : /* static */
    4108                 : nsresult
    4109            1273 : nsContentUtils::CreateDocument(const nsAString& aNamespaceURI, 
    4110                 :                                const nsAString& aQualifiedName, 
    4111                 :                                nsIDOMDocumentType* aDoctype,
    4112                 :                                nsIURI* aDocumentURI, nsIURI* aBaseURI,
    4113                 :                                nsIPrincipal* aPrincipal,
    4114                 :                                nsIScriptGlobalObject* aEventObject,
    4115                 :                                DocumentFlavor aFlavor,
    4116                 :                                nsIDOMDocument** aResult)
    4117                 : {
    4118                 :   nsresult rv = NS_NewDOMDocument(aResult, aNamespaceURI, aQualifiedName,
    4119                 :                                   aDoctype, aDocumentURI, aBaseURI, aPrincipal,
    4120            1273 :                                   true, aEventObject, aFlavor);
    4121            1273 :   NS_ENSURE_SUCCESS(rv, rv);
    4122                 : 
    4123            2546 :   nsCOMPtr<nsIDocument> document = do_QueryInterface(*aResult);
    4124                 :   
    4125                 :   // created documents are immediately "complete" (ready to use)
    4126            1273 :   document->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
    4127            1273 :   return NS_OK;
    4128                 : }
    4129                 : 
    4130                 : /* static */
    4131                 : nsresult
    4132               1 : nsContentUtils::SetNodeTextContent(nsIContent* aContent,
    4133                 :                                    const nsAString& aValue,
    4134                 :                                    bool aTryReuse)
    4135                 : {
    4136                 :   // Fire DOMNodeRemoved mutation events before we do anything else.
    4137               2 :   nsCOMPtr<nsIContent> owningContent;
    4138                 : 
    4139                 :   // Batch possible DOMSubtreeModified events.
    4140               2 :   mozAutoSubtreeModified subtree(nsnull, nsnull);
    4141                 : 
    4142                 :   // Scope firing mutation events so that we don't carry any state that
    4143                 :   // might be stale
    4144                 :   {
    4145                 :     // We're relying on mozAutoSubtreeModified to keep a strong reference if
    4146                 :     // needed.
    4147               1 :     nsIDocument* doc = aContent->OwnerDoc();
    4148                 : 
    4149                 :     // Optimize the common case of there being no observers
    4150               1 :     if (HasMutationListeners(doc, NS_EVENT_BITS_MUTATION_NODEREMOVED)) {
    4151               1 :       subtree.UpdateTarget(doc, nsnull);
    4152               1 :       owningContent = aContent;
    4153               2 :       nsCOMPtr<nsINode> child;
    4154               1 :       bool skipFirst = aTryReuse;
    4155               2 :       for (child = aContent->GetFirstChild();
    4156               1 :            child && child->GetNodeParent() == aContent;
    4157               0 :            child = child->GetNextSibling()) {
    4158               0 :         if (skipFirst && child->IsNodeOfType(nsINode::eTEXT)) {
    4159               0 :           skipFirst = false;
    4160               0 :           continue;
    4161                 :         }
    4162               0 :         nsContentUtils::MaybeFireNodeRemoved(child, aContent, doc);
    4163                 :       }
    4164                 :     }
    4165                 :   }
    4166                 : 
    4167                 :   // Might as well stick a batch around this since we're performing several
    4168                 :   // mutations.
    4169                 :   mozAutoDocUpdate updateBatch(aContent->GetCurrentDoc(),
    4170               2 :     UPDATE_CONTENT_MODEL, true);
    4171                 : 
    4172               1 :   PRUint32 childCount = aContent->GetChildCount();
    4173                 : 
    4174               1 :   if (aTryReuse && !aValue.IsEmpty()) {
    4175               0 :     PRUint32 removeIndex = 0;
    4176                 : 
    4177               0 :     for (PRUint32 i = 0; i < childCount; ++i) {
    4178               0 :       nsIContent* child = aContent->GetChildAt(removeIndex);
    4179               0 :       if (removeIndex == 0 && child && child->IsNodeOfType(nsINode::eTEXT)) {
    4180               0 :         nsresult rv = child->SetText(aValue, true);
    4181               0 :         NS_ENSURE_SUCCESS(rv, rv);
    4182                 : 
    4183               0 :         removeIndex = 1;
    4184                 :       }
    4185                 :       else {
    4186               0 :         aContent->RemoveChildAt(removeIndex, true);
    4187                 :       }
    4188                 :     }
    4189                 : 
    4190               0 :     if (removeIndex == 1) {
    4191               0 :       return NS_OK;
    4192                 :     }
    4193                 :   }
    4194                 :   else {
    4195               1 :     for (PRUint32 i = 0; i < childCount; ++i) {
    4196               0 :       aContent->RemoveChildAt(0, true);
    4197                 :     }
    4198                 :   }
    4199                 : 
    4200               1 :   if (aValue.IsEmpty()) {
    4201               0 :     return NS_OK;
    4202                 :   }
    4203                 : 
    4204               2 :   nsCOMPtr<nsIContent> textContent;
    4205               1 :   nsresult rv = NS_NewTextNode(getter_AddRefs(textContent),
    4206               1 :                                aContent->NodeInfo()->NodeInfoManager());
    4207               1 :   NS_ENSURE_SUCCESS(rv, rv);
    4208                 : 
    4209               1 :   textContent->SetText(aValue, true);
    4210                 : 
    4211               1 :   return aContent->AppendChildTo(textContent, true);
    4212                 : }
    4213                 : 
    4214            3875 : static void AppendNodeTextContentsRecurse(nsINode* aNode, nsAString& aResult)
    4215                 : {
    4216            7737 :   for (nsIContent* child = aNode->GetFirstChild();
    4217                 :        child;
    4218            3862 :        child = child->GetNextSibling()) {
    4219            3862 :     if (child->IsElement()) {
    4220               0 :       AppendNodeTextContentsRecurse(child, aResult);
    4221                 :     }
    4222            3862 :     else if (child->IsNodeOfType(nsINode::eTEXT)) {
    4223            3862 :       child->AppendTextTo(aResult);
    4224                 :     }
    4225                 :   }
    4226            3875 : }
    4227                 : 
    4228                 : /* static */
    4229                 : void
    4230            3875 : nsContentUtils::AppendNodeTextContent(nsINode* aNode, bool aDeep,
    4231                 :                                       nsAString& aResult)
    4232                 : {
    4233            3875 :   if (aNode->IsNodeOfType(nsINode::eTEXT)) {
    4234               0 :     static_cast<nsIContent*>(aNode)->AppendTextTo(aResult);
    4235                 :   }
    4236            3875 :   else if (aDeep) {
    4237            3875 :     AppendNodeTextContentsRecurse(aNode, aResult);
    4238                 :   }
    4239                 :   else {
    4240               0 :     for (nsIContent* child = aNode->GetFirstChild();
    4241                 :          child;
    4242               0 :          child = child->GetNextSibling()) {
    4243               0 :       if (child->IsNodeOfType(nsINode::eTEXT)) {
    4244               0 :         child->AppendTextTo(aResult);
    4245                 :       }
    4246                 :     }
    4247                 :   }
    4248            3875 : }
    4249                 : 
    4250                 : bool
    4251               0 : nsContentUtils::HasNonEmptyTextContent(nsINode* aNode)
    4252                 : {
    4253               0 :   for (nsIContent* child = aNode->GetFirstChild();
    4254                 :        child;
    4255               0 :        child = child->GetNextSibling()) {
    4256               0 :     if (child->IsNodeOfType(nsINode::eTEXT) &&
    4257               0 :         child->TextLength() > 0) {
    4258               0 :       return true;
    4259                 :     }
    4260                 :   }
    4261                 : 
    4262               0 :   return false;
    4263                 : }
    4264                 : 
    4265                 : /* static */
    4266                 : bool
    4267              52 : nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode,
    4268                 :                                       const nsIContent* aContent)
    4269                 : {
    4270              52 :   NS_PRECONDITION(aNode,
    4271                 :                   "Must have a node to work with");
    4272              52 :   NS_PRECONDITION(aContent,
    4273                 :                   "Must have a content to work with");
    4274                 :   
    4275              52 :   if (!aNode->IsNodeOfType(nsINode::eCONTENT)) {
    4276                 :     /**
    4277                 :      * The root isn't an nsIContent, so it's a document or attribute.  The only
    4278                 :      * nodes in the same anonymous subtree as it will have a null
    4279                 :      * bindingParent.
    4280                 :      *
    4281                 :      * XXXbz strictly speaking, that's not true for attribute nodes.
    4282                 :      */
    4283              48 :     return aContent->GetBindingParent() == nsnull;
    4284                 :   }
    4285                 : 
    4286               4 :   return static_cast<const nsIContent*>(aNode)->GetBindingParent() ==
    4287               4 :          aContent->GetBindingParent();
    4288                 :  
    4289                 : }
    4290                 : 
    4291               0 : class AnonymousContentDestroyer : public nsRunnable {
    4292                 : public:
    4293               0 :   AnonymousContentDestroyer(nsCOMPtr<nsIContent>* aContent) {
    4294               0 :     mContent.swap(*aContent);
    4295               0 :     mParent = mContent->GetParent();
    4296               0 :     mDoc = mContent->OwnerDoc();
    4297               0 :   }
    4298               0 :   NS_IMETHOD Run() {
    4299               0 :     mContent->UnbindFromTree();
    4300               0 :     return NS_OK;
    4301                 :   }
    4302                 : private:
    4303                 :   nsCOMPtr<nsIContent> mContent;
    4304                 :   // Hold strong refs to the parent content and document so that they
    4305                 :   // don't die unexpectedly
    4306                 :   nsCOMPtr<nsIDocument> mDoc;
    4307                 :   nsCOMPtr<nsIContent> mParent;
    4308                 : };
    4309                 : 
    4310                 : /* static */
    4311                 : void
    4312               0 : nsContentUtils::DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent)
    4313                 : {
    4314               0 :   if (*aContent) {
    4315               0 :     AddScriptRunner(new AnonymousContentDestroyer(aContent));
    4316                 :   }
    4317               0 : }
    4318                 : 
    4319                 : /* static */
    4320                 : nsIDOMScriptObjectFactory*
    4321               0 : nsContentUtils::GetDOMScriptObjectFactory()
    4322                 : {
    4323               0 :   if (!sDOMScriptObjectFactory) {
    4324                 :     static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
    4325                 :                          NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
    4326                 : 
    4327               0 :     CallGetService(kDOMScriptObjectFactoryCID, &sDOMScriptObjectFactory);
    4328                 :   }
    4329                 : 
    4330               0 :   return sDOMScriptObjectFactory;
    4331                 : }
    4332                 : 
    4333                 : /* static */
    4334                 : nsresult
    4335               0 : nsContentUtils::HoldScriptObject(PRUint32 aLangID, void *aObject)
    4336                 : {
    4337               0 :   NS_ASSERTION(aObject, "unexpected null object");
    4338               0 :   NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
    4339                 :                "Should use HoldJSObjects.");
    4340                 :   nsresult rv;
    4341                 : 
    4342               0 :   PRUint32 langIndex = NS_STID_INDEX(aLangID);
    4343               0 :   nsIScriptRuntime *runtime = sScriptRuntimes[langIndex];
    4344               0 :   if (!runtime) {
    4345               0 :     nsIDOMScriptObjectFactory *factory = GetDOMScriptObjectFactory();
    4346               0 :     NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE);
    4347                 : 
    4348               0 :     rv = factory->GetScriptRuntimeByID(aLangID, &runtime);
    4349               0 :     NS_ENSURE_SUCCESS(rv, rv);
    4350                 : 
    4351                 :     // This makes sScriptRuntimes hold a strong ref.
    4352               0 :     sScriptRuntimes[langIndex] = runtime;
    4353                 :   }
    4354                 : 
    4355               0 :   rv = runtime->HoldScriptObject(aObject);
    4356               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4357                 : 
    4358               0 :   ++sScriptRootCount[langIndex];
    4359               0 :   NS_LOG_ADDREF(sScriptRuntimes[langIndex], sScriptRootCount[langIndex],
    4360               0 :                 "HoldScriptObject", sizeof(void*));
    4361                 : 
    4362               0 :   return NS_OK;
    4363                 : }
    4364                 : 
    4365                 : /* static */
    4366                 : void
    4367               0 : nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject,
    4368                 :                                  void *aClosure)
    4369                 : {
    4370               0 :   NS_ASSERTION(aObject, "unexpected null object");
    4371               0 :   NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
    4372                 :                "Should use DropJSObjects.");
    4373               0 :   PRUint32 langIndex = NS_STID_INDEX(aLangID);
    4374               0 :   NS_LOG_RELEASE(sScriptRuntimes[langIndex], sScriptRootCount[langIndex] - 1,
    4375               0 :                  "HoldScriptObject");
    4376               0 :   sScriptRuntimes[langIndex]->DropScriptObject(aObject);
    4377               0 :   if (--sScriptRootCount[langIndex] == 0) {
    4378               0 :     NS_RELEASE(sScriptRuntimes[langIndex]);
    4379                 :   }
    4380               0 : }
    4381                 : 
    4382                 : /* static */
    4383                 : nsresult
    4384            7458 : nsContentUtils::HoldJSObjects(void* aScriptObjectHolder,
    4385                 :                               nsScriptObjectTracer* aTracer)
    4386                 : {
    4387            7458 :   NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED);
    4388                 : 
    4389            7458 :   nsresult rv = sXPConnect->AddJSHolder(aScriptObjectHolder, aTracer);
    4390            7458 :   NS_ENSURE_SUCCESS(rv, rv);
    4391                 : 
    4392            7458 :   if (sJSGCThingRootCount++ == 0) {
    4393              52 :     nsLayoutStatics::AddRef();
    4394                 :   }
    4395            7458 :   NS_LOG_ADDREF(sXPConnect, sJSGCThingRootCount, "HoldJSObjects",
    4396           14916 :                 sizeof(void*));
    4397                 : 
    4398            7458 :   return NS_OK;
    4399                 : }
    4400                 : 
    4401                 : /* static */
    4402                 : nsresult
    4403            7456 : nsContentUtils::DropJSObjects(void* aScriptObjectHolder)
    4404                 : {
    4405            7456 :   NS_LOG_RELEASE(sXPConnect, sJSGCThingRootCount - 1, "HoldJSObjects");
    4406            7456 :   nsresult rv = sXPConnect->RemoveJSHolder(aScriptObjectHolder);
    4407            7456 :   if (--sJSGCThingRootCount == 0) {
    4408              51 :     nsLayoutStatics::Release();
    4409                 :   }
    4410            7456 :   return rv;
    4411                 : }
    4412                 : 
    4413                 : /* static */
    4414                 : void
    4415               0 : nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling)
    4416                 : {
    4417               0 :   nsIMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
    4418               0 : }
    4419                 : 
    4420               0 : static bool SchemeIs(nsIURI* aURI, const char* aScheme)
    4421                 : {
    4422               0 :   nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
    4423               0 :   NS_ENSURE_TRUE(baseURI, false);
    4424                 : 
    4425               0 :   bool isScheme = false;
    4426               0 :   return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
    4427                 : }
    4428                 : 
    4429                 : /* static */
    4430                 : nsresult
    4431               0 : nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
    4432                 :                                         nsIPrincipal* aLoadingPrincipal,
    4433                 :                                         PRUint32 aCheckLoadFlags,
    4434                 :                                         bool aAllowData,
    4435                 :                                         PRUint32 aContentPolicyType,
    4436                 :                                         nsISupports* aContext,
    4437                 :                                         const nsACString& aMimeGuess,
    4438                 :                                         nsISupports* aExtra)
    4439                 : {
    4440               0 :   NS_PRECONDITION(aLoadingPrincipal, "Must have a loading principal here");
    4441                 : 
    4442               0 :   bool isSystemPrin = false;
    4443               0 :   if (NS_SUCCEEDED(sSecurityManager->IsSystemPrincipal(aLoadingPrincipal,
    4444                 :                                                        &isSystemPrin)) &&
    4445                 :       isSystemPrin) {
    4446               0 :     return NS_OK;
    4447                 :   }
    4448                 :   
    4449                 :   // XXXbz do we want to fast-path skin stylesheets loading XBL here somehow?
    4450                 :   // CheckLoadURIWithPrincipal
    4451                 :   nsresult rv = sSecurityManager->
    4452               0 :     CheckLoadURIWithPrincipal(aLoadingPrincipal, aURIToLoad, aCheckLoadFlags);
    4453               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4454                 : 
    4455                 :   // Content Policy
    4456               0 :   PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
    4457                 :   rv = NS_CheckContentLoadPolicy(aContentPolicyType,
    4458                 :                                  aURIToLoad,
    4459                 :                                  aLoadingPrincipal,
    4460                 :                                  aContext,
    4461                 :                                  aMimeGuess,
    4462                 :                                  aExtra,
    4463                 :                                  &shouldLoad,
    4464                 :                                  GetContentPolicy(),
    4465               0 :                                  sSecurityManager);
    4466               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4467               0 :   if (NS_CP_REJECTED(shouldLoad)) {
    4468               0 :     return NS_ERROR_CONTENT_BLOCKED;
    4469                 :   }
    4470                 : 
    4471                 :   // Same Origin
    4472               0 :   if ((aAllowData && SchemeIs(aURIToLoad, "data")) ||
    4473                 :       ((aCheckLoadFlags & nsIScriptSecurityManager::ALLOW_CHROME) &&
    4474               0 :        SchemeIs(aURIToLoad, "chrome"))) {
    4475               0 :     return NS_OK;
    4476                 :   }
    4477                 : 
    4478               0 :   return aLoadingPrincipal->CheckMayLoad(aURIToLoad, true);
    4479                 : }
    4480                 : 
    4481                 : bool
    4482            4085 : nsContentUtils::IsSystemPrincipal(nsIPrincipal* aPrincipal)
    4483                 : {
    4484                 :   bool isSystem;
    4485            4085 :   nsresult rv = sSecurityManager->IsSystemPrincipal(aPrincipal, &isSystem);
    4486            4085 :   return NS_SUCCEEDED(rv) && isSystem;
    4487                 : }
    4488                 : 
    4489                 : /* static */
    4490                 : void
    4491               0 : nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
    4492                 :                             nsIURI *aLinkURI, const nsString &aTargetSpec,
    4493                 :                             bool aClick, bool aIsUserTriggered,
    4494                 :                             bool aIsTrusted)
    4495                 : {
    4496               0 :   NS_ASSERTION(aPresContext, "Need a nsPresContext");
    4497               0 :   NS_PRECONDITION(aLinkURI, "No link URI");
    4498                 : 
    4499               0 :   if (aContent->IsEditable()) {
    4500               0 :     return;
    4501                 :   }
    4502                 : 
    4503               0 :   nsILinkHandler *handler = aPresContext->GetLinkHandler();
    4504               0 :   if (!handler) {
    4505               0 :     return;
    4506                 :   }
    4507                 : 
    4508               0 :   if (!aClick) {
    4509               0 :     handler->OnOverLink(aContent, aLinkURI, aTargetSpec.get());
    4510                 : 
    4511               0 :     return;
    4512                 :   }
    4513                 : 
    4514                 :   // Check that this page is allowed to load this URI.
    4515               0 :   nsresult proceed = NS_OK;
    4516                 : 
    4517               0 :   if (sSecurityManager) {
    4518                 :     PRUint32 flag =
    4519                 :       aIsUserTriggered ?
    4520                 :       (PRUint32)nsIScriptSecurityManager::STANDARD :
    4521               0 :       (PRUint32)nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT;
    4522                 :     proceed =
    4523                 :       sSecurityManager->CheckLoadURIWithPrincipal(aContent->NodePrincipal(),
    4524               0 :                                                   aLinkURI, flag);
    4525                 :   }
    4526                 : 
    4527                 :   // Only pass off the click event if the script security manager says it's ok.
    4528               0 :   if (NS_SUCCEEDED(proceed)) {
    4529                 :     handler->OnLinkClick(aContent, aLinkURI, aTargetSpec.get(), nsnull, nsnull,
    4530               0 :                          aIsTrusted);
    4531                 :   }
    4532                 : }
    4533                 : 
    4534                 : /* static */
    4535                 : nsIWidget*
    4536               0 : nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget)
    4537                 : {
    4538               0 :   if (!aWidget)
    4539               0 :     return nsnull;
    4540                 : 
    4541               0 :   return aWidget->GetTopLevelWidget();
    4542                 : }
    4543                 : 
    4544                 : /* static */
    4545                 : const nsDependentString
    4546               0 : nsContentUtils::GetLocalizedEllipsis()
    4547                 : {
    4548                 :   static PRUnichar sBuf[4] = { 0, 0, 0, 0 };
    4549               0 :   if (!sBuf[0]) {
    4550               0 :     nsAdoptingString tmp = Preferences::GetLocalizedString("intl.ellipsis");
    4551               0 :     PRUint32 len = NS_MIN(PRUint32(tmp.Length()),
    4552               0 :                           PRUint32(ArrayLength(sBuf) - 1));
    4553               0 :     CopyUnicodeTo(tmp, 0, sBuf, len);
    4554               0 :     if (!sBuf[0])
    4555               0 :       sBuf[0] = PRUnichar(0x2026);
    4556                 :   }
    4557               0 :   return nsDependentString(sBuf);
    4558                 : }
    4559                 : 
    4560                 : //static
    4561                 : nsEvent*
    4562               0 : nsContentUtils::GetNativeEvent(nsIDOMEvent* aDOMEvent)
    4563                 : {
    4564               0 :   nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aDOMEvent));
    4565               0 :   if (!privateEvent)
    4566               0 :     return nsnull;
    4567               0 :   return privateEvent->GetInternalNSEvent();
    4568                 : }
    4569                 : 
    4570                 : //static
    4571                 : bool
    4572               0 : nsContentUtils::DOMEventToNativeKeyEvent(nsIDOMKeyEvent* aKeyEvent,
    4573                 :                                          nsNativeKeyEvent* aNativeEvent,
    4574                 :                                          bool aGetCharCode)
    4575                 : {
    4576               0 :   nsCOMPtr<nsIDOMNSEvent> nsevent = do_QueryInterface(aKeyEvent);
    4577                 :   bool defaultPrevented;
    4578               0 :   nsevent->GetPreventDefault(&defaultPrevented);
    4579               0 :   if (defaultPrevented)
    4580               0 :     return false;
    4581                 : 
    4582               0 :   bool trusted = false;
    4583               0 :   nsevent->GetIsTrusted(&trusted);
    4584               0 :   if (!trusted)
    4585               0 :     return false;
    4586                 : 
    4587               0 :   if (aGetCharCode) {
    4588               0 :     aKeyEvent->GetCharCode(&aNativeEvent->charCode);
    4589                 :   } else {
    4590               0 :     aNativeEvent->charCode = 0;
    4591                 :   }
    4592               0 :   aKeyEvent->GetKeyCode(&aNativeEvent->keyCode);
    4593               0 :   aKeyEvent->GetAltKey(&aNativeEvent->altKey);
    4594               0 :   aKeyEvent->GetCtrlKey(&aNativeEvent->ctrlKey);
    4595               0 :   aKeyEvent->GetShiftKey(&aNativeEvent->shiftKey);
    4596               0 :   aKeyEvent->GetMetaKey(&aNativeEvent->metaKey);
    4597                 : 
    4598               0 :   aNativeEvent->nativeEvent = GetNativeEvent(aKeyEvent);
    4599                 : 
    4600               0 :   return true;
    4601                 : }
    4602                 : 
    4603                 : static bool
    4604               0 : HasASCIIDigit(const nsTArray<nsShortcutCandidate>& aCandidates)
    4605                 : {
    4606               0 :   for (PRUint32 i = 0; i < aCandidates.Length(); ++i) {
    4607               0 :     PRUint32 ch = aCandidates[i].mCharCode;
    4608               0 :     if (ch >= '0' && ch <= '9')
    4609               0 :       return true;
    4610                 :   }
    4611               0 :   return false;
    4612                 : }
    4613                 : 
    4614                 : static bool
    4615               0 : CharsCaseInsensitiveEqual(PRUint32 aChar1, PRUint32 aChar2)
    4616                 : {
    4617                 :   return aChar1 == aChar2 ||
    4618                 :          (IS_IN_BMP(aChar1) && IS_IN_BMP(aChar2) &&
    4619               0 :           ToLowerCase(PRUnichar(aChar1)) == ToLowerCase(PRUnichar(aChar2)));
    4620                 : }
    4621                 : 
    4622                 : static bool
    4623               0 : IsCaseChangeableChar(PRUint32 aChar)
    4624                 : {
    4625                 :   return IS_IN_BMP(aChar) &&
    4626               0 :          ToLowerCase(PRUnichar(aChar)) != ToUpperCase(PRUnichar(aChar));
    4627                 : }
    4628                 : 
    4629                 : /* static */
    4630                 : void
    4631               0 : nsContentUtils::GetAccelKeyCandidates(nsIDOMKeyEvent* aDOMKeyEvent,
    4632                 :                   nsTArray<nsShortcutCandidate>& aCandidates)
    4633                 : {
    4634               0 :   NS_PRECONDITION(aCandidates.IsEmpty(), "aCandidates must be empty");
    4635                 : 
    4636               0 :   nsAutoString eventType;
    4637               0 :   aDOMKeyEvent->GetType(eventType);
    4638                 :   // Don't process if aDOMKeyEvent is not a keypress event.
    4639               0 :   if (!eventType.EqualsLiteral("keypress"))
    4640                 :     return;
    4641                 : 
    4642                 :   nsKeyEvent* nativeKeyEvent =
    4643               0 :     static_cast<nsKeyEvent*>(GetNativeEvent(aDOMKeyEvent));
    4644               0 :   if (nativeKeyEvent) {
    4645               0 :     NS_ASSERTION(nativeKeyEvent->eventStructType == NS_KEY_EVENT,
    4646                 :                  "wrong type of native event");
    4647                 :     // nsShortcutCandidate::mCharCode is a candidate charCode.
    4648                 :     // nsShoftcutCandidate::mIgnoreShift means the mCharCode should be tried to
    4649                 :     // execute a command with/without shift key state. If this is TRUE, the
    4650                 :     // shifted key state should be ignored. Otherwise, don't ignore the state.
    4651                 :     // the priority of the charCodes are (shift key is not pressed):
    4652                 :     //   0: charCode/false,
    4653                 :     //   1: unshiftedCharCodes[0]/false, 2: unshiftedCharCodes[1]/false...
    4654                 :     // the priority of the charCodes are (shift key is pressed):
    4655                 :     //   0: charCode/false,
    4656                 :     //   1: shiftedCharCodes[0]/false, 2: shiftedCharCodes[0]/true,
    4657                 :     //   3: shiftedCharCodes[1]/false, 4: shiftedCharCodes[1]/true...
    4658               0 :     if (nativeKeyEvent->charCode) {
    4659               0 :       nsShortcutCandidate key(nativeKeyEvent->charCode, false);
    4660               0 :       aCandidates.AppendElement(key);
    4661                 :     }
    4662                 : 
    4663               0 :     PRUint32 len = nativeKeyEvent->alternativeCharCodes.Length();
    4664               0 :     if (!nativeKeyEvent->isShift) {
    4665               0 :       for (PRUint32 i = 0; i < len; ++i) {
    4666                 :         PRUint32 ch =
    4667               0 :           nativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode;
    4668               0 :         if (!ch || ch == nativeKeyEvent->charCode)
    4669               0 :           continue;
    4670                 : 
    4671               0 :         nsShortcutCandidate key(ch, false);
    4672               0 :         aCandidates.AppendElement(key);
    4673                 :       }
    4674                 :       // If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
    4675                 :       // this keyboard layout is AZERTY or similar layout, probably.
    4676                 :       // In this case, Accel+[0-9] should be accessible without shift key.
    4677                 :       // However, the priority should be lowest.
    4678               0 :       if (!HasASCIIDigit(aCandidates)) {
    4679               0 :         for (PRUint32 i = 0; i < len; ++i) {
    4680                 :           PRUint32 ch =
    4681               0 :             nativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode;
    4682               0 :           if (ch >= '0' && ch <= '9') {
    4683               0 :             nsShortcutCandidate key(ch, false);
    4684               0 :             aCandidates.AppendElement(key);
    4685               0 :             break;
    4686                 :           }
    4687                 :         }
    4688                 :       }
    4689                 :     } else {
    4690               0 :       for (PRUint32 i = 0; i < len; ++i) {
    4691               0 :         PRUint32 ch = nativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode;
    4692               0 :         if (!ch)
    4693               0 :           continue;
    4694                 : 
    4695               0 :         if (ch != nativeKeyEvent->charCode) {
    4696               0 :           nsShortcutCandidate key(ch, false);
    4697               0 :           aCandidates.AppendElement(key);
    4698                 :         }
    4699                 : 
    4700                 :         // If the char is an alphabet, the shift key state should not be
    4701                 :         // ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
    4702                 : 
    4703                 :         // And checking the charCode is same as unshiftedCharCode too.
    4704                 :         // E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
    4705                 :         PRUint32 unshiftCh =
    4706               0 :           nativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode;
    4707               0 :         if (CharsCaseInsensitiveEqual(ch, unshiftCh))
    4708               0 :           continue;
    4709                 : 
    4710                 :         // On the Hebrew keyboard layout on Windows, the unshifted char is a
    4711                 :         // localized character but the shifted char is a Latin alphabet,
    4712                 :         // then, we should not execute without the shift state. See bug 433192.
    4713               0 :         if (IsCaseChangeableChar(ch))
    4714               0 :           continue;
    4715                 : 
    4716                 :         // Setting the alternative charCode candidates for retry without shift
    4717                 :         // key state only when the shift key is pressed.
    4718               0 :         nsShortcutCandidate key(ch, true);
    4719               0 :         aCandidates.AppendElement(key);
    4720                 :       }
    4721                 :     }
    4722                 :   } else {
    4723                 :     PRUint32 charCode;
    4724               0 :     aDOMKeyEvent->GetCharCode(&charCode);
    4725               0 :     if (charCode) {
    4726               0 :       nsShortcutCandidate key(charCode, false);
    4727               0 :       aCandidates.AppendElement(key);
    4728                 :     }
    4729                 :   }
    4730                 : }
    4731                 : 
    4732                 : /* static */
    4733                 : void
    4734               0 : nsContentUtils::GetAccessKeyCandidates(nsKeyEvent* aNativeKeyEvent,
    4735                 :                                        nsTArray<PRUint32>& aCandidates)
    4736                 : {
    4737               0 :   NS_PRECONDITION(aCandidates.IsEmpty(), "aCandidates must be empty");
    4738                 : 
    4739                 :   // return the lower cased charCode candidates for access keys.
    4740                 :   // the priority of the charCodes are:
    4741                 :   //   0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
    4742                 :   //   3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
    4743               0 :   if (aNativeKeyEvent->charCode) {
    4744               0 :     PRUint32 ch = aNativeKeyEvent->charCode;
    4745               0 :     if (IS_IN_BMP(ch))
    4746               0 :       ch = ToLowerCase(PRUnichar(ch));
    4747               0 :     aCandidates.AppendElement(ch);
    4748                 :   }
    4749               0 :   for (PRUint32 i = 0;
    4750               0 :        i < aNativeKeyEvent->alternativeCharCodes.Length(); ++i) {
    4751                 :     PRUint32 ch[2] =
    4752               0 :       { aNativeKeyEvent->alternativeCharCodes[i].mUnshiftedCharCode,
    4753               0 :         aNativeKeyEvent->alternativeCharCodes[i].mShiftedCharCode };
    4754               0 :     for (PRUint32 j = 0; j < 2; ++j) {
    4755               0 :       if (!ch[j])
    4756               0 :         continue;
    4757               0 :       if (IS_IN_BMP(ch[j]))
    4758               0 :         ch[j] = ToLowerCase(PRUnichar(ch[j]));
    4759                 :       // Don't append the charCode that was already appended.
    4760               0 :       if (aCandidates.IndexOf(ch[j]) == aCandidates.NoIndex)
    4761               0 :         aCandidates.AppendElement(ch[j]);
    4762                 :     }
    4763                 :   }
    4764                 :   return;
    4765                 : }
    4766                 : 
    4767                 : /* static */
    4768                 : void
    4769          285283 : nsContentUtils::AddScriptBlocker()
    4770                 : {
    4771          285283 :   if (!sScriptBlockerCount) {
    4772          259228 :     NS_ASSERTION(sRunnersCountAtFirstBlocker == 0,
    4773                 :                  "Should not already have a count");
    4774          259228 :     sRunnersCountAtFirstBlocker = sBlockedScriptRunners->Length();
    4775                 :   }
    4776          285283 :   ++sScriptBlockerCount;
    4777          285283 : }
    4778                 : 
    4779                 : /* static */
    4780                 : void
    4781          285283 : nsContentUtils::RemoveScriptBlocker()
    4782                 : {
    4783          285283 :   NS_ASSERTION(sScriptBlockerCount != 0, "Negative script blockers");
    4784          285283 :   --sScriptBlockerCount;
    4785          285283 :   if (sScriptBlockerCount) {
    4786           26055 :     return;
    4787                 :   }
    4788                 : 
    4789          259228 :   PRUint32 firstBlocker = sRunnersCountAtFirstBlocker;
    4790          259228 :   PRUint32 lastBlocker = sBlockedScriptRunners->Length();
    4791          259228 :   PRUint32 originalFirstBlocker = firstBlocker;
    4792          259228 :   PRUint32 blockersCount = lastBlocker - firstBlocker;
    4793          259228 :   sRunnersCountAtFirstBlocker = 0;
    4794          259228 :   NS_ASSERTION(firstBlocker <= lastBlocker,
    4795                 :                "bad sRunnersCountAtFirstBlocker");
    4796                 : 
    4797          518824 :   while (firstBlocker < lastBlocker) {
    4798             736 :     nsCOMPtr<nsIRunnable> runnable = (*sBlockedScriptRunners)[firstBlocker];
    4799             368 :     ++firstBlocker;
    4800                 : 
    4801             368 :     runnable->Run();
    4802             368 :     NS_ASSERTION(sRunnersCountAtFirstBlocker == 0,
    4803                 :                  "Bad count");
    4804             368 :     NS_ASSERTION(!sScriptBlockerCount, "This is really bad");
    4805                 :   }
    4806          259228 :   sBlockedScriptRunners->RemoveElementsAt(originalFirstBlocker, blockersCount);
    4807                 : }
    4808                 : 
    4809                 : /* static */
    4810                 : bool
    4811            4733 : nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable)
    4812                 : {
    4813            4733 :   if (!aRunnable) {
    4814               0 :     return false;
    4815                 :   }
    4816                 : 
    4817            4733 :   if (sScriptBlockerCount) {
    4818             368 :     return sBlockedScriptRunners->AppendElement(aRunnable) != nsnull;
    4819                 :   }
    4820                 :   
    4821            8730 :   nsCOMPtr<nsIRunnable> run = aRunnable;
    4822            4365 :   run->Run();
    4823                 : 
    4824            4365 :   return true;
    4825                 : }
    4826                 : 
    4827                 : /* 
    4828                 :  * Helper function for nsContentUtils::ProcessViewportInfo.
    4829                 :  *
    4830                 :  * Handles a single key=value pair. If it corresponds to a valid viewport
    4831                 :  * attribute, add it to the document header data. No validation is done on the
    4832                 :  * value itself (this is done at display time).
    4833                 :  */
    4834               0 : static void ProcessViewportToken(nsIDocument *aDocument, 
    4835                 :                                  const nsAString &token) {
    4836                 : 
    4837                 :   /* Iterators. */
    4838               0 :   nsAString::const_iterator tip, tail, end;
    4839               0 :   token.BeginReading(tip);
    4840               0 :   tail = tip;
    4841               0 :   token.EndReading(end);
    4842                 : 
    4843                 :   /* Move tip to the '='. */
    4844               0 :   while ((tip != end) && (*tip != '='))
    4845               0 :     ++tip;
    4846                 : 
    4847                 :   /* If we didn't find an '=', punt. */
    4848               0 :   if (tip == end)
    4849               0 :     return;
    4850                 : 
    4851                 :   /* Extract the key and value. */
    4852                 :   const nsAString &key =
    4853               0 :     nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(tail, tip),
    4854               0 :                                                         true);
    4855                 :   const nsAString &value =
    4856               0 :     nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(Substring(++tip, end),
    4857               0 :                                                         true);
    4858                 : 
    4859                 :   /* Check for known keys. If we find a match, insert the appropriate
    4860                 :    * information into the document header. */
    4861               0 :   nsCOMPtr<nsIAtom> key_atom = do_GetAtom(key);
    4862               0 :   if (key_atom == nsGkAtoms::height)
    4863               0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_height, value);
    4864               0 :   else if (key_atom == nsGkAtoms::width)
    4865               0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_width, value);
    4866               0 :   else if (key_atom == nsGkAtoms::initial_scale)
    4867               0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_initial_scale, value);
    4868               0 :   else if (key_atom == nsGkAtoms::minimum_scale)
    4869               0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_minimum_scale, value);
    4870               0 :   else if (key_atom == nsGkAtoms::maximum_scale)
    4871               0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_maximum_scale, value);
    4872               0 :   else if (key_atom == nsGkAtoms::user_scalable)
    4873               0 :     aDocument->SetHeaderData(nsGkAtoms::viewport_user_scalable, value);
    4874                 : }
    4875                 : 
    4876                 : #define IS_SEPARATOR(c) ((c == '=') || (c == ',') || (c == ';') || \
    4877                 :                          (c == '\t') || (c == '\n') || (c == '\r'))
    4878                 : 
    4879                 : /* static */
    4880                 : ViewportInfo
    4881               0 : nsContentUtils::GetViewportInfo(nsIDocument *aDocument)
    4882                 : {
    4883                 :   ViewportInfo ret;
    4884               0 :   ret.defaultZoom = 1.0;
    4885               0 :   ret.autoSize = true;
    4886               0 :   ret.allowZoom = true;
    4887               0 :   ret.autoScale = true;
    4888                 : 
    4889                 :   // If the docType specifies that we are on a site optimized for mobile,
    4890                 :   // then we want to return specially crafted defaults for the viewport info.
    4891                 :   nsCOMPtr<nsIDOMDocument>
    4892               0 :     domDoc(do_QueryInterface(aDocument));
    4893                 : 
    4894               0 :   nsCOMPtr<nsIDOMDocumentType> docType;
    4895               0 :   nsresult rv = domDoc->GetDoctype(getter_AddRefs(docType));
    4896               0 :   if (NS_SUCCEEDED(rv) && docType) {
    4897               0 :     nsAutoString docId;
    4898               0 :     rv = docType->GetPublicId(docId);
    4899               0 :     if (NS_SUCCEEDED(rv)) {
    4900               0 :       if ((docId.Find("WAP") != -1) ||
    4901               0 :           (docId.Find("Mobile") != -1) ||
    4902               0 :           (docId.Find("WML") != -1))
    4903                 :       {
    4904                 :         return ret;
    4905                 :       }
    4906                 :     }
    4907                 :   }
    4908                 : 
    4909               0 :   if (aDocument->IsXUL()) {
    4910               0 :     ret.autoScale = false;
    4911                 :     return ret;
    4912                 :   }
    4913                 : 
    4914               0 :   nsIDOMWindow* window = aDocument->GetWindow();
    4915               0 :   nsCOMPtr<nsIDOMWindowUtils> windowUtils(do_GetInterface(window));
    4916                 : 
    4917               0 :   if (!windowUtils) {
    4918                 :     return ret;
    4919                 :   }
    4920                 : 
    4921               0 :   nsAutoString handheldFriendly;
    4922               0 :   aDocument->GetHeaderData(nsGkAtoms::handheldFriendly, handheldFriendly);
    4923                 : 
    4924               0 :   if (handheldFriendly.EqualsLiteral("true")) {
    4925                 :     return ret;
    4926                 :   }
    4927                 : 
    4928                 :   PRInt32 errorCode;
    4929                 : 
    4930               0 :   nsAutoString minScaleStr;
    4931               0 :   aDocument->GetHeaderData(nsGkAtoms::minimum_scale, minScaleStr);
    4932                 : 
    4933               0 :   float scaleMinFloat = minScaleStr.ToFloat(&errorCode);
    4934                 : 
    4935               0 :   if (errorCode) {
    4936               0 :     scaleMinFloat = kViewportMinScale;
    4937                 :   }
    4938                 : 
    4939               0 :   scaleMinFloat = NS_MIN(scaleMinFloat, kViewportMaxScale);
    4940               0 :   scaleMinFloat = NS_MAX(scaleMinFloat, kViewportMinScale);
    4941                 : 
    4942               0 :   nsAutoString maxScaleStr;
    4943               0 :   aDocument->GetHeaderData(nsGkAtoms::maximum_scale, maxScaleStr);
    4944                 : 
    4945                 :   // We define a special error code variable for the scale and max scale,
    4946                 :   // because they are used later (see the width calculations).
    4947                 :   PRInt32 scaleMaxErrorCode;
    4948               0 :   float scaleMaxFloat = maxScaleStr.ToFloat(&scaleMaxErrorCode);
    4949                 : 
    4950               0 :   if (scaleMaxErrorCode) {
    4951               0 :     scaleMaxFloat = kViewportMaxScale;
    4952                 :   }
    4953                 : 
    4954               0 :   scaleMaxFloat = NS_MIN(scaleMaxFloat, kViewportMaxScale);
    4955               0 :   scaleMaxFloat = NS_MAX(scaleMaxFloat, kViewportMinScale);
    4956                 : 
    4957               0 :   nsAutoString scaleStr;
    4958               0 :   aDocument->GetHeaderData(nsGkAtoms::viewport_initial_scale, scaleStr);
    4959                 : 
    4960                 :   PRInt32 scaleErrorCode;
    4961               0 :   float scaleFloat = scaleStr.ToFloat(&scaleErrorCode);
    4962               0 :   scaleFloat = NS_MIN(scaleFloat, scaleMaxFloat);
    4963               0 :   scaleFloat = NS_MAX(scaleFloat, scaleMinFloat);
    4964                 : 
    4965               0 :   nsAutoString widthStr, heightStr;
    4966                 : 
    4967               0 :   aDocument->GetHeaderData(nsGkAtoms::viewport_height, heightStr);
    4968               0 :   aDocument->GetHeaderData(nsGkAtoms::viewport_width, widthStr);
    4969                 : 
    4970               0 :   bool autoSize = false;
    4971                 : 
    4972               0 :   if (widthStr.EqualsLiteral("device-width")) {
    4973               0 :     autoSize = true;
    4974                 :   }
    4975                 : 
    4976               0 :   if (widthStr.IsEmpty() &&
    4977               0 :      (heightStr.EqualsLiteral("device-height") ||
    4978                 :           scaleFloat == 1.0))
    4979                 :   {
    4980               0 :     autoSize = true;
    4981                 :   }
    4982                 : 
    4983                 :   // XXXjwir3:
    4984                 :   // See bug 706918, comment 23 for more information on this particular section
    4985                 :   // of the code. We're using "screen size" in place of the size of the content
    4986                 :   // area, because on mobile, these are close or equal. This will work for our
    4987                 :   // purposes (bug 706198), but it will need to be changed in the future to be
    4988                 :   // more correct when we bring the rest of the viewport code into platform.
    4989                 :   // We actually want the size of the content area, in the event that we don't
    4990                 :   // have any metadata about the width and/or height. On mobile, the screen size
    4991                 :   // and the size of the content area are very close, or the same value.
    4992                 :   // In XUL fennec, the content area is the size of the <browser> widget, but
    4993                 :   // in native fennec, the content area is the size of the Gecko LayerView
    4994                 :   // object.
    4995                 : 
    4996                 :   // TODO:
    4997                 :   // Once bug 716575 has been resolved, this code should be changed so that it
    4998                 :   // does the right thing on all platforms.
    4999                 :   nsresult result;
    5000                 :   PRInt32 screenLeft, screenTop, screenWidth, screenHeight;
    5001                 :   nsCOMPtr<nsIScreenManager> screenMgr =
    5002               0 :     do_GetService("@mozilla.org/gfx/screenmanager;1", &result);
    5003                 : 
    5004               0 :   nsCOMPtr<nsIScreen> screen;
    5005               0 :   screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
    5006               0 :   screen->GetRect(&screenLeft, &screenTop, &screenWidth, &screenHeight);
    5007                 : 
    5008               0 :   PRUint32 width = widthStr.ToInteger(&errorCode);
    5009               0 :   if (errorCode) {
    5010               0 :     if (autoSize) {
    5011               0 :       width = screenWidth;
    5012                 :     } else {
    5013               0 :       width = Preferences::GetInt("browser.viewport.desktopWidth", 0);
    5014                 :     }
    5015                 :   }
    5016                 : 
    5017               0 :   width = NS_MIN(width, kViewportMaxWidth);
    5018               0 :   width = NS_MAX(width, kViewportMinWidth);
    5019                 : 
    5020                 :   // Also recalculate the default zoom, if it wasn't specified in the metadata,
    5021                 :   // and the width is specified.
    5022               0 :   if (scaleStr.IsEmpty() && !widthStr.IsEmpty()) {
    5023               0 :     scaleFloat = NS_MAX(scaleFloat, (float)(screenWidth/width));
    5024                 :   }
    5025                 : 
    5026               0 :   PRUint32 height = heightStr.ToInteger(&errorCode);
    5027                 : 
    5028               0 :   if (errorCode) {
    5029               0 :     height = width * ((float)screenHeight / screenWidth);
    5030                 :   }
    5031                 : 
    5032                 :   // If height was provided by the user, but width wasn't, then we should
    5033                 :   // calculate the width.
    5034               0 :   if (widthStr.IsEmpty() && !heightStr.IsEmpty()) {
    5035               0 :     width = (PRUint32) ((height * screenWidth) / screenHeight);
    5036                 :   }
    5037                 : 
    5038               0 :   height = NS_MIN(height, kViewportMaxHeight);
    5039               0 :   height = NS_MAX(height, kViewportMinHeight);
    5040                 : 
    5041                 :   // We need to perform a conversion, but only if the initial or maximum
    5042                 :   // scale were set explicitly by the user.
    5043               0 :   if (!scaleStr.IsEmpty() && !scaleErrorCode) {
    5044               0 :     width = NS_MAX(width, (PRUint32)(screenWidth / scaleFloat));
    5045               0 :     height = NS_MAX(height, (PRUint32)(screenHeight / scaleFloat));
    5046               0 :   } else if (!maxScaleStr.IsEmpty() && !scaleMaxErrorCode) {
    5047               0 :     width = NS_MAX(width, (PRUint32)(screenWidth / scaleMaxFloat));
    5048               0 :     height = NS_MAX(height, (PRUint32)(screenHeight / scaleMaxFloat));
    5049                 :   }
    5050                 : 
    5051               0 :   bool allowZoom = true;
    5052               0 :   nsAutoString userScalable;
    5053               0 :   aDocument->GetHeaderData(nsGkAtoms::viewport_user_scalable, userScalable);
    5054                 : 
    5055               0 :   if ((userScalable.EqualsLiteral("0")) ||
    5056               0 :       (userScalable.EqualsLiteral("no")) ||
    5057               0 :       (userScalable.EqualsLiteral("false"))) {
    5058               0 :     allowZoom = false;
    5059                 :   }
    5060                 : 
    5061               0 :   ret.allowZoom = allowZoom;
    5062               0 :   ret.width = width;
    5063               0 :   ret.height = height;
    5064               0 :   ret.defaultZoom = scaleFloat;
    5065               0 :   ret.minZoom = scaleMinFloat;
    5066               0 :   ret.maxZoom = scaleMaxFloat;
    5067               0 :   ret.autoSize = autoSize;
    5068                 :   return ret;
    5069                 : }
    5070                 : 
    5071                 : /* static */
    5072                 : nsresult
    5073               0 : nsContentUtils::ProcessViewportInfo(nsIDocument *aDocument,
    5074                 :                                     const nsAString &viewportInfo) {
    5075                 : 
    5076                 :   /* We never fail. */
    5077               0 :   nsresult rv = NS_OK;
    5078                 : 
    5079                 :   /* Iterators. */
    5080               0 :   nsAString::const_iterator tip, tail, end;
    5081               0 :   viewportInfo.BeginReading(tip);
    5082               0 :   tail = tip;
    5083               0 :   viewportInfo.EndReading(end);
    5084                 : 
    5085                 :   /* Read the tip to the first non-separator character. */
    5086               0 :   while ((tip != end) && (IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
    5087               0 :     ++tip;
    5088                 : 
    5089                 :   /* Read through and find tokens separated by separators. */
    5090               0 :   while (tip != end) {
    5091                 : 
    5092                 :     /* Synchronize tip and tail. */
    5093               0 :     tail = tip;
    5094                 : 
    5095                 :     /* Advance tip past non-separator characters. */
    5096               0 :     while ((tip != end) && !IS_SEPARATOR(*tip))
    5097               0 :       ++tip;
    5098                 : 
    5099                 :     /* Allow white spaces that surround the '=' character */
    5100               0 :     if ((tip != end) && (*tip == '=')) {
    5101               0 :       ++tip;
    5102                 : 
    5103               0 :       while ((tip != end) && nsCRT::IsAsciiSpace(*tip))
    5104               0 :         ++tip;
    5105                 : 
    5106               0 :       while ((tip != end) && !(IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
    5107               0 :         ++tip;
    5108                 :     }
    5109                 : 
    5110                 :     /* Our token consists of the characters between tail and tip. */
    5111               0 :     ProcessViewportToken(aDocument, Substring(tail, tip));
    5112                 : 
    5113                 :     /* Skip separators. */
    5114               0 :     while ((tip != end) && (IS_SEPARATOR(*tip) || nsCRT::IsAsciiSpace(*tip)))
    5115               0 :       ++tip;
    5116                 :   }
    5117                 : 
    5118               0 :   return rv;
    5119                 : 
    5120                 : }
    5121                 : 
    5122                 : #undef IS_SEPARATOR
    5123                 : 
    5124                 : /* static */
    5125                 : void
    5126               0 : nsContentUtils::HidePopupsInDocument(nsIDocument* aDocument)
    5127                 : {
    5128                 : #ifdef MOZ_XUL
    5129               0 :   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
    5130               0 :   if (pm && aDocument) {
    5131               0 :     nsCOMPtr<nsISupports> container = aDocument->GetContainer();
    5132               0 :     nsCOMPtr<nsIDocShellTreeItem> docShellToHide = do_QueryInterface(container);
    5133               0 :     if (docShellToHide)
    5134               0 :       pm->HidePopupsInDocShell(docShellToHide);
    5135                 :   }
    5136                 : #endif
    5137               0 : }
    5138                 : 
    5139                 : /* static */
    5140                 : already_AddRefed<nsIDragSession>
    5141               0 : nsContentUtils::GetDragSession()
    5142                 : {
    5143               0 :   nsIDragSession* dragSession = nsnull;
    5144                 :   nsCOMPtr<nsIDragService> dragService =
    5145               0 :     do_GetService("@mozilla.org/widget/dragservice;1");
    5146               0 :   if (dragService)
    5147               0 :     dragService->GetCurrentSession(&dragSession);
    5148               0 :   return dragSession;
    5149                 : }
    5150                 : 
    5151                 : /* static */
    5152                 : nsresult
    5153               0 : nsContentUtils::SetDataTransferInEvent(nsDragEvent* aDragEvent)
    5154                 : {
    5155               0 :   if (aDragEvent->dataTransfer || !NS_IS_TRUSTED_EVENT(aDragEvent))
    5156               0 :     return NS_OK;
    5157                 : 
    5158                 :   // For draggesture and dragstart events, the data transfer object is
    5159                 :   // created before the event fires, so it should already be set. For other
    5160                 :   // drag events, get the object from the drag session.
    5161               0 :   NS_ASSERTION(aDragEvent->message != NS_DRAGDROP_GESTURE &&
    5162                 :                aDragEvent->message != NS_DRAGDROP_START,
    5163                 :                "draggesture event created without a dataTransfer");
    5164                 : 
    5165               0 :   nsCOMPtr<nsIDragSession> dragSession = GetDragSession();
    5166               0 :   NS_ENSURE_TRUE(dragSession, NS_OK); // no drag in progress
    5167                 : 
    5168               0 :   nsCOMPtr<nsIDOMDataTransfer> initialDataTransfer;
    5169               0 :   dragSession->GetDataTransfer(getter_AddRefs(initialDataTransfer));
    5170               0 :   if (!initialDataTransfer) {
    5171                 :     // A dataTransfer won't exist when a drag was started by some other
    5172                 :     // means, for instance calling the drag service directly, or a drag
    5173                 :     // from another application. In either case, a new dataTransfer should
    5174                 :     // be created that reflects the data.
    5175                 :     initialDataTransfer =
    5176               0 :       new nsDOMDataTransfer(aDragEvent->message);
    5177               0 :     NS_ENSURE_TRUE(initialDataTransfer, NS_ERROR_OUT_OF_MEMORY);
    5178                 : 
    5179                 :     // now set it in the drag session so we don't need to create it again
    5180               0 :     dragSession->SetDataTransfer(initialDataTransfer);
    5181                 :   }
    5182                 : 
    5183                 :   // each event should use a clone of the original dataTransfer.
    5184               0 :   initialDataTransfer->Clone(aDragEvent->message, aDragEvent->userCancelled,
    5185               0 :                              getter_AddRefs(aDragEvent->dataTransfer));
    5186               0 :   NS_ENSURE_TRUE(aDragEvent->dataTransfer, NS_ERROR_OUT_OF_MEMORY);
    5187                 : 
    5188                 :   // for the dragenter and dragover events, initialize the drop effect
    5189                 :   // from the drop action, which platform specific widget code sets before
    5190                 :   // the event is fired based on the keyboard state.
    5191               0 :   if (aDragEvent->message == NS_DRAGDROP_ENTER ||
    5192                 :       aDragEvent->message == NS_DRAGDROP_OVER) {
    5193                 :     PRUint32 action, effectAllowed;
    5194               0 :     dragSession->GetDragAction(&action);
    5195               0 :     aDragEvent->dataTransfer->GetEffectAllowedInt(&effectAllowed);
    5196               0 :     aDragEvent->dataTransfer->SetDropEffectInt(FilterDropEffect(action, effectAllowed));
    5197                 :   }
    5198               0 :   else if (aDragEvent->message == NS_DRAGDROP_DROP ||
    5199                 :            aDragEvent->message == NS_DRAGDROP_DRAGDROP ||
    5200                 :            aDragEvent->message == NS_DRAGDROP_END) {
    5201                 :     // For the drop and dragend events, set the drop effect based on the
    5202                 :     // last value that the dropEffect had. This will have been set in
    5203                 :     // nsEventStateManager::PostHandleEvent for the last dragenter or
    5204                 :     // dragover event.
    5205                 :     PRUint32 dropEffect;
    5206               0 :     initialDataTransfer->GetDropEffectInt(&dropEffect);
    5207               0 :     aDragEvent->dataTransfer->SetDropEffectInt(dropEffect);
    5208                 :   }
    5209                 : 
    5210               0 :   return NS_OK;
    5211                 : }
    5212                 : 
    5213                 : /* static */
    5214                 : PRUint32
    5215               0 : nsContentUtils::FilterDropEffect(PRUint32 aAction, PRUint32 aEffectAllowed)
    5216                 : {
    5217                 :   // It is possible for the drag action to include more than one action, but
    5218                 :   // the widget code which sets the action from the keyboard state should only
    5219                 :   // be including one. If multiple actions were set, we just consider them in
    5220                 :   //  the following order:
    5221                 :   //   copy, link, move
    5222               0 :   if (aAction & nsIDragService::DRAGDROP_ACTION_COPY)
    5223               0 :     aAction = nsIDragService::DRAGDROP_ACTION_COPY;
    5224               0 :   else if (aAction & nsIDragService::DRAGDROP_ACTION_LINK)
    5225               0 :     aAction = nsIDragService::DRAGDROP_ACTION_LINK;
    5226               0 :   else if (aAction & nsIDragService::DRAGDROP_ACTION_MOVE)
    5227               0 :     aAction = nsIDragService::DRAGDROP_ACTION_MOVE;
    5228                 : 
    5229                 :   // Filter the action based on the effectAllowed. If the effectAllowed
    5230                 :   // doesn't include the action, then that action cannot be done, so adjust
    5231                 :   // the action to something that is allowed. For a copy, adjust to move or
    5232                 :   // link. For a move, adjust to copy or link. For a link, adjust to move or
    5233                 :   // link. Otherwise, use none.
    5234               0 :   if (aAction & aEffectAllowed ||
    5235                 :       aEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
    5236               0 :     return aAction;
    5237               0 :   if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_MOVE)
    5238               0 :     return nsIDragService::DRAGDROP_ACTION_MOVE;
    5239               0 :   if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_COPY)
    5240               0 :     return nsIDragService::DRAGDROP_ACTION_COPY;
    5241               0 :   if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_LINK)
    5242               0 :     return nsIDragService::DRAGDROP_ACTION_LINK;
    5243               0 :   return nsIDragService::DRAGDROP_ACTION_NONE;
    5244                 : }
    5245                 : 
    5246                 : /* static */
    5247                 : bool
    5248               2 : nsContentUtils::URIIsLocalFile(nsIURI *aURI)
    5249                 : {
    5250                 :   bool isFile;
    5251               4 :   nsCOMPtr<nsINetUtil> util = do_QueryInterface(sIOService);
    5252                 : 
    5253                 :   // Important: we do NOT test the entire URI chain here!
    5254               4 :   return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
    5255                 :                                 nsIProtocolHandler::URI_IS_LOCAL_FILE,
    5256                 :                                 &isFile)) &&
    5257               4 :          isFile;
    5258                 : }
    5259                 : 
    5260                 : nsresult
    5261               0 : nsContentUtils::SplitURIAtHash(nsIURI *aURI,
    5262                 :                                nsACString &aBeforeHash,
    5263                 :                                nsACString &aAfterHash)
    5264                 : {
    5265                 :   // See bug 225910 for why we can't do this using nsIURL.
    5266                 : 
    5267               0 :   aBeforeHash.Truncate();
    5268               0 :   aAfterHash.Truncate();
    5269                 : 
    5270               0 :   NS_ENSURE_ARG_POINTER(aURI);
    5271                 : 
    5272               0 :   nsCAutoString spec;
    5273               0 :   nsresult rv = aURI->GetSpec(spec);
    5274               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5275                 : 
    5276               0 :   PRInt32 index = spec.FindChar('#');
    5277               0 :   if (index == -1) {
    5278               0 :     index = spec.Length();
    5279                 :   }
    5280                 : 
    5281               0 :   aBeforeHash.Assign(Substring(spec, 0, index));
    5282               0 :   aAfterHash.Assign(Substring(spec, index));
    5283               0 :   return NS_OK;
    5284                 : }
    5285                 : 
    5286                 : /* static */
    5287                 : nsIScriptContext*
    5288               2 : nsContentUtils::GetContextForEventHandlers(nsINode* aNode,
    5289                 :                                            nsresult* aRv)
    5290                 : {
    5291               2 :   *aRv = NS_OK;
    5292               2 :   bool hasHadScriptObject = true;
    5293                 :   nsIScriptGlobalObject* sgo =
    5294               2 :     aNode->OwnerDoc()->GetScriptHandlingObject(hasHadScriptObject);
    5295                 :   // It is bad if the document doesn't have event handling context,
    5296                 :   // but it used to have one.
    5297               2 :   if (!sgo && hasHadScriptObject) {
    5298               0 :     *aRv = NS_ERROR_UNEXPECTED;
    5299               0 :     return nsnull;
    5300                 :   }
    5301                 : 
    5302               2 :   if (sgo) {
    5303               0 :     nsIScriptContext* scx = sgo->GetContext();
    5304                 :     // Bad, no context from script global object!
    5305               0 :     if (!scx) {
    5306               0 :       *aRv = NS_ERROR_UNEXPECTED;
    5307               0 :       return nsnull;
    5308                 :     }
    5309               0 :     return scx;
    5310                 :   }
    5311                 : 
    5312               2 :   return nsnull;
    5313                 : }
    5314                 : 
    5315                 : /* static */
    5316                 : JSContext *
    5317              70 : nsContentUtils::GetCurrentJSContext()
    5318                 : {
    5319              70 :   JSContext *cx = nsnull;
    5320                 : 
    5321              70 :   sThreadJSContextStack->Peek(&cx);
    5322                 : 
    5323              70 :   return cx;
    5324                 : }
    5325                 : 
    5326                 : /* static */
    5327                 : nsresult
    5328               0 : nsContentUtils::ASCIIToLower(nsAString& aStr)
    5329                 : {
    5330               0 :   PRUnichar* iter = aStr.BeginWriting();
    5331               0 :   PRUnichar* end = aStr.EndWriting();
    5332               0 :   if (NS_UNLIKELY(!iter || !end)) {
    5333               0 :     return NS_ERROR_OUT_OF_MEMORY;
    5334                 :   }
    5335               0 :   while (iter != end) {
    5336               0 :     PRUnichar c = *iter;
    5337               0 :     if (c >= 'A' && c <= 'Z') {
    5338               0 :       *iter = c + ('a' - 'A');
    5339                 :     }
    5340               0 :     ++iter;
    5341                 :   }
    5342               0 :   return NS_OK;
    5343                 : }
    5344                 : 
    5345                 : /* static */
    5346                 : nsresult
    5347            3338 : nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest)
    5348                 : {
    5349            3338 :   PRUint32 len = aSource.Length();
    5350            3338 :   aDest.SetLength(len);
    5351            3338 :   if (aDest.Length() == len) {
    5352            3338 :     PRUnichar* dest = aDest.BeginWriting();
    5353            3338 :     if (NS_UNLIKELY(!dest)) {
    5354               0 :       return NS_ERROR_OUT_OF_MEMORY;
    5355                 :     }
    5356            3338 :     const PRUnichar* iter = aSource.BeginReading();
    5357            3338 :     const PRUnichar* end = aSource.EndReading();
    5358           36730 :     while (iter != end) {
    5359           30054 :       PRUnichar c = *iter;
    5360                 :       *dest = (c >= 'A' && c <= 'Z') ?
    5361           30054 :          c + ('a' - 'A') : c;
    5362           30054 :       ++iter;
    5363           30054 :       ++dest;
    5364                 :     }
    5365            3338 :     return NS_OK;
    5366                 :   }
    5367               0 :   return NS_ERROR_OUT_OF_MEMORY;
    5368                 : }
    5369                 : 
    5370                 : /* static */
    5371                 : nsresult
    5372               0 : nsContentUtils::ASCIIToUpper(nsAString& aStr)
    5373                 : {
    5374               0 :   PRUnichar* iter = aStr.BeginWriting();
    5375               0 :   PRUnichar* end = aStr.EndWriting();
    5376               0 :   if (NS_UNLIKELY(!iter || !end)) {
    5377               0 :     return NS_ERROR_OUT_OF_MEMORY;
    5378                 :   }
    5379               0 :   while (iter != end) {
    5380               0 :     PRUnichar c = *iter;
    5381               0 :     if (c >= 'a' && c <= 'z') {
    5382               0 :       *iter = c + ('A' - 'a');
    5383                 :     }
    5384               0 :     ++iter;
    5385                 :   }
    5386               0 :   return NS_OK;
    5387                 : }
    5388                 : 
    5389                 : /* static */
    5390                 : nsresult
    5391             775 : nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest)
    5392                 : {
    5393             775 :   PRUint32 len = aSource.Length();
    5394             775 :   aDest.SetLength(len);
    5395             775 :   if (aDest.Length() == len) {
    5396             775 :     PRUnichar* dest = aDest.BeginWriting();
    5397             775 :     if (NS_UNLIKELY(!dest)) {
    5398               0 :       return NS_ERROR_OUT_OF_MEMORY;
    5399                 :     }
    5400             775 :     const PRUnichar* iter = aSource.BeginReading();
    5401             775 :     const PRUnichar* end = aSource.EndReading();
    5402            4490 :     while (iter != end) {
    5403            2940 :       PRUnichar c = *iter;
    5404                 :       *dest = (c >= 'a' && c <= 'z') ?
    5405            2940 :          c + ('A' - 'a') : c;
    5406            2940 :       ++iter;
    5407            2940 :       ++dest;
    5408                 :     }
    5409             775 :     return NS_OK;
    5410                 :   }
    5411               0 :   return NS_ERROR_OUT_OF_MEMORY;
    5412                 : }
    5413                 : 
    5414                 : /* static */
    5415                 : bool
    5416               0 : nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1,
    5417                 :                                       const nsAString& aStr2)
    5418                 : {
    5419               0 :   PRUint32 len = aStr1.Length();
    5420               0 :   if (len != aStr2.Length()) {
    5421               0 :     return false;
    5422                 :   }
    5423                 : 
    5424               0 :   const PRUnichar* str1 = aStr1.BeginReading();
    5425               0 :   const PRUnichar* str2 = aStr2.BeginReading();
    5426               0 :   const PRUnichar* end = str1 + len;
    5427                 : 
    5428               0 :   while (str1 < end) {
    5429               0 :     PRUnichar c1 = *str1++;
    5430               0 :     PRUnichar c2 = *str2++;
    5431                 : 
    5432                 :     // First check if any bits other than the 0x0020 differs
    5433               0 :     if ((c1 ^ c2) & 0xffdf) {
    5434               0 :       return false;
    5435                 :     }
    5436                 : 
    5437                 :     // We know they can only differ in the 0x0020 bit.
    5438                 :     // Likely the two chars are the same, so check that first
    5439               0 :     if (c1 != c2) {
    5440                 :       // They do differ, but since it's only in the 0x0020 bit, check if it's
    5441                 :       // the same ascii char, but just differing in case
    5442               0 :       PRUnichar c1Upper = c1 & 0xffdf;
    5443               0 :       if (!('A' <= c1Upper && c1Upper <= 'Z')) {
    5444               0 :         return false;
    5445                 :       }
    5446                 :     }
    5447                 :   }
    5448                 : 
    5449               0 :   return true;
    5450                 : }
    5451                 : 
    5452                 : /* static */
    5453                 : bool
    5454               0 : nsContentUtils::EqualsLiteralIgnoreASCIICase(const nsAString& aStr1,
    5455                 :                                              const char* aStr2,
    5456                 :                                              const PRUint32 len)
    5457                 : {
    5458               0 :   if (aStr1.Length() != len) {
    5459               0 :     return false;
    5460                 :   }
    5461                 :   
    5462               0 :   const PRUnichar* str1 = aStr1.BeginReading();
    5463               0 :   const char*      str2 = aStr2;
    5464               0 :   const PRUnichar* end = str1 + len;
    5465                 :   
    5466               0 :   while (str1 < end) {
    5467               0 :     PRUnichar c1 = *str1++;
    5468               0 :     PRUnichar c2 = *str2++;
    5469                 : 
    5470                 :     // First check if any bits other than the 0x0020 differs
    5471               0 :     if ((c1 ^ c2) & 0xffdf) {
    5472               0 :       return false;
    5473                 :     }
    5474                 :     
    5475                 :     // We know they can only differ in the 0x0020 bit.
    5476                 :     // Likely the two chars are the same, so check that first
    5477               0 :     if (c1 != c2) {
    5478                 :       // They do differ, but since it's only in the 0x0020 bit, check if it's
    5479                 :       // the same ascii char, but just differing in case
    5480               0 :       PRUnichar c1Upper = c1 & 0xffdf;
    5481               0 :       if (!('A' <= c1Upper && c1Upper <= 'Z')) {
    5482               0 :         return false;
    5483                 :       }
    5484                 :     }
    5485                 :   }
    5486                 :   
    5487               0 :   return true;
    5488                 : }
    5489                 : 
    5490                 : /* static */
    5491                 : nsIInterfaceRequestor*
    5492               0 : nsContentUtils::GetSameOriginChecker()
    5493                 : {
    5494               0 :   if (!sSameOriginChecker) {
    5495               0 :     sSameOriginChecker = new nsSameOriginChecker();
    5496               0 :     NS_IF_ADDREF(sSameOriginChecker);
    5497                 :   }
    5498               0 :   return sSameOriginChecker;
    5499                 : }
    5500                 : 
    5501                 : /* static */
    5502                 : nsresult
    5503               0 : nsContentUtils::CheckSameOrigin(nsIChannel *aOldChannel, nsIChannel *aNewChannel)
    5504                 : {
    5505               0 :   if (!nsContentUtils::GetSecurityManager())
    5506               0 :     return NS_ERROR_NOT_AVAILABLE;
    5507                 : 
    5508               0 :   nsCOMPtr<nsIPrincipal> oldPrincipal;
    5509               0 :   nsContentUtils::GetSecurityManager()->
    5510               0 :     GetChannelPrincipal(aOldChannel, getter_AddRefs(oldPrincipal));
    5511                 : 
    5512               0 :   nsCOMPtr<nsIURI> newURI;
    5513               0 :   aNewChannel->GetURI(getter_AddRefs(newURI));
    5514               0 :   nsCOMPtr<nsIURI> newOriginalURI;
    5515               0 :   aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
    5516                 : 
    5517               0 :   NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI);
    5518                 : 
    5519               0 :   nsresult rv = oldPrincipal->CheckMayLoad(newURI, false);
    5520               0 :   if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
    5521               0 :     rv = oldPrincipal->CheckMayLoad(newOriginalURI, false);
    5522                 :   }
    5523                 : 
    5524               0 :   return rv;
    5525                 : }
    5526                 : 
    5527               0 : NS_IMPL_ISUPPORTS2(nsSameOriginChecker,
    5528                 :                    nsIChannelEventSink,
    5529                 :                    nsIInterfaceRequestor)
    5530                 : 
    5531                 : NS_IMETHODIMP
    5532               0 : nsSameOriginChecker::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
    5533                 :                                             nsIChannel *aNewChannel,
    5534                 :                                             PRUint32 aFlags,
    5535                 :                                             nsIAsyncVerifyRedirectCallback *cb)
    5536                 : {
    5537               0 :   NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
    5538                 : 
    5539               0 :   nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel);
    5540               0 :   if (NS_SUCCEEDED(rv)) {
    5541               0 :     cb->OnRedirectVerifyCallback(NS_OK);
    5542                 :   }
    5543                 : 
    5544               0 :   return rv;
    5545                 : }
    5546                 : 
    5547                 : NS_IMETHODIMP
    5548               0 : nsSameOriginChecker::GetInterface(const nsIID & aIID, void **aResult)
    5549                 : {
    5550               0 :   return QueryInterface(aIID, aResult);
    5551                 : }
    5552                 : 
    5553                 : /* static */
    5554                 : nsresult
    5555               0 : nsContentUtils::GetASCIIOrigin(nsIPrincipal* aPrincipal, nsCString& aOrigin)
    5556                 : {
    5557               0 :   NS_PRECONDITION(aPrincipal, "missing principal");
    5558                 : 
    5559               0 :   aOrigin.Truncate();
    5560                 : 
    5561               0 :   nsCOMPtr<nsIURI> uri;
    5562               0 :   nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
    5563               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5564                 : 
    5565               0 :   if (uri) {
    5566               0 :     return GetASCIIOrigin(uri, aOrigin);
    5567                 :   }
    5568                 : 
    5569               0 :   aOrigin.AssignLiteral("null");
    5570                 : 
    5571               0 :   return NS_OK;
    5572                 : }
    5573                 : 
    5574                 : /* static */
    5575                 : nsresult
    5576              96 : nsContentUtils::GetASCIIOrigin(nsIURI* aURI, nsCString& aOrigin)
    5577                 : {
    5578              96 :   NS_PRECONDITION(aURI, "missing uri");
    5579                 : 
    5580              96 :   aOrigin.Truncate();
    5581                 : 
    5582             192 :   nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
    5583              96 :   NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
    5584                 : 
    5585             192 :   nsCString host;
    5586              96 :   nsresult rv = uri->GetAsciiHost(host);
    5587                 : 
    5588              96 :   if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
    5589             192 :     nsCString scheme;
    5590              96 :     rv = uri->GetScheme(scheme);
    5591              96 :     NS_ENSURE_SUCCESS(rv, rv);
    5592                 : 
    5593              96 :     PRInt32 port = -1;
    5594              96 :     uri->GetPort(&port);
    5595              96 :     if (port != -1 && port == NS_GetDefaultPort(scheme.get()))
    5596               0 :       port = -1;
    5597                 : 
    5598             192 :     nsCString hostPort;
    5599              96 :     rv = NS_GenerateHostPort(host, port, hostPort);
    5600              96 :     NS_ENSURE_SUCCESS(rv, rv);
    5601                 : 
    5602             192 :     aOrigin = scheme + NS_LITERAL_CSTRING("://") + hostPort;
    5603                 :   }
    5604                 :   else {
    5605               0 :     aOrigin.AssignLiteral("null");
    5606                 :   }
    5607                 : 
    5608              96 :   return NS_OK;
    5609                 : }
    5610                 : 
    5611                 : /* static */
    5612                 : nsresult
    5613               0 : nsContentUtils::GetUTFOrigin(nsIPrincipal* aPrincipal, nsString& aOrigin)
    5614                 : {
    5615               0 :   NS_PRECONDITION(aPrincipal, "missing principal");
    5616                 : 
    5617               0 :   aOrigin.Truncate();
    5618                 : 
    5619               0 :   nsCOMPtr<nsIURI> uri;
    5620               0 :   nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
    5621               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5622                 : 
    5623               0 :   if (uri) {
    5624               0 :     return GetUTFOrigin(uri, aOrigin);
    5625                 :   }
    5626                 : 
    5627               0 :   aOrigin.AssignLiteral("null");
    5628                 : 
    5629               0 :   return NS_OK;
    5630                 : }
    5631                 : 
    5632                 : /* static */
    5633                 : nsresult
    5634               0 : nsContentUtils::GetUTFOrigin(nsIURI* aURI, nsString& aOrigin)
    5635                 : {
    5636               0 :   NS_PRECONDITION(aURI, "missing uri");
    5637                 : 
    5638               0 :   aOrigin.Truncate();
    5639                 : 
    5640               0 :   nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
    5641               0 :   NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED);
    5642                 : 
    5643               0 :   nsCString host;
    5644               0 :   nsresult rv = uri->GetHost(host);
    5645                 : 
    5646               0 :   if (NS_SUCCEEDED(rv) && !host.IsEmpty()) {
    5647               0 :     nsCString scheme;
    5648               0 :     rv = uri->GetScheme(scheme);
    5649               0 :     NS_ENSURE_SUCCESS(rv, rv);
    5650                 : 
    5651               0 :     PRInt32 port = -1;
    5652               0 :     uri->GetPort(&port);
    5653               0 :     if (port != -1 && port == NS_GetDefaultPort(scheme.get()))
    5654               0 :       port = -1;
    5655                 : 
    5656               0 :     nsCString hostPort;
    5657               0 :     rv = NS_GenerateHostPort(host, port, hostPort);
    5658               0 :     NS_ENSURE_SUCCESS(rv, rv);
    5659                 : 
    5660                 :     aOrigin = NS_ConvertUTF8toUTF16(
    5661               0 :       scheme + NS_LITERAL_CSTRING("://") + hostPort);
    5662                 :   }
    5663                 :   else {
    5664               0 :     aOrigin.AssignLiteral("null");
    5665                 :   }
    5666                 :   
    5667               0 :   return NS_OK;
    5668                 : }
    5669                 : 
    5670                 : /* static */
    5671                 : already_AddRefed<nsIDocument>
    5672            6160 : nsContentUtils::GetDocumentFromScriptContext(nsIScriptContext *aScriptContext)
    5673                 : {
    5674            6160 :   if (!aScriptContext)
    5675            6160 :     return nsnull;
    5676                 : 
    5677                 :   nsCOMPtr<nsIDOMWindow> window =
    5678               0 :     do_QueryInterface(aScriptContext->GetGlobalObject());
    5679               0 :   nsIDocument *doc = nsnull;
    5680               0 :   if (window) {
    5681               0 :     nsCOMPtr<nsIDOMDocument> domdoc;
    5682               0 :     window->GetDocument(getter_AddRefs(domdoc));
    5683               0 :     if (domdoc) {
    5684               0 :       CallQueryInterface(domdoc, &doc);
    5685                 :     }
    5686                 :   }
    5687               0 :   return doc;
    5688                 : }
    5689                 : 
    5690                 : /* static */
    5691                 : bool
    5692               0 : nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal, nsIChannel* aChannel)
    5693                 : {
    5694               0 :   nsCOMPtr<nsIURI> channelURI;
    5695               0 :   nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
    5696               0 :   NS_ENSURE_SUCCESS(rv, false);
    5697                 : 
    5698               0 :   return NS_SUCCEEDED(aPrincipal->CheckMayLoad(channelURI, false));
    5699                 : }
    5700                 : 
    5701               0 : nsContentTypeParser::nsContentTypeParser(const nsAString& aString)
    5702               0 :   : mString(aString), mService(nsnull)
    5703                 : {
    5704               0 :   CallGetService("@mozilla.org/network/mime-hdrparam;1", &mService);
    5705               0 : }
    5706                 : 
    5707               0 : nsContentTypeParser::~nsContentTypeParser()
    5708                 : {
    5709               0 :   NS_IF_RELEASE(mService);
    5710               0 : }
    5711                 : 
    5712                 : nsresult
    5713               0 : nsContentTypeParser::GetParameter(const char* aParameterName, nsAString& aResult)
    5714                 : {
    5715               0 :   NS_ENSURE_TRUE(mService, NS_ERROR_FAILURE);
    5716                 :   return mService->GetParameter(mString, aParameterName,
    5717               0 :                                 EmptyCString(), false, nsnull,
    5718               0 :                                 aResult);
    5719                 : }
    5720                 : 
    5721                 : /* static */
    5722                 : 
    5723                 : // If you change this code, change also AllowedToAct() in
    5724                 : // XPCSystemOnlyWrapper.cpp!
    5725                 : bool
    5726               0 : nsContentUtils::CanAccessNativeAnon()
    5727                 : {
    5728               0 :   JSContext* cx = nsnull;
    5729               0 :   sThreadJSContextStack->Peek(&cx);
    5730               0 :   if (!cx) {
    5731               0 :     return true;
    5732                 :   }
    5733                 :   JSStackFrame* fp;
    5734                 :   nsIPrincipal* principal =
    5735               0 :     sSecurityManager->GetCxSubjectPrincipalAndFrame(cx, &fp);
    5736               0 :   NS_ENSURE_TRUE(principal, false);
    5737                 : 
    5738               0 :   if (!fp) {
    5739               0 :     if (!JS_FrameIterator(cx, &fp)) {
    5740                 :       // No code at all is running. So we must be arriving here as the result
    5741                 :       // of C++ code asking us to do something. Allow access.
    5742               0 :       return true;
    5743                 :     }
    5744                 : 
    5745                 :     // Some code is running, we can't make the assumption, as above, but we
    5746                 :     // can't use a native frame, so clear fp.
    5747               0 :     fp = nsnull;
    5748               0 :   } else if (!JS_IsScriptFrame(cx, fp)) {
    5749               0 :     fp = nsnull;
    5750                 :   }
    5751                 : 
    5752                 :   bool privileged;
    5753               0 :   if (NS_SUCCEEDED(sSecurityManager->IsSystemPrincipal(principal, &privileged)) &&
    5754                 :       privileged) {
    5755                 :     // Chrome things are allowed to touch us.
    5756               0 :     return true;
    5757                 :   }
    5758                 : 
    5759                 :   // XXX HACK EWW! Allow chrome://global/ access to these things, even
    5760                 :   // if they've been cloned into less privileged contexts.
    5761                 :   static const char prefix[] = "chrome://global/";
    5762                 :   const char *filename;
    5763               0 :   if (fp && JS_IsScriptFrame(cx, fp) &&
    5764               0 :       (filename = JS_GetScriptFilename(cx, JS_GetFrameScript(cx, fp))) &&
    5765               0 :       !strncmp(filename, prefix, ArrayLength(prefix) - 1)) {
    5766               0 :     return true;
    5767                 :   }
    5768                 : 
    5769                 :   // Before we throw, check for UniversalXPConnect.
    5770               0 :   nsresult rv = sSecurityManager->IsCapabilityEnabled("UniversalXPConnect", &privileged);
    5771               0 :   if (NS_SUCCEEDED(rv) && privileged) {
    5772               0 :     return true;
    5773                 :   }
    5774                 : 
    5775               0 :   return false;
    5776                 : }
    5777                 : 
    5778                 : /* static */ nsresult
    5779               0 : nsContentUtils::DispatchXULCommand(nsIContent* aTarget,
    5780                 :                                    bool aTrusted,
    5781                 :                                    nsIDOMEvent* aSourceEvent,
    5782                 :                                    nsIPresShell* aShell,
    5783                 :                                    bool aCtrl,
    5784                 :                                    bool aAlt,
    5785                 :                                    bool aShift,
    5786                 :                                    bool aMeta)
    5787                 : {
    5788               0 :   NS_ENSURE_STATE(aTarget);
    5789               0 :   nsIDocument* doc = aTarget->OwnerDoc();
    5790               0 :   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(doc);
    5791               0 :   NS_ENSURE_STATE(domDoc);
    5792               0 :   nsCOMPtr<nsIDOMEvent> event;
    5793               0 :   domDoc->CreateEvent(NS_LITERAL_STRING("xulcommandevent"),
    5794               0 :                       getter_AddRefs(event));
    5795               0 :   nsCOMPtr<nsIDOMXULCommandEvent> xulCommand = do_QueryInterface(event);
    5796               0 :   nsCOMPtr<nsIPrivateDOMEvent> pEvent = do_QueryInterface(xulCommand);
    5797               0 :   NS_ENSURE_STATE(pEvent);
    5798               0 :   nsresult rv = xulCommand->InitCommandEvent(NS_LITERAL_STRING("command"),
    5799               0 :                                              true, true, doc->GetWindow(),
    5800                 :                                              0, aCtrl, aAlt, aShift, aMeta,
    5801               0 :                                              aSourceEvent);
    5802               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5803                 : 
    5804               0 :   if (aShell) {
    5805               0 :     nsEventStatus status = nsEventStatus_eIgnore;
    5806               0 :     nsCOMPtr<nsIPresShell> kungFuDeathGrip = aShell;
    5807               0 :     return aShell->HandleDOMEventWithTarget(aTarget, event, &status);
    5808                 :   }
    5809                 : 
    5810               0 :   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(aTarget);
    5811               0 :   NS_ENSURE_STATE(target);
    5812                 :   bool dummy;
    5813               0 :   return target->DispatchEvent(event, &dummy);
    5814                 : }
    5815                 : 
    5816                 : // static
    5817                 : nsresult
    5818            1933 : nsContentUtils::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
    5819                 :                            nsWrapperCache *cache, const nsIID* aIID, jsval *vp,
    5820                 :                            nsIXPConnectJSObjectHolder **aHolder,
    5821                 :                            bool aAllowWrapping)
    5822                 : {
    5823            1933 :   if (!native) {
    5824               0 :     NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!");
    5825                 : 
    5826               0 :     *vp = JSVAL_NULL;
    5827                 : 
    5828               0 :     return NS_OK;
    5829                 :   }
    5830                 : 
    5831            1933 :   JSObject *wrapper = xpc_FastGetCachedWrapper(cache, scope, vp);
    5832            1933 :   if (wrapper) {
    5833               0 :     return NS_OK;
    5834                 :   }
    5835                 : 
    5836            1933 :   NS_ENSURE_TRUE(sXPConnect && sThreadJSContextStack, NS_ERROR_UNEXPECTED);
    5837                 : 
    5838                 :   // Keep sXPConnect and sThreadJSContextStack alive. If we're on the main
    5839                 :   // thread then this can be done simply and cheaply by adding a reference to
    5840                 :   // nsLayoutStatics. If we're not on the main thread then we need to add a
    5841                 :   // more expensive reference sXPConnect directly. We have to use manual
    5842                 :   // AddRef and Release calls so don't early-exit from this function after we've
    5843                 :   // added the reference!
    5844            1933 :   bool isMainThread = NS_IsMainThread();
    5845                 : 
    5846            1933 :   if (isMainThread) {
    5847            1933 :     nsLayoutStatics::AddRef();
    5848                 :   }
    5849                 :   else {
    5850               0 :     sXPConnect->AddRef();
    5851                 :   }
    5852                 : 
    5853                 :   JSContext *topJSContext;
    5854            1933 :   nsresult rv = sThreadJSContextStack->Peek(&topJSContext);
    5855            1933 :   if (NS_SUCCEEDED(rv)) {
    5856            1933 :     bool push = topJSContext != cx;
    5857            1933 :     if (push) {
    5858            1861 :       rv = sThreadJSContextStack->Push(cx);
    5859                 :     }
    5860            1933 :     if (NS_SUCCEEDED(rv)) {
    5861                 :       rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
    5862            1933 :                                          aAllowWrapping, vp, aHolder);
    5863            1933 :       if (push) {
    5864            1861 :         sThreadJSContextStack->Pop(nsnull);
    5865                 :       }
    5866                 :     }
    5867                 :   }
    5868                 : 
    5869            1933 :   if (isMainThread) {
    5870            1933 :     nsLayoutStatics::Release();
    5871                 :   }
    5872                 :   else {
    5873               0 :     sXPConnect->Release();
    5874                 :   }
    5875                 : 
    5876            1933 :   return rv;
    5877                 : }
    5878                 : 
    5879                 : nsresult
    5880               0 : nsContentUtils::CreateArrayBuffer(JSContext *aCx, const nsACString& aData,
    5881                 :                                   JSObject** aResult)
    5882                 : {
    5883               0 :   if (!aCx) {
    5884               0 :     return NS_ERROR_FAILURE;
    5885                 :   }
    5886                 : 
    5887               0 :   PRInt32 dataLen = aData.Length();
    5888               0 :   *aResult = js_CreateArrayBuffer(aCx, dataLen);
    5889               0 :   if (!*aResult) {
    5890               0 :     return NS_ERROR_FAILURE;
    5891                 :   }
    5892                 : 
    5893               0 :   if (dataLen > 0) {
    5894               0 :     JSObject *abuf = js::ArrayBuffer::getArrayBuffer(*aResult);
    5895               0 :     NS_ASSERTION(abuf, "What happened?");
    5896               0 :     memcpy(JS_GetArrayBufferData(abuf), aData.BeginReading(), dataLen);
    5897                 :   }
    5898                 : 
    5899               0 :   return NS_OK;
    5900                 : }
    5901                 : 
    5902                 : void
    5903               0 : nsContentUtils::StripNullChars(const nsAString& aInStr, nsAString& aOutStr)
    5904                 : {
    5905                 :   // In common cases where we don't have nulls in the
    5906                 :   // string we can simple simply bypass the checking code.
    5907               0 :   PRInt32 firstNullPos = aInStr.FindChar('\0');
    5908               0 :   if (firstNullPos == kNotFound) {
    5909               0 :     aOutStr.Assign(aInStr);
    5910               0 :     return;
    5911                 :   }
    5912                 : 
    5913               0 :   aOutStr.SetCapacity(aInStr.Length() - 1);
    5914               0 :   nsAString::const_iterator start, end;
    5915               0 :   aInStr.BeginReading(start);
    5916               0 :   aInStr.EndReading(end);
    5917               0 :   while (start != end) {
    5918               0 :     if (*start != '\0')
    5919               0 :       aOutStr.Append(*start);
    5920               0 :     ++start;
    5921                 :   }
    5922                 : }
    5923                 : 
    5924               0 : struct ClassMatchingInfo {
    5925                 :   nsAttrValue::AtomArray mClasses;
    5926                 :   nsCaseTreatment mCaseTreatment;
    5927                 : };
    5928                 : 
    5929                 : static bool
    5930               0 : MatchClassNames(nsIContent* aContent, PRInt32 aNamespaceID, nsIAtom* aAtom,
    5931                 :                 void* aData)
    5932                 : {
    5933                 :   // We can't match if there are no class names
    5934               0 :   const nsAttrValue* classAttr = aContent->GetClasses();
    5935               0 :   if (!classAttr) {
    5936               0 :     return false;
    5937                 :   }
    5938                 :   
    5939                 :   // need to match *all* of the classes
    5940               0 :   ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
    5941               0 :   PRUint32 length = info->mClasses.Length();
    5942               0 :   if (!length) {
    5943                 :     // If we actually had no classes, don't match.
    5944               0 :     return false;
    5945                 :   }
    5946                 :   PRUint32 i;
    5947               0 :   for (i = 0; i < length; ++i) {
    5948               0 :     if (!classAttr->Contains(info->mClasses[i],
    5949               0 :                              info->mCaseTreatment)) {
    5950               0 :       return false;
    5951                 :     }
    5952                 :   }
    5953                 :   
    5954               0 :   return true;
    5955                 : }
    5956                 : 
    5957                 : static void
    5958               0 : DestroyClassNameArray(void* aData)
    5959                 : {
    5960               0 :   ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
    5961               0 :   delete info;
    5962               0 : }
    5963                 : 
    5964                 : static void*
    5965               0 : AllocClassMatchingInfo(nsINode* aRootNode,
    5966                 :                        const nsString* aClasses)
    5967                 : {
    5968               0 :   nsAttrValue attrValue;
    5969               0 :   attrValue.ParseAtomArray(*aClasses);
    5970                 :   // nsAttrValue::Equals is sensitive to order, so we'll send an array
    5971               0 :   ClassMatchingInfo* info = new ClassMatchingInfo;
    5972               0 :   NS_ENSURE_TRUE(info, nsnull);
    5973                 : 
    5974               0 :   if (attrValue.Type() == nsAttrValue::eAtomArray) {
    5975               0 :     info->mClasses.SwapElements(*(attrValue.GetAtomArrayValue()));
    5976               0 :   } else if (attrValue.Type() == nsAttrValue::eAtom) {
    5977               0 :     info->mClasses.AppendElement(attrValue.GetAtomValue());
    5978                 :   }
    5979                 : 
    5980                 :   info->mCaseTreatment =
    5981               0 :     aRootNode->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks ?
    5982               0 :     eIgnoreCase : eCaseMatters;
    5983               0 :   return info;
    5984                 : }
    5985                 : 
    5986                 : // static
    5987                 : 
    5988                 : nsresult
    5989               0 : nsContentUtils::GetElementsByClassName(nsINode* aRootNode,
    5990                 :                                        const nsAString& aClasses,
    5991                 :                                        nsIDOMNodeList** aReturn)
    5992                 : {
    5993               0 :   NS_PRECONDITION(aRootNode, "Must have root node");
    5994                 :   
    5995                 :   nsContentList* elements =
    5996                 :     NS_GetFuncStringContentList(aRootNode, MatchClassNames,
    5997                 :                                 DestroyClassNameArray,
    5998                 :                                 AllocClassMatchingInfo,
    5999               0 :                                 aClasses).get();
    6000               0 :   NS_ENSURE_TRUE(elements, NS_ERROR_OUT_OF_MEMORY);
    6001                 : 
    6002                 :   // Transfer ownership
    6003               0 :   *aReturn = elements;
    6004                 : 
    6005               0 :   return NS_OK;
    6006                 : }
    6007                 : 
    6008                 : #ifdef DEBUG
    6009                 : class DebugWrapperTraversalCallback : public nsCycleCollectionTraversalCallback
    6010                 : {
    6011                 : public:
    6012               5 :   DebugWrapperTraversalCallback(void* aWrapper) : mFound(false),
    6013               5 :                                                   mWrapper(aWrapper)
    6014                 :   {
    6015               5 :     mFlags = WANT_ALL_TRACES;
    6016               5 :   }
    6017                 : 
    6018               5 :   NS_IMETHOD_(void) DescribeRefCountedNode(nsrefcnt refCount,
    6019                 :                                            size_t objSz,
    6020                 :                                            const char *objName)
    6021                 :   {
    6022               5 :   }
    6023               0 :   NS_IMETHOD_(void) DescribeGCedNode(bool isMarked,
    6024                 :                                      size_t objSz,
    6025                 :                                      const char *objName)
    6026                 :   {
    6027               0 :   }
    6028               0 :   NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root)
    6029                 :   {
    6030               0 :   }
    6031               0 :   NS_IMETHOD_(void) NoteRoot(PRUint32 langID, void* root,
    6032                 :                              nsCycleCollectionParticipant* helper)
    6033                 :   {
    6034               0 :   }
    6035              12 :   NS_IMETHOD_(void) NoteScriptChild(PRUint32 langID, void* child)
    6036                 :   {
    6037              12 :     if (langID == nsIProgrammingLanguage::JAVASCRIPT &&
    6038                 :         child == mWrapper) {
    6039              10 :       mFound = true;
    6040                 :     }
    6041              12 :   }
    6042              34 :   NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child)
    6043                 :   {
    6044              34 :   }
    6045               4 :   NS_IMETHOD_(void) NoteNativeChild(void* child,
    6046                 :                                     nsCycleCollectionParticipant* helper)
    6047                 :   {
    6048               4 :   }
    6049                 : 
    6050               0 :   NS_IMETHOD_(void) NoteNextEdgeName(const char* name)
    6051                 :   {
    6052               0 :   }
    6053                 : 
    6054               0 :   NS_IMETHOD_(void) NoteWeakMapping(void* map, void* key, void* val)
    6055                 :   {
    6056               0 :   }
    6057                 : 
    6058                 :   bool mFound;
    6059                 : 
    6060                 : private:
    6061                 :   void* mWrapper;
    6062                 : };
    6063                 : 
    6064                 : static void
    6065               6 : DebugWrapperTraceCallback(PRUint32 langID, void *p, const char *name,
    6066                 :                           void *closure)
    6067                 : {
    6068                 :   DebugWrapperTraversalCallback* callback =
    6069               6 :     static_cast<DebugWrapperTraversalCallback*>(closure);
    6070               6 :   callback->NoteScriptChild(langID, p);
    6071               6 : }
    6072                 : 
    6073                 : // static
    6074                 : void
    6075               5 : nsContentUtils::CheckCCWrapperTraversal(nsISupports* aScriptObjectHolder,
    6076                 :                                         nsWrapperCache* aCache)
    6077                 : {
    6078               5 :   JSObject* wrapper = aCache->GetWrapper();
    6079               5 :   if (!wrapper) {
    6080               0 :     return;
    6081                 :   }
    6082                 : 
    6083                 :   nsXPCOMCycleCollectionParticipant* participant;
    6084               5 :   CallQueryInterface(aScriptObjectHolder, &participant);
    6085                 : 
    6086               5 :   DebugWrapperTraversalCallback callback(wrapper);
    6087                 : 
    6088               5 :   participant->Traverse(aScriptObjectHolder, callback);
    6089               5 :   NS_ASSERTION(callback.mFound,
    6090                 :                "Cycle collection participant didn't traverse to preserved "
    6091                 :                "wrapper! This will probably crash.");
    6092                 : 
    6093               5 :   callback.mFound = false;
    6094               5 :   participant->Trace(aScriptObjectHolder, DebugWrapperTraceCallback, &callback);
    6095               5 :   NS_ASSERTION(callback.mFound,
    6096                 :                "Cycle collection participant didn't trace preserved wrapper! "
    6097                 :                "This will probably crash.");
    6098                 : }
    6099                 : #endif
    6100                 : 
    6101                 : // static
    6102                 : bool
    6103               0 : nsContentUtils::IsFocusedContent(const nsIContent* aContent)
    6104                 : {
    6105               0 :   nsFocusManager* fm = nsFocusManager::GetFocusManager();
    6106                 : 
    6107               0 :   return fm && fm->GetFocusedContent() == aContent;
    6108                 : }
    6109                 : 
    6110                 : bool
    6111               0 : nsContentUtils::IsSubDocumentTabbable(nsIContent* aContent)
    6112                 : {
    6113               0 :   nsIDocument* doc = aContent->GetCurrentDoc();
    6114               0 :   if (!doc) {
    6115               0 :     return false;
    6116                 :   }
    6117                 : 
    6118                 :   // XXXbz should this use OwnerDoc() for GetSubDocumentFor?
    6119                 :   // sXBL/XBL2 issue!
    6120               0 :   nsIDocument* subDoc = doc->GetSubDocumentFor(aContent);
    6121               0 :   if (!subDoc) {
    6122               0 :     return false;
    6123                 :   }
    6124                 : 
    6125               0 :   nsCOMPtr<nsISupports> container = subDoc->GetContainer();
    6126               0 :   nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
    6127               0 :   if (!docShell) {
    6128               0 :     return false;
    6129                 :   }
    6130                 : 
    6131               0 :   nsCOMPtr<nsIContentViewer> contentViewer;
    6132               0 :   docShell->GetContentViewer(getter_AddRefs(contentViewer));
    6133               0 :   if (!contentViewer) {
    6134               0 :     return false;
    6135                 :   }
    6136                 : 
    6137               0 :   nsCOMPtr<nsIContentViewer> zombieViewer;
    6138               0 :   contentViewer->GetPreviousViewer(getter_AddRefs(zombieViewer));
    6139                 : 
    6140                 :   // If there are 2 viewers for the current docshell, that
    6141                 :   // means the current document is a zombie document.
    6142                 :   // Only navigate into the subdocument if it's not a zombie.
    6143               0 :   return !zombieViewer;
    6144                 : }
    6145                 : 
    6146                 : void
    6147               0 : nsContentUtils::FlushLayoutForTree(nsIDOMWindow* aWindow)
    6148                 : {
    6149               0 :     nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
    6150               0 :     if (!piWin)
    6151                 :         return;
    6152                 : 
    6153                 :     // Note that because FlushPendingNotifications flushes parents, this
    6154                 :     // is O(N^2) in docshell tree depth.  However, the docshell tree is
    6155                 :     // usually pretty shallow.
    6156                 : 
    6157               0 :     nsCOMPtr<nsIDOMDocument> domDoc;
    6158               0 :     aWindow->GetDocument(getter_AddRefs(domDoc));
    6159               0 :     nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
    6160               0 :     if (doc) {
    6161               0 :         doc->FlushPendingNotifications(Flush_Layout);
    6162                 :     }
    6163                 : 
    6164                 :     nsCOMPtr<nsIDocShellTreeNode> node =
    6165               0 :         do_QueryInterface(piWin->GetDocShell());
    6166               0 :     if (node) {
    6167               0 :         PRInt32 i = 0, i_end;
    6168               0 :         node->GetChildCount(&i_end);
    6169               0 :         for (; i < i_end; ++i) {
    6170               0 :             nsCOMPtr<nsIDocShellTreeItem> item;
    6171               0 :             node->GetChildAt(i, getter_AddRefs(item));
    6172               0 :             nsCOMPtr<nsIDOMWindow> win = do_GetInterface(item);
    6173               0 :             if (win) {
    6174               0 :                 FlushLayoutForTree(win);
    6175                 :             }
    6176                 :         }
    6177                 :     }
    6178                 : }
    6179                 : 
    6180               0 : void nsContentUtils::RemoveNewlines(nsString &aString)
    6181                 : {
    6182                 :   // strip CR/LF and null
    6183                 :   static const char badChars[] = {'\r', '\n', 0};
    6184               0 :   aString.StripChars(badChars);
    6185               0 : }
    6186                 : 
    6187                 : void
    6188               1 : nsContentUtils::PlatformToDOMLineBreaks(nsString &aString)
    6189                 : {
    6190               1 :   if (aString.FindChar(PRUnichar('\r')) != -1) {
    6191                 :     // Windows linebreaks: Map CRLF to LF:
    6192               0 :     aString.ReplaceSubstring(NS_LITERAL_STRING("\r\n").get(),
    6193               0 :                              NS_LITERAL_STRING("\n").get());
    6194                 : 
    6195                 :     // Mac linebreaks: Map any remaining CR to LF:
    6196               0 :     aString.ReplaceSubstring(NS_LITERAL_STRING("\r").get(),
    6197               0 :                              NS_LITERAL_STRING("\n").get());
    6198                 :   }
    6199               1 : }
    6200                 : 
    6201                 : nsIWidget *
    6202               0 : nsContentUtils::WidgetForDocument(nsIDocument *aDoc)
    6203                 : {
    6204               0 :   nsIDocument* doc = aDoc;
    6205               0 :   nsIDocument* displayDoc = doc->GetDisplayDocument();
    6206               0 :   if (displayDoc) {
    6207               0 :     doc = displayDoc;
    6208                 :   }
    6209                 : 
    6210               0 :   nsIPresShell* shell = doc->GetShell();
    6211               0 :   nsCOMPtr<nsISupports> container = doc->GetContainer();
    6212               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = do_QueryInterface(container);
    6213               0 :   while (!shell && docShellTreeItem) {
    6214                 :     // We may be in a display:none subdocument, or we may not have a presshell
    6215                 :     // created yet.
    6216                 :     // Walk the docshell tree to find the nearest container that has a presshell,
    6217                 :     // and find the root widget from that.
    6218               0 :     nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
    6219               0 :     nsCOMPtr<nsIPresShell> presShell;
    6220               0 :     docShell->GetPresShell(getter_AddRefs(presShell));
    6221               0 :     if (presShell) {
    6222               0 :       shell = presShell;
    6223                 :     } else {
    6224               0 :       nsCOMPtr<nsIDocShellTreeItem> parent;
    6225               0 :       docShellTreeItem->GetParent(getter_AddRefs(parent));
    6226               0 :       docShellTreeItem = parent;
    6227                 :     }
    6228                 :   }
    6229                 : 
    6230               0 :   if (shell) {
    6231               0 :     nsIViewManager* VM = shell->GetViewManager();
    6232               0 :     if (VM) {
    6233               0 :       nsIView* rootView = VM->GetRootView();
    6234               0 :       if (rootView) {
    6235               0 :         nsIView* displayRoot = nsIViewManager::GetDisplayRootFor(rootView);
    6236               0 :         if (displayRoot) {
    6237               0 :           return displayRoot->GetNearestWidget(nsnull);
    6238                 :         }
    6239                 :       }
    6240                 :     }
    6241                 :   }
    6242                 : 
    6243               0 :   return nsnull;
    6244                 : }
    6245                 : 
    6246                 : static already_AddRefed<LayerManager>
    6247               0 : LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
    6248                 :                                 bool* aAllowRetaining)
    6249                 : {
    6250               0 :   nsIWidget *widget = nsContentUtils::WidgetForDocument(aDoc);
    6251               0 :   if (widget) {
    6252                 :     nsRefPtr<LayerManager> manager =
    6253                 :       widget->GetLayerManager(aRequirePersistent ? nsIWidget::LAYER_MANAGER_PERSISTENT : 
    6254                 :                               nsIWidget::LAYER_MANAGER_CURRENT,
    6255               0 :                               aAllowRetaining);
    6256               0 :     return manager.forget();
    6257                 :   }
    6258                 : 
    6259               0 :   return nsnull;
    6260                 : }
    6261                 : 
    6262                 : already_AddRefed<LayerManager>
    6263               0 : nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
    6264                 : {
    6265               0 :   return LayerManagerForDocumentInternal(aDoc, false, aAllowRetaining);
    6266                 : }
    6267                 : 
    6268                 : already_AddRefed<LayerManager>
    6269               0 : nsContentUtils::PersistentLayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
    6270                 : {
    6271               0 :   return LayerManagerForDocumentInternal(aDoc, true, aAllowRetaining);
    6272                 : }
    6273                 : 
    6274                 : bool
    6275               0 : nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal)
    6276                 : {
    6277               0 :   if (IsSystemPrincipal(aPrincipal)) {
    6278               0 :     return true;
    6279                 :   }
    6280                 :   
    6281               0 :   nsCOMPtr<nsIURI> princURI;
    6282               0 :   aPrincipal->GetURI(getter_AddRefs(princURI));
    6283                 :   
    6284                 :   return princURI &&
    6285               0 :          ((sAllowXULXBL_for_file && SchemeIs(princURI, "file")) ||
    6286               0 :           IsSitePermAllow(princURI, "allowXULXBL"));
    6287                 : }
    6288                 : 
    6289                 : already_AddRefed<nsIDocumentLoaderFactory>
    6290               0 : nsContentUtils::FindInternalContentViewer(const char* aType,
    6291                 :                                           ContentViewerType* aLoaderType)
    6292                 : {
    6293               0 :   if (aLoaderType) {
    6294               0 :     *aLoaderType = TYPE_UNSUPPORTED;
    6295                 :   }
    6296                 : 
    6297                 :   // one helper factory, please
    6298               0 :   nsCOMPtr<nsICategoryManager> catMan(do_GetService(NS_CATEGORYMANAGER_CONTRACTID));
    6299               0 :   if (!catMan)
    6300               0 :     return NULL;
    6301                 : 
    6302               0 :   nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
    6303                 : 
    6304               0 :   nsXPIDLCString contractID;
    6305               0 :   nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", aType, getter_Copies(contractID));
    6306               0 :   if (NS_SUCCEEDED(rv)) {
    6307               0 :     docFactory = do_GetService(contractID);
    6308               0 :     if (docFactory && aLoaderType) {
    6309               0 :       if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID))
    6310               0 :         *aLoaderType = TYPE_CONTENT;
    6311               0 :       else if (contractID.EqualsLiteral(PLUGIN_DLF_CONTRACTID))
    6312               0 :         *aLoaderType = TYPE_PLUGIN;
    6313                 :       else
    6314               0 :       *aLoaderType = TYPE_UNKNOWN;
    6315                 :     }
    6316               0 :     return docFactory.forget();
    6317                 :   }
    6318                 : 
    6319                 : #ifdef MOZ_MEDIA
    6320                 : #ifdef MOZ_OGG
    6321               0 :   if (nsHTMLMediaElement::IsOggEnabled()) {
    6322               0 :     for (unsigned int i = 0; i < ArrayLength(nsHTMLMediaElement::gOggTypes); ++i) {
    6323               0 :       const char* type = nsHTMLMediaElement::gOggTypes[i];
    6324               0 :       if (!strcmp(aType, type)) {
    6325               0 :         docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
    6326               0 :         if (docFactory && aLoaderType) {
    6327               0 :           *aLoaderType = TYPE_CONTENT;
    6328                 :         }
    6329               0 :         return docFactory.forget();
    6330                 :       }
    6331                 :     }
    6332                 :   }
    6333                 : #endif
    6334                 : 
    6335                 : #ifdef MOZ_WEBM
    6336               0 :   if (nsHTMLMediaElement::IsWebMEnabled()) {
    6337               0 :     for (unsigned int i = 0; i < ArrayLength(nsHTMLMediaElement::gWebMTypes); ++i) {
    6338               0 :       const char* type = nsHTMLMediaElement::gWebMTypes[i];
    6339               0 :       if (!strcmp(aType, type)) {
    6340               0 :         docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
    6341               0 :         if (docFactory && aLoaderType) {
    6342               0 :           *aLoaderType = TYPE_CONTENT;
    6343                 :         }
    6344               0 :         return docFactory.forget();
    6345                 :       }
    6346                 :     }
    6347                 :   }
    6348                 : #endif
    6349                 : #endif // MOZ_MEDIA
    6350                 : 
    6351               0 :   return NULL;
    6352                 : }
    6353                 : 
    6354                 : // static
    6355                 : bool
    6356               0 : nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
    6357                 :                                   nsIDocument* aDocument)
    6358                 : {
    6359               0 :   NS_ASSERTION(aDocument, "aDocument should be a valid pointer (not null)");
    6360               0 :   NS_ENSURE_TRUE(aDocument->GetScriptGlobalObject(), true);
    6361                 : 
    6362               0 :   JSContext* ctx = (JSContext*) aDocument->GetScriptGlobalObject()->
    6363               0 :                                   GetContext()->GetNativeContext();
    6364               0 :   NS_ENSURE_TRUE(ctx, true);
    6365                 : 
    6366               0 :   JSAutoRequest ar(ctx);
    6367                 : 
    6368                 :   // The pattern has to match the entire value.
    6369               0 :   aPattern.Insert(NS_LITERAL_STRING("^(?:"), 0);
    6370               0 :   aPattern.Append(NS_LITERAL_STRING(")$"));
    6371                 : 
    6372                 :   JSObject* re = JS_NewUCRegExpObjectNoStatics(ctx, reinterpret_cast<jschar*>
    6373               0 :                                                  (aPattern.BeginWriting()),
    6374               0 :                                                 aPattern.Length(), 0);
    6375               0 :   NS_ENSURE_TRUE(re, true);
    6376                 : 
    6377               0 :   jsval rval = JSVAL_NULL;
    6378               0 :   size_t idx = 0;
    6379                 :   JSBool res;
    6380                 : 
    6381                 :   res = JS_ExecuteRegExpNoStatics(ctx, re, reinterpret_cast<jschar*>
    6382               0 :                                     (aValue.BeginWriting()),
    6383               0 :                                   aValue.Length(), &idx, JS_TRUE, &rval);
    6384                 : 
    6385               0 :   return res == JS_FALSE || rval != JSVAL_NULL;
    6386                 : }
    6387                 : 
    6388                 : // static
    6389                 : nsresult
    6390               4 : nsContentUtils::URIInheritsSecurityContext(nsIURI *aURI, bool *aResult)
    6391                 : {
    6392                 :   // Note: about:blank URIs do NOT inherit the security context from the
    6393                 :   // current document, which is what this function tests for...
    6394                 :   return NS_URIChainHasFlags(aURI,
    6395                 :                              nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
    6396               4 :                              aResult);
    6397                 : }
    6398                 : 
    6399                 : // static
    6400                 : bool
    6401               4 : nsContentUtils::SetUpChannelOwner(nsIPrincipal* aLoadingPrincipal,
    6402                 :                                   nsIChannel* aChannel,
    6403                 :                                   nsIURI* aURI,
    6404                 :                                   bool aSetUpForAboutBlank)
    6405                 : {
    6406                 :   //
    6407                 :   // Set the owner of the channel, but only for channels that can't
    6408                 :   // provide their own security context.
    6409                 :   //
    6410                 :   // XXX: It seems wrong that the owner is ignored - even if one is
    6411                 :   //      supplied) unless the URI is javascript or data or about:blank.
    6412                 :   // XXX: If this is ever changed, check all callers for what owners
    6413                 :   //      they're passing in.  In particular, see the code and
    6414                 :   //      comments in nsDocShell::LoadURI where we fall back on
    6415                 :   //      inheriting the owner if called from chrome.  That would be
    6416                 :   //      very wrong if this code changed anything but channels that
    6417                 :   //      can't provide their own security context!
    6418                 :   //
    6419                 :   //      (Currently chrome URIs set the owner when they are created!
    6420                 :   //      So setting a NULL owner would be bad!)
    6421                 :   //
    6422                 :   bool inherit;
    6423                 :   // We expect URIInheritsSecurityContext to return success for an
    6424                 :   // about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
    6425                 :   // This condition needs to match the one in nsDocShell::InternalLoad where
    6426                 :   // we're checking for things that will use the owner.
    6427               4 :   if (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &inherit)) &&
    6428               0 :       (inherit || (aSetUpForAboutBlank && NS_IsAboutBlank(aURI)))) {
    6429               2 :     aChannel->SetOwner(aLoadingPrincipal);
    6430               2 :     return true;
    6431                 :   }
    6432                 : 
    6433                 :   //
    6434                 :   // file: uri special-casing
    6435                 :   //
    6436                 :   // If this is a file: load opened from another file: then it may need
    6437                 :   // to inherit the owner from the referrer so they can script each other.
    6438                 :   // If we don't set the owner explicitly then each file: gets an owner
    6439                 :   // based on its own codebase later.
    6440                 :   //
    6441               2 :   if (URIIsLocalFile(aURI) && aLoadingPrincipal &&
    6442               0 :       NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false)) &&
    6443                 :       // One more check here.  CheckMayLoad will always return true for the
    6444                 :       // system principal, but we do NOT want to inherit in that case.
    6445               0 :       !IsSystemPrincipal(aLoadingPrincipal)) {
    6446               0 :     aChannel->SetOwner(aLoadingPrincipal);
    6447               0 :     return true;
    6448                 :   }
    6449                 : 
    6450               2 :   return false;
    6451                 : }
    6452                 : 
    6453                 : bool
    6454               0 : nsContentUtils::IsFullScreenApiEnabled()
    6455                 : {
    6456               0 :   return sIsFullScreenApiEnabled;
    6457                 : }
    6458                 : 
    6459               0 : bool nsContentUtils::IsRequestFullScreenAllowed()
    6460                 : {
    6461               0 :   return !sTrustedFullScreenOnly ||
    6462               0 :          nsEventStateManager::IsHandlingUserInput() ||
    6463               0 :          IsCallerChrome();
    6464                 : }
    6465                 : 
    6466                 : bool
    6467               0 : nsContentUtils::IsFullScreenKeyInputRestricted()
    6468                 : {
    6469               0 :   return sFullScreenKeyInputRestricted;
    6470                 : }
    6471                 : 
    6472                 : static void
    6473               0 : CheckForWindowedPlugins(nsIContent* aContent, void* aResult)
    6474                 : {
    6475               0 :   if (!aContent->IsInDoc()) {
    6476               0 :     return;
    6477                 :   }
    6478               0 :   nsCOMPtr<nsIObjectLoadingContent> olc(do_QueryInterface(aContent));
    6479               0 :   if (!olc) {
    6480                 :     return;
    6481                 :   }
    6482               0 :   nsRefPtr<nsNPAPIPluginInstance> plugin;
    6483               0 :   olc->GetPluginInstance(getter_AddRefs(plugin));
    6484               0 :   if (!plugin) {
    6485                 :     return;
    6486                 :   }
    6487               0 :   bool isWindowless = false;
    6488               0 :   nsresult res = plugin->IsWindowless(&isWindowless);
    6489               0 :   if (NS_SUCCEEDED(res) && !isWindowless) {
    6490               0 :     *static_cast<bool*>(aResult) = true;
    6491                 :   }
    6492                 : }
    6493                 : 
    6494                 : static bool
    6495               0 : DocTreeContainsWindowedPlugins(nsIDocument* aDoc, void* aResult)
    6496                 : {
    6497               0 :   if (!nsContentUtils::IsChromeDoc(aDoc)) {
    6498               0 :     aDoc->EnumerateFreezableElements(CheckForWindowedPlugins, aResult);
    6499                 :   }
    6500               0 :   if (*static_cast<bool*>(aResult)) {
    6501                 :     // Return false to stop iteration, we found a windowed plugin.
    6502               0 :     return false;
    6503                 :   }
    6504               0 :   aDoc->EnumerateSubDocuments(DocTreeContainsWindowedPlugins, aResult);
    6505                 :   // Return false to stop iteration if we found a windowed plugin in
    6506                 :   // the sub documents.
    6507               0 :   return !*static_cast<bool*>(aResult);
    6508                 : }
    6509                 : 
    6510                 : /* static */
    6511                 : bool
    6512               0 : nsContentUtils::HasPluginWithUncontrolledEventDispatch(nsIDocument* aDoc)
    6513                 : {
    6514                 : #ifdef XP_MACOSX
    6515                 :   // We control dispatch to all mac plugins.
    6516                 :   return false;
    6517                 : #endif
    6518               0 :   bool result = false;
    6519                 :   
    6520                 :   // Find the top of the document's branch, the child of the chrome document.
    6521               0 :   nsIDocument* doc = aDoc;
    6522               0 :   nsIDocument* parent = nsnull;
    6523               0 :   while (doc && (parent = doc->GetParentDocument()) && !IsChromeDoc(parent)) {
    6524               0 :     doc = parent;
    6525                 :   }
    6526                 : 
    6527               0 :   DocTreeContainsWindowedPlugins(doc, &result);
    6528               0 :   return result;
    6529                 : }
    6530                 : 
    6531                 : /* static */
    6532                 : bool
    6533               0 : nsContentUtils::HasPluginWithUncontrolledEventDispatch(nsIContent* aContent)
    6534                 : {
    6535                 : #ifdef XP_MACOSX
    6536                 :   // We control dispatch to all mac plugins.
    6537                 :   return false;
    6538                 : #endif
    6539               0 :   bool result = false;
    6540               0 :   CheckForWindowedPlugins(aContent, &result);
    6541               0 :   return result;
    6542                 : }
    6543                 : 
    6544                 : /* static */
    6545                 : nsIDocument*
    6546               0 : nsContentUtils::GetRootDocument(nsIDocument* aDoc)
    6547                 : {
    6548               0 :   if (!aDoc) {
    6549               0 :     return nsnull;
    6550                 :   }
    6551               0 :   nsIDocument* doc = aDoc;
    6552               0 :   while (doc->GetParentDocument()) {
    6553               0 :     doc = doc->GetParentDocument();
    6554                 :   }
    6555               0 :   return doc;
    6556                 : }
    6557                 : 
    6558                 : // static
    6559                 : void
    6560          236785 : nsContentUtils::ReleaseWrapper(nsISupports* aScriptObjectHolder,
    6561                 :                                nsWrapperCache* aCache)
    6562                 : {
    6563          236785 :   if (aCache->PreservingWrapper()) {
    6564               3 :     DropJSObjects(aScriptObjectHolder);
    6565               3 :     aCache->SetPreservingWrapper(false);
    6566                 :   }
    6567                 : 
    6568          236785 :   aCache->ClearWrapperIfProxy();
    6569          236785 : }
    6570                 : 
    6571                 : // static
    6572                 : void
    6573          146657 : nsContentUtils::TraceWrapper(nsWrapperCache* aCache, TraceCallback aCallback,
    6574                 :                              void *aClosure)
    6575                 : {
    6576          146657 :   if (aCache->PreservingWrapper()) {
    6577              42 :     JSObject *wrapper = aCache->GetWrapperPreserveColor();
    6578              42 :     if (wrapper) {
    6579                 :       aCallback(nsIProgrammingLanguage::JAVASCRIPT, wrapper,
    6580              42 :                 "Preserved wrapper", aClosure);
    6581                 :     }
    6582                 :   }
    6583                 :   else {
    6584          146615 :     JSObject *expando = aCache->GetExpandoObjectPreserveColor();
    6585          146615 :     if (expando) {
    6586                 :       aCallback(nsIProgrammingLanguage::JAVASCRIPT, expando, "Expando object",
    6587               0 :                 aClosure);
    6588                 :     }
    6589                 :   }
    6590          146657 : }

Generated by: LCOV version 1.7