LCOV - code coverage report
Current view: directory - content/html/document/src - nsHTMLDocument.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1480 74 5.0 %
Date: 2012-06-02 Functions: 119 14 11.8 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set sw=2 ts=2 et tw=80: */
       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.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      25                 :  *   Kathleen Brade <brade@netscape.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "mozilla/Util.h"
      42                 : 
      43                 : #include "nsCOMPtr.h"
      44                 : #include "nsXPIDLString.h"
      45                 : #include "nsPrintfCString.h"
      46                 : #include "nsReadableUtils.h"
      47                 : #include "nsUnicharUtils.h"
      48                 : #include "nsHTMLDocument.h"
      49                 : #include "nsIHTMLContentSink.h"
      50                 : #include "nsIXMLContentSink.h"
      51                 : #include "nsHTMLParts.h"
      52                 : #include "nsHTMLStyleSheet.h"
      53                 : #include "nsGkAtoms.h"
      54                 : #include "nsIPresShell.h"
      55                 : #include "nsPresContext.h"
      56                 : #include "nsIDOMNode.h" // for Find
      57                 : #include "nsIDOMNodeList.h"
      58                 : #include "nsIDOMElement.h"
      59                 : #include "nsPIDOMWindow.h"
      60                 : #include "nsDOMString.h"
      61                 : #include "nsIStreamListener.h"
      62                 : #include "nsIURI.h"
      63                 : #include "nsIIOService.h"
      64                 : #include "nsNetUtil.h"
      65                 : #include "nsIContentViewerContainer.h"
      66                 : #include "nsIContentViewer.h"
      67                 : #include "nsIMarkupDocumentViewer.h"
      68                 : #include "nsIDocShell.h"
      69                 : #include "nsIDocShellTreeItem.h"
      70                 : #include "nsDocShellLoadTypes.h"
      71                 : #include "nsIWebNavigation.h"
      72                 : #include "nsIBaseWindow.h"
      73                 : #include "nsIWebShellServices.h"
      74                 : #include "nsIScriptContext.h"
      75                 : #include "nsIXPConnect.h"
      76                 : #include "nsContentList.h"
      77                 : #include "nsDOMError.h"
      78                 : #include "nsIPrincipal.h"
      79                 : #include "nsIScriptSecurityManager.h"
      80                 : #include "nsAttrName.h"
      81                 : #include "nsNodeUtils.h"
      82                 : 
      83                 : #include "nsNetCID.h"
      84                 : #include "nsIIOService.h"
      85                 : #include "nsICookieService.h"
      86                 : 
      87                 : #include "nsIServiceManager.h"
      88                 : #include "nsIConsoleService.h"
      89                 : #include "nsIComponentManager.h"
      90                 : #include "nsParserCIID.h"
      91                 : #include "nsIDOMHTMLElement.h"
      92                 : #include "nsIDOMHTMLBodyElement.h"
      93                 : #include "nsIDOMHTMLHeadElement.h"
      94                 : #include "nsINameSpaceManager.h"
      95                 : #include "nsGenericHTMLElement.h"
      96                 : #include "mozilla/css/Loader.h"
      97                 : #include "nsIHttpChannel.h"
      98                 : #include "nsIFile.h"
      99                 : #include "nsEventListenerManager.h"
     100                 : #include "nsFrameSelection.h"
     101                 : #include "nsISelectionPrivate.h"//for toStringwithformat code
     102                 : 
     103                 : #include "nsContentUtils.h"
     104                 : #include "nsJSUtils.h"
     105                 : #include "nsIDocumentEncoder.h" //for outputting selection
     106                 : #include "nsICachingChannel.h"
     107                 : #include "nsIJSContextStack.h"
     108                 : #include "nsIContentViewer.h"
     109                 : #include "nsIWyciwygChannel.h"
     110                 : #include "nsIScriptElement.h"
     111                 : #include "nsIScriptError.h"
     112                 : #include "nsIMutableArray.h"
     113                 : #include "nsArrayUtils.h"
     114                 : #include "nsIEffectiveTLDService.h"
     115                 : 
     116                 : #include "nsIPrompt.h"
     117                 : //AHMED 12-2
     118                 : #include "nsBidiUtils.h"
     119                 : 
     120                 : #include "nsIEditingSession.h"
     121                 : #include "nsIEditor.h"
     122                 : #include "nsNodeInfoManager.h"
     123                 : #include "nsIPlaintextEditor.h"
     124                 : #include "nsIHTMLEditor.h"
     125                 : #include "nsIEditorDocShell.h"
     126                 : #include "nsIEditorStyleSheets.h"
     127                 : #include "nsIInlineSpellChecker.h"
     128                 : #include "nsRange.h"
     129                 : #include "mozAutoDocUpdate.h"
     130                 : #include "nsCCUncollectableMarker.h"
     131                 : #include "nsHtml5Module.h"
     132                 : #include "prprf.h"
     133                 : #include "mozilla/dom/Element.h"
     134                 : #include "mozilla/Preferences.h"
     135                 : #include "nsMimeTypes.h"
     136                 : #include "nsIRequest.h"
     137                 : 
     138                 : using namespace mozilla;
     139                 : using namespace mozilla::dom;
     140                 : 
     141                 : #define NS_MAX_DOCUMENT_WRITE_DEPTH 20
     142                 : 
     143                 : #include "prmem.h"
     144                 : #include "prtime.h"
     145                 : 
     146                 : // Find/Search Includes
     147                 : const PRInt32 kForward  = 0;
     148                 : const PRInt32 kBackward = 1;
     149                 : 
     150                 : //#define DEBUG_charset
     151                 : 
     152                 : static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
     153                 : 
     154                 : PRUint32       nsHTMLDocument::gWyciwygSessionCnt = 0;
     155                 : 
     156                 : // this function will return false if the command is not recognized
     157                 : // inCommandID will be converted as necessary for internal operations
     158                 : // inParam will be converted as necessary for internal operations
     159                 : // outParam will be Empty if no parameter is needed or if returning a boolean
     160                 : // outIsBoolean will determine whether to send param as a boolean or string
     161                 : // outBooleanParam will not be set unless outIsBoolean
     162                 : static bool ConvertToMidasInternalCommand(const nsAString & inCommandID,
     163                 :                                             const nsAString & inParam,
     164                 :                                             nsACString& outCommandID,
     165                 :                                             nsACString& outParam,
     166                 :                                             bool& isBoolean,
     167                 :                                             bool& boolValue);
     168                 : 
     169                 : static bool ConvertToMidasInternalCommand(const nsAString & inCommandID,
     170                 :                                             nsACString& outCommandID);
     171                 : 
     172                 : // ==================================================================
     173                 : // =
     174                 : // ==================================================================
     175                 : static void
     176               0 : ReportUseOfDeprecatedMethod(nsHTMLDocument* aDoc, const char* aWarning)
     177                 : {
     178                 :   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
     179                 :                                   "DOM Events", aDoc,
     180                 :                                   nsContentUtils::eDOM_PROPERTIES,
     181               0 :                                   aWarning);
     182               0 : }
     183                 : 
     184                 : static nsresult
     185               0 : RemoveFromAgentSheets(nsCOMArray<nsIStyleSheet> &aAgentSheets, const nsAString& url)
     186                 : {
     187               0 :   nsCOMPtr<nsIURI> uri;
     188               0 :   nsresult rv = NS_NewURI(getter_AddRefs(uri), url);
     189               0 :   NS_ENSURE_SUCCESS(rv, rv);
     190                 : 
     191               0 :   for (PRInt32 i = aAgentSheets.Count() - 1; i >= 0; --i) {
     192               0 :     nsIStyleSheet* sheet = aAgentSheets[i];
     193               0 :     nsIURI* sheetURI = sheet->GetSheetURI();
     194                 : 
     195               0 :     bool equals = false;
     196               0 :     uri->Equals(sheetURI, &equals);
     197               0 :     if (equals) {
     198               0 :       aAgentSheets.RemoveObjectAt(i);
     199                 :     }
     200                 :   }
     201                 : 
     202               0 :   return NS_OK;
     203                 : }
     204                 : 
     205                 : nsresult
     206             234 : NS_NewHTMLDocument(nsIDocument** aInstancePtrResult)
     207                 : {
     208             234 :   nsHTMLDocument* doc = new nsHTMLDocument();
     209             234 :   NS_ENSURE_TRUE(doc, NS_ERROR_OUT_OF_MEMORY);
     210                 : 
     211             234 :   NS_ADDREF(doc);
     212             234 :   nsresult rv = doc->Init();
     213                 : 
     214             234 :   if (NS_FAILED(rv)) {
     215               0 :     NS_RELEASE(doc);
     216                 :   }
     217                 : 
     218             234 :   *aInstancePtrResult = doc;
     219                 : 
     220             234 :   return rv;
     221                 : }
     222                 : 
     223                 :   // NOTE! nsDocument::operator new() zeroes out all members, so don't
     224                 :   // bother initializing members to 0.
     225                 : 
     226             234 : nsHTMLDocument::nsHTMLDocument()
     227             234 :   : nsDocument("text/html")
     228                 : {
     229                 :   // NOTE! nsDocument::operator new() zeroes out all members, so don't
     230                 :   // bother initializing members to 0.
     231                 : 
     232             234 :   mIsRegularHTML = true;
     233             234 :   mDefaultElementType = kNameSpaceID_XHTML;
     234             234 :   mCompatMode = eCompatibility_NavQuirks;
     235             234 : }
     236                 : 
     237            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLDocument)
     238                 : 
     239             238 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
     240             238 :   NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()),
     241                 :                "Shouldn't traverse nsHTMLDocument!");
     242             238 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mImages)
     243             238 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplets)
     244             238 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEmbeds)
     245             238 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLinks)
     246             238 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAnchors)
     247             238 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScripts)
     248             238 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mForms, nsIDOMNodeList)
     249             238 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mFormControls,
     250                 :                                                        nsIDOMNodeList)
     251             238 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mWyciwygChannel)
     252             238 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMidasCommandManager)
     253             238 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     254                 : 
     255             234 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
     256             234 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mImages)
     257             234 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mApplets)
     258             234 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mEmbeds)
     259             234 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLinks)
     260             234 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAnchors)
     261             234 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mScripts)
     262             234 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mForms)
     263             234 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFormControls)
     264             234 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mWyciwygChannel)
     265             234 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMidasCommandManager)
     266             234 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     267                 : 
     268            9594 : NS_IMPL_ADDREF_INHERITED(nsHTMLDocument, nsDocument)
     269            9594 : NS_IMPL_RELEASE_INHERITED(nsHTMLDocument, nsDocument)
     270                 : 
     271                 : 
     272               0 : DOMCI_NODE_DATA(HTMLDocument, nsHTMLDocument)
     273                 : 
     274                 : // QueryInterface implementation for nsHTMLDocument
     275           15561 : NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLDocument)
     276                 :   NS_DOCUMENT_INTERFACE_TABLE_BEGIN(nsHTMLDocument)
     277                 :     NS_INTERFACE_TABLE_ENTRY(nsHTMLDocument, nsIHTMLDocument)
     278                 :     NS_INTERFACE_TABLE_ENTRY(nsHTMLDocument, nsIDOMHTMLDocument)
     279            9052 :   NS_OFFSET_AND_INTERFACE_TABLE_END
     280            9052 :   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
     281            5776 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLDocument)
     282            5776 : NS_INTERFACE_MAP_END_INHERITING(nsDocument)
     283                 : 
     284                 : 
     285                 : nsresult
     286             234 : nsHTMLDocument::Init()
     287                 : {
     288             234 :   nsresult rv = nsDocument::Init();
     289             234 :   NS_ENSURE_SUCCESS(rv, rv);
     290                 : 
     291                 :   // Now reset the compatibility mode of the CSSLoader
     292                 :   // to match our compat mode.
     293             234 :   CSSLoader()->SetCompatibilityMode(mCompatMode);
     294                 : 
     295             234 :   return NS_OK;
     296                 : }
     297                 : 
     298                 : 
     299                 : void
     300               0 : nsHTMLDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
     301                 : {
     302               0 :   nsDocument::Reset(aChannel, aLoadGroup);
     303                 : 
     304               0 :   if (aChannel) {
     305               0 :     aChannel->GetLoadFlags(&mLoadFlags);
     306                 :   }
     307               0 : }
     308                 : 
     309                 : void
     310               0 : nsHTMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
     311                 :                            nsIPrincipal* aPrincipal)
     312                 : {
     313               0 :   mLoadFlags = nsIRequest::LOAD_NORMAL;
     314                 : 
     315               0 :   nsDocument::ResetToURI(aURI, aLoadGroup, aPrincipal);
     316                 : 
     317               0 :   mImages = nsnull;
     318               0 :   mApplets = nsnull;
     319               0 :   mEmbeds = nsnull;
     320               0 :   mLinks = nsnull;
     321               0 :   mAnchors = nsnull;
     322               0 :   mScripts = nsnull;
     323                 : 
     324               0 :   mForms = nsnull;
     325                 : 
     326               0 :   NS_ASSERTION(!mWyciwygChannel,
     327                 :                "nsHTMLDocument::Reset() - Wyciwyg Channel  still exists!");
     328                 : 
     329               0 :   mWyciwygChannel = nsnull;
     330                 : 
     331                 :   // Make the content type default to "text/html", we are a HTML
     332                 :   // document, after all. Once we start getting data, this may be
     333                 :   // changed.
     334               0 :   SetContentTypeInternal(nsDependentCString("text/html"));
     335               0 : }
     336                 : 
     337                 : nsresult
     338               0 : nsHTMLDocument::CreateShell(nsPresContext* aContext,
     339                 :                             nsIViewManager* aViewManager,
     340                 :                             nsStyleSet* aStyleSet,
     341                 :                             nsIPresShell** aInstancePtrResult)
     342                 : {
     343                 :   return doCreateShell(aContext, aViewManager, aStyleSet, mCompatMode,
     344               0 :                        aInstancePtrResult);
     345                 : }
     346                 : 
     347                 : // The following Try*Charset will return false only if the charset source
     348                 : // should be considered (ie. aCharsetSource < thisCharsetSource) but we failed
     349                 : // to get the charset from this source.
     350                 : 
     351                 : bool
     352               0 : nsHTMLDocument::TryHintCharset(nsIMarkupDocumentViewer* aMarkupDV,
     353                 :                                PRInt32& aCharsetSource, nsACString& aCharset)
     354                 : {
     355               0 :   if (aMarkupDV) {
     356                 :     PRInt32 requestCharsetSource;
     357               0 :     nsresult rv = aMarkupDV->GetHintCharacterSetSource(&requestCharsetSource);
     358                 : 
     359               0 :     if(NS_SUCCEEDED(rv) && kCharsetUninitialized != requestCharsetSource) {
     360               0 :       nsCAutoString requestCharset;
     361               0 :       rv = aMarkupDV->GetHintCharacterSet(requestCharset);
     362               0 :       aMarkupDV->SetHintCharacterSetSource((PRInt32)(kCharsetUninitialized));
     363                 : 
     364               0 :       if(requestCharsetSource <= aCharsetSource)
     365               0 :         return true;
     366                 : 
     367               0 :       if(NS_SUCCEEDED(rv)) {
     368               0 :         aCharsetSource = requestCharsetSource;
     369               0 :         aCharset = requestCharset;
     370                 : 
     371               0 :         return true;
     372                 :       }
     373                 :     }
     374                 :   }
     375               0 :   return false;
     376                 : }
     377                 : 
     378                 : 
     379                 : bool
     380               0 : nsHTMLDocument::TryUserForcedCharset(nsIMarkupDocumentViewer* aMarkupDV,
     381                 :                                      nsIDocShell*  aDocShell,
     382                 :                                      PRInt32& aCharsetSource,
     383                 :                                      nsACString& aCharset)
     384                 : {
     385               0 :   nsresult rv = NS_OK;
     386                 : 
     387               0 :   if(kCharsetFromUserForced <= aCharsetSource)
     388               0 :     return true;
     389                 : 
     390               0 :   nsCAutoString forceCharsetFromDocShell;
     391               0 :   if (aMarkupDV) {
     392               0 :     rv = aMarkupDV->GetForceCharacterSet(forceCharsetFromDocShell);
     393                 :   }
     394                 : 
     395               0 :   if(NS_SUCCEEDED(rv) && !forceCharsetFromDocShell.IsEmpty()) {
     396               0 :     aCharset = forceCharsetFromDocShell;
     397                 :     //TODO: we should define appropriate constant for force charset
     398               0 :     aCharsetSource = kCharsetFromUserForced;
     399               0 :   } else if (aDocShell) {
     400               0 :     nsCOMPtr<nsIAtom> csAtom;
     401               0 :     aDocShell->GetForcedCharset(getter_AddRefs(csAtom));
     402               0 :     if (csAtom) {
     403               0 :       csAtom->ToUTF8String(aCharset);
     404               0 :       aCharsetSource = kCharsetFromUserForced;
     405               0 :       aDocShell->SetForcedCharset(nsnull);
     406               0 :       return true;
     407                 :     }
     408                 :   }
     409                 : 
     410               0 :   return false;
     411                 : }
     412                 : 
     413                 : bool
     414               0 : nsHTMLDocument::TryCacheCharset(nsICachingChannel* aCachingChannel,
     415                 :                                 PRInt32& aCharsetSource,
     416                 :                                 nsACString& aCharset)
     417                 : {
     418                 :   nsresult rv;
     419                 : 
     420               0 :   if (kCharsetFromCache <= aCharsetSource) {
     421               0 :     return true;
     422                 :   }
     423                 : 
     424               0 :   nsCString cachedCharset;
     425               0 :   rv = aCachingChannel->GetCacheTokenCachedCharset(cachedCharset);
     426               0 :   if (NS_SUCCEEDED(rv) && !cachedCharset.IsEmpty())
     427                 :   {
     428               0 :     aCharset = cachedCharset;
     429               0 :     aCharsetSource = kCharsetFromCache;
     430                 : 
     431               0 :     return true;
     432                 :   }
     433                 : 
     434               0 :   return false;
     435                 : }
     436                 : 
     437                 : static bool
     438               0 : CheckSameOrigin(nsINode* aNode1, nsINode* aNode2)
     439                 : {
     440               0 :   NS_PRECONDITION(aNode1, "Null node?");
     441               0 :   NS_PRECONDITION(aNode2, "Null node?");
     442                 : 
     443                 :   bool equal;
     444                 :   return
     445               0 :     NS_SUCCEEDED(aNode1->NodePrincipal()->
     446                 :                    Equals(aNode2->NodePrincipal(), &equal)) &&
     447               0 :     equal;
     448                 : }
     449                 : 
     450                 : bool
     451               0 : nsHTMLDocument::TryParentCharset(nsIDocShell*  aDocShell,
     452                 :                                  nsIDocument* aParentDocument,
     453                 :                                  PRInt32& aCharsetSource,
     454                 :                                  nsACString& aCharset)
     455                 : {
     456               0 :   if (aDocShell) {
     457                 :     PRInt32 source;
     458               0 :     nsCOMPtr<nsIAtom> csAtom;
     459                 :     PRInt32 parentSource;
     460               0 :     aDocShell->GetParentCharsetSource(&parentSource);
     461               0 :     if (kCharsetFromParentForced <= parentSource)
     462               0 :       source = kCharsetFromParentForced;
     463               0 :     else if (kCharsetFromHintPrevDoc == parentSource) {
     464                 :       // Make sure that's OK
     465               0 :       if (!aParentDocument || !CheckSameOrigin(this, aParentDocument)) {
     466               0 :         return false;
     467                 :       }
     468                 :       
     469                 :       // if parent is posted doc, set this prevent autodections
     470                 :       // I'm not sure this makes much sense... but whatever.
     471               0 :       source = kCharsetFromHintPrevDoc;
     472                 :     }
     473               0 :     else if (kCharsetFromCache <= parentSource) {
     474                 :       // Make sure that's OK
     475               0 :       if (!aParentDocument || !CheckSameOrigin(this, aParentDocument)) {
     476               0 :         return false;
     477                 :       }
     478                 : 
     479               0 :       source = kCharsetFromParentFrame;
     480                 :     }
     481                 :     else
     482               0 :       return false;
     483                 : 
     484               0 :     if (source < aCharsetSource)
     485               0 :       return true;
     486                 : 
     487               0 :     aDocShell->GetParentCharset(getter_AddRefs(csAtom));
     488               0 :     if (csAtom) {
     489               0 :       csAtom->ToUTF8String(aCharset);
     490               0 :       aCharsetSource = source;
     491               0 :       return true;
     492                 :     }
     493                 :   }
     494               0 :   return false;
     495                 : }
     496                 : 
     497                 : bool
     498               0 : nsHTMLDocument::UseWeakDocTypeDefault(PRInt32& aCharsetSource,
     499                 :                                       nsACString& aCharset)
     500                 : {
     501               0 :   if (kCharsetFromWeakDocTypeDefault <= aCharsetSource)
     502               0 :     return true;
     503                 :   // fallback value in case docshell return error
     504               0 :   aCharset.AssignLiteral("ISO-8859-1");
     505                 : 
     506                 :   const nsAdoptingCString& defCharset =
     507               0 :     Preferences::GetLocalizedCString("intl.charset.default");
     508                 : 
     509               0 :   if (!defCharset.IsEmpty()) {
     510               0 :     aCharset = defCharset;
     511               0 :     aCharsetSource = kCharsetFromWeakDocTypeDefault;
     512                 :   }
     513               0 :   return true;
     514                 : }
     515                 : 
     516                 : bool
     517               0 : nsHTMLDocument::TryDefaultCharset( nsIMarkupDocumentViewer* aMarkupDV,
     518                 :                                    PRInt32& aCharsetSource,
     519                 :                                    nsACString& aCharset)
     520                 : {
     521               0 :   if(kCharsetFromUserDefault <= aCharsetSource)
     522               0 :     return true;
     523                 : 
     524               0 :   nsCAutoString defaultCharsetFromDocShell;
     525               0 :   if (aMarkupDV) {
     526                 :     nsresult rv =
     527               0 :       aMarkupDV->GetDefaultCharacterSet(defaultCharsetFromDocShell);
     528               0 :     if(NS_SUCCEEDED(rv)) {
     529               0 :       aCharset = defaultCharsetFromDocShell;
     530                 : 
     531               0 :       aCharsetSource = kCharsetFromUserDefault;
     532               0 :       return true;
     533                 :     }
     534                 :   }
     535               0 :   return false;
     536                 : }
     537                 : 
     538                 : void
     539             234 : nsHTMLDocument::SetDocumentCharacterSet(const nsACString& aCharSetID)
     540                 : {
     541             234 :   nsDocument::SetDocumentCharacterSet(aCharSetID);
     542                 :   // Make sure to stash this charset on our channel as needed if it's a wyciwyg
     543                 :   // channel.
     544             468 :   nsCOMPtr<nsIWyciwygChannel> wyciwygChannel = do_QueryInterface(mChannel);
     545             234 :   if (wyciwygChannel) {
     546               0 :     wyciwygChannel->SetCharsetAndSource(GetDocumentCharacterSetSource(),
     547               0 :                                         aCharSetID);
     548                 :   }
     549             234 : }
     550                 : 
     551                 : nsresult
     552               0 : nsHTMLDocument::StartDocumentLoad(const char* aCommand,
     553                 :                                   nsIChannel* aChannel,
     554                 :                                   nsILoadGroup* aLoadGroup,
     555                 :                                   nsISupports* aContainer,
     556                 :                                   nsIStreamListener **aDocListener,
     557                 :                                   bool aReset,
     558                 :                                   nsIContentSink* aSink)
     559                 : {
     560               0 :   if (!aCommand) {
     561               0 :     MOZ_ASSERT(false, "Command is mandatory");
     562               0 :     return NS_ERROR_INVALID_POINTER;
     563                 :   }
     564               0 :   if (aSink) {
     565               0 :     MOZ_ASSERT(false, "Got a sink override. Should not happen for HTML doc.");
     566               0 :     return NS_ERROR_INVALID_ARG;
     567                 :   }
     568               0 :   if (!mIsRegularHTML) {
     569               0 :     MOZ_ASSERT(false, "Must not set HTML doc to XHTML mode before load start.");
     570               0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
     571                 :   }
     572                 : 
     573               0 :   nsCAutoString contentType;
     574               0 :   aChannel->GetContentType(contentType);
     575                 : 
     576               0 :   bool view = !strcmp(aCommand, "view") ||
     577               0 :               !strcmp(aCommand, "external-resource");
     578               0 :   bool viewSource = !strcmp(aCommand, "view-source");
     579               0 :   bool asData = !strcmp(aCommand, kLoadAsData);
     580               0 :   if(!(view || viewSource || asData)) {
     581               0 :     MOZ_ASSERT(false, "Bad parser command");
     582               0 :     return NS_ERROR_INVALID_ARG;
     583                 :   }
     584                 : 
     585               0 :   bool html = contentType.EqualsLiteral(TEXT_HTML);
     586               0 :   bool xhtml = !html && contentType.EqualsLiteral(APPLICATION_XHTML_XML);
     587               0 :   bool plainText = !html && !xhtml && (contentType.EqualsLiteral(TEXT_PLAIN) ||
     588               0 :     contentType.EqualsLiteral(TEXT_CSS) ||
     589               0 :     contentType.EqualsLiteral(APPLICATION_JAVASCRIPT) ||
     590               0 :     contentType.EqualsLiteral(APPLICATION_XJAVASCRIPT) ||
     591               0 :     contentType.EqualsLiteral(TEXT_ECMASCRIPT) ||
     592               0 :     contentType.EqualsLiteral(APPLICATION_ECMASCRIPT) ||
     593               0 :     contentType.EqualsLiteral(TEXT_JAVASCRIPT) ||
     594               0 :     contentType.EqualsLiteral(APPLICATION_JSON));
     595               0 :   if (!(html || xhtml || plainText || viewSource)) {
     596               0 :     MOZ_ASSERT(false, "Channel with bad content type.");
     597               0 :     return NS_ERROR_INVALID_ARG;
     598                 :   }
     599                 : 
     600               0 :   bool loadAsHtml5 = true;
     601                 : 
     602               0 :   if (!viewSource && xhtml) {
     603                 :       // We're parsing XHTML as XML, remember that.
     604               0 :       mIsRegularHTML = false;
     605               0 :       mCompatMode = eCompatibility_FullStandards;
     606               0 :       loadAsHtml5 = false;
     607                 :   }
     608                 :   
     609                 :   // TODO: Proper about:blank treatment is bug 543435
     610               0 :   if (loadAsHtml5 && view) {
     611                 :     // mDocumentURI hasn't been set, yet, so get the URI from the channel
     612               0 :     nsCOMPtr<nsIURI> uri;
     613               0 :     aChannel->GetOriginalURI(getter_AddRefs(uri));
     614                 :     // Adapted from nsDocShell:
     615                 :     // GetSpec can be expensive for some URIs, so check the scheme first.
     616               0 :     bool isAbout = false;
     617               0 :     if (uri && NS_SUCCEEDED(uri->SchemeIs("about", &isAbout)) && isAbout) {
     618               0 :       nsCAutoString str;
     619               0 :       uri->GetSpec(str);
     620               0 :       if (str.EqualsLiteral("about:blank")) {
     621               0 :         loadAsHtml5 = false;    
     622                 :       }
     623                 :     }
     624                 :   }
     625                 :   
     626               0 :   CSSLoader()->SetCompatibilityMode(mCompatMode);
     627                 :   
     628                 :   nsresult rv = nsDocument::StartDocumentLoad(aCommand,
     629                 :                                               aChannel, aLoadGroup,
     630                 :                                               aContainer,
     631               0 :                                               aDocListener, aReset);
     632               0 :   if (NS_FAILED(rv)) {
     633               0 :     return rv;
     634                 :   }
     635                 : 
     636                 :   // Store the security info for future use with wyciwyg channels.
     637               0 :   aChannel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
     638                 : 
     639               0 :   nsCOMPtr<nsIURI> uri;
     640               0 :   rv = aChannel->GetURI(getter_AddRefs(uri));
     641               0 :   if (NS_FAILED(rv)) {
     642               0 :     return rv;
     643                 :   }
     644                 : 
     645               0 :   nsCOMPtr<nsICachingChannel> cachingChan = do_QueryInterface(aChannel);
     646                 : 
     647               0 :   if (loadAsHtml5) {
     648               0 :     mParser = nsHtml5Module::NewHtml5Parser();
     649               0 :     if (plainText) {
     650               0 :       if (viewSource) {
     651               0 :         mParser->MarkAsNotScriptCreated("view-source-plain");
     652                 :       } else {
     653               0 :         mParser->MarkAsNotScriptCreated("plain-text");
     654                 :       }
     655               0 :     } else if (viewSource && !html) {
     656               0 :       mParser->MarkAsNotScriptCreated("view-source-xml");
     657                 :     } else {
     658               0 :       mParser->MarkAsNotScriptCreated(aCommand);
     659                 :     }
     660                 :   } else {
     661               0 :     mParser = do_CreateInstance(kCParserCID, &rv);
     662               0 :     NS_ENSURE_SUCCESS(rv, rv);
     663                 :   }
     664                 : 
     665               0 :   PRInt32 textType = GET_BIDI_OPTION_TEXTTYPE(GetBidiOptions());
     666                 : 
     667                 :   // Look for the parent document.  Note that at this point we don't have our
     668                 :   // content viewer set up yet, and therefore do not have a useful
     669                 :   // mParentDocument.
     670                 : 
     671                 :   // in this block of code, if we get an error result, we return it
     672                 :   // but if we get a null pointer, that's perfectly legal for parent
     673                 :   // and parentContentViewer
     674               0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
     675                 : 
     676               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(docShell));
     677                 : 
     678               0 :   nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
     679               0 :   if (docShellAsItem) {
     680               0 :     docShellAsItem->GetSameTypeParent(getter_AddRefs(parentAsItem));
     681                 :   }
     682                 : 
     683               0 :   nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
     684               0 :   nsCOMPtr<nsIDocument> parentDocument;
     685               0 :   nsCOMPtr<nsIContentViewer> parentContentViewer;
     686               0 :   if (parent) {
     687               0 :     rv = parent->GetContentViewer(getter_AddRefs(parentContentViewer));
     688               0 :     NS_ENSURE_SUCCESS(rv, rv);
     689               0 :     if (parentContentViewer) {
     690               0 :       parentDocument = parentContentViewer->GetDocument();
     691                 :     }
     692                 :   }
     693                 : 
     694                 :   //
     695                 :   // The following logic is mirrored in nsWebShell::Embed!
     696                 :   //
     697               0 :   nsCOMPtr<nsIMarkupDocumentViewer> muCV;
     698               0 :   bool muCVIsParent = false;
     699               0 :   nsCOMPtr<nsIContentViewer> cv;
     700               0 :   if (docShell) {
     701               0 :     docShell->GetContentViewer(getter_AddRefs(cv));
     702                 :   }
     703               0 :   if (cv) {
     704               0 :      muCV = do_QueryInterface(cv);
     705                 :   } else {
     706               0 :     muCV = do_QueryInterface(parentContentViewer);
     707               0 :     if (muCV) {
     708               0 :       muCVIsParent = true;
     709                 :     }
     710                 :   }
     711                 : 
     712               0 :   nsCAutoString urlSpec;
     713               0 :   uri->GetSpec(urlSpec);
     714                 : #ifdef DEBUG_charset
     715                 :   printf("Determining charset for %s\n", urlSpec.get());
     716                 : #endif
     717                 : 
     718                 :   // These are the charset source and charset for our document
     719                 :   PRInt32 charsetSource;
     720               0 :   nsCAutoString charset;
     721                 : 
     722                 :   // These are the charset source and charset for the parser.  This can differ
     723                 :   // from that for the document if the channel is a wyciwyg channel.
     724                 :   PRInt32 parserCharsetSource;
     725               0 :   nsCAutoString parserCharset;
     726                 : 
     727               0 :   nsCOMPtr<nsIWyciwygChannel> wyciwygChannel;
     728                 :   
     729               0 :   if (!IsHTML() || !docShell) { // no docshell for text/html XHR
     730               0 :     charsetSource = IsHTML() ? kCharsetFromWeakDocTypeDefault
     731               0 :                              : kCharsetFromDocTypeDefault;
     732               0 :     charset.AssignLiteral("UTF-8");
     733               0 :     TryChannelCharset(aChannel, charsetSource, charset);
     734               0 :     parserCharsetSource = charsetSource;
     735               0 :     parserCharset = charset;
     736                 :   } else {
     737               0 :     NS_ASSERTION(docShell && docShellAsItem, "Unexpected null value");
     738                 : 
     739               0 :     charsetSource = kCharsetUninitialized;
     740               0 :     wyciwygChannel = do_QueryInterface(aChannel);
     741                 : 
     742                 :     // The following charset resolving calls has implied knowledge
     743                 :     // about charset source priority order. Each try will return true
     744                 :     // if the source is higher or equal to the source as its name
     745                 :     // describes. Some try call might change charset source to
     746                 :     // multiple values, like TryHintCharset and TryParentCharset. It
     747                 :     // should be always safe to try more sources.
     748               0 :     if (!TryUserForcedCharset(muCV, docShell, charsetSource, charset)) {
     749               0 :       TryHintCharset(muCV, charsetSource, charset);
     750               0 :       TryParentCharset(docShell, parentDocument, charsetSource, charset);
     751                 : 
     752                 :       // Don't actually get the charset from the channel if this is a
     753                 :       // wyciwyg channel; it'll always be UTF-16
     754               0 :       if (!wyciwygChannel &&
     755               0 :           TryChannelCharset(aChannel, charsetSource, charset)) {
     756                 :         // Use the channel's charset (e.g., charset from HTTP
     757                 :         // "Content-Type" header).
     758                 :       }
     759               0 :       else if (cachingChan && !urlSpec.IsEmpty() &&
     760               0 :                TryCacheCharset(cachingChan, charsetSource, charset)) {
     761                 :         // Use the cache's charset.
     762                 :       }
     763               0 :       else if (TryDefaultCharset(muCV, charsetSource, charset)) {
     764                 :         // Use the default charset.
     765                 :         // previous document charset might be inherited as default charset.
     766                 :       }
     767                 :       else {
     768                 :         // Use the weak doc type default charset
     769               0 :         UseWeakDocTypeDefault(charsetSource, charset);
     770                 :       }
     771                 :     }
     772                 : 
     773               0 :     bool isPostPage = false;
     774                 :     // check if current doc is from POST command
     775               0 :     nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
     776               0 :     if (httpChannel) {
     777               0 :       nsCAutoString methodStr;
     778               0 :       rv = httpChannel->GetRequestMethod(methodStr);
     779               0 :       isPostPage = (NS_SUCCEEDED(rv) &&
     780               0 :                     methodStr.EqualsLiteral("POST"));
     781                 :     }
     782                 : 
     783               0 :     if (isPostPage && muCV && kCharsetFromHintPrevDoc > charsetSource) {
     784               0 :       nsCAutoString requestCharset;
     785               0 :       muCV->GetPrevDocCharacterSet(requestCharset);
     786               0 :       if (!requestCharset.IsEmpty()) {
     787               0 :         charsetSource = kCharsetFromHintPrevDoc;
     788               0 :         charset = requestCharset;
     789                 :       }
     790                 :     }
     791                 : 
     792               0 :     if (wyciwygChannel) {
     793                 :       // We know for sure that the parser needs to be using UTF16.
     794               0 :       parserCharset = "UTF-16";
     795                 :       parserCharsetSource = charsetSource < kCharsetFromChannel ?
     796               0 :         kCharsetFromChannel : charsetSource;
     797                 :         
     798               0 :       nsCAutoString cachedCharset;
     799                 :       PRInt32 cachedSource;
     800               0 :       rv = wyciwygChannel->GetCharsetAndSource(&cachedSource, cachedCharset);
     801               0 :       if (NS_SUCCEEDED(rv)) {
     802               0 :         if (cachedSource > charsetSource) {
     803               0 :           charsetSource = cachedSource;
     804               0 :           charset = cachedCharset;
     805                 :         }
     806                 :       } else {
     807                 :         // Don't propagate this error.
     808               0 :         rv = NS_OK;
     809                 :       }
     810                 :       
     811                 :     } else {
     812               0 :       parserCharset = charset;
     813               0 :       parserCharsetSource = charsetSource;
     814                 :     }
     815                 : 
     816                 :     // ahmed
     817                 :     // Check if 864 but in Implicit mode !
     818               0 :     if ((textType == IBMBIDI_TEXTTYPE_LOGICAL) &&
     819               0 :         (charset.LowerCaseEqualsLiteral("ibm864"))) {
     820               0 :       charset.AssignLiteral("IBM864i");
     821                 :     }
     822                 :   }
     823                 : 
     824               0 :   SetDocumentCharacterSetSource(charsetSource);
     825               0 :   SetDocumentCharacterSet(charset);
     826                 : 
     827                 :   // set doc charset to muCV for next document.
     828                 :   // Don't propagate this back up to the parent document if we have one.
     829               0 :   if (muCV && !muCVIsParent)
     830               0 :     muCV->SetPrevDocCharacterSet(charset);
     831                 : 
     832               0 :   if (cachingChan) {
     833               0 :     NS_ASSERTION(charset == parserCharset,
     834                 :                  "How did those end up different here?  wyciwyg channels are "
     835                 :                  "not nsICachingChannel");
     836               0 :     rv = cachingChan->SetCacheTokenCachedCharset(charset);
     837               0 :     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "cannot SetMetaDataElement");
     838               0 :     rv = NS_OK; // don't propagate error
     839                 :   }
     840                 : 
     841                 :   // Set the parser as the stream listener for the document loader...
     842               0 :   rv = NS_OK;
     843               0 :   nsCOMPtr<nsIStreamListener> listener = mParser->GetStreamListener();
     844               0 :   listener.forget(aDocListener);
     845                 : 
     846                 : #ifdef DEBUG_charset
     847                 :   printf(" charset = %s source %d\n",
     848                 :         charset.get(), charsetSource);
     849                 : #endif
     850               0 :   mParser->SetDocumentCharset(parserCharset, parserCharsetSource);
     851               0 :   mParser->SetCommand(aCommand);
     852                 : 
     853               0 :   if (!IsHTML()) {
     854               0 :     MOZ_ASSERT(!loadAsHtml5);
     855               0 :     nsCOMPtr<nsIXMLContentSink> xmlsink;
     856               0 :     NS_NewXMLContentSink(getter_AddRefs(xmlsink), this, uri,
     857               0 :                          docShell, aChannel);
     858               0 :     mParser->SetContentSink(xmlsink);
     859                 :   } else {
     860               0 :     if (loadAsHtml5) {
     861               0 :       nsHtml5Module::Initialize(mParser, this, uri, docShell, aChannel);
     862                 :     } else {
     863                 :       // about:blank *only*
     864               0 :       nsCOMPtr<nsIHTMLContentSink> htmlsink;
     865               0 :       NS_NewHTMLContentSink(getter_AddRefs(htmlsink), this, uri,
     866               0 :                             docShell, aChannel);
     867               0 :       mParser->SetContentSink(htmlsink);
     868                 :     }
     869                 :   }
     870                 : 
     871                 :   // parser the content of the URI
     872               0 :   mParser->Parse(uri, nsnull, (void *)this);
     873                 : 
     874               0 :   return rv;
     875                 : }
     876                 : 
     877                 : void
     878               0 : nsHTMLDocument::StopDocumentLoad()
     879                 : {
     880               0 :   BlockOnload();
     881                 : 
     882                 :   // Remove the wyciwyg channel request from the document load group
     883                 :   // that we added in Open() if Open() was called on this doc.
     884               0 :   RemoveWyciwygChannel();
     885               0 :   NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::StopDocumentLoad(): "
     886                 :                "nsIWyciwygChannel could not be removed!");
     887                 : 
     888               0 :   nsDocument::StopDocumentLoad();
     889               0 :   UnblockOnload(false);
     890                 :   return;
     891                 : }
     892                 : 
     893                 : void
     894               0 : nsHTMLDocument::BeginLoad()
     895                 : {
     896               0 :   if (IsEditingOn()) {
     897                 :     // Reset() blows away all event listeners in the document, and our
     898                 :     // editor relies heavily on those. Midas is turned on, to make it
     899                 :     // work, re-initialize it to give it a chance to add its event
     900                 :     // listeners again.
     901                 : 
     902               0 :     TurnEditingOff();
     903               0 :     EditingStateChanged();
     904                 :   }
     905               0 :   nsDocument::BeginLoad();
     906               0 : }
     907                 : 
     908                 : void
     909               0 : nsHTMLDocument::EndLoad()
     910                 : {
     911                 :   bool turnOnEditing =
     912               0 :     mParser && (HasFlag(NODE_IS_EDITABLE) || mContentEditableCount > 0);
     913                 :   // Note: nsDocument::EndLoad nulls out mParser.
     914               0 :   nsDocument::EndLoad();
     915               0 :   if (turnOnEditing) {
     916               0 :     EditingStateChanged();
     917                 :   }
     918               0 : }
     919                 : 
     920                 : void
     921             468 : nsHTMLDocument::SetCompatibilityMode(nsCompatibility aMode)
     922                 : {
     923             468 :   NS_ASSERTION(IsHTML() || aMode == eCompatibility_FullStandards,
     924                 :                "Bad compat mode for XHTML document!");
     925                 : 
     926             468 :   mCompatMode = aMode;
     927             468 :   CSSLoader()->SetCompatibilityMode(mCompatMode);
     928             936 :   nsCOMPtr<nsIPresShell> shell = GetShell();
     929             468 :   if (shell) {
     930               0 :     nsPresContext *pc = shell->GetPresContext();
     931               0 :     if (pc) {
     932               0 :       pc->CompatibilityModeChanged();
     933                 :     }
     934                 :   }
     935             468 : }
     936                 : 
     937                 : //
     938                 : // nsIDOMHTMLDocument interface implementation
     939                 : //
     940                 : void
     941               0 : nsHTMLDocument::GetDomainURI(nsIURI **aURI)
     942                 : {
     943               0 :   nsIPrincipal *principal = NodePrincipal();
     944                 : 
     945               0 :   principal->GetDomain(aURI);
     946               0 :   if (!*aURI) {
     947               0 :     principal->GetURI(aURI);
     948                 :   }
     949               0 : }
     950                 : 
     951                 : 
     952                 : NS_IMETHODIMP
     953               0 : nsHTMLDocument::GetDomain(nsAString& aDomain)
     954                 : {
     955               0 :   nsCOMPtr<nsIURI> uri;
     956               0 :   GetDomainURI(getter_AddRefs(uri));
     957                 : 
     958               0 :   if (!uri) {
     959               0 :     return NS_ERROR_FAILURE;
     960                 :   }
     961                 : 
     962               0 :   nsCAutoString hostName;
     963                 : 
     964               0 :   if (NS_SUCCEEDED(uri->GetHost(hostName))) {
     965               0 :     CopyUTF8toUTF16(hostName, aDomain);
     966                 :   } else {
     967                 :     // If we can't get the host from the URI (e.g. about:, javascript:,
     968                 :     // etc), just return an null string.
     969               0 :     SetDOMStringToNull(aDomain);
     970                 :   }
     971                 : 
     972               0 :   return NS_OK;
     973                 : }
     974                 : 
     975                 : NS_IMETHODIMP
     976               0 : nsHTMLDocument::SetDomain(const nsAString& aDomain)
     977                 : {
     978               0 :   if (aDomain.IsEmpty())
     979               0 :     return NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN;
     980                 : 
     981                 :   // Create new URI
     982               0 :   nsCOMPtr<nsIURI> uri;
     983               0 :   GetDomainURI(getter_AddRefs(uri));
     984                 : 
     985               0 :   if (!uri) {
     986               0 :     return NS_ERROR_FAILURE;
     987                 :   }
     988                 : 
     989               0 :   nsCAutoString newURIString;
     990               0 :   if (NS_FAILED(uri->GetScheme(newURIString)))
     991               0 :     return NS_ERROR_FAILURE;
     992               0 :   nsCAutoString path;
     993               0 :   if (NS_FAILED(uri->GetPath(path)))
     994               0 :     return NS_ERROR_FAILURE;
     995               0 :   newURIString.AppendLiteral("://");
     996               0 :   AppendUTF16toUTF8(aDomain, newURIString);
     997               0 :   newURIString.Append(path);
     998                 : 
     999               0 :   nsCOMPtr<nsIURI> newURI;
    1000               0 :   if (NS_FAILED(NS_NewURI(getter_AddRefs(newURI), newURIString)))
    1001               0 :     return NS_ERROR_FAILURE;
    1002                 : 
    1003                 :   // Check new domain - must be a superdomain of the current host
    1004                 :   // For example, a page from foo.bar.com may set domain to bar.com,
    1005                 :   // but not to ar.com, baz.com, or fi.foo.bar.com.
    1006               0 :   nsCAutoString current, domain;
    1007               0 :   if (NS_FAILED(uri->GetAsciiHost(current)))
    1008               0 :     current.Truncate();
    1009               0 :   if (NS_FAILED(newURI->GetAsciiHost(domain)))
    1010               0 :     domain.Truncate();
    1011                 : 
    1012               0 :   bool ok = current.Equals(domain);
    1013               0 :   if (current.Length() > domain.Length() &&
    1014               0 :       StringEndsWith(current, domain) &&
    1015               0 :       current.CharAt(current.Length() - domain.Length() - 1) == '.') {
    1016                 :     // We're golden if the new domain is the current page's base domain or a
    1017                 :     // subdomain of it.
    1018                 :     nsCOMPtr<nsIEffectiveTLDService> tldService =
    1019               0 :       do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
    1020               0 :     if (!tldService)
    1021               0 :       return NS_ERROR_NOT_AVAILABLE;
    1022                 : 
    1023               0 :     nsCAutoString currentBaseDomain;
    1024               0 :     ok = NS_SUCCEEDED(tldService->GetBaseDomain(uri, 0, currentBaseDomain));
    1025               0 :     NS_ASSERTION(StringEndsWith(domain, currentBaseDomain) ==
    1026                 :                  (domain.Length() >= currentBaseDomain.Length()),
    1027                 :                  "uh-oh!  slight optimization wasn't valid somehow!");
    1028               0 :     ok = ok && domain.Length() >= currentBaseDomain.Length();
    1029                 :   }
    1030               0 :   if (!ok) {
    1031                 :     // Error: illegal domain
    1032               0 :     return NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN;
    1033                 :   }
    1034                 : 
    1035               0 :   return NodePrincipal()->SetDomain(newURI);
    1036                 : }
    1037                 : 
    1038                 : NS_IMETHODIMP
    1039               0 : nsHTMLDocument::GetURL(nsAString& aURL)
    1040                 : {
    1041               0 :   nsCAutoString str;
    1042                 : 
    1043               0 :   if (mDocumentURI) {
    1044               0 :     mDocumentURI->GetSpec(str);
    1045                 :   }
    1046                 : 
    1047               0 :   CopyUTF8toUTF16(str, aURL);
    1048                 : 
    1049               0 :   return NS_OK;
    1050                 : }
    1051                 : 
    1052                 : nsIContent*
    1053               0 : nsHTMLDocument::GetBody()
    1054                 : {
    1055               0 :   Element* body = GetBodyElement();
    1056                 : 
    1057               0 :   if (body) {
    1058                 :     // There is a body element, return that as the body.
    1059               0 :     return body;
    1060                 :   }
    1061                 : 
    1062                 :   // The document is most likely a frameset document so look for the
    1063                 :   // outer most frameset element
    1064                 :   nsRefPtr<nsContentList> nodeList =
    1065               0 :     NS_GetContentList(this, kNameSpaceID_XHTML, NS_LITERAL_STRING("frameset"));
    1066                 : 
    1067               0 :   return nodeList->GetNodeAt(0);
    1068                 : }
    1069                 : 
    1070                 : NS_IMETHODIMP
    1071               0 : nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody)
    1072                 : {
    1073               0 :   *aBody = nsnull;
    1074                 : 
    1075               0 :   nsIContent *body = GetBody();
    1076                 : 
    1077               0 :   return body ? CallQueryInterface(body, aBody) : NS_OK;
    1078                 : }
    1079                 : 
    1080                 : NS_IMETHODIMP
    1081               0 : nsHTMLDocument::SetBody(nsIDOMHTMLElement* aBody)
    1082                 : {
    1083               0 :   nsCOMPtr<nsIContent> newBody = do_QueryInterface(aBody);
    1084               0 :   Element* root = GetRootElement();
    1085                 : 
    1086                 :   // The body element must be either a body tag or a frameset tag. And we must
    1087                 :   // have a html root tag, otherwise GetBody will not return the newly set
    1088                 :   // body.
    1089               0 :   if (!newBody || !(newBody->Tag() == nsGkAtoms::body ||
    1090               0 :                     newBody->Tag() == nsGkAtoms::frameset) ||
    1091               0 :       !root || !root->IsHTML() ||
    1092               0 :       root->Tag() != nsGkAtoms::html) {
    1093               0 :     return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
    1094                 :   }
    1095                 : 
    1096               0 :   nsCOMPtr<nsIDOMElement> rootElem = do_QueryInterface(root);
    1097               0 :   nsCOMPtr<nsIDOMNode> tmp;
    1098                 : 
    1099                 :   // Use DOM methods so that we pass through the appropriate security checks.
    1100               0 :   nsCOMPtr<nsIDOMNode> currentBody = do_QueryInterface(GetBodyElement());
    1101               0 :   if (currentBody) {
    1102               0 :     return rootElem->ReplaceChild(aBody, currentBody, getter_AddRefs(tmp));
    1103                 :   }
    1104                 : 
    1105               0 :   return rootElem->AppendChild(aBody, getter_AddRefs(tmp));
    1106                 : }
    1107                 : 
    1108                 : NS_IMETHODIMP
    1109               0 : nsHTMLDocument::GetHead(nsIDOMHTMLHeadElement** aHead)
    1110                 : {
    1111               0 :   *aHead = nsnull;
    1112                 : 
    1113               0 :   Element* head = GetHeadElement();
    1114                 : 
    1115               0 :   return head ? CallQueryInterface(head, aHead) : NS_OK;
    1116                 : }
    1117                 : 
    1118                 : NS_IMETHODIMP
    1119               0 : nsHTMLDocument::GetImages(nsIDOMHTMLCollection** aImages)
    1120                 : {
    1121               0 :   if (!mImages) {
    1122               0 :     mImages = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::img, nsGkAtoms::img);
    1123                 :   }
    1124                 : 
    1125               0 :   *aImages = mImages;
    1126               0 :   NS_ADDREF(*aImages);
    1127                 : 
    1128               0 :   return NS_OK;
    1129                 : }
    1130                 : 
    1131                 : NS_IMETHODIMP
    1132               0 : nsHTMLDocument::GetApplets(nsIDOMHTMLCollection** aApplets)
    1133                 : {
    1134               0 :   if (!mApplets) {
    1135               0 :     mApplets = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::applet, nsGkAtoms::applet);
    1136                 :   }
    1137                 : 
    1138               0 :   *aApplets = mApplets;
    1139               0 :   NS_ADDREF(*aApplets);
    1140                 : 
    1141               0 :   return NS_OK;
    1142                 : }
    1143                 : 
    1144                 : bool
    1145               0 : nsHTMLDocument::MatchLinks(nsIContent *aContent, PRInt32 aNamespaceID,
    1146                 :                            nsIAtom* aAtom, void* aData)
    1147                 : {
    1148               0 :   nsIDocument* doc = aContent->GetCurrentDoc();
    1149                 : 
    1150               0 :   if (doc) {
    1151               0 :     NS_ASSERTION(aContent->IsInDoc(),
    1152                 :                  "This method should never be called on content nodes that "
    1153                 :                  "are not in a document!");
    1154                 : #ifdef DEBUG
    1155                 :     {
    1156                 :       nsCOMPtr<nsIHTMLDocument> htmldoc =
    1157               0 :         do_QueryInterface(aContent->GetCurrentDoc());
    1158               0 :       NS_ASSERTION(htmldoc,
    1159                 :                    "Huh, how did this happen? This should only be used with "
    1160                 :                    "HTML documents!");
    1161                 :     }
    1162                 : #endif
    1163                 : 
    1164               0 :     nsINodeInfo *ni = aContent->NodeInfo();
    1165                 : 
    1166               0 :     nsIAtom *localName = ni->NameAtom();
    1167               0 :     if (ni->NamespaceID() == kNameSpaceID_XHTML &&
    1168                 :         (localName == nsGkAtoms::a || localName == nsGkAtoms::area)) {
    1169               0 :       return aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::href);
    1170                 :     }
    1171                 :   }
    1172                 : 
    1173               0 :   return false;
    1174                 : }
    1175                 : 
    1176                 : NS_IMETHODIMP
    1177               0 : nsHTMLDocument::GetLinks(nsIDOMHTMLCollection** aLinks)
    1178                 : {
    1179               0 :   if (!mLinks) {
    1180               0 :     mLinks = new nsContentList(this, MatchLinks, nsnull, nsnull);
    1181                 :   }
    1182                 : 
    1183               0 :   *aLinks = mLinks;
    1184               0 :   NS_ADDREF(*aLinks);
    1185                 : 
    1186               0 :   return NS_OK;
    1187                 : }
    1188                 : 
    1189                 : bool
    1190               0 : nsHTMLDocument::MatchAnchors(nsIContent *aContent, PRInt32 aNamespaceID,
    1191                 :                              nsIAtom* aAtom, void* aData)
    1192                 : {
    1193               0 :   NS_ASSERTION(aContent->IsInDoc(),
    1194                 :                "This method should never be called on content nodes that "
    1195                 :                "are not in a document!");
    1196                 : #ifdef DEBUG
    1197                 :   {
    1198                 :     nsCOMPtr<nsIHTMLDocument> htmldoc =
    1199               0 :       do_QueryInterface(aContent->GetCurrentDoc());
    1200               0 :     NS_ASSERTION(htmldoc,
    1201                 :                  "Huh, how did this happen? This should only be used with "
    1202                 :                  "HTML documents!");
    1203                 :   }
    1204                 : #endif
    1205                 : 
    1206               0 :   if (aContent->NodeInfo()->Equals(nsGkAtoms::a, kNameSpaceID_XHTML)) {
    1207               0 :     return aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::name);
    1208                 :   }
    1209                 : 
    1210               0 :   return false;
    1211                 : }
    1212                 : 
    1213                 : NS_IMETHODIMP
    1214               0 : nsHTMLDocument::GetAnchors(nsIDOMHTMLCollection** aAnchors)
    1215                 : {
    1216               0 :   if (!mAnchors) {
    1217               0 :     mAnchors = new nsContentList(this, MatchAnchors, nsnull, nsnull);
    1218                 :   }
    1219                 : 
    1220               0 :   *aAnchors = mAnchors;
    1221               0 :   NS_ADDREF(*aAnchors);
    1222                 : 
    1223               0 :   return NS_OK;
    1224                 : }
    1225                 : 
    1226                 : NS_IMETHODIMP
    1227               0 : nsHTMLDocument::GetScripts(nsIDOMHTMLCollection** aScripts)
    1228                 : {
    1229               0 :   if (!mScripts) {
    1230               0 :     mScripts = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::script, nsGkAtoms::script);
    1231                 :   }
    1232                 : 
    1233               0 :   *aScripts = mScripts;
    1234               0 :   NS_ADDREF(*aScripts);
    1235                 : 
    1236               0 :   return NS_OK;
    1237                 : }
    1238                 : 
    1239                 : NS_IMETHODIMP
    1240               0 : nsHTMLDocument::GetCookie(nsAString& aCookie)
    1241                 : {
    1242               0 :   aCookie.Truncate(); // clear current cookie in case service fails;
    1243                 :                       // no cookie isn't an error condition.
    1244                 : 
    1245               0 :   if (mDisableCookieAccess) {
    1246               0 :     return NS_OK;
    1247                 :   }
    1248                 : 
    1249                 :   // not having a cookie service isn't an error
    1250               0 :   nsCOMPtr<nsICookieService> service = do_GetService(NS_COOKIESERVICE_CONTRACTID);
    1251               0 :   if (service) {
    1252                 :     // Get a URI from the document principal. We use the original
    1253                 :     // codebase in case the codebase was changed by SetDomain
    1254               0 :     nsCOMPtr<nsIURI> codebaseURI;
    1255               0 :     NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
    1256                 : 
    1257               0 :     if (!codebaseURI) {
    1258                 :       // Document's principal is not a codebase (may be system), so
    1259                 :       // can't set cookies
    1260                 : 
    1261               0 :       return NS_OK;
    1262                 :     }
    1263                 : 
    1264               0 :     nsXPIDLCString cookie;
    1265               0 :     service->GetCookieString(codebaseURI, mChannel, getter_Copies(cookie));
    1266               0 :     CopyASCIItoUTF16(cookie, aCookie);
    1267                 :   }
    1268                 : 
    1269               0 :   return NS_OK;
    1270                 : }
    1271                 : 
    1272                 : NS_IMETHODIMP
    1273               0 : nsHTMLDocument::SetCookie(const nsAString& aCookie)
    1274                 : {
    1275               0 :   if (mDisableCookieAccess) {
    1276               0 :     return NS_OK;
    1277                 :   }
    1278                 : 
    1279                 :   // not having a cookie service isn't an error
    1280               0 :   nsCOMPtr<nsICookieService> service = do_GetService(NS_COOKIESERVICE_CONTRACTID);
    1281               0 :   if (service && mDocumentURI) {
    1282               0 :     nsCOMPtr<nsIPrompt> prompt;
    1283               0 :     nsCOMPtr<nsPIDOMWindow> window = GetWindow();
    1284               0 :     if (window) {
    1285               0 :       window->GetPrompter(getter_AddRefs(prompt));
    1286                 :     }
    1287                 : 
    1288                 :     // The for getting the URI matches nsNavigator::GetCookieEnabled
    1289               0 :     nsCOMPtr<nsIURI> codebaseURI;
    1290               0 :     NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
    1291                 : 
    1292               0 :     if (!codebaseURI) {
    1293                 :       // Document's principal is not a codebase (may be system), so
    1294                 :       // can't set cookies
    1295                 : 
    1296               0 :       return NS_OK;
    1297                 :     }
    1298                 : 
    1299               0 :     NS_LossyConvertUTF16toASCII cookie(aCookie);
    1300               0 :     service->SetCookieString(codebaseURI, prompt, cookie.get(), mChannel);
    1301                 :   }
    1302                 : 
    1303               0 :   return NS_OK;
    1304                 : }
    1305                 : 
    1306                 : NS_IMETHODIMP
    1307               0 : nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl,
    1308                 :                      const nsAString& aReplaceOrName,
    1309                 :                      const nsAString& aFeatures,
    1310                 :                      JSContext* cx, PRUint8 aOptionalArgCount,
    1311                 :                      nsISupports** aReturn)
    1312                 : {
    1313               0 :   NS_ASSERTION(nsContentUtils::CanCallerAccess(static_cast<nsIDOMHTMLDocument*>(this)),
    1314                 :                "XOW should have caught this!");
    1315                 : 
    1316                 :   // When called with 3 or more arguments, document.open() calls window.open().
    1317               0 :   if (aOptionalArgCount > 2) {
    1318               0 :     nsCOMPtr<nsIDOMWindow> window = GetWindowInternal();
    1319               0 :     if (!window) {
    1320               0 :       return NS_OK;
    1321                 :     }
    1322               0 :     nsCOMPtr<nsIDOMWindow> newWindow;
    1323               0 :     nsresult rv = window->Open(aContentTypeOrUrl, aReplaceOrName, aFeatures,
    1324               0 :                                getter_AddRefs(newWindow));
    1325               0 :     *aReturn = newWindow.forget().get();
    1326               0 :     return rv;
    1327                 :   }
    1328                 : 
    1329               0 :   if (!IsHTML() || mDisableDocWrite) {
    1330                 :     // No calling document.open() on XHTML
    1331               0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
    1332                 :   }
    1333                 : 
    1334               0 :   nsCAutoString contentType;
    1335               0 :   contentType.AssignLiteral("text/html");
    1336               0 :   if (aOptionalArgCount > 0) {
    1337               0 :     nsAutoString type;
    1338               0 :     nsContentUtils::ASCIIToLower(aContentTypeOrUrl, type);
    1339               0 :     nsCAutoString actualType, dummy;
    1340               0 :     NS_ParseContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
    1341               0 :     if (!actualType.EqualsLiteral("text/html") &&
    1342               0 :         !type.EqualsLiteral("replace")) {
    1343               0 :       contentType.AssignLiteral("text/plain");
    1344                 :     }
    1345                 :   }
    1346                 : 
    1347                 :   // If we already have a parser we ignore the document.open call.
    1348               0 :   if (mParser) {
    1349               0 :     return NS_OK;
    1350                 :   }
    1351                 : 
    1352                 :   // No calling document.open() without a script global object
    1353               0 :   if (!mScriptGlobalObject) {
    1354               0 :     return NS_OK;
    1355                 :   }
    1356                 : 
    1357               0 :   nsPIDOMWindow* outer = GetWindow();
    1358               0 :   if (!outer || (GetInnerWindow() != outer->GetCurrentInnerWindow())) {
    1359               0 :     return NS_OK;
    1360                 :   }
    1361                 : 
    1362                 :   // check whether we're in the middle of unload.  If so, ignore this call.
    1363               0 :   nsCOMPtr<nsIDocShell> shell = do_QueryReferent(mDocumentContainer);
    1364               0 :   if (!shell) {
    1365                 :     // We won't be able to create a parser anyway.
    1366               0 :     return NS_OK;
    1367                 :   }
    1368                 : 
    1369                 :   bool inUnload;
    1370               0 :   shell->GetIsInUnload(&inUnload);
    1371               0 :   if (inUnload) {
    1372               0 :     return NS_OK;
    1373                 :   }
    1374                 : 
    1375                 :   // Note: We want to use GetDocumentFromContext here because this document
    1376                 :   // should inherit the security information of the document that's opening us,
    1377                 :   // (since if it's secure, then it's presumably trusted).
    1378                 :   nsCOMPtr<nsIDocument> callerDoc =
    1379               0 :     do_QueryInterface(nsContentUtils::GetDocumentFromContext());
    1380               0 :   if (!callerDoc) {
    1381                 :     // If we're called from C++ or in some other way without an originating
    1382                 :     // document we can't do a document.open w/o changing the principal of the
    1383                 :     // document to something like about:blank (as that's the only sane thing to
    1384                 :     // do when we don't know the origin of this call), and since we can't
    1385                 :     // change the principals of a document for security reasons we'll have to
    1386                 :     // refuse to go ahead with this call.
    1387                 : 
    1388               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1389                 :   }
    1390                 : 
    1391                 :   // Grab a reference to the calling documents security info (if any)
    1392                 :   // and URIs as they may be lost in the call to Reset().
    1393               0 :   nsCOMPtr<nsISupports> securityInfo = callerDoc->GetSecurityInfo();
    1394               0 :   nsCOMPtr<nsIURI> uri = callerDoc->GetDocumentURI();
    1395               0 :   nsCOMPtr<nsIURI> baseURI = callerDoc->GetBaseURI();
    1396               0 :   nsCOMPtr<nsIPrincipal> callerPrincipal = callerDoc->NodePrincipal();
    1397               0 :   nsCOMPtr<nsIChannel> callerChannel = callerDoc->GetChannel();
    1398                 : 
    1399                 :   // We're called from script. Make sure the script is from the same
    1400                 :   // origin, not just that the caller can access the document. This is
    1401                 :   // needed to keep document principals from ever changing, which is
    1402                 :   // needed because of the way we use our XOW code, and is a sane
    1403                 :   // thing to do anyways.
    1404                 : 
    1405               0 :   bool equals = false;
    1406               0 :   if (NS_FAILED(callerPrincipal->Equals(NodePrincipal(), &equals)) ||
    1407               0 :       !equals) {
    1408                 : 
    1409                 : #ifdef DEBUG
    1410               0 :     nsCOMPtr<nsIURI> callerDocURI = callerDoc->GetDocumentURI();
    1411               0 :     nsCOMPtr<nsIURI> thisURI = nsIDocument::GetDocumentURI();
    1412               0 :     nsCAutoString callerSpec;
    1413               0 :     nsCAutoString thisSpec;
    1414               0 :     if (callerDocURI) {
    1415               0 :       callerDocURI->GetSpec(callerSpec);
    1416                 :     }
    1417               0 :     if (thisURI) {
    1418               0 :       thisURI->GetSpec(thisSpec);
    1419                 :     }
    1420               0 :     printf("nsHTMLDocument::Open callerDoc %s this %s\n", callerSpec.get(), thisSpec.get());
    1421                 : #endif
    1422                 : 
    1423               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1424                 :   }
    1425                 : 
    1426                 :   // Stop current loads targeted at the window this document is in.
    1427               0 :   if (mScriptGlobalObject) {
    1428               0 :     nsCOMPtr<nsIContentViewer> cv;
    1429               0 :     shell->GetContentViewer(getter_AddRefs(cv));
    1430                 : 
    1431               0 :     if (cv) {
    1432                 :       bool okToUnload;
    1433               0 :       if (NS_SUCCEEDED(cv->PermitUnload(false, &okToUnload)) && !okToUnload) {
    1434                 :         // We don't want to unload, so stop here, but don't throw an
    1435                 :         // exception.
    1436               0 :         return NS_OK;
    1437                 :       }
    1438                 :     }
    1439                 : 
    1440               0 :     nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(shell));
    1441               0 :     webnav->Stop(nsIWebNavigation::STOP_NETWORK);
    1442                 : 
    1443                 :     // The Stop call may have cancelled the onload blocker request or prevented
    1444                 :     // it from getting added, so we need to make sure it gets added to the
    1445                 :     // document again otherwise the document could have a non-zero onload block
    1446                 :     // count without the onload blocker request being in the loadgroup.
    1447               0 :     EnsureOnloadBlocker();
    1448                 :   }
    1449                 : 
    1450                 :   // The open occurred after the document finished loading.
    1451                 :   // So we reset the document and create a new one.
    1452               0 :   nsCOMPtr<nsIChannel> channel;
    1453               0 :   nsCOMPtr<nsILoadGroup> group = do_QueryReferent(mDocumentLoadGroup);
    1454                 : 
    1455               0 :   nsresult rv = NS_NewChannel(getter_AddRefs(channel), uri, nsnull, group);
    1456                 : 
    1457               0 :   if (NS_FAILED(rv)) {
    1458               0 :     return rv;
    1459                 :   }
    1460                 : 
    1461                 :   // We can't depend on channels implementing property bags, so do our
    1462                 :   // base URI manually after reset.
    1463                 : 
    1464                 :   // Set the caller principal, if any, on the channel so that we'll
    1465                 :   // make sure to use it when we reset.
    1466               0 :   rv = channel->SetOwner(callerPrincipal);
    1467               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1468                 : 
    1469               0 :   if (callerChannel) {
    1470                 :     nsLoadFlags callerLoadFlags;
    1471               0 :     rv = callerChannel->GetLoadFlags(&callerLoadFlags);
    1472               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1473                 : 
    1474                 :     nsLoadFlags loadFlags;
    1475               0 :     rv = channel->GetLoadFlags(&loadFlags);
    1476               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1477                 : 
    1478               0 :     loadFlags |= callerLoadFlags & nsIRequest::INHIBIT_PERSISTENT_CACHING;
    1479                 : 
    1480               0 :     rv = channel->SetLoadFlags(loadFlags);
    1481               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1482                 :   }
    1483                 : 
    1484                 :   // Before we reset the doc notify the globalwindow of the change,
    1485                 :   // but only if we still have a window (i.e. our window object the
    1486                 :   // current inner window in our outer window).
    1487                 : 
    1488                 :   // Hold onto ourselves on the offchance that we're down to one ref
    1489                 :   nsCOMPtr<nsIDOMDocument> kungFuDeathGrip =
    1490               0 :     do_QueryInterface((nsIHTMLDocument*)this);
    1491                 : 
    1492               0 :   nsPIDOMWindow *window = GetInnerWindow();
    1493               0 :   if (window) {
    1494                 :     // Remember the old scope in case the call to SetNewDocument changes it.
    1495               0 :     nsCOMPtr<nsIScriptGlobalObject> oldScope(do_QueryReferent(mScopeObject));
    1496                 : 
    1497                 : #ifdef DEBUG
    1498               0 :     bool willReparent = mWillReparent;
    1499               0 :     mWillReparent = true;
    1500                 : #endif
    1501                 : 
    1502                 :     // Should this pass true for aForceReuseInnerWindow?
    1503               0 :     rv = window->SetNewDocument(this, nsnull, false);
    1504               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1505                 : 
    1506                 : #ifdef DEBUG
    1507               0 :     mWillReparent = willReparent;
    1508                 : #endif
    1509                 : 
    1510                 :     // Now make sure we're not flagged as the initial document anymore, now
    1511                 :     // that we've had stuff done to us.  From now on, if anyone tries to
    1512                 :     // document.open() us, they get a new inner window.
    1513               0 :     SetIsInitialDocument(false);
    1514                 : 
    1515               0 :     nsCOMPtr<nsIScriptGlobalObject> newScope(do_QueryReferent(mScopeObject));
    1516               0 :     if (oldScope && newScope != oldScope) {
    1517               0 :       rv = nsContentUtils::ReparentContentWrappersInScope(cx, oldScope, newScope);
    1518               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1519                 :     }
    1520                 :   }
    1521                 : 
    1522                 :   // Call Reset(), this will now do the full reset
    1523               0 :   Reset(channel, group);
    1524               0 :   if (baseURI) {
    1525               0 :     mDocumentBaseURI = baseURI;
    1526                 :   }
    1527                 : 
    1528                 :   // Store the security info of the caller now that we're done
    1529                 :   // resetting the document.
    1530               0 :   mSecurityInfo = securityInfo;
    1531                 : 
    1532               0 :   mParserAborted = false;
    1533               0 :   mParser = nsHtml5Module::NewHtml5Parser();
    1534               0 :   nsHtml5Module::Initialize(mParser, this, uri, shell, channel);
    1535               0 :   rv = NS_OK;
    1536                 : 
    1537                 :   // This will be propagated to the parser when someone actually calls write()
    1538               0 :   SetContentTypeInternal(contentType);
    1539                 : 
    1540                 :   // Prepare the docshell and the document viewer for the impending
    1541                 :   // out of band document.write()
    1542               0 :   shell->PrepareForNewContentModel();
    1543                 : 
    1544                 :   // Now check whether we were opened with a "replace" argument.  If
    1545                 :   // so, we need to tell the docshell to not create a new history
    1546                 :   // entry for this load. Otherwise, make sure that we're doing a normal load,
    1547                 :   // not whatever type of load was previously done on this docshell.
    1548               0 :   shell->SetLoadType(
    1549               0 :     (aOptionalArgCount > 1 && aReplaceOrName.EqualsLiteral("replace"))
    1550               0 :     ? LOAD_NORMAL_REPLACE : LOAD_NORMAL);
    1551                 : 
    1552               0 :   nsCOMPtr<nsIContentViewer> cv;
    1553               0 :   shell->GetContentViewer(getter_AddRefs(cv));
    1554               0 :   if (cv) {
    1555               0 :     cv->LoadStart(static_cast<nsIHTMLDocument *>(this));
    1556                 :   }
    1557                 : 
    1558                 :   // Add a wyciwyg channel request into the document load group
    1559               0 :   NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::Open(): wyciwyg "
    1560                 :                "channel already exists!");
    1561                 : 
    1562                 :   // In case the editor is listening and will see the new channel
    1563                 :   // being added, make sure mWriteLevel is non-zero so that the editor
    1564                 :   // knows that document.open/write/close() is being called on this
    1565                 :   // document.
    1566               0 :   ++mWriteLevel;
    1567                 : 
    1568               0 :   CreateAndAddWyciwygChannel();
    1569                 : 
    1570               0 :   --mWriteLevel;
    1571                 : 
    1572               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1573               0 :   return CallQueryInterface(this, aReturn);
    1574                 : }
    1575                 : 
    1576                 : NS_IMETHODIMP
    1577               0 : nsHTMLDocument::Clear()
    1578                 : {
    1579                 :   // This method has been deprecated
    1580               0 :   return NS_OK;
    1581                 : }
    1582                 : 
    1583                 : NS_IMETHODIMP
    1584               0 : nsHTMLDocument::Close()
    1585                 : {
    1586               0 :   if (!IsHTML()) {
    1587                 :     // No calling document.close() on XHTML!
    1588                 : 
    1589               0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
    1590                 :   }
    1591                 : 
    1592               0 :   if (!mParser || !mParser->IsScriptCreated()) {
    1593               0 :     return NS_OK;
    1594                 :   }
    1595                 : 
    1596               0 :   ++mWriteLevel;
    1597               0 :   nsresult rv = mParser->Parse(EmptyString(), nsnull,
    1598               0 :                                GetContentTypeInternal(), true);
    1599               0 :   --mWriteLevel;
    1600                 : 
    1601                 :   // XXX Make sure that all the document.written content is
    1602                 :   // reflowed.  We should remove this call once we change
    1603                 :   // nsHTMLDocument::OpenCommon() so that it completely destroys the
    1604                 :   // earlier document's content and frame hierarchy.  Right now, it
    1605                 :   // re-uses the earlier document's root content object and
    1606                 :   // corresponding frame objects.  These re-used frame objects think
    1607                 :   // that they have already been reflowed, so they drop initial
    1608                 :   // reflows.  For certain cases of document.written content, like a
    1609                 :   // frameset document, the dropping of the initial reflow means
    1610                 :   // that we end up in document.close() without appended any reflow
    1611                 :   // commands to the reflow queue and, consequently, without adding
    1612                 :   // the dummy layout request to the load group.  Since the dummy
    1613                 :   // layout request is not added to the load group, the onload
    1614                 :   // handler of the frameset fires before the frames get reflowed
    1615                 :   // and loaded.  That is the long explanation for why we need this
    1616                 :   // one line of code here!
    1617                 :   // XXXbz as far as I can tell this may not be needed anymore; all
    1618                 :   // the testcases in bug 57636 pass without this line...  Leaving
    1619                 :   // it be for now, though.  In any case, there's no reason to do
    1620                 :   // this if we have no presshell, since in that case none of the
    1621                 :   // above about reusing frames applies.
    1622                 :   //
    1623                 :   // XXXhsivonen keeping this around for bug 577508 / 253951 still :-(
    1624               0 :   if (GetShell()) {
    1625               0 :     FlushPendingNotifications(Flush_Layout);
    1626                 :   }
    1627                 : 
    1628                 :   // Removing the wyciwygChannel here is wrong when document.close() is
    1629                 :   // called from within the document itself. However, legacy requires the
    1630                 :   // channel to be removed here. Otherwise, the load event never fires.
    1631               0 :   NS_ASSERTION(mWyciwygChannel, "nsHTMLDocument::Close(): Trying to remove "
    1632                 :                "nonexistent wyciwyg channel!");
    1633               0 :   RemoveWyciwygChannel();
    1634               0 :   NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::Close(): "
    1635                 :                "nsIWyciwygChannel could not be removed!");
    1636               0 :   return rv;
    1637                 : }
    1638                 : 
    1639                 : nsresult
    1640               0 : nsHTMLDocument::WriteCommon(JSContext *cx,
    1641                 :                             const nsAString& aText,
    1642                 :                             bool aNewlineTerminate)
    1643                 : {
    1644                 :   mTooDeepWriteRecursion =
    1645               0 :     (mWriteLevel > NS_MAX_DOCUMENT_WRITE_DEPTH || mTooDeepWriteRecursion);
    1646               0 :   NS_ENSURE_STATE(!mTooDeepWriteRecursion);
    1647                 : 
    1648               0 :   if (!IsHTML() || mDisableDocWrite) {
    1649                 :     // No calling document.write*() on XHTML!
    1650                 : 
    1651               0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
    1652                 :   }
    1653                 : 
    1654               0 :   if (mParserAborted) {
    1655                 :     // Hixie says aborting the parser doesn't undefine the insertion point.
    1656                 :     // However, since we null out mParser in that case, we track the
    1657                 :     // theoretically defined insertion point using mParserAborted.
    1658               0 :     return NS_OK;
    1659                 :   }
    1660                 : 
    1661               0 :   nsresult rv = NS_OK;
    1662                 : 
    1663               0 :   void *key = GenerateParserKey();
    1664               0 :   if (mParser && !mParser->IsInsertionPointDefined()) {
    1665               0 :     if (mExternalScriptsBeingEvaluated) {
    1666                 :       // Instead of implying a call to document.open(), ignore the call.
    1667                 :       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    1668                 :                                       "DOM Events", this,
    1669                 :                                       nsContentUtils::eDOM_PROPERTIES,
    1670                 :                                       "DocumentWriteIgnored",
    1671                 :                                       nsnull, 0,
    1672               0 :                                       mDocumentURI);
    1673               0 :       return NS_OK;
    1674                 :     }
    1675               0 :     mParser->Terminate();
    1676               0 :     NS_ASSERTION(!mParser, "mParser should have been null'd out");
    1677                 :   }
    1678                 : 
    1679               0 :   if (!mParser) {
    1680               0 :     if (mExternalScriptsBeingEvaluated) {
    1681                 :       // Instead of implying a call to document.open(), ignore the call.
    1682                 :       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    1683                 :                                       "DOM Events", this,
    1684                 :                                       nsContentUtils::eDOM_PROPERTIES,
    1685                 :                                       "DocumentWriteIgnored",
    1686                 :                                       nsnull, 0,
    1687               0 :                                       mDocumentURI);
    1688               0 :       return NS_OK;
    1689                 :     }
    1690               0 :     nsCOMPtr<nsISupports> ignored;
    1691               0 :     rv = Open(NS_LITERAL_STRING("text/html"), EmptyString(), EmptyString(), cx,
    1692               0 :               1, getter_AddRefs(ignored));
    1693                 : 
    1694                 :     // If Open() fails, or if it didn't create a parser (as it won't
    1695                 :     // if the user chose to not discard the current document through
    1696                 :     // onbeforeunload), don't write anything.
    1697               0 :     if (NS_FAILED(rv) || !mParser) {
    1698               0 :       return rv;
    1699                 :     }
    1700               0 :     NS_ABORT_IF_FALSE(!JS_IsExceptionPending(cx),
    1701                 :                       "Open() succeeded but JS exception is pending");
    1702                 :   }
    1703                 : 
    1704               0 :   static NS_NAMED_LITERAL_STRING(new_line, "\n");
    1705                 : 
    1706                 :   // Save the data in cache if the write isn't from within the doc
    1707               0 :   if (mWyciwygChannel && !key) {
    1708               0 :     if (!aText.IsEmpty()) {
    1709               0 :       mWyciwygChannel->WriteToCacheEntry(aText);
    1710                 :     }
    1711                 : 
    1712               0 :     if (aNewlineTerminate) {
    1713               0 :       mWyciwygChannel->WriteToCacheEntry(new_line);
    1714                 :     }
    1715                 :   }
    1716                 : 
    1717               0 :   ++mWriteLevel;
    1718                 : 
    1719                 :   // This could be done with less code, but for performance reasons it
    1720                 :   // makes sense to have the code for two separate Parse() calls here
    1721                 :   // since the concatenation of strings costs more than we like. And
    1722                 :   // why pay that price when we don't need to?
    1723               0 :   if (aNewlineTerminate) {
    1724               0 :     rv = mParser->Parse(aText + new_line,
    1725               0 :                         key, GetContentTypeInternal(),
    1726               0 :                         false);
    1727                 :   } else {
    1728               0 :     rv = mParser->Parse(aText,
    1729               0 :                         key, GetContentTypeInternal(),
    1730               0 :                         false);
    1731                 :   }
    1732                 : 
    1733               0 :   --mWriteLevel;
    1734                 : 
    1735               0 :   mTooDeepWriteRecursion = (mWriteLevel != 0 && mTooDeepWriteRecursion);
    1736                 : 
    1737               0 :   return rv;
    1738                 : }
    1739                 : 
    1740                 : NS_IMETHODIMP
    1741               0 : nsHTMLDocument::Write(const nsAString& aText, JSContext *cx)
    1742                 : {
    1743               0 :   return WriteCommon(cx, aText, false);
    1744                 : }
    1745                 : 
    1746                 : NS_IMETHODIMP
    1747               0 : nsHTMLDocument::Writeln(const nsAString& aText, JSContext *cx)
    1748                 : {
    1749               0 :   return WriteCommon(cx, aText, true);
    1750                 : }
    1751                 : 
    1752                 : bool
    1753               0 : nsHTMLDocument::MatchNameAttribute(nsIContent* aContent, PRInt32 aNamespaceID,
    1754                 :                                    nsIAtom* aAtom, void* aData)
    1755                 : {
    1756               0 :   NS_PRECONDITION(aContent, "Must have content node to work with!");
    1757               0 :   nsString* elementName = static_cast<nsString*>(aData);
    1758                 :   return
    1759               0 :     aContent->GetNameSpaceID() == kNameSpaceID_XHTML &&
    1760                 :     aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
    1761               0 :                           *elementName, eCaseMatters);
    1762                 : }
    1763                 : 
    1764                 : /* static */
    1765                 : void*
    1766               0 : nsHTMLDocument::UseExistingNameString(nsINode* aRootNode, const nsString* aName)
    1767                 : {
    1768               0 :   return const_cast<nsString*>(aName);
    1769                 : }
    1770                 : 
    1771                 : NS_IMETHODIMP
    1772               0 : nsHTMLDocument::GetElementsByName(const nsAString& aElementName,
    1773                 :                                   nsIDOMNodeList** aReturn)
    1774                 : {
    1775               0 :   nsRefPtr<nsContentList> list = GetElementsByName(aElementName);
    1776               0 :   NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
    1777                 : 
    1778                 :   // Transfer ownership
    1779               0 :   list.forget(aReturn);
    1780                 : 
    1781               0 :   return NS_OK;
    1782                 : }
    1783                 : 
    1784                 : void
    1785               0 : nsHTMLDocument::AddedForm()
    1786                 : {
    1787               0 :   ++mNumForms;
    1788               0 : }
    1789                 : 
    1790                 : void
    1791               0 : nsHTMLDocument::RemovedForm()
    1792                 : {
    1793               0 :   --mNumForms;
    1794               0 : }
    1795                 : 
    1796                 : PRInt32
    1797               0 : nsHTMLDocument::GetNumFormsSynchronous()
    1798                 : {
    1799               0 :   return mNumForms;
    1800                 : }
    1801                 : 
    1802                 : NS_IMETHODIMP
    1803               0 : nsHTMLDocument::GetAlinkColor(nsAString& aAlinkColor)
    1804                 : {
    1805               0 :   aAlinkColor.Truncate();
    1806                 : 
    1807               0 :   nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyElement());
    1808               0 :   if (body) {
    1809               0 :     body->GetALink(aAlinkColor);
    1810                 :   }
    1811                 : 
    1812               0 :   return NS_OK;
    1813                 : }
    1814                 : 
    1815                 : NS_IMETHODIMP
    1816               0 : nsHTMLDocument::SetAlinkColor(const nsAString& aAlinkColor)
    1817                 : {
    1818               0 :   nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyElement());
    1819               0 :   if (body) {
    1820               0 :     body->SetALink(aAlinkColor);
    1821                 :   }
    1822                 : 
    1823               0 :   return NS_OK;
    1824                 : }
    1825                 : 
    1826                 : NS_IMETHODIMP
    1827               0 : nsHTMLDocument::GetLinkColor(nsAString& aLinkColor)
    1828                 : {
    1829               0 :   aLinkColor.Truncate();
    1830                 : 
    1831               0 :   nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyElement());
    1832               0 :   if (body) {
    1833               0 :     body->GetLink(aLinkColor);
    1834                 :   }
    1835                 : 
    1836               0 :   return NS_OK;
    1837                 : }
    1838                 : 
    1839                 : NS_IMETHODIMP
    1840               0 : nsHTMLDocument::SetLinkColor(const nsAString& aLinkColor)
    1841                 : {
    1842               0 :   nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyElement());
    1843               0 :   if (body) {
    1844               0 :     body->SetLink(aLinkColor);
    1845                 :   }
    1846                 : 
    1847               0 :   return NS_OK;
    1848                 : }
    1849                 : 
    1850                 : NS_IMETHODIMP
    1851               0 : nsHTMLDocument::GetVlinkColor(nsAString& aVlinkColor)
    1852                 : {
    1853               0 :   aVlinkColor.Truncate();
    1854                 : 
    1855               0 :   nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyElement());
    1856               0 :   if (body) {
    1857               0 :     body->GetVLink(aVlinkColor);
    1858                 :   }
    1859                 : 
    1860               0 :   return NS_OK;
    1861                 : }
    1862                 : 
    1863                 : NS_IMETHODIMP
    1864               0 : nsHTMLDocument::SetVlinkColor(const nsAString& aVlinkColor)
    1865                 : {
    1866               0 :   nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyElement());
    1867               0 :   if (body) {
    1868               0 :     body->SetVLink(aVlinkColor);
    1869                 :   }
    1870                 : 
    1871               0 :   return NS_OK;
    1872                 : }
    1873                 : 
    1874                 : NS_IMETHODIMP
    1875               0 : nsHTMLDocument::GetBgColor(nsAString& aBgColor)
    1876                 : {
    1877               0 :   aBgColor.Truncate();
    1878                 : 
    1879               0 :   nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyElement());
    1880               0 :   if (body) {
    1881               0 :     body->GetBgColor(aBgColor);
    1882                 :   }
    1883                 : 
    1884               0 :   return NS_OK;
    1885                 : }
    1886                 : 
    1887                 : NS_IMETHODIMP
    1888               0 : nsHTMLDocument::SetBgColor(const nsAString& aBgColor)
    1889                 : {
    1890               0 :   nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyElement());
    1891               0 :   if (body) {
    1892               0 :     body->SetBgColor(aBgColor);
    1893                 :   }
    1894                 : 
    1895               0 :   return NS_OK;
    1896                 : }
    1897                 : 
    1898                 : NS_IMETHODIMP
    1899               0 : nsHTMLDocument::GetFgColor(nsAString& aFgColor)
    1900                 : {
    1901               0 :   aFgColor.Truncate();
    1902                 : 
    1903               0 :   nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyElement());
    1904               0 :   if (body) {
    1905               0 :     body->GetText(aFgColor);
    1906                 :   }
    1907                 : 
    1908               0 :   return NS_OK;
    1909                 : }
    1910                 : 
    1911                 : NS_IMETHODIMP
    1912               0 : nsHTMLDocument::SetFgColor(const nsAString& aFgColor)
    1913                 : {
    1914               0 :   nsCOMPtr<nsIDOMHTMLBodyElement> body = do_QueryInterface(GetBodyElement());
    1915               0 :   if (body) {
    1916               0 :     body->SetText(aFgColor);
    1917                 :   }
    1918                 : 
    1919               0 :   return NS_OK;
    1920                 : }
    1921                 : 
    1922                 : 
    1923                 : NS_IMETHODIMP
    1924               0 : nsHTMLDocument::GetEmbeds(nsIDOMHTMLCollection** aEmbeds)
    1925                 : {
    1926               0 :   if (!mEmbeds) {
    1927               0 :     mEmbeds = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::embed, nsGkAtoms::embed);
    1928                 :   }
    1929                 : 
    1930               0 :   *aEmbeds = mEmbeds;
    1931               0 :   NS_ADDREF(*aEmbeds);
    1932                 : 
    1933               0 :   return NS_OK;
    1934                 : }
    1935                 : 
    1936                 : NS_IMETHODIMP
    1937               0 : nsHTMLDocument::GetSelection(nsISelection** aReturn)
    1938                 : {
    1939               0 :   nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(GetScopeObject());
    1940               0 :   nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(window);
    1941               0 :   NS_ENSURE_TRUE(pwin, NS_OK);
    1942               0 :   NS_ASSERTION(pwin->IsInnerWindow(), "Should have inner window here!");
    1943               0 :   NS_ENSURE_TRUE(pwin->GetOuterWindow() &&
    1944                 :                  pwin->GetOuterWindow()->GetCurrentInnerWindow() == pwin,
    1945                 :                  NS_OK);
    1946                 : 
    1947               0 :   return window->GetSelection(aReturn);
    1948                 :   
    1949                 : }
    1950                 : 
    1951                 : NS_IMETHODIMP
    1952               0 : nsHTMLDocument::CaptureEvents(PRInt32 aEventFlags)
    1953                 : {
    1954               0 :   ReportUseOfDeprecatedMethod(this, "UseOfCaptureEventsWarning");
    1955               0 :   return NS_OK;
    1956                 : }
    1957                 : 
    1958                 : NS_IMETHODIMP
    1959               0 : nsHTMLDocument::ReleaseEvents(PRInt32 aEventFlags)
    1960                 : {
    1961               0 :   ReportUseOfDeprecatedMethod(this, "UseOfReleaseEventsWarning");
    1962               0 :   return NS_OK;
    1963                 : }
    1964                 : 
    1965                 : NS_IMETHODIMP
    1966               0 : nsHTMLDocument::RouteEvent(nsIDOMEvent* aEvt)
    1967                 : {
    1968               0 :   ReportUseOfDeprecatedMethod(this, "UseOfRouteEventWarning");
    1969               0 :   return NS_OK;
    1970                 : }
    1971                 : 
    1972                 : // readonly attribute DOMString compatMode;
    1973                 : // Returns "BackCompat" if we are in quirks mode, "CSS1Compat" if we are
    1974                 : // in almost standards or full standards mode. See bug 105640.  This was
    1975                 : // implemented to match MSIE's compatMode property
    1976                 : NS_IMETHODIMP
    1977               0 : nsHTMLDocument::GetCompatMode(nsAString& aCompatMode)
    1978                 : {
    1979               0 :   NS_ASSERTION(mCompatMode == eCompatibility_NavQuirks ||
    1980                 :                mCompatMode == eCompatibility_AlmostStandards ||
    1981                 :                mCompatMode == eCompatibility_FullStandards,
    1982                 :                "mCompatMode is neither quirks nor strict for this document");
    1983                 : 
    1984               0 :   if (mCompatMode == eCompatibility_NavQuirks) {
    1985               0 :     aCompatMode.AssignLiteral("BackCompat");
    1986                 :   } else {
    1987               0 :     aCompatMode.AssignLiteral("CSS1Compat");
    1988                 :   }
    1989                 : 
    1990               0 :   return NS_OK;
    1991                 : }
    1992                 : 
    1993                 : // Mapped to document.embeds for NS4 compatibility
    1994                 : NS_IMETHODIMP
    1995               0 : nsHTMLDocument::GetPlugins(nsIDOMHTMLCollection** aPlugins)
    1996                 : {
    1997               0 :   *aPlugins = nsnull;
    1998                 : 
    1999               0 :   return GetEmbeds(aPlugins);
    2000                 : }
    2001                 : 
    2002                 : nsresult
    2003               0 : nsHTMLDocument::ResolveName(const nsAString& aName,
    2004                 :                             nsIContent *aForm,
    2005                 :                             nsISupports **aResult,
    2006                 :                             nsWrapperCache **aCache)
    2007                 : {
    2008               0 :   *aResult = nsnull;
    2009               0 :   *aCache = nsnull;
    2010                 : 
    2011               0 :   nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aName);
    2012               0 :   if (!entry) {
    2013               0 :     return NS_OK;
    2014                 :   }
    2015                 : 
    2016               0 :   PRUint32 length = 0;
    2017               0 :   nsBaseContentList *list = entry->GetNameContentList();
    2018               0 :   if (list) {
    2019               0 :     list->GetLength(&length);
    2020                 :   }
    2021                 : 
    2022               0 :   if (length > 0) {
    2023               0 :     if (length == 1) {
    2024                 :       // Only one element in the list, return the element instead of
    2025                 :       // returning the list
    2026                 : 
    2027               0 :       nsIContent *node = list->GetNodeAt(0);
    2028               0 :       if (!aForm || nsContentUtils::BelongsInForm(aForm, node)) {
    2029               0 :         NS_ADDREF(*aResult = node);
    2030               0 :         *aCache = node;
    2031                 :       }
    2032                 : 
    2033               0 :       return NS_OK;
    2034                 :     }
    2035                 : 
    2036                 :     // The list contains more than one element, return the whole
    2037                 :     // list, unless...
    2038                 : 
    2039               0 :     if (aForm) {
    2040                 :       // ... we're called from a form, in that case we create a
    2041                 :       // nsFormContentList which will filter out the elements in the
    2042                 :       // list that don't belong to aForm
    2043                 : 
    2044               0 :       nsFormContentList *fc_list = new nsFormContentList(aForm, *list);
    2045               0 :       NS_ENSURE_TRUE(fc_list, NS_ERROR_OUT_OF_MEMORY);
    2046                 : 
    2047                 :       PRUint32 len;
    2048               0 :       fc_list->GetLength(&len);
    2049                 : 
    2050               0 :       if (len < 2) {
    2051                 :         // After the nsFormContentList is done filtering there's either
    2052                 :         // nothing or one element in the list.  Return that element, or null
    2053                 :         // if there's no element in the list.
    2054                 : 
    2055               0 :         nsIContent *node = fc_list->GetNodeAt(0);
    2056                 : 
    2057               0 :         NS_IF_ADDREF(*aResult = node);
    2058               0 :         *aCache = node;
    2059                 : 
    2060               0 :         delete fc_list;
    2061                 : 
    2062               0 :         return NS_OK;
    2063                 :       }
    2064                 : 
    2065               0 :       list = fc_list;
    2066                 :     }
    2067                 : 
    2068               0 :     return CallQueryInterface(list, aResult);
    2069                 :   }
    2070                 : 
    2071                 :   // No named items were found, see if there's one registerd by id for
    2072                 :   // aName. If we get this far, FindNamedItems() will have been called
    2073                 :   // for aName, so we're guaranteed that if there is an element with
    2074                 :   // the id aName, it'll be entry's IdContent.
    2075                 : 
    2076               0 :   Element *e = entry->GetIdElement();
    2077                 : 
    2078               0 :   if (e && e->IsHTML()) {
    2079               0 :     nsIAtom *tag = e->Tag();
    2080                 : 
    2081               0 :     if ((tag == nsGkAtoms::embed  ||
    2082                 :          tag == nsGkAtoms::img    ||
    2083                 :          tag == nsGkAtoms::object ||
    2084                 :          tag == nsGkAtoms::applet) &&
    2085               0 :         (!aForm || nsContentUtils::BelongsInForm(aForm, e))) {
    2086               0 :       NS_ADDREF(*aResult = e);
    2087               0 :       *aCache = e;
    2088                 :     }
    2089                 :   }
    2090                 : 
    2091               0 :   return NS_OK;
    2092                 : }
    2093                 : 
    2094                 : //----------------------------
    2095                 : 
    2096                 : // forms related stuff
    2097                 : 
    2098                 : NS_IMETHODIMP
    2099               0 : nsHTMLDocument::GetForms(nsIDOMHTMLCollection** aForms)
    2100                 : {
    2101               0 :   nsContentList *forms = nsHTMLDocument::GetForms();
    2102               0 :   if (!forms)
    2103               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2104                 : 
    2105               0 :   NS_ADDREF(*aForms = forms);
    2106               0 :   return NS_OK;
    2107                 : }
    2108                 : 
    2109                 : nsContentList*
    2110               0 : nsHTMLDocument::GetForms()
    2111                 : {
    2112               0 :   if (!mForms) {
    2113               0 :     mForms = new nsContentList(this, kNameSpaceID_XHTML, nsGkAtoms::form, nsGkAtoms::form);
    2114                 :   }
    2115                 : 
    2116               0 :   return mForms;
    2117                 : }
    2118                 : 
    2119               0 : static bool MatchFormControls(nsIContent* aContent, PRInt32 aNamespaceID,
    2120                 :                                 nsIAtom* aAtom, void* aData)
    2121                 : {
    2122               0 :   return aContent->IsNodeOfType(nsIContent::eHTML_FORM_CONTROL);
    2123                 : }
    2124                 : 
    2125                 : nsContentList*
    2126               0 : nsHTMLDocument::GetFormControls()
    2127                 : {
    2128               0 :   if (!mFormControls) {
    2129               0 :     mFormControls = new nsContentList(this, MatchFormControls, nsnull, nsnull);
    2130                 :   }
    2131                 : 
    2132               0 :   return mFormControls;
    2133                 : }
    2134                 : 
    2135                 : nsresult
    2136               0 : nsHTMLDocument::CreateAndAddWyciwygChannel(void)
    2137                 : {
    2138               0 :   nsresult rv = NS_OK;
    2139               0 :   nsCAutoString url, originalSpec;
    2140                 : 
    2141               0 :   mDocumentURI->GetSpec(originalSpec);
    2142                 : 
    2143                 :   // Generate the wyciwyg url
    2144               0 :   url = NS_LITERAL_CSTRING("wyciwyg://")
    2145               0 :       + nsPrintfCString("%d", gWyciwygSessionCnt++)
    2146               0 :       + NS_LITERAL_CSTRING("/")
    2147               0 :       + originalSpec;
    2148                 : 
    2149               0 :   nsCOMPtr<nsIURI> wcwgURI;
    2150               0 :   NS_NewURI(getter_AddRefs(wcwgURI), url);
    2151                 : 
    2152                 :   // Create the nsIWyciwygChannel to store out-of-band
    2153                 :   // document.write() script to cache
    2154               0 :   nsCOMPtr<nsIChannel> channel;
    2155                 :   // Create a wyciwyg Channel
    2156               0 :   rv = NS_NewChannel(getter_AddRefs(channel), wcwgURI);
    2157               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2158                 : 
    2159               0 :   mWyciwygChannel = do_QueryInterface(channel);
    2160                 : 
    2161               0 :   mWyciwygChannel->SetSecurityInfo(mSecurityInfo);
    2162                 : 
    2163                 :   // Note: we want to treat this like a "previous document" hint so that,
    2164                 :   // e.g. a <meta> tag in the document.write content can override it.
    2165               0 :   SetDocumentCharacterSetSource(kCharsetFromHintPrevDoc);
    2166               0 :   mWyciwygChannel->SetCharsetAndSource(kCharsetFromHintPrevDoc,
    2167               0 :                                        GetDocumentCharacterSet());
    2168                 : 
    2169                 :   // Use our new principal
    2170               0 :   channel->SetOwner(NodePrincipal());
    2171                 : 
    2172                 :   // Inherit load flags from the original document's channel
    2173               0 :   channel->SetLoadFlags(mLoadFlags);
    2174                 : 
    2175               0 :   nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
    2176                 : 
    2177                 :   // Use the Parent document's loadgroup to trigger load notifications
    2178               0 :   if (loadGroup && channel) {
    2179               0 :     rv = channel->SetLoadGroup(loadGroup);
    2180               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2181                 : 
    2182               0 :     nsLoadFlags loadFlags = 0;
    2183               0 :     channel->GetLoadFlags(&loadFlags);
    2184               0 :     loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
    2185               0 :     channel->SetLoadFlags(loadFlags);
    2186                 : 
    2187               0 :     channel->SetOriginalURI(wcwgURI);
    2188                 : 
    2189               0 :     rv = loadGroup->AddRequest(mWyciwygChannel, nsnull);
    2190               0 :     NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to add request to load group.");
    2191                 :   }
    2192                 : 
    2193               0 :   return rv;
    2194                 : }
    2195                 : 
    2196                 : nsresult
    2197               0 : nsHTMLDocument::RemoveWyciwygChannel(void)
    2198                 : {
    2199               0 :   nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
    2200                 : 
    2201                 :   // note there can be a write request without a load group if
    2202                 :   // this is a synchronously constructed about:blank document
    2203               0 :   if (loadGroup && mWyciwygChannel) {
    2204               0 :     mWyciwygChannel->CloseCacheEntry(NS_OK);
    2205               0 :     loadGroup->RemoveRequest(mWyciwygChannel, nsnull, NS_OK);
    2206                 :   }
    2207                 : 
    2208               0 :   mWyciwygChannel = nsnull;
    2209                 : 
    2210               0 :   return NS_OK;
    2211                 : }
    2212                 : 
    2213                 : void *
    2214               0 : nsHTMLDocument::GenerateParserKey(void)
    2215                 : {
    2216               0 :   if (!mScriptLoader) {
    2217                 :     // If we don't have a script loader, then the parser probably isn't parsing
    2218                 :     // anything anyway, so just return null.
    2219               0 :     return nsnull;
    2220                 :   }
    2221                 : 
    2222                 :   // The script loader provides us with the currently executing script element,
    2223                 :   // which is guaranteed to be unique per script.
    2224               0 :   nsIScriptElement* script = mScriptLoader->GetCurrentParserInsertedScript();
    2225               0 :   if (script && mParser && mParser->IsScriptCreated()) {
    2226               0 :     nsCOMPtr<nsIParser> creatorParser = script->GetCreatorParser();
    2227               0 :     if (creatorParser != mParser) {
    2228                 :       // Make scripts that aren't inserted by the active parser of this document
    2229                 :       // participate in the context of the script that document.open()ed
    2230                 :       // this document.
    2231               0 :       return nsnull;
    2232                 :     }
    2233                 :   }
    2234               0 :   return script;
    2235                 : }
    2236                 : 
    2237                 : /* attribute DOMString designMode; */
    2238                 : NS_IMETHODIMP
    2239               0 : nsHTMLDocument::GetDesignMode(nsAString & aDesignMode)
    2240                 : {
    2241               0 :   if (HasFlag(NODE_IS_EDITABLE)) {
    2242               0 :     aDesignMode.AssignLiteral("on");
    2243                 :   }
    2244                 :   else {
    2245               0 :     aDesignMode.AssignLiteral("off");
    2246                 :   }
    2247               0 :   return NS_OK;
    2248                 : }
    2249                 : 
    2250                 : void
    2251             246 : nsHTMLDocument::MaybeEditingStateChanged()
    2252                 : {
    2253             246 :   if (mUpdateNestLevel == 0 && (mContentEditableCount > 0) != IsEditingOn()) {
    2254               0 :     if (nsContentUtils::IsSafeToRunScript()) {
    2255               0 :       EditingStateChanged();
    2256               0 :     } else if (!mInDestructor) {
    2257                 :       nsContentUtils::AddScriptRunner(
    2258               0 :         NS_NewRunnableMethod(this, &nsHTMLDocument::MaybeEditingStateChanged));
    2259                 :     }
    2260                 :   }
    2261             246 : }
    2262                 : 
    2263                 : void
    2264             246 : nsHTMLDocument::EndUpdate(nsUpdateType aUpdateType)
    2265                 : {
    2266             246 :   nsDocument::EndUpdate(aUpdateType);
    2267                 : 
    2268             246 :   MaybeEditingStateChanged();
    2269             246 : }
    2270                 : 
    2271                 : 
    2272                 : // Helper class, used below in ChangeContentEditableCount().
    2273                 : class DeferredContentEditableCountChangeEvent : public nsRunnable
    2274               0 : {
    2275                 : public:
    2276               0 :   DeferredContentEditableCountChangeEvent(nsHTMLDocument *aDoc,
    2277                 :                                           nsIContent *aElement)
    2278                 :     : mDoc(aDoc)
    2279               0 :     , mElement(aElement)
    2280                 :   {
    2281               0 :   }
    2282                 : 
    2283               0 :   NS_IMETHOD Run() {
    2284               0 :     if (mElement && mElement->OwnerDoc() == mDoc) {
    2285               0 :       mDoc->DeferredContentEditableCountChange(mElement);
    2286                 :     }
    2287               0 :     return NS_OK;
    2288                 :   }
    2289                 : 
    2290                 : private:
    2291                 :   nsRefPtr<nsHTMLDocument> mDoc;
    2292                 :   nsCOMPtr<nsIContent> mElement;
    2293                 : };
    2294                 : 
    2295                 : nsresult
    2296               0 : nsHTMLDocument::ChangeContentEditableCount(nsIContent *aElement,
    2297                 :                                            PRInt32 aChange)
    2298                 : {
    2299                 :   NS_ASSERTION(mContentEditableCount + aChange >= 0,
    2300                 :                "Trying to decrement too much.");
    2301                 : 
    2302               0 :   mContentEditableCount += aChange;
    2303                 : 
    2304                 :   nsContentUtils::AddScriptRunner(
    2305               0 :     new DeferredContentEditableCountChangeEvent(this, aElement));
    2306                 : 
    2307               0 :   return NS_OK;
    2308                 : }
    2309                 : 
    2310                 : void
    2311               0 : nsHTMLDocument::DeferredContentEditableCountChange(nsIContent *aElement)
    2312                 : {
    2313               0 :   if (mParser ||
    2314               0 :       (mUpdateNestLevel > 0 && (mContentEditableCount > 0) != IsEditingOn())) {
    2315               0 :     return;
    2316                 :   }
    2317                 : 
    2318               0 :   EditingState oldState = mEditingState;
    2319                 : 
    2320               0 :   nsresult rv = EditingStateChanged();
    2321               0 :   NS_ENSURE_SUCCESS(rv, );
    2322                 : 
    2323               0 :   if (oldState == mEditingState && mEditingState == eContentEditable) {
    2324                 :     // We just changed the contentEditable state of a node, we need to reset
    2325                 :     // the spellchecking state of that node.
    2326               0 :     nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
    2327               0 :     if (node) {
    2328               0 :       nsPIDOMWindow *window = GetWindow();
    2329               0 :       if (!window)
    2330                 :         return;
    2331                 : 
    2332               0 :       nsIDocShell *docshell = window->GetDocShell();
    2333               0 :       if (!docshell)
    2334                 :         return;
    2335                 : 
    2336                 :       nsCOMPtr<nsIEditorDocShell> editorDocShell =
    2337               0 :         do_QueryInterface(docshell, &rv);
    2338               0 :       NS_ENSURE_SUCCESS(rv, );
    2339                 : 
    2340               0 :       nsCOMPtr<nsIEditor> editor;
    2341               0 :       editorDocShell->GetEditor(getter_AddRefs(editor));
    2342               0 :       if (editor) {
    2343               0 :         nsRefPtr<nsRange> range = new nsRange();
    2344               0 :         rv = range->SelectNode(node);
    2345               0 :         if (NS_FAILED(rv)) {
    2346                 :           // The node might be detached from the document at this point,
    2347                 :           // which would cause this call to fail.  In this case, we can
    2348                 :           // safely ignore the contenteditable count change.
    2349                 :           return;
    2350                 :         }
    2351                 : 
    2352               0 :         nsCOMPtr<nsIInlineSpellChecker> spellChecker;
    2353               0 :         rv = editor->GetInlineSpellChecker(false,
    2354               0 :                                            getter_AddRefs(spellChecker));
    2355               0 :         NS_ENSURE_SUCCESS(rv, );
    2356                 : 
    2357               0 :         if (spellChecker) {
    2358               0 :           rv = spellChecker->SpellCheckRange(range);
    2359                 :         }
    2360                 :       }
    2361                 :     }
    2362                 :   }
    2363                 : }
    2364                 : 
    2365                 : static bool
    2366               0 : DocAllResultMatch(nsIContent* aContent, PRInt32 aNamespaceID, nsIAtom* aAtom,
    2367                 :                   void* aData)
    2368                 : {
    2369               0 :   if (aContent->GetID() == aAtom) {
    2370               0 :     return true;
    2371                 :   }
    2372                 : 
    2373               0 :   nsGenericHTMLElement* elm = nsGenericHTMLElement::FromContent(aContent);
    2374               0 :   if (!elm) {
    2375               0 :     return false;
    2376                 :   }
    2377                 : 
    2378               0 :   nsIAtom* tag = elm->Tag();
    2379               0 :   if (tag != nsGkAtoms::a &&
    2380                 :       tag != nsGkAtoms::applet &&
    2381                 :       tag != nsGkAtoms::button &&
    2382                 :       tag != nsGkAtoms::embed &&
    2383                 :       tag != nsGkAtoms::form &&
    2384                 :       tag != nsGkAtoms::iframe &&
    2385                 :       tag != nsGkAtoms::img &&
    2386                 :       tag != nsGkAtoms::input &&
    2387                 :       tag != nsGkAtoms::map &&
    2388                 :       tag != nsGkAtoms::meta &&
    2389                 :       tag != nsGkAtoms::object &&
    2390                 :       tag != nsGkAtoms::select &&
    2391                 :       tag != nsGkAtoms::textarea) {
    2392               0 :     return false;
    2393                 :   }
    2394                 : 
    2395               0 :   const nsAttrValue* val = elm->GetParsedAttr(nsGkAtoms::name);
    2396               0 :   return val && val->Type() == nsAttrValue::eAtom &&
    2397               0 :          val->GetAtomValue() == aAtom;
    2398                 : }
    2399                 : 
    2400                 : 
    2401                 : nsISupports*
    2402               0 : nsHTMLDocument::GetDocumentAllResult(const nsAString& aID,
    2403                 :                                      nsWrapperCache** aCache,
    2404                 :                                      nsresult *aResult)
    2405                 : {
    2406               0 :   *aCache = nsnull;
    2407               0 :   *aResult = NS_OK;
    2408                 : 
    2409               0 :   nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(aID);
    2410               0 :   if (!entry) {
    2411               0 :     *aResult = NS_ERROR_OUT_OF_MEMORY;
    2412                 : 
    2413               0 :     return nsnull;
    2414                 :   }
    2415                 : 
    2416               0 :   Element* root = GetRootElement();
    2417               0 :   if (!root) {
    2418               0 :     return nsnull;
    2419                 :   }
    2420                 : 
    2421               0 :   nsRefPtr<nsContentList> docAllList = entry->GetDocAllList();
    2422               0 :   if (!docAllList) {
    2423               0 :     nsCOMPtr<nsIAtom> id = do_GetAtom(aID);
    2424                 : 
    2425                 :     docAllList = new nsContentList(root, DocAllResultMatch,
    2426               0 :                                    nsnull, nsnull, true, id);
    2427               0 :     entry->SetDocAllList(docAllList);
    2428                 :   }
    2429                 : 
    2430                 :   // Check if there are more than 1 entries. Do this by getting the second one
    2431                 :   // rather than the length since getting the length always requires walking
    2432                 :   // the entire document.
    2433                 : 
    2434               0 :   nsIContent* cont = docAllList->Item(1, true);
    2435               0 :   if (cont) {
    2436               0 :     *aCache = docAllList;
    2437               0 :     return static_cast<nsINodeList*>(docAllList);
    2438                 :   }
    2439                 : 
    2440                 :   // There's only 0 or 1 items. Return the first one or null.
    2441               0 :   *aCache = cont = docAllList->Item(0, true);
    2442                 : 
    2443               0 :   return cont;
    2444                 : }
    2445                 : 
    2446                 : static void
    2447               0 : NotifyEditableStateChange(nsINode *aNode, nsIDocument *aDocument)
    2448                 : {
    2449               0 :   for (nsIContent* child = aNode->GetFirstChild();
    2450                 :        child;
    2451               0 :        child = child->GetNextSibling()) {
    2452               0 :     if (child->IsElement()) {
    2453               0 :       child->AsElement()->UpdateState(true);
    2454                 :     }
    2455               0 :     NotifyEditableStateChange(child, aDocument);
    2456                 :   }
    2457               0 : }
    2458                 : 
    2459                 : void
    2460               0 : nsHTMLDocument::TearingDownEditor(nsIEditor *aEditor)
    2461                 : {
    2462               0 :   if (IsEditingOn()) {
    2463               0 :     EditingState oldState = mEditingState;
    2464               0 :     mEditingState = eTearingDown;
    2465                 : 
    2466               0 :     nsCOMPtr<nsIPresShell> presShell = GetShell();
    2467               0 :     if (!presShell)
    2468                 :       return;
    2469                 : 
    2470               0 :     nsCOMArray<nsIStyleSheet> agentSheets;
    2471               0 :     presShell->GetAgentStyleSheets(agentSheets);
    2472                 : 
    2473               0 :     RemoveFromAgentSheets(agentSheets, NS_LITERAL_STRING("resource://gre/res/contenteditable.css"));
    2474               0 :     if (oldState == eDesignMode)
    2475               0 :       RemoveFromAgentSheets(agentSheets, NS_LITERAL_STRING("resource://gre/res/designmode.css"));
    2476                 : 
    2477               0 :     presShell->SetAgentStyleSheets(agentSheets);
    2478                 : 
    2479               0 :     presShell->ReconstructStyleData();
    2480                 :   }
    2481                 : }
    2482                 : 
    2483                 : nsresult
    2484               0 : nsHTMLDocument::TurnEditingOff()
    2485                 : {
    2486               0 :   NS_ASSERTION(mEditingState != eOff, "Editing is already off.");
    2487                 : 
    2488               0 :   nsPIDOMWindow *window = GetWindow();
    2489               0 :   if (!window)
    2490               0 :     return NS_ERROR_FAILURE;
    2491                 : 
    2492               0 :   nsIDocShell *docshell = window->GetDocShell();
    2493               0 :   if (!docshell)
    2494               0 :     return NS_ERROR_FAILURE;
    2495                 : 
    2496                 :   nsresult rv;
    2497               0 :   nsCOMPtr<nsIEditingSession> editSession = do_GetInterface(docshell, &rv);
    2498               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2499                 : 
    2500                 :   // turn editing off
    2501               0 :   rv = editSession->TearDownEditorOnWindow(window);
    2502               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2503                 : 
    2504               0 :   mEditingState = eOff;
    2505                 : 
    2506               0 :   return NS_OK;
    2507                 : }
    2508                 : 
    2509               0 : static bool HasPresShell(nsPIDOMWindow *aWindow)
    2510                 : {
    2511               0 :   nsIDocShell *docShell = aWindow->GetDocShell();
    2512               0 :   if (!docShell)
    2513               0 :     return false;
    2514               0 :   nsCOMPtr<nsIPresShell> presShell;
    2515               0 :   docShell->GetPresShell(getter_AddRefs(presShell));
    2516               0 :   return presShell != nsnull;
    2517                 : }
    2518                 : 
    2519                 : nsresult
    2520               0 : nsHTMLDocument::SetEditingState(EditingState aState)
    2521                 : {
    2522               0 :   mEditingState = aState;
    2523               0 :   return NS_OK;
    2524                 : }
    2525                 : 
    2526                 : nsresult
    2527               0 : nsHTMLDocument::EditingStateChanged()
    2528                 : {
    2529               0 :   if (mRemovedFromDocShell) {
    2530               0 :     return NS_OK;
    2531                 :   }
    2532                 : 
    2533               0 :   if (mEditingState == eSettingUp || mEditingState == eTearingDown) {
    2534                 :     // XXX We shouldn't recurse.
    2535               0 :     return NS_OK;
    2536                 :   }
    2537                 : 
    2538               0 :   bool designMode = HasFlag(NODE_IS_EDITABLE);
    2539                 :   EditingState newState = designMode ? eDesignMode :
    2540               0 :                           (mContentEditableCount > 0 ? eContentEditable : eOff);
    2541               0 :   if (mEditingState == newState) {
    2542                 :     // No changes in editing mode.
    2543               0 :     return NS_OK;
    2544                 :   }
    2545                 : 
    2546               0 :   if (newState == eOff) {
    2547                 :     // Editing is being turned off.
    2548               0 :     nsAutoScriptBlocker scriptBlocker;
    2549               0 :     NotifyEditableStateChange(this, this);
    2550               0 :     return TurnEditingOff();
    2551                 :   }
    2552                 : 
    2553                 :   // Flush out style changes on our _parent_ document, if any, so that
    2554                 :   // our check for a presshell won't get stale information.
    2555               0 :   if (mParentDocument) {
    2556               0 :     mParentDocument->FlushPendingNotifications(Flush_Style);
    2557                 :   }
    2558                 : 
    2559                 :   // get editing session, make sure this is a strong reference so the
    2560                 :   // window can't get deleted during the rest of this call.
    2561               0 :   nsCOMPtr<nsPIDOMWindow> window = GetWindow();
    2562               0 :   if (!window)
    2563               0 :     return NS_ERROR_FAILURE;
    2564                 : 
    2565               0 :   nsIDocShell *docshell = window->GetDocShell();
    2566               0 :   if (!docshell)
    2567               0 :     return NS_ERROR_FAILURE;
    2568                 : 
    2569                 :   nsresult rv;
    2570               0 :   nsCOMPtr<nsIEditingSession> editSession = do_GetInterface(docshell, &rv);
    2571               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2572                 : 
    2573               0 :   nsCOMPtr<nsIEditor> existingEditor;
    2574               0 :   editSession->GetEditorForWindow(window, getter_AddRefs(existingEditor));
    2575               0 :   if (existingEditor) {
    2576                 :     // We might already have an editor if it was set up for mail, let's see
    2577                 :     // if this is actually the case.
    2578               0 :     nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(existingEditor);
    2579               0 :     NS_ABORT_IF_FALSE(htmlEditor, "If we have an editor, it must be an HTML editor");
    2580               0 :     PRUint32 flags = 0;
    2581               0 :     existingEditor->GetFlags(&flags);
    2582               0 :     if (flags & nsIPlaintextEditor::eEditorMailMask) {
    2583                 :       // We already have a mail editor, then we should not attempt to create
    2584                 :       // another one.
    2585               0 :       return NS_OK;
    2586                 :     }
    2587                 :   }
    2588                 : 
    2589               0 :   if (!HasPresShell(window)) {
    2590                 :     // We should not make the window editable or setup its editor.
    2591                 :     // It's probably style=display:none.
    2592               0 :     return NS_OK;
    2593                 :   }
    2594                 : 
    2595               0 :   bool makeWindowEditable = mEditingState == eOff;
    2596               0 :   bool updateState = false;
    2597               0 :   bool spellRecheckAll = false;
    2598               0 :   nsCOMPtr<nsIEditor> editor;
    2599                 : 
    2600                 :   {
    2601               0 :     EditingState oldState = mEditingState;
    2602               0 :     nsAutoEditingState push(this, eSettingUp);
    2603                 : 
    2604               0 :     if (makeWindowEditable) {
    2605                 :       // Editing is being turned on (through designMode or contentEditable)
    2606                 :       // Turn on editor.
    2607                 :       // XXX This can cause flushing which can change the editing state, so make
    2608                 :       //     sure to avoid recursing.
    2609               0 :       rv = editSession->MakeWindowEditable(window, "html", false, false,
    2610               0 :                                            true);
    2611               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2612                 :     }
    2613                 : 
    2614                 :     // XXX Need to call TearDownEditorOnWindow for all failures.
    2615                 :     nsCOMPtr<nsIEditorDocShell> editorDocShell =
    2616               0 :       do_QueryInterface(docshell, &rv);
    2617               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2618                 : 
    2619               0 :     editorDocShell->GetEditor(getter_AddRefs(editor));
    2620               0 :     if (!editor)
    2621               0 :       return NS_ERROR_FAILURE;
    2622                 : 
    2623               0 :     nsCOMPtr<nsIPresShell> presShell = GetShell();
    2624               0 :     NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
    2625                 : 
    2626                 :     // If we're entering the design mode, put the selection at the beginning of
    2627                 :     // the document for compatibility reasons.
    2628               0 :     if (designMode && oldState == eOff) {
    2629               0 :       editor->BeginningOfDocument();
    2630                 :     }
    2631                 : 
    2632               0 :     nsCOMArray<nsIStyleSheet> agentSheets;
    2633               0 :     rv = presShell->GetAgentStyleSheets(agentSheets);
    2634               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2635                 : 
    2636               0 :     nsCOMPtr<nsIURI> uri;
    2637               0 :     rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_STRING("resource://gre/res/contenteditable.css"));
    2638               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2639                 : 
    2640               0 :     nsRefPtr<nsCSSStyleSheet> sheet;
    2641               0 :     rv = LoadChromeSheetSync(uri, true, getter_AddRefs(sheet));
    2642               0 :     NS_ENSURE_TRUE(sheet, rv);
    2643                 : 
    2644               0 :     rv = agentSheets.AppendObject(sheet);
    2645               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2646                 : 
    2647                 :     // Should we update the editable state of all the nodes in the document? We
    2648                 :     // need to do this when the designMode value changes, as that overrides
    2649                 :     // specific states on the elements.
    2650               0 :     if (designMode) {
    2651                 :       // designMode is being turned on (overrides contentEditable).
    2652               0 :       rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_STRING("resource://gre/res/designmode.css"));
    2653               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2654                 : 
    2655               0 :       rv = LoadChromeSheetSync(uri, true, getter_AddRefs(sheet));
    2656               0 :       NS_ENSURE_TRUE(sheet, rv);
    2657                 : 
    2658               0 :       rv = agentSheets.AppendObject(sheet);
    2659               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2660                 : 
    2661                 :       // Disable scripting and plugins.
    2662               0 :       rv = editSession->DisableJSAndPlugins(window);
    2663               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2664                 : 
    2665               0 :       updateState = true;
    2666               0 :       spellRecheckAll = oldState == eContentEditable;
    2667                 :     }
    2668               0 :     else if (oldState == eDesignMode) {
    2669                 :       // designMode is being turned off (contentEditable is still on).
    2670               0 :       RemoveFromAgentSheets(agentSheets, NS_LITERAL_STRING("resource://gre/res/designmode.css"));
    2671                 : 
    2672               0 :       rv = editSession->RestoreJSAndPlugins(window);
    2673               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2674                 : 
    2675               0 :       updateState = true;
    2676                 :     }
    2677                 : 
    2678               0 :     rv = presShell->SetAgentStyleSheets(agentSheets);
    2679               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2680                 : 
    2681               0 :     presShell->ReconstructStyleData();
    2682                 :   }
    2683                 : 
    2684               0 :   mEditingState = newState;
    2685                 : 
    2686               0 :   if (makeWindowEditable) {
    2687                 :     // Set the editor to not insert br's on return when in p
    2688                 :     // elements by default.
    2689                 :     // XXX Do we only want to do this for designMode?
    2690                 :     bool unused;
    2691               0 :     rv = ExecCommand(NS_LITERAL_STRING("insertBrOnReturn"), false,
    2692               0 :                      NS_LITERAL_STRING("false"), &unused);
    2693                 : 
    2694               0 :     if (NS_FAILED(rv)) {
    2695                 :       // Editor setup failed. Editing is not on after all.
    2696                 :       // XXX Should we reset the editable flag on nodes?
    2697               0 :       editSession->TearDownEditorOnWindow(window);
    2698               0 :       mEditingState = eOff;
    2699                 : 
    2700               0 :       return rv;
    2701                 :     }
    2702                 :   }
    2703                 : 
    2704               0 :   if (updateState) {
    2705               0 :     nsAutoScriptBlocker scriptBlocker;
    2706               0 :     NotifyEditableStateChange(this, this);
    2707                 :   }
    2708                 : 
    2709                 :   // Resync the editor's spellcheck state.
    2710               0 :   if (spellRecheckAll) {
    2711               0 :     nsCOMPtr<nsISelectionController> selcon;
    2712               0 :     nsresult rv = editor->GetSelectionController(getter_AddRefs(selcon));
    2713               0 :     NS_ENSURE_SUCCESS(rv, rv); 
    2714                 : 
    2715               0 :     nsCOMPtr<nsISelection> spellCheckSelection;
    2716               0 :     rv = selcon->GetSelection(nsISelectionController::SELECTION_SPELLCHECK,
    2717               0 :                               getter_AddRefs(spellCheckSelection));
    2718               0 :     if (NS_SUCCEEDED(rv)) {
    2719               0 :       spellCheckSelection->RemoveAllRanges();
    2720                 :     }
    2721                 :   }
    2722               0 :   editor->SyncRealTimeSpell();
    2723                 : 
    2724               0 :   return NS_OK;
    2725                 : }
    2726                 : 
    2727                 : NS_IMETHODIMP
    2728               0 : nsHTMLDocument::SetDesignMode(const nsAString & aDesignMode)
    2729                 : {
    2730               0 :   nsresult rv = NS_OK;
    2731                 : 
    2732               0 :   if (!nsContentUtils::IsCallerTrustedForWrite()) {
    2733               0 :     nsCOMPtr<nsIPrincipal> subject;
    2734               0 :     nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
    2735               0 :     rv = secMan->GetSubjectPrincipal(getter_AddRefs(subject));
    2736               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2737               0 :     if (subject) {
    2738                 :       bool subsumes;
    2739               0 :       rv = subject->Subsumes(NodePrincipal(), &subsumes);
    2740               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2741                 : 
    2742               0 :       NS_ENSURE_TRUE(subsumes, NS_ERROR_DOM_PROP_ACCESS_DENIED);
    2743                 :     }
    2744                 :   }
    2745                 : 
    2746               0 :   bool editableMode = HasFlag(NODE_IS_EDITABLE);
    2747               0 :   if (aDesignMode.LowerCaseEqualsASCII(editableMode ? "off" : "on")) {
    2748               0 :     SetEditableFlag(!editableMode);
    2749                 : 
    2750               0 :     return EditingStateChanged();
    2751                 :   }
    2752                 : 
    2753               0 :   return NS_OK;
    2754                 : }
    2755                 : 
    2756                 : nsresult
    2757               0 : nsHTMLDocument::GetMidasCommandManager(nsICommandManager** aCmdMgr)
    2758                 : {
    2759                 :   // initialize return value
    2760               0 :   NS_ENSURE_ARG_POINTER(aCmdMgr);
    2761                 : 
    2762                 :   // check if we have it cached
    2763               0 :   if (mMidasCommandManager) {
    2764               0 :     NS_ADDREF(*aCmdMgr = mMidasCommandManager);
    2765               0 :     return NS_OK;
    2766                 :   }
    2767                 : 
    2768               0 :   *aCmdMgr = nsnull;
    2769                 : 
    2770               0 :   nsPIDOMWindow *window = GetWindow();
    2771               0 :   if (!window)
    2772               0 :     return NS_ERROR_FAILURE;
    2773                 : 
    2774               0 :   nsIDocShell *docshell = window->GetDocShell();
    2775               0 :   if (!docshell)
    2776               0 :     return NS_ERROR_FAILURE;
    2777                 : 
    2778               0 :   mMidasCommandManager = do_GetInterface(docshell);
    2779               0 :   if (!mMidasCommandManager)
    2780               0 :     return NS_ERROR_FAILURE;
    2781                 : 
    2782               0 :   NS_ADDREF(*aCmdMgr = mMidasCommandManager);
    2783                 : 
    2784               0 :   return NS_OK;
    2785                 : }
    2786                 : 
    2787                 : 
    2788                 : struct MidasCommand {
    2789                 :   const char*  incomingCommandString;
    2790                 :   const char*  internalCommandString;
    2791                 :   const char*  internalParamString;
    2792                 :   bool useNewParam;
    2793                 :   bool convertToBoolean;
    2794                 : };
    2795                 : 
    2796                 : static const struct MidasCommand gMidasCommandTable[] = {
    2797                 :   { "bold",          "cmd_bold",            "", true,  false },
    2798                 :   { "italic",        "cmd_italic",          "", true,  false },
    2799                 :   { "underline",     "cmd_underline",       "", true,  false },
    2800                 :   { "strikethrough", "cmd_strikethrough",   "", true,  false },
    2801                 :   { "subscript",     "cmd_subscript",       "", true,  false },
    2802                 :   { "superscript",   "cmd_superscript",     "", true,  false },
    2803                 :   { "cut",           "cmd_cut",             "", true,  false },
    2804                 :   { "copy",          "cmd_copy",            "", true,  false },
    2805                 :   { "paste",         "cmd_paste",           "", true,  false },
    2806                 :   { "delete",        "cmd_delete",          "", true,  false },
    2807                 :   { "selectall",     "cmd_selectAll",       "", true,  false },
    2808                 :   { "undo",          "cmd_undo",            "", true,  false },
    2809                 :   { "redo",          "cmd_redo",            "", true,  false },
    2810                 :   { "indent",        "cmd_indent",          "", true,  false },
    2811                 :   { "outdent",       "cmd_outdent",         "", true,  false },
    2812                 :   { "backcolor",     "cmd_backgroundColor", "", false, false },
    2813                 :   { "forecolor",     "cmd_fontColor",       "", false, false },
    2814                 :   { "hilitecolor",   "cmd_highlight",       "", false, false },
    2815                 :   { "fontname",      "cmd_fontFace",        "", false, false },
    2816                 :   { "fontsize",      "cmd_fontSize",        "", false, false },
    2817                 :   { "increasefontsize", "cmd_increaseFont", "", false, false },
    2818                 :   { "decreasefontsize", "cmd_decreaseFont", "", false, false },
    2819                 :   { "inserthorizontalrule", "cmd_insertHR", "", true,  false },
    2820                 :   { "createlink",    "cmd_insertLinkNoUI",  "", false, false },
    2821                 :   { "insertimage",   "cmd_insertImageNoUI", "", false, false },
    2822                 :   { "inserthtml",    "cmd_insertHTML",      "", false, false },
    2823                 :   { "gethtml",       "cmd_getContents",     "", false, false },
    2824                 :   { "justifyleft",   "cmd_align",       "left", true,  false },
    2825                 :   { "justifyright",  "cmd_align",      "right", true,  false },
    2826                 :   { "justifycenter", "cmd_align",     "center", true,  false },
    2827                 :   { "justifyfull",   "cmd_align",    "justify", true,  false },
    2828                 :   { "removeformat",  "cmd_removeStyles",    "", true,  false },
    2829                 :   { "unlink",        "cmd_removeLinks",     "", true,  false },
    2830                 :   { "insertorderedlist",   "cmd_ol",        "", true,  false },
    2831                 :   { "insertunorderedlist", "cmd_ul",        "", true,  false },
    2832                 :   { "insertparagraph", "cmd_paragraphState", "p", true, false },
    2833                 :   { "formatblock",   "cmd_paragraphState",  "", false, false },
    2834                 :   { "heading",       "cmd_paragraphState",  "", false, false },
    2835                 :   { "styleWithCSS",  "cmd_setDocumentUseCSS", "", false, true },
    2836                 :   { "contentReadOnly", "cmd_setDocumentReadOnly", "", false, true },
    2837                 :   { "insertBrOnReturn", "cmd_insertBrOnReturn", "", false, true },
    2838                 :   { "enableObjectResizing", "cmd_enableObjectResizing", "", false, true },
    2839                 :   { "enableInlineTableEditing", "cmd_enableInlineTableEditing", "", false, true },
    2840                 : #if 0
    2841                 : // no editor support to remove alignments right now
    2842                 :   { "justifynone",   "cmd_align",           "", true,  false },
    2843                 : 
    2844                 : // the following will need special review before being turned on
    2845                 :   { "saveas",        "cmd_saveAs",          "", true,  false },
    2846                 :   { "print",         "cmd_print",           "", true,  false },
    2847                 : #endif
    2848                 :   { NULL, NULL, NULL, false, false }
    2849                 : };
    2850                 : 
    2851                 : #define MidasCommandCount ((sizeof(gMidasCommandTable) / sizeof(struct MidasCommand)) - 1)
    2852                 : 
    2853                 : static const char* const gBlocks[] = {
    2854                 :   "ADDRESS",
    2855                 :   "BLOCKQUOTE",
    2856                 :   "DD",
    2857                 :   "DIV",
    2858                 :   "DL",
    2859                 :   "DT",
    2860                 :   "H1",
    2861                 :   "H2",
    2862                 :   "H3",
    2863                 :   "H4",
    2864                 :   "H5",
    2865                 :   "H6",
    2866                 :   "P",
    2867                 :   "PRE"
    2868                 : };
    2869                 : 
    2870                 : static bool
    2871               0 : ConvertToMidasInternalCommandInner(const nsAString & inCommandID,
    2872                 :                                    const nsAString & inParam,
    2873                 :                                    nsACString& outCommandID,
    2874                 :                                    nsACString& outParam,
    2875                 :                                    bool& outIsBoolean,
    2876                 :                                    bool& outBooleanValue,
    2877                 :                                    bool aIgnoreParams)
    2878                 : {
    2879               0 :   NS_ConvertUTF16toUTF8 convertedCommandID(inCommandID);
    2880                 : 
    2881                 :   // Hack to support old boolean commands that were backwards (see bug 301490).
    2882               0 :   bool invertBool = false;
    2883               0 :   if (convertedCommandID.LowerCaseEqualsLiteral("usecss")) {
    2884               0 :     convertedCommandID.Assign("styleWithCSS");
    2885               0 :     invertBool = true;
    2886                 :   }
    2887               0 :   else if (convertedCommandID.LowerCaseEqualsLiteral("readonly")) {
    2888               0 :     convertedCommandID.Assign("contentReadOnly");
    2889               0 :     invertBool = true;
    2890                 :   }
    2891                 : 
    2892                 :   PRUint32 i;
    2893               0 :   bool found = false;
    2894               0 :   for (i = 0; i < MidasCommandCount; ++i) {
    2895               0 :     if (convertedCommandID.Equals(gMidasCommandTable[i].incomingCommandString,
    2896               0 :                                   nsCaseInsensitiveCStringComparator())) {
    2897               0 :       found = true;
    2898               0 :       break;
    2899                 :     }
    2900                 :   }
    2901                 : 
    2902               0 :   if (found) {
    2903                 :     // set outCommandID (what we use internally)
    2904               0 :     outCommandID.Assign(gMidasCommandTable[i].internalCommandString);
    2905                 : 
    2906                 :     // set outParam & outIsBoolean based on flags from the table
    2907               0 :     outIsBoolean = gMidasCommandTable[i].convertToBoolean;
    2908                 : 
    2909               0 :     if (!aIgnoreParams) {
    2910               0 :       if (gMidasCommandTable[i].useNewParam) {
    2911               0 :         outParam.Assign(gMidasCommandTable[i].internalParamString);
    2912                 :       }
    2913                 :       else {
    2914                 :         // handle checking of param passed in
    2915               0 :         if (outIsBoolean) {
    2916                 :           // if this is a boolean value and it's not explicitly false
    2917                 :           // (e.g. no value) we default to "true". For old backwards commands
    2918                 :           // we invert the check (see bug 301490).
    2919               0 :           if (invertBool) {
    2920               0 :             outBooleanValue = inParam.LowerCaseEqualsLiteral("false");
    2921                 :           }
    2922                 :           else {
    2923               0 :             outBooleanValue = !inParam.LowerCaseEqualsLiteral("false");
    2924                 :           }
    2925               0 :           outParam.Truncate();
    2926                 :         }
    2927                 :         else {
    2928                 :           // check to see if we need to convert the parameter
    2929               0 :           if (outCommandID.EqualsLiteral("cmd_paragraphState")) {
    2930               0 :             const PRUnichar *start = inParam.BeginReading();
    2931               0 :             const PRUnichar *end = inParam.EndReading();
    2932               0 :             if (start != end && *start == '<' && *(end - 1) == '>') {
    2933               0 :               ++start;
    2934               0 :               --end;
    2935                 :             }
    2936                 : 
    2937               0 :             NS_ConvertUTF16toUTF8 convertedParam(Substring(start, end));
    2938                 :             PRUint32 j;
    2939               0 :             for (j = 0; j < ArrayLength(gBlocks); ++j) {
    2940               0 :               if (convertedParam.Equals(gBlocks[j],
    2941               0 :                                         nsCaseInsensitiveCStringComparator())) {
    2942               0 :                 outParam.Assign(gBlocks[j]);
    2943               0 :                 break;
    2944                 :               }
    2945                 :             }
    2946                 : 
    2947               0 :             return j != ArrayLength(gBlocks);
    2948                 :           }
    2949                 :           else {
    2950               0 :             CopyUTF16toUTF8(inParam, outParam);
    2951                 :           }
    2952                 :         }
    2953                 :       }
    2954                 :     }
    2955                 :   } // end else for useNewParam (do convert existing param)
    2956                 :   else {
    2957                 :     // reset results if the command is not found in our table
    2958               0 :     outCommandID.SetLength(0);
    2959               0 :     outParam.SetLength(0);
    2960               0 :     outIsBoolean = false;
    2961                 :   }
    2962                 : 
    2963               0 :   return found;
    2964                 : }
    2965                 : 
    2966                 : static bool
    2967               0 : ConvertToMidasInternalCommand(const nsAString & inCommandID,
    2968                 :                               const nsAString & inParam,
    2969                 :                               nsACString& outCommandID,
    2970                 :                               nsACString& outParam,
    2971                 :                               bool& outIsBoolean,
    2972                 :                               bool& outBooleanValue)
    2973                 : {
    2974                 :   return ConvertToMidasInternalCommandInner(inCommandID, inParam, outCommandID,
    2975                 :                                             outParam, outIsBoolean,
    2976               0 :                                             outBooleanValue, false);
    2977                 : }
    2978                 : 
    2979                 : static bool
    2980               0 : ConvertToMidasInternalCommand(const nsAString & inCommandID,
    2981                 :                               nsACString& outCommandID)
    2982                 : {
    2983               0 :   nsCAutoString dummyCString;
    2984               0 :   nsAutoString dummyString;
    2985                 :   bool dummyBool;
    2986                 :   return ConvertToMidasInternalCommandInner(inCommandID, dummyString,
    2987                 :                                             outCommandID, dummyCString,
    2988               0 :                                             dummyBool, dummyBool, true);
    2989                 : }
    2990                 : 
    2991                 : jsid
    2992            1464 : nsHTMLDocument::sCutCopyInternal_id = JSID_VOID;
    2993                 : jsid
    2994            1464 : nsHTMLDocument::sPasteInternal_id = JSID_VOID;
    2995                 : 
    2996                 : /* Helper function to check security of clipboard commands. If aPaste is */
    2997                 : /* true, we check paste, else we check cutcopy */
    2998                 : nsresult
    2999               0 : nsHTMLDocument::DoClipboardSecurityCheck(bool aPaste)
    3000                 : {
    3001               0 :   nsresult rv = NS_ERROR_FAILURE;
    3002                 : 
    3003                 :   nsCOMPtr<nsIJSContextStack> stack =
    3004               0 :     do_GetService("@mozilla.org/js/xpc/ContextStack;1");
    3005                 : 
    3006               0 :   if (stack) {
    3007               0 :     JSContext *cx = nsnull;
    3008               0 :     stack->Peek(&cx);
    3009               0 :     if (!cx) {
    3010               0 :       return NS_OK;
    3011                 :     }
    3012                 : 
    3013               0 :     JSAutoRequest ar(cx);
    3014                 : 
    3015               0 :     NS_NAMED_LITERAL_CSTRING(classNameStr, "Clipboard");
    3016                 : 
    3017               0 :     nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
    3018                 : 
    3019               0 :     if (aPaste) {
    3020               0 :       if (nsHTMLDocument::sPasteInternal_id == JSID_VOID) {
    3021                 :         nsHTMLDocument::sPasteInternal_id =
    3022               0 :           INTERNED_STRING_TO_JSID(cx, ::JS_InternString(cx, "paste"));
    3023                 :       }
    3024                 :       rv = secMan->CheckPropertyAccess(cx, nsnull, classNameStr.get(),
    3025                 :                                        nsHTMLDocument::sPasteInternal_id,
    3026               0 :                                        nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
    3027                 :     } else {
    3028               0 :       if (nsHTMLDocument::sCutCopyInternal_id == JSID_VOID) {
    3029                 :         nsHTMLDocument::sCutCopyInternal_id =
    3030               0 :           INTERNED_STRING_TO_JSID(cx, ::JS_InternString(cx, "cutcopy"));
    3031                 :       }
    3032                 :       rv = secMan->CheckPropertyAccess(cx, nsnull, classNameStr.get(),
    3033                 :                                        nsHTMLDocument::sCutCopyInternal_id,
    3034               0 :                                        nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
    3035                 :     }
    3036                 :   }
    3037               0 :   return rv;
    3038                 : }
    3039                 : 
    3040                 : /* TODO: don't let this call do anything if the page is not done loading */
    3041                 : /* boolean execCommand(in DOMString commandID, in boolean doShowUI,
    3042                 :                                                in DOMString value); */
    3043                 : NS_IMETHODIMP
    3044               0 : nsHTMLDocument::ExecCommand(const nsAString & commandID,
    3045                 :                             bool doShowUI,
    3046                 :                             const nsAString & value,
    3047                 :                             bool *_retval)
    3048                 : {
    3049               0 :   NS_ENSURE_ARG_POINTER(_retval);
    3050                 : 
    3051                 :   //  for optional parameters see dom/src/base/nsHistory.cpp: HistoryImpl::Go()
    3052                 :   //  this might add some ugly JS dependencies?
    3053                 : 
    3054               0 :   *_retval = false;
    3055                 : 
    3056                 :   // if editing is not on, bail
    3057               0 :   if (!IsEditingOnAfterFlush())
    3058               0 :     return NS_ERROR_FAILURE;
    3059                 : 
    3060                 :   // if they are requesting UI from us, let's fail since we have no UI
    3061               0 :   if (doShowUI)
    3062               0 :     return NS_OK;
    3063                 : 
    3064               0 :   nsresult rv = NS_OK;
    3065                 : 
    3066               0 :   if (commandID.LowerCaseEqualsLiteral("gethtml"))
    3067               0 :     return NS_ERROR_FAILURE;
    3068                 : 
    3069               0 :   if (commandID.LowerCaseEqualsLiteral("cut") ||
    3070               0 :       (commandID.LowerCaseEqualsLiteral("copy"))) {
    3071               0 :     rv = DoClipboardSecurityCheck(false);
    3072               0 :   } else if (commandID.LowerCaseEqualsLiteral("paste")) {
    3073               0 :     rv = DoClipboardSecurityCheck(true);
    3074                 :   }
    3075                 : 
    3076               0 :   if (NS_FAILED(rv))
    3077               0 :     return rv;
    3078                 : 
    3079                 :   // get command manager and dispatch command to our window if it's acceptable
    3080               0 :   nsCOMPtr<nsICommandManager> cmdMgr;
    3081               0 :   GetMidasCommandManager(getter_AddRefs(cmdMgr));
    3082               0 :   if (!cmdMgr)
    3083               0 :     return NS_ERROR_FAILURE;
    3084                 : 
    3085               0 :   nsIDOMWindow *window = GetWindow();
    3086               0 :   if (!window)
    3087               0 :     return NS_ERROR_FAILURE;
    3088                 : 
    3089               0 :   nsCAutoString cmdToDispatch, paramStr;
    3090                 :   bool isBool, boolVal;
    3091               0 :   if (!ConvertToMidasInternalCommand(commandID, value,
    3092               0 :                                      cmdToDispatch, paramStr, isBool, boolVal))
    3093               0 :     return NS_OK;
    3094                 : 
    3095               0 :   if (!isBool && paramStr.IsEmpty()) {
    3096               0 :     rv = cmdMgr->DoCommand(cmdToDispatch.get(), nsnull, window);
    3097                 :   } else {
    3098                 :     // we have a command that requires a parameter, create params
    3099                 :     nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
    3100               0 :                                             NS_COMMAND_PARAMS_CONTRACTID, &rv);
    3101               0 :     if (!cmdParams)
    3102               0 :       return NS_ERROR_OUT_OF_MEMORY;
    3103                 : 
    3104               0 :     if (isBool)
    3105               0 :       rv = cmdParams->SetBooleanValue("state_attribute", boolVal);
    3106               0 :     else if (cmdToDispatch.Equals("cmd_fontFace"))
    3107               0 :       rv = cmdParams->SetStringValue("state_attribute", value);
    3108               0 :     else if (cmdToDispatch.Equals("cmd_insertHTML"))
    3109               0 :       rv = cmdParams->SetStringValue("state_data", value);
    3110                 :     else
    3111               0 :       rv = cmdParams->SetCStringValue("state_attribute", paramStr.get());
    3112               0 :     if (NS_FAILED(rv))
    3113               0 :       return rv;
    3114               0 :     rv = cmdMgr->DoCommand(cmdToDispatch.get(), cmdParams, window);
    3115                 :   }
    3116                 : 
    3117               0 :   *_retval = NS_SUCCEEDED(rv);
    3118                 : 
    3119               0 :   return rv;
    3120                 : }
    3121                 : 
    3122                 : /* TODO: don't let this call do anything if the page is not done loading */
    3123                 : /* boolean execCommandShowHelp(in DOMString commandID); */
    3124                 : NS_IMETHODIMP
    3125               0 : nsHTMLDocument::ExecCommandShowHelp(const nsAString & commandID,
    3126                 :                                     bool *_retval)
    3127                 : {
    3128               0 :   NS_ENSURE_ARG_POINTER(_retval);
    3129               0 :   *_retval = false;
    3130                 : 
    3131                 :   // if editing is not on, bail
    3132               0 :   if (!IsEditingOnAfterFlush())
    3133               0 :     return NS_ERROR_FAILURE;
    3134                 : 
    3135               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    3136                 : }
    3137                 : 
    3138                 : /* boolean queryCommandEnabled(in DOMString commandID); */
    3139                 : NS_IMETHODIMP
    3140               0 : nsHTMLDocument::QueryCommandEnabled(const nsAString & commandID,
    3141                 :                                     bool *_retval)
    3142                 : {
    3143               0 :   NS_ENSURE_ARG_POINTER(_retval);
    3144               0 :   *_retval = false;
    3145                 : 
    3146                 :   // if editing is not on, bail
    3147               0 :   if (!IsEditingOnAfterFlush())
    3148               0 :     return NS_ERROR_FAILURE;
    3149                 : 
    3150                 :   // get command manager and dispatch command to our window if it's acceptable
    3151               0 :   nsCOMPtr<nsICommandManager> cmdMgr;
    3152               0 :   GetMidasCommandManager(getter_AddRefs(cmdMgr));
    3153               0 :   if (!cmdMgr)
    3154               0 :     return NS_ERROR_FAILURE;
    3155                 : 
    3156               0 :   nsIDOMWindow *window = GetWindow();
    3157               0 :   if (!window)
    3158               0 :     return NS_ERROR_FAILURE;
    3159                 : 
    3160               0 :   nsCAutoString cmdToDispatch;
    3161               0 :   if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch))
    3162               0 :     return NS_OK; // queryCommandEnabled returns false on unsupported commands
    3163                 : 
    3164               0 :   return cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, _retval);
    3165                 : }
    3166                 : 
    3167                 : /* boolean queryCommandIndeterm (in DOMString commandID); */
    3168                 : NS_IMETHODIMP
    3169               0 : nsHTMLDocument::QueryCommandIndeterm(const nsAString & commandID,
    3170                 :                                      bool *_retval)
    3171                 : {
    3172               0 :   NS_ENSURE_ARG_POINTER(_retval);
    3173               0 :   *_retval = false;
    3174                 : 
    3175                 :   // if editing is not on, bail
    3176               0 :   if (!IsEditingOnAfterFlush())
    3177               0 :     return NS_ERROR_FAILURE;
    3178                 : 
    3179                 :   // get command manager and dispatch command to our window if it's acceptable
    3180               0 :   nsCOMPtr<nsICommandManager> cmdMgr;
    3181               0 :   GetMidasCommandManager(getter_AddRefs(cmdMgr));
    3182               0 :   if (!cmdMgr)
    3183               0 :     return NS_ERROR_FAILURE;
    3184                 : 
    3185               0 :   nsIDOMWindow *window = GetWindow();
    3186               0 :   if (!window)
    3187               0 :     return NS_ERROR_FAILURE;
    3188                 : 
    3189               0 :   nsCAutoString cmdToDispatch, paramToCheck;
    3190                 :   bool dummy;
    3191               0 :   if (!ConvertToMidasInternalCommand(commandID, commandID,
    3192               0 :                                      cmdToDispatch, paramToCheck, dummy, dummy))
    3193               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    3194                 : 
    3195                 :   nsresult rv;
    3196                 :   nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
    3197               0 :                                            NS_COMMAND_PARAMS_CONTRACTID, &rv);
    3198               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3199                 : 
    3200               0 :   rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, cmdParams);
    3201               0 :   if (NS_FAILED(rv))
    3202               0 :     return rv;
    3203                 : 
    3204                 :   // if command does not have a state_mixed value, this call fails, so we fail too,
    3205                 :   // which is what is expected
    3206               0 :   rv = cmdParams->GetBooleanValue("state_mixed", _retval);
    3207               0 :   return rv;
    3208                 : }
    3209                 : 
    3210                 : /* boolean queryCommandState(in DOMString commandID); */
    3211                 : NS_IMETHODIMP
    3212               0 : nsHTMLDocument::QueryCommandState(const nsAString & commandID, bool *_retval)
    3213                 : {
    3214               0 :   NS_ENSURE_ARG_POINTER(_retval);
    3215               0 :   *_retval = false;
    3216                 : 
    3217                 :   // if editing is not on, bail
    3218               0 :   if (!IsEditingOnAfterFlush())
    3219               0 :     return NS_ERROR_FAILURE;
    3220                 : 
    3221                 :   // get command manager and dispatch command to our window if it's acceptable
    3222               0 :   nsCOMPtr<nsICommandManager> cmdMgr;
    3223               0 :   GetMidasCommandManager(getter_AddRefs(cmdMgr));
    3224               0 :   if (!cmdMgr)
    3225               0 :     return NS_ERROR_FAILURE;
    3226                 : 
    3227               0 :   nsIDOMWindow *window = GetWindow();
    3228               0 :   if (!window)
    3229               0 :     return NS_ERROR_FAILURE;
    3230                 : 
    3231               0 :   nsCAutoString cmdToDispatch, paramToCheck;
    3232                 :   bool dummy, dummy2;
    3233               0 :   if (!ConvertToMidasInternalCommand(commandID, commandID,
    3234               0 :                                      cmdToDispatch, paramToCheck, dummy, dummy2))
    3235               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    3236                 : 
    3237                 :   nsresult rv;
    3238                 :   nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
    3239               0 :                                            NS_COMMAND_PARAMS_CONTRACTID, &rv);
    3240               0 :   if (!cmdParams)
    3241               0 :     return NS_ERROR_OUT_OF_MEMORY;
    3242                 : 
    3243               0 :   rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, cmdParams);
    3244               0 :   if (NS_FAILED(rv))
    3245               0 :     return rv;
    3246                 : 
    3247                 :   // handle alignment as a special case (possibly other commands too?)
    3248                 :   // Alignment is special because the external api is individual
    3249                 :   // commands but internally we use cmd_align with different
    3250                 :   // parameters.  When getting the state of this command, we need to
    3251                 :   // return the boolean for this particular alignment rather than the
    3252                 :   // string of 'which alignment is this?'
    3253               0 :   if (cmdToDispatch.Equals("cmd_align")) {
    3254               0 :     char * actualAlignmentType = nsnull;
    3255               0 :     rv = cmdParams->GetCStringValue("state_attribute", &actualAlignmentType);
    3256               0 :     if (NS_SUCCEEDED(rv) && actualAlignmentType && actualAlignmentType[0]) {
    3257               0 :       *_retval = paramToCheck.Equals(actualAlignmentType);
    3258                 :     }
    3259               0 :     if (actualAlignmentType)
    3260               0 :       nsMemory::Free(actualAlignmentType);
    3261                 :   }
    3262                 :   else {
    3263               0 :     rv = cmdParams->GetBooleanValue("state_all", _retval);
    3264               0 :     if (NS_FAILED(rv))
    3265               0 :       *_retval = false;
    3266                 :   }
    3267                 : 
    3268               0 :   return rv;
    3269                 : }
    3270                 : 
    3271                 : /* boolean queryCommandSupported(in DOMString commandID); */
    3272                 : NS_IMETHODIMP
    3273               0 : nsHTMLDocument::QueryCommandSupported(const nsAString & commandID,
    3274                 :                                       bool *_retval)
    3275                 : {
    3276               0 :   NS_ENSURE_ARG_POINTER(_retval);
    3277               0 :   *_retval = false;
    3278                 : 
    3279                 :   // if editing is not on, bail
    3280               0 :   if (!IsEditingOnAfterFlush())
    3281               0 :     return NS_ERROR_FAILURE;
    3282                 : 
    3283                 :   // get command manager
    3284               0 :   nsCOMPtr<nsICommandManager> cmdMgr;
    3285               0 :   GetMidasCommandManager(getter_AddRefs(cmdMgr));
    3286               0 :   if (!cmdMgr)
    3287               0 :     return NS_ERROR_FAILURE;
    3288                 : 
    3289                 :   // commandID is supported if it can be converted to a Midas command
    3290               0 :   nsCAutoString cmdToDispatch;
    3291               0 :   if (ConvertToMidasInternalCommand(commandID, cmdToDispatch))
    3292               0 :     *_retval = true;
    3293                 : 
    3294               0 :   return NS_OK;
    3295                 : }
    3296                 : 
    3297                 : /* DOMString queryCommandText(in DOMString commandID); */
    3298                 : NS_IMETHODIMP
    3299               0 : nsHTMLDocument::QueryCommandText(const nsAString & commandID,
    3300                 :                                  nsAString & _retval)
    3301                 : {
    3302               0 :   _retval.SetLength(0);
    3303                 : 
    3304                 :   // if editing is not on, bail
    3305               0 :   if (!IsEditingOnAfterFlush())
    3306               0 :     return NS_ERROR_FAILURE;
    3307                 : 
    3308               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    3309                 : }
    3310                 : 
    3311                 : /* DOMString queryCommandValue(in DOMString commandID); */
    3312                 : NS_IMETHODIMP
    3313               0 : nsHTMLDocument::QueryCommandValue(const nsAString & commandID,
    3314                 :                                   nsAString &_retval)
    3315                 : {
    3316               0 :   _retval.SetLength(0);
    3317                 : 
    3318                 :   // if editing is not on, bail
    3319               0 :   if (!IsEditingOnAfterFlush())
    3320               0 :     return NS_ERROR_FAILURE;
    3321                 : 
    3322                 :   // get command manager and dispatch command to our window if it's acceptable
    3323               0 :   nsCOMPtr<nsICommandManager> cmdMgr;
    3324               0 :   GetMidasCommandManager(getter_AddRefs(cmdMgr));
    3325               0 :   if (!cmdMgr)
    3326               0 :     return NS_ERROR_FAILURE;
    3327                 : 
    3328               0 :   nsIDOMWindow *window = GetWindow();
    3329               0 :   if (!window)
    3330               0 :     return NS_ERROR_FAILURE;
    3331                 : 
    3332               0 :   nsCAutoString cmdToDispatch, paramStr;
    3333               0 :   if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch))
    3334               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    3335                 : 
    3336                 :   // create params
    3337                 :   nsresult rv;
    3338                 :   nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
    3339               0 :                                            NS_COMMAND_PARAMS_CONTRACTID, &rv);
    3340               0 :   if (!cmdParams)
    3341               0 :     return NS_ERROR_OUT_OF_MEMORY;
    3342                 : 
    3343                 :   // this is a special command since we are calling "DoCommand rather than
    3344                 :   // GetCommandState like the other commands
    3345               0 :   if (cmdToDispatch.Equals("cmd_getContents"))
    3346                 :   {
    3347               0 :     rv = cmdParams->SetBooleanValue("selection_only", true);
    3348               0 :     if (NS_FAILED(rv)) return rv;
    3349               0 :     rv = cmdParams->SetCStringValue("format", "text/html");
    3350               0 :     if (NS_FAILED(rv)) return rv;
    3351               0 :     rv = cmdMgr->DoCommand(cmdToDispatch.get(), cmdParams, window);
    3352               0 :     if (NS_FAILED(rv)) return rv;
    3353               0 :     return cmdParams->GetStringValue("result", _retval);
    3354                 :   }
    3355                 : 
    3356               0 :   rv = cmdParams->SetCStringValue("state_attribute", paramStr.get());
    3357               0 :   if (NS_FAILED(rv))
    3358               0 :     return rv;
    3359                 : 
    3360               0 :   rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, cmdParams);
    3361               0 :   if (NS_FAILED(rv))
    3362               0 :     return rv;
    3363                 : 
    3364               0 :   nsXPIDLCString cStringResult;
    3365               0 :   rv = cmdParams->GetCStringValue("state_attribute",
    3366               0 :                                   getter_Copies(cStringResult));
    3367               0 :   CopyUTF8toUTF16(cStringResult, _retval);
    3368                 : 
    3369               0 :   return rv;
    3370                 : }
    3371                 : 
    3372                 : nsresult
    3373               0 : nsHTMLDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
    3374                 : {
    3375               0 :   NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
    3376                 :                "Can't import this document into another document!");
    3377                 : 
    3378               0 :   nsRefPtr<nsHTMLDocument> clone = new nsHTMLDocument();
    3379               0 :   NS_ENSURE_TRUE(clone, NS_ERROR_OUT_OF_MEMORY);
    3380               0 :   nsresult rv = CloneDocHelper(clone.get());
    3381               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3382                 : 
    3383                 :   // State from nsHTMLDocument
    3384               0 :   clone->mLoadFlags = mLoadFlags;
    3385                 : 
    3386               0 :   return CallQueryInterface(clone.get(), aResult);
    3387                 : }
    3388                 : 
    3389                 : bool
    3390               0 : nsHTMLDocument::IsEditingOnAfterFlush()
    3391                 : {
    3392               0 :   nsIDocument* doc = GetParentDocument();
    3393               0 :   if (doc) {
    3394                 :     // Make sure frames are up to date, since that can affect whether
    3395                 :     // we're editable.
    3396               0 :     doc->FlushPendingNotifications(Flush_Frames);
    3397                 :   }
    3398                 : 
    3399               0 :   return IsEditingOn();
    3400                 : }
    3401                 : 
    3402                 : void
    3403               0 : nsHTMLDocument::RemovedFromDocShell()
    3404                 : {
    3405               0 :   mEditingState = eOff;
    3406               0 :   nsDocument::RemovedFromDocShell();
    3407               0 : }
    3408                 : 
    3409                 : /* virtual */ void
    3410               0 : nsHTMLDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
    3411                 : {
    3412               0 :   nsDocument::DocSizeOfExcludingThis(aWindowSizes);
    3413                 : 
    3414                 :   // Measurement of the following members may be added later if DMD finds it is
    3415                 :   // worthwhile:
    3416                 :   // - mImages
    3417                 :   // - mApplets
    3418                 :   // - mEmbeds
    3419                 :   // - mLinks
    3420                 :   // - mAnchors
    3421                 :   // - mScripts
    3422                 :   // - mForms
    3423                 :   // - mFormControls
    3424                 :   // - mWyciwygChannel
    3425                 :   // - mMidasCommandManager
    3426            4392 : }

Generated by: LCOV version 1.7