LCOV - app.info - content/html/document/src/nsHTMLDocument.cpp

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-04-21 | 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             216 : NS_NewHTMLDocument(nsIDocument** aInstancePtrResult)
         207                 : {
         208             216 :   nsHTMLDocument* doc = new nsHTMLDocument();
         209             216 :   NS_ENSURE_TRUE(doc, NS_ERROR_OUT_OF_MEMORY);
         210                 :
         211             216 :   NS_ADDREF(doc);
         212             216 :   nsresult rv = doc->Init();
         213                 :
         214             216 :   if (NS_FAILED(rv)) {
         215               0 :     NS_RELEASE(doc);
         216                 :   }
         217                 :
         218             216 :   *aInstancePtrResult = doc;
         219                 :
         220             216 :   return rv;
         221                 : }
         222                 :
         223                 :   // NOTE! nsDocument::operator new() zeroes out all members, so don't
         224                 :   // bother initializing members to 0.
         225                 :
         226             216 : nsHTMLDocument::nsHTMLDocument()
         227             216 :   : nsDocument("text/html")
         228                 : {
         229                 :   // NOTE! nsDocument::operator new() zeroes out all members, so don't
         230                 :   // bother initializing members to 0.
         231                 :
         232             216 :   mIsRegularHTML = true;
         233             216 :   mDefaultElementType = kNameSpaceID_XHTML;
         234             216 :   mCompatMode = eCompatibility_NavQuirks;
         235             216 : }
         236                 :
         237            1396 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLDocument)
         238                 :
         239             290 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
         240             290 :   NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()),
         241                 :                "Shouldn't traverse nsHTMLDocument!");
         242             290 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mImages)
         243             290 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplets)
         244             290 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEmbeds)
         245             290 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLinks)
         246             290 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAnchors)
         247             290 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScripts)
         248             290 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mForms, nsIDOMNodeList)
         249             290 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mFormControls,
         250                 :                                                        nsIDOMNodeList)
         251             290 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mWyciwygChannel)
         252             290 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMidasCommandManager)
         253             290 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
         254                 :
         255             216 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
         256             216 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mImages)
         257             216 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mApplets)
         258             216 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mEmbeds)
         259             216 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLinks)
         260             216 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAnchors)
         261             216 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mScripts)
         262             216 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mForms)
         263             216 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFormControls)
         264             216 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mWyciwygChannel)
         265             216 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMidasCommandManager)
         266             216 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
         267                 :
         268            8856 : NS_IMPL_ADDREF_INHERITED(nsHTMLDocument, nsDocument)
         269            8856 : NS_IMPL_RELEASE_INHERITED(nsHTMLDocument, nsDocument)
         270                 :
         271                 :
         272               0 : DOMCI_NODE_DATA(HTMLDocument, nsHTMLDocument)
         273                 :
         274                 : // QueryInterface implementation for nsHTMLDocument
         275           14772 : 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            8698 :   NS_OFFSET_AND_INTERFACE_TABLE_END
         280            8698 :   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
         281            5674 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLDocument)
         282            5674 : NS_INTERFACE_MAP_END_INHERITING(nsDocument)
         283                 :
         284                 :
         285                 : nsresult
         286             216 : nsHTMLDocument::Init()
         287                 : {
         288             216 :   nsresult rv = nsDocument::Init();
         289             216 :   NS_ENSURE_SUCCESS(rv, rv);
         290                 :
         291                 :   // Now reset the compatibility mode of the CSSLoader
         292                 :   // to match our compat mode.
         293             216 :   CSSLoader()->SetCompatibilityMode(mCompatMode);
         294                 :
         295             216 :   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             216 : nsHTMLDocument::SetDocumentCharacterSet(const nsACString& aCharSetID)
         540                 : {
         541             216 :   nsDocument::SetDocumentCharacterSet(aCharSetID);
         542                 :   // Make sure to stash this charset on our channel as needed if it's a wyciwyg
         543                 :   // channel.
         544             432 :   nsCOMPtr<nsIWyciwygChannel> wyciwygChannel = do_QueryInterface(mChannel);
         545             216 :   if (wyciwygChannel) {
         546               0 :     wyciwygChannel->SetCharsetAndSource(GetDocumentCharacterSetSource(),
         547               0 :                                         aCharSetID);
         548                 :   }
         549             216 : }
         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             432 : nsHTMLDocument::SetCompatibilityMode(nsCompatibility aMode)
         922                 : {
         923             432 :   NS_ASSERTION(IsHTML() || aMode == eCompatibility_FullStandards,
         924                 :                "Bad compat mode for XHTML document!");
         925                 :
         926             432 :   mCompatMode = aMode;
         927             432 :   CSSLoader()->SetCompatibilityMode(mCompatMode);
         928             864 :   nsCOMPtr<nsIPresShell> shell = GetShell();
         929             432 :   if (shell) {
         930               0 :     nsPresContext *pc = shell->GetPresContext();
         931               0 :     if (pc) {
         932               0 :       pc->CompatibilityModeChanged();
         933                 :     }
         934                 :   }
         935             432 : }
         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             226 : nsHTMLDocument::MaybeEditingStateChanged()
        2252                 : {
        2253             226 :   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             226 : }
        2262                 :
        2263                 : void
        2264             226 : nsHTMLDocument::EndUpdate(nsUpdateType aUpdateType)
        2265                 : {
        2266             226 :   nsDocument::EndUpdate(aUpdateType);
        2267                 :
        2268             226 :   MaybeEditingStateChanged();
        2269             226 : }
        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            1396 : nsHTMLDocument::sCutCopyInternal_id = JSID_VOID;
        2993                 : jsid
        2994            1396 : 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            4188 : }

Generated by: LCOV version 1.7