LCOV - code coverage report
Current view: directory - editor/composer/src - nsEditingSession.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 508 0 0.0 %
Date: 2012-06-02 Functions: 39 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=78: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.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                 :  *   Simon Fraser   <sfraser@netscape.com>
      25                 :  *   Michael Judge  <mjudge@netscape.com>
      26                 :  *   Charles Manske <cmanske@netscape.com>
      27                 :  *   Kathleen Brade <brade@netscape.com>
      28                 :  *
      29                 :  * Alternatively, the contents of this file may be used under the terms of
      30                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      31                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      33                 :  * of those above. If you wish to allow use of your version of this file only
      34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      35                 :  * use your version of this file under the terms of the MPL, indicate your
      36                 :  * decision by deleting the provisions above and replace them with the notice
      37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      38                 :  * the provisions above, a recipient may use your version of this file under
      39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      40                 :  *
      41                 :  * ***** END LICENSE BLOCK ***** */
      42                 : 
      43                 : #include "nsPIDOMWindow.h"
      44                 : #include "nsIDOMWindowUtils.h"
      45                 : #include "nsIDOMHTMLDocument.h"
      46                 : #include "nsIDocument.h"
      47                 : #include "nsIHTMLDocument.h"
      48                 : #include "nsIDOMDocument.h"
      49                 : #include "nsIURI.h"
      50                 : #include "nsISelectionPrivate.h"
      51                 : #include "nsITransactionManager.h"
      52                 : 
      53                 : #include "nsIEditorDocShell.h"
      54                 : #include "nsIDocShell.h"
      55                 : 
      56                 : #include "nsIChannel.h"
      57                 : #include "nsIWebProgress.h"
      58                 : #include "nsIWebNavigation.h"
      59                 : #include "nsIRefreshURI.h"
      60                 : 
      61                 : #include "nsIControllers.h"
      62                 : #include "nsIController.h"
      63                 : #include "nsIControllerContext.h"
      64                 : #include "nsICommandManager.h"
      65                 : #include "nsPICommandUpdater.h"
      66                 : 
      67                 : #include "nsIPresShell.h"
      68                 : 
      69                 : #include "nsComposerCommandsUpdater.h"
      70                 : #include "nsEditingSession.h"
      71                 : 
      72                 : #include "nsComponentManagerUtils.h"
      73                 : #include "nsIInterfaceRequestorUtils.h"
      74                 : 
      75                 : #include "nsIContentViewer.h"
      76                 : #include "nsISelectionController.h"
      77                 : #include "nsIPlaintextEditor.h"
      78                 : #include "nsIEditor.h"
      79                 : 
      80                 : #include "nsIScriptContext.h"
      81                 : #include "imgIContainer.h"
      82                 : 
      83                 : #if DEBUG
      84                 : //#define NOISY_DOC_LOADING  1
      85                 : #endif
      86                 : 
      87                 : /*---------------------------------------------------------------------------
      88                 : 
      89                 :   nsEditingSession
      90                 : 
      91                 : ----------------------------------------------------------------------------*/
      92               0 : nsEditingSession::nsEditingSession()
      93                 : : mDoneSetup(false)
      94                 : , mCanCreateEditor(false)
      95                 : , mInteractive(false)
      96                 : , mMakeWholeDocumentEditable(true)
      97                 : , mDisabledJSAndPlugins(false)
      98                 : , mScriptsEnabled(true)
      99                 : , mPluginsEnabled(true)
     100                 : , mProgressListenerRegistered(false)
     101                 : , mImageAnimationMode(0)
     102                 : , mEditorFlags(0)
     103                 : , mEditorStatus(eEditorOK)
     104                 : , mBaseCommandControllerId(0)
     105                 : , mDocStateControllerId(0)
     106               0 : , mHTMLCommandControllerId(0)
     107                 : {
     108               0 : }
     109                 : 
     110                 : /*---------------------------------------------------------------------------
     111                 : 
     112                 :   ~nsEditingSession
     113                 : 
     114                 : ----------------------------------------------------------------------------*/
     115               0 : nsEditingSession::~nsEditingSession()
     116                 : {
     117                 :   // Must cancel previous timer?
     118               0 :   if (mLoadBlankDocTimer)
     119               0 :     mLoadBlankDocTimer->Cancel();
     120               0 : }
     121                 : 
     122               0 : NS_IMPL_ISUPPORTS3(nsEditingSession, nsIEditingSession, nsIWebProgressListener, 
     123                 :                    nsISupportsWeakReference)
     124                 : 
     125                 : /*---------------------------------------------------------------------------
     126                 : 
     127                 :   MakeWindowEditable
     128                 : 
     129                 :   aEditorType string, "html" "htmlsimple" "text" "textsimple"
     130                 :   void makeWindowEditable(in nsIDOMWindow aWindow, in string aEditorType, 
     131                 :                           in boolean aDoAfterUriLoad,
     132                 :                           in boolean aMakeWholeDocumentEditable,
     133                 :                           in boolean aInteractive);
     134                 : ----------------------------------------------------------------------------*/
     135                 : #define DEFAULT_EDITOR_TYPE "html"
     136                 : 
     137                 : NS_IMETHODIMP
     138               0 : nsEditingSession::MakeWindowEditable(nsIDOMWindow *aWindow,
     139                 :                                      const char *aEditorType, 
     140                 :                                      bool aDoAfterUriLoad,
     141                 :                                      bool aMakeWholeDocumentEditable,
     142                 :                                      bool aInteractive)
     143                 : {
     144               0 :   mEditorType.Truncate();
     145               0 :   mEditorFlags = 0;
     146                 : 
     147                 :   // disable plugins
     148               0 :   nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
     149               0 :   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
     150                 : 
     151               0 :   mDocShell = do_GetWeakReference(docShell);
     152               0 :   mInteractive = aInteractive;
     153               0 :   mMakeWholeDocumentEditable = aMakeWholeDocumentEditable;
     154                 : 
     155                 :   nsresult rv;
     156               0 :   if (!mInteractive) {
     157               0 :     rv = DisableJSAndPlugins(aWindow);
     158               0 :     NS_ENSURE_SUCCESS(rv, rv);
     159                 :   }
     160                 : 
     161                 :   // Always remove existing editor
     162               0 :   TearDownEditorOnWindow(aWindow);
     163                 :   
     164                 :   // Tells embedder that startup is in progress
     165               0 :   mEditorStatus = eEditorCreationInProgress;
     166                 : 
     167                 :   //temporary to set editor type here. we will need different classes soon.
     168               0 :   if (!aEditorType)
     169               0 :     aEditorType = DEFAULT_EDITOR_TYPE;
     170               0 :   mEditorType = aEditorType;
     171                 : 
     172                 :   // if all this does is setup listeners and I don't need listeners, 
     173                 :   // can't this step be ignored?? (based on aDoAfterURILoad)
     174               0 :   rv = PrepareForEditing(aWindow);
     175               0 :   NS_ENSURE_SUCCESS(rv, rv);  
     176                 :   
     177               0 :   nsCOMPtr<nsIEditorDocShell> editorDocShell;
     178               0 :   rv = GetEditorDocShellFromWindow(aWindow, getter_AddRefs(editorDocShell));
     179               0 :   NS_ENSURE_SUCCESS(rv, rv);  
     180                 :   
     181                 :   // set the flag on the docShell to say that it's editable
     182               0 :   rv = editorDocShell->MakeEditable(aDoAfterUriLoad);
     183               0 :   NS_ENSURE_SUCCESS(rv, rv);  
     184                 : 
     185                 :   // Setup commands common to plaintext and html editors,
     186                 :   //  including the document creation observers
     187                 :   // the first is an editing controller
     188                 :   rv = SetupEditorCommandController("@mozilla.org/editor/editingcontroller;1",
     189                 :                                     aWindow,
     190                 :                                     static_cast<nsIEditingSession*>(this),
     191               0 :                                     &mBaseCommandControllerId);
     192               0 :   NS_ENSURE_SUCCESS(rv, rv);
     193                 : 
     194                 :   // The second is a controller to monitor doc state,
     195                 :   // such as creation and "dirty flag"
     196                 :   rv = SetupEditorCommandController("@mozilla.org/editor/editordocstatecontroller;1",
     197                 :                                     aWindow,
     198                 :                                     static_cast<nsIEditingSession*>(this),
     199               0 :                                     &mDocStateControllerId);
     200               0 :   NS_ENSURE_SUCCESS(rv, rv);
     201                 : 
     202                 :   // aDoAfterUriLoad can be false only when making an existing window editable
     203               0 :   if (!aDoAfterUriLoad)
     204                 :   {
     205               0 :     rv = SetupEditorOnWindow(aWindow);
     206                 : 
     207                 :     // mEditorStatus is set to the error reason
     208                 :     // Since this is used only when editing an existing page,
     209                 :     //  it IS ok to destroy current editor
     210               0 :     if (NS_FAILED(rv))
     211               0 :       TearDownEditorOnWindow(aWindow);
     212                 :   }
     213               0 :   return rv;
     214                 : }
     215                 : 
     216                 : NS_IMETHODIMP
     217               0 : nsEditingSession::DisableJSAndPlugins(nsIDOMWindow *aWindow)
     218                 : {
     219               0 :   nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
     220               0 :   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
     221                 : 
     222                 :   bool tmp;
     223               0 :   nsresult rv = docShell->GetAllowJavascript(&tmp);
     224               0 :   NS_ENSURE_SUCCESS(rv, rv);
     225                 : 
     226               0 :   mScriptsEnabled = tmp;
     227                 : 
     228               0 :   rv = docShell->SetAllowJavascript(false);
     229               0 :   NS_ENSURE_SUCCESS(rv, rv);
     230                 : 
     231                 :   // Disable plugins in this document:
     232               0 :   rv = docShell->GetAllowPlugins(&tmp);
     233               0 :   NS_ENSURE_SUCCESS(rv, rv);
     234                 : 
     235               0 :   mPluginsEnabled = tmp;
     236                 : 
     237               0 :   rv = docShell->SetAllowPlugins(false);
     238               0 :   NS_ENSURE_SUCCESS(rv, rv);
     239                 : 
     240               0 :   mDisabledJSAndPlugins = true;
     241                 : 
     242               0 :   return NS_OK;
     243                 : }
     244                 : 
     245                 : NS_IMETHODIMP
     246               0 : nsEditingSession::RestoreJSAndPlugins(nsIDOMWindow *aWindow)
     247                 : {
     248               0 :   NS_ENSURE_TRUE(mDisabledJSAndPlugins, NS_OK);
     249                 : 
     250               0 :   mDisabledJSAndPlugins = false;
     251                 : 
     252               0 :   nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
     253               0 :   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
     254                 : 
     255               0 :   nsresult rv = docShell->SetAllowJavascript(mScriptsEnabled);
     256               0 :   NS_ENSURE_SUCCESS(rv, rv);
     257                 : 
     258                 :   // Disable plugins in this document:
     259               0 :   return docShell->SetAllowPlugins(mPluginsEnabled);
     260                 : }
     261                 : 
     262                 : NS_IMETHODIMP
     263               0 : nsEditingSession::GetJsAndPluginsDisabled(bool *aResult)
     264                 : {
     265               0 :   NS_ENSURE_ARG_POINTER(aResult);
     266               0 :   *aResult = mDisabledJSAndPlugins;
     267               0 :   return NS_OK;
     268                 : }
     269                 : 
     270                 : /*---------------------------------------------------------------------------
     271                 : 
     272                 :   WindowIsEditable
     273                 : 
     274                 :   boolean windowIsEditable (in nsIDOMWindow aWindow);
     275                 : ----------------------------------------------------------------------------*/
     276                 : NS_IMETHODIMP
     277               0 : nsEditingSession::WindowIsEditable(nsIDOMWindow *aWindow, bool *outIsEditable)
     278                 : {
     279               0 :   nsCOMPtr<nsIEditorDocShell> editorDocShell;
     280                 :   nsresult rv = GetEditorDocShellFromWindow(aWindow,
     281               0 :                                             getter_AddRefs(editorDocShell));
     282               0 :   NS_ENSURE_SUCCESS(rv, rv);  
     283                 : 
     284               0 :   return editorDocShell->GetEditable(outIsEditable);
     285                 : }
     286                 : 
     287                 : 
     288                 : // These are MIME types that are automatically parsed as "text/plain"
     289                 : //   and thus we can edit them as plaintext
     290                 : // Note: in older versions, we attempted to convert the mimetype of
     291                 : //   the network channel for these and "text/xml" to "text/plain", 
     292                 : //   but further investigation reveals that strategy doesn't work
     293                 : const char* const gSupportedTextTypes[] = {
     294                 :   "text/plain",
     295                 :   "text/css",
     296                 :   "text/rdf",
     297                 :   "text/xsl",
     298                 :   "text/javascript",           // obsolete type
     299                 :   "text/ecmascript",           // obsolete type
     300                 :   "application/javascript",
     301                 :   "application/ecmascript",
     302                 :   "application/x-javascript",  // obsolete type
     303                 :   "text/xul",                  // obsolete type
     304                 :   "application/vnd.mozilla.xul+xml",
     305                 :   NULL      // IMPORTANT! Null must be at end
     306                 : };
     307                 : 
     308                 : bool
     309               0 : IsSupportedTextType(const char* aMIMEType)
     310                 : {
     311               0 :   NS_ENSURE_TRUE(aMIMEType, false);
     312                 : 
     313               0 :   PRInt32 i = 0;
     314               0 :   while (gSupportedTextTypes[i])
     315                 :   {
     316               0 :     if (strcmp(gSupportedTextTypes[i], aMIMEType) == 0)
     317                 :     {
     318               0 :       return true;
     319                 :     }
     320                 : 
     321               0 :     i ++;
     322                 :   }
     323                 :   
     324               0 :   return false;
     325                 : }
     326                 : 
     327                 : /*---------------------------------------------------------------------------
     328                 : 
     329                 :   SetupEditorOnWindow
     330                 : 
     331                 :   nsIEditor setupEditorOnWindow (in nsIDOMWindow aWindow);
     332                 : ----------------------------------------------------------------------------*/
     333                 : NS_IMETHODIMP
     334               0 : nsEditingSession::SetupEditorOnWindow(nsIDOMWindow *aWindow)
     335                 : {
     336               0 :   mDoneSetup = true;
     337                 : 
     338                 :   nsresult rv;
     339                 : 
     340                 :   //MIME CHECKING
     341                 :   //must get the content type
     342                 :   // Note: the doc gets this from the network channel during StartPageLoad,
     343                 :   //    so we don't have to get it from there ourselves
     344               0 :   nsCOMPtr<nsIDOMDocument> doc;
     345               0 :   nsCAutoString mimeCType;
     346                 : 
     347                 :   //then lets check the mime type
     348               0 :   if (NS_SUCCEEDED(aWindow->GetDocument(getter_AddRefs(doc))) && doc)
     349                 :   {
     350               0 :     nsAutoString mimeType;
     351               0 :     if (NS_SUCCEEDED(doc->GetContentType(mimeType)))
     352               0 :       AppendUTF16toUTF8(mimeType, mimeCType);
     353                 : 
     354               0 :     if (IsSupportedTextType(mimeCType.get()))
     355                 :     {
     356               0 :       mEditorType.AssignLiteral("text");
     357               0 :       mimeCType = "text/plain";
     358                 :     }
     359               0 :     else if (!mimeCType.EqualsLiteral("text/html") &&
     360               0 :              !mimeCType.EqualsLiteral("application/xhtml+xml"))
     361                 :     {
     362                 :       // Neither an acceptable text or html type.
     363               0 :       mEditorStatus = eEditorErrorCantEditMimeType;
     364                 : 
     365                 :       // Turn editor into HTML -- we will load blank page later
     366               0 :       mEditorType.AssignLiteral("html");
     367               0 :       mimeCType.AssignLiteral("text/html");
     368                 :     }
     369                 : 
     370                 :     // Flush out frame construction to make sure that the subframe's
     371                 :     // presshell is set up if it needs to be.
     372               0 :     nsCOMPtr<nsIDocument> document = do_QueryInterface(doc);
     373               0 :     if (document) {
     374               0 :       document->FlushPendingNotifications(Flush_Frames);
     375               0 :       if (mMakeWholeDocumentEditable) {
     376               0 :         document->SetEditableFlag(true);
     377               0 :         nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(document);
     378               0 :         if (htmlDocument) {
     379                 :           // Enable usage of the execCommand API
     380               0 :           htmlDocument->SetEditingState(nsIHTMLDocument::eDesignMode);
     381                 :         }
     382                 :       }
     383                 :     }
     384                 :   }
     385               0 :   bool needHTMLController = false;
     386                 : 
     387               0 :   const char *classString = "@mozilla.org/editor/htmleditor;1";
     388               0 :   if (mEditorType.EqualsLiteral("textmail"))
     389                 :   {
     390                 :     mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask | 
     391                 :                    nsIPlaintextEditor::eEditorEnableWrapHackMask | 
     392               0 :                    nsIPlaintextEditor::eEditorMailMask;
     393                 :   }
     394               0 :   else if (mEditorType.EqualsLiteral("text"))
     395                 :   {
     396                 :     mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask | 
     397               0 :                    nsIPlaintextEditor::eEditorEnableWrapHackMask;
     398                 :   }
     399               0 :   else if (mEditorType.EqualsLiteral("htmlmail"))
     400                 :   {
     401               0 :     if (mimeCType.EqualsLiteral("text/html"))
     402                 :     {
     403               0 :       needHTMLController = true;
     404               0 :       mEditorFlags = nsIPlaintextEditor::eEditorMailMask;
     405                 :     }
     406                 :     else //set the flags back to textplain.
     407                 :       mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask | 
     408               0 :                      nsIPlaintextEditor::eEditorEnableWrapHackMask;
     409                 :   }
     410                 :   else // Defaulted to html
     411                 :   {
     412               0 :     needHTMLController = true;
     413                 :   }
     414                 : 
     415               0 :   if (mInteractive) {
     416               0 :     mEditorFlags |= nsIPlaintextEditor::eEditorAllowInteraction;
     417                 :   }
     418                 : 
     419                 :   // make the UI state maintainer
     420               0 :   mStateMaintainer = new nsComposerCommandsUpdater();
     421                 : 
     422                 :   // now init the state maintainer
     423                 :   // This allows notification of error state
     424                 :   //  even if we don't create an editor
     425               0 :   rv = mStateMaintainer->Init(aWindow);
     426               0 :   NS_ENSURE_SUCCESS(rv, rv);
     427                 : 
     428               0 :   if (mEditorStatus != eEditorCreationInProgress)
     429                 :   {
     430               0 :     mStateMaintainer->NotifyDocumentCreated();
     431               0 :     return NS_ERROR_FAILURE;
     432                 :   }
     433                 : 
     434                 :   // Create editor and do other things 
     435                 :   //  only if we haven't found some error above,
     436               0 :   nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
     437               0 :   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);  
     438                 : 
     439               0 :   if (!mInteractive) {
     440                 :     // Disable animation of images in this document:
     441               0 :     nsCOMPtr<nsIDOMWindowUtils> utils(do_GetInterface(aWindow));
     442               0 :     NS_ENSURE_TRUE(utils, NS_ERROR_FAILURE);
     443                 : 
     444               0 :     rv = utils->GetImageAnimationMode(&mImageAnimationMode);
     445               0 :     NS_ENSURE_SUCCESS(rv, rv);
     446               0 :     utils->SetImageAnimationMode(imgIContainer::kDontAnimMode);
     447                 :   }
     448                 : 
     449                 :   // create and set editor
     450               0 :   nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(docShell, &rv);
     451               0 :   NS_ENSURE_SUCCESS(rv, rv);
     452                 : 
     453                 :   // Try to reuse an existing editor
     454               0 :   nsCOMPtr<nsIEditor> editor = do_QueryReferent(mExistingEditor);
     455               0 :   if (editor) {
     456               0 :     editor->PreDestroy(false);
     457                 :   } else {
     458               0 :     editor = do_CreateInstance(classString, &rv);
     459               0 :     NS_ENSURE_SUCCESS(rv, rv);
     460               0 :     mExistingEditor = do_GetWeakReference(editor);
     461                 :   }
     462                 :   // set the editor on the docShell. The docShell now owns it.
     463               0 :   rv = editorDocShell->SetEditor(editor);
     464               0 :   NS_ENSURE_SUCCESS(rv, rv);
     465                 : 
     466                 :   // setup the HTML editor command controller
     467               0 :   if (needHTMLController)
     468                 :   {
     469                 :     // The third controller takes an nsIEditor as the context
     470                 :     rv = SetupEditorCommandController("@mozilla.org/editor/htmleditorcontroller;1",
     471                 :                                       aWindow, editor,
     472               0 :                                       &mHTMLCommandControllerId);
     473               0 :     NS_ENSURE_SUCCESS(rv, rv);
     474                 :   }
     475                 : 
     476                 :   // Set mimetype on editor
     477               0 :   rv = editor->SetContentsMIMEType(mimeCType.get());
     478               0 :   NS_ENSURE_SUCCESS(rv, rv);
     479                 : 
     480               0 :   nsCOMPtr<nsIContentViewer> contentViewer;
     481               0 :   rv = docShell->GetContentViewer(getter_AddRefs(contentViewer));
     482               0 :   NS_ENSURE_SUCCESS(rv, rv);
     483               0 :   NS_ENSURE_TRUE(contentViewer, NS_ERROR_FAILURE);
     484                 : 
     485               0 :   nsCOMPtr<nsIDOMDocument> domDoc;  
     486               0 :   rv = contentViewer->GetDOMDocument(getter_AddRefs(domDoc));
     487               0 :   NS_ENSURE_SUCCESS(rv, rv);
     488               0 :   NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);
     489                 : 
     490                 :   // Set up as a doc state listener
     491                 :   // Important! We must have this to broadcast the "obs_documentCreated" message
     492               0 :   rv = editor->AddDocumentStateListener(mStateMaintainer);
     493               0 :   NS_ENSURE_SUCCESS(rv, rv);
     494                 : 
     495               0 :   rv = editor->Init(domDoc, nsnull /* root content */,
     496               0 :                     nsnull, mEditorFlags);
     497               0 :   NS_ENSURE_SUCCESS(rv, rv);
     498                 : 
     499               0 :   nsCOMPtr<nsISelection> selection;
     500               0 :   editor->GetSelection(getter_AddRefs(selection));
     501               0 :   nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection);
     502               0 :   NS_ENSURE_TRUE(selPriv, NS_ERROR_FAILURE);
     503                 : 
     504               0 :   rv = selPriv->AddSelectionListener(mStateMaintainer);
     505               0 :   NS_ENSURE_SUCCESS(rv, rv);
     506                 : 
     507                 :   // and as a transaction listener
     508               0 :   nsCOMPtr<nsITransactionManager> txnMgr;
     509               0 :   editor->GetTransactionManager(getter_AddRefs(txnMgr));
     510               0 :   if (txnMgr)
     511               0 :     txnMgr->AddListener(mStateMaintainer);
     512                 : 
     513                 :   // Set context on all controllers to be the editor
     514               0 :   rv = SetEditorOnControllers(aWindow, editor);
     515               0 :   NS_ENSURE_SUCCESS(rv, rv);
     516                 : 
     517                 :   // Everything went fine!
     518               0 :   mEditorStatus = eEditorOK;
     519                 : 
     520                 :   // This will trigger documentCreation notification
     521               0 :   return editor->PostCreate();
     522                 : }
     523                 : 
     524                 : // Removes all listeners and controllers from aWindow and aEditor.
     525                 : void
     526               0 : nsEditingSession::RemoveListenersAndControllers(nsIDOMWindow *aWindow,
     527                 :                                                 nsIEditor *aEditor)
     528                 : {
     529               0 :   if (!mStateMaintainer || !aEditor)
     530               0 :     return;
     531                 : 
     532                 :   // Remove all the listeners
     533               0 :   nsCOMPtr<nsISelection> selection;
     534               0 :   aEditor->GetSelection(getter_AddRefs(selection));
     535               0 :   nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection);
     536               0 :   if (selPriv)
     537               0 :     selPriv->RemoveSelectionListener(mStateMaintainer);
     538                 : 
     539               0 :   aEditor->RemoveDocumentStateListener(mStateMaintainer);
     540                 : 
     541               0 :   nsCOMPtr<nsITransactionManager> txnMgr;
     542               0 :   aEditor->GetTransactionManager(getter_AddRefs(txnMgr));
     543               0 :   if (txnMgr)
     544               0 :     txnMgr->RemoveListener(mStateMaintainer);
     545                 : 
     546                 :   // Remove editor controllers from the window now that we're not
     547                 :   // editing in that window any more.
     548               0 :   RemoveEditorControllers(aWindow);
     549                 : }
     550                 : 
     551                 : /*---------------------------------------------------------------------------
     552                 : 
     553                 :   TearDownEditorOnWindow
     554                 : 
     555                 :   void tearDownEditorOnWindow (in nsIDOMWindow aWindow);
     556                 : ----------------------------------------------------------------------------*/
     557                 : NS_IMETHODIMP
     558               0 : nsEditingSession::TearDownEditorOnWindow(nsIDOMWindow *aWindow)
     559                 : {
     560               0 :   if (!mDoneSetup) {
     561               0 :     return NS_OK;
     562                 :   }
     563                 : 
     564               0 :   NS_ENSURE_TRUE(aWindow, NS_ERROR_NULL_POINTER);
     565                 : 
     566                 :   nsresult rv;
     567                 :   
     568                 :   // Kill any existing reload timer
     569               0 :   if (mLoadBlankDocTimer)
     570                 :   {
     571               0 :     mLoadBlankDocTimer->Cancel();
     572               0 :     mLoadBlankDocTimer = nsnull;
     573                 :   }
     574                 : 
     575               0 :   mDoneSetup = false;
     576                 : 
     577                 :   // Check if we're turning off editing (from contentEditable or designMode).
     578               0 :   nsCOMPtr<nsIDOMDocument> domDoc;
     579               0 :   aWindow->GetDocument(getter_AddRefs(domDoc));
     580               0 :   nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(domDoc);
     581               0 :   bool stopEditing = htmlDoc && htmlDoc->IsEditingOn();
     582               0 :   if (stopEditing)
     583               0 :     RemoveWebProgressListener(aWindow);
     584                 : 
     585               0 :   nsCOMPtr<nsIEditorDocShell> editorDocShell;
     586               0 :   rv = GetEditorDocShellFromWindow(aWindow, getter_AddRefs(editorDocShell));
     587               0 :   NS_ENSURE_SUCCESS(rv, rv);
     588                 :   
     589               0 :   nsCOMPtr<nsIEditor> editor;
     590               0 :   rv = editorDocShell->GetEditor(getter_AddRefs(editor));
     591               0 :   NS_ENSURE_SUCCESS(rv, rv);
     592                 : 
     593               0 :   if (stopEditing)
     594               0 :     htmlDoc->TearingDownEditor(editor);
     595                 : 
     596               0 :   if (mStateMaintainer && editor)
     597                 :   {
     598                 :     // Null out the editor on the controllers first to prevent their weak 
     599                 :     // references from pointing to a destroyed editor.
     600               0 :     SetEditorOnControllers(aWindow, nsnull);
     601                 :   }
     602                 : 
     603                 :   // Null out the editor on the docShell to trigger PreDestroy which
     604                 :   // needs to happen before document state listeners are removed below.
     605               0 :   editorDocShell->SetEditor(nsnull);
     606                 : 
     607               0 :   RemoveListenersAndControllers(aWindow, editor);
     608                 : 
     609               0 :   if (stopEditing)
     610                 :   {
     611                 :     // Make things the way they were before we started editing.
     612               0 :     RestoreJSAndPlugins(aWindow);
     613               0 :     RestoreAnimationMode(aWindow);
     614                 : 
     615               0 :     if (mMakeWholeDocumentEditable)
     616                 :     {
     617               0 :       nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc, &rv);
     618               0 :       NS_ENSURE_SUCCESS(rv, rv);
     619                 : 
     620               0 :       doc->SetEditableFlag(false);
     621               0 :       nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(doc);
     622               0 :       if (htmlDocument) {
     623               0 :         htmlDocument->SetEditingState(nsIHTMLDocument::eOff);
     624                 :       }
     625                 :     }
     626                 :   }
     627                 : 
     628               0 :   return rv;
     629                 : }
     630                 : 
     631                 : /*---------------------------------------------------------------------------
     632                 : 
     633                 :   GetEditorForFrame
     634                 : 
     635                 :   nsIEditor getEditorForFrame (in nsIDOMWindow aWindow);
     636                 : ----------------------------------------------------------------------------*/
     637                 : NS_IMETHODIMP 
     638               0 : nsEditingSession::GetEditorForWindow(nsIDOMWindow *aWindow,
     639                 :                                      nsIEditor **outEditor)
     640                 : {
     641               0 :   nsCOMPtr<nsIEditorDocShell> editorDocShell;
     642                 :   nsresult rv = GetEditorDocShellFromWindow(aWindow,
     643               0 :                                             getter_AddRefs(editorDocShell));
     644               0 :   NS_ENSURE_SUCCESS(rv, rv);  
     645                 :   
     646               0 :   return editorDocShell->GetEditor(outEditor);
     647                 : }
     648                 : 
     649                 : /*---------------------------------------------------------------------------
     650                 : 
     651                 :   OnStateChange
     652                 : 
     653                 : ----------------------------------------------------------------------------*/
     654                 : NS_IMETHODIMP
     655               0 : nsEditingSession::OnStateChange(nsIWebProgress *aWebProgress,
     656                 :                                 nsIRequest *aRequest,
     657                 :                                 PRUint32 aStateFlags, nsresult aStatus)
     658                 : {
     659                 : 
     660                 : #ifdef NOISY_DOC_LOADING
     661                 :   nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
     662                 :   if (channel)
     663                 :   {
     664                 :     nsCAutoString contentType;
     665                 :     channel->GetContentType(contentType);
     666                 :     if (!contentType.IsEmpty())
     667                 :       printf(" ++++++ MIMETYPE = %s\n", contentType.get());
     668                 :   }
     669                 : #endif
     670                 : 
     671                 :   //
     672                 :   // A Request has started...
     673                 :   //
     674               0 :   if (aStateFlags & nsIWebProgressListener::STATE_START)
     675                 :   {
     676                 : #ifdef NOISY_DOC_LOADING
     677                 :   {
     678                 :     nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
     679                 :     if (channel)
     680                 :     {
     681                 :       nsCOMPtr<nsIURI> uri;
     682                 :       channel->GetURI(getter_AddRefs(uri));
     683                 :       if (uri)
     684                 :       {
     685                 :         nsXPIDLCString spec;
     686                 :         uri->GetSpec(spec);
     687                 :         printf(" **** STATE_START: CHANNEL URI=%s, flags=%x\n",
     688                 :                spec.get(), aStateFlags);
     689                 :       }
     690                 :     }
     691                 :     else
     692                 :       printf("    STATE_START: NO CHANNEL flags=%x\n", aStateFlags);
     693                 :   }
     694                 : #endif
     695                 :     // Page level notification...
     696               0 :     if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK)
     697                 :     {
     698               0 :       nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
     699               0 :       StartPageLoad(channel);
     700                 : #ifdef NOISY_DOC_LOADING
     701                 :       printf("STATE_START & STATE_IS_NETWORK flags=%x\n", aStateFlags);
     702                 : #endif
     703                 :     }
     704                 : 
     705                 :     // Document level notification...
     706               0 :     if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT &&
     707               0 :         !(aStateFlags & nsIWebProgressListener::STATE_RESTORING)) {
     708                 : #ifdef NOISY_DOC_LOADING
     709                 :       printf("STATE_START & STATE_IS_DOCUMENT flags=%x\n", aStateFlags);
     710                 : #endif
     711                 : 
     712                 :       bool progressIsForTargetDocument =
     713               0 :         IsProgressForTargetDocument(aWebProgress);
     714                 : 
     715               0 :       if (progressIsForTargetDocument)
     716                 :       {
     717               0 :         nsCOMPtr<nsIDOMWindow> window;
     718               0 :         aWebProgress->GetDOMWindow(getter_AddRefs(window));
     719                 : 
     720               0 :         nsCOMPtr<nsIDOMDocument> doc;
     721               0 :         window->GetDocument(getter_AddRefs(doc));
     722                 : 
     723               0 :         nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(doc));
     724                 : 
     725               0 :         if (htmlDoc && htmlDoc->IsWriting())
     726                 :         {
     727               0 :           nsCOMPtr<nsIDOMHTMLDocument> htmlDomDoc = do_QueryInterface(doc);
     728               0 :           nsAutoString designMode;
     729               0 :           htmlDomDoc->GetDesignMode(designMode);
     730                 : 
     731               0 :           if (designMode.EqualsLiteral("on"))
     732                 :           {
     733                 :             // This notification is for data coming in through
     734                 :             // document.open/write/close(), ignore it.
     735                 : 
     736               0 :             return NS_OK;
     737                 :           }
     738                 :         }
     739                 : 
     740               0 :         mCanCreateEditor = true;
     741               0 :         StartDocumentLoad(aWebProgress, progressIsForTargetDocument);
     742                 :       }
     743                 :     }
     744                 :   }
     745                 :   //
     746                 :   // A Request is being processed
     747                 :   //
     748               0 :   else if (aStateFlags & nsIWebProgressListener::STATE_TRANSFERRING)
     749                 :   {
     750               0 :     if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT)
     751                 :     {
     752                 :       // document transfer started
     753                 :     }
     754                 :   }
     755                 :   //
     756                 :   // Got a redirection
     757                 :   //
     758               0 :   else if (aStateFlags & nsIWebProgressListener::STATE_REDIRECTING)
     759                 :   {
     760               0 :     if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT)
     761                 :     {
     762                 :       // got a redirect
     763                 :     }
     764                 :   }
     765                 :   //
     766                 :   // A network or document Request has finished...
     767                 :   //
     768               0 :   else if (aStateFlags & nsIWebProgressListener::STATE_STOP)
     769                 :   {
     770                 : 
     771                 : #ifdef NOISY_DOC_LOADING
     772                 :   {
     773                 :     nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
     774                 :     if (channel)
     775                 :     {
     776                 :       nsCOMPtr<nsIURI> uri;
     777                 :       channel->GetURI(getter_AddRefs(uri));
     778                 :       if (uri)
     779                 :       {
     780                 :         nsXPIDLCString spec;
     781                 :         uri->GetSpec(spec);
     782                 :         printf(" **** STATE_STOP: CHANNEL URI=%s, flags=%x\n",
     783                 :                spec.get(), aStateFlags);
     784                 :       }
     785                 :     }
     786                 :     else
     787                 :       printf("     STATE_STOP: NO CHANNEL  flags=%x\n", aStateFlags);
     788                 :   }
     789                 : #endif
     790                 : 
     791                 :     // Document level notification...
     792               0 :     if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT)
     793                 :     {
     794               0 :       nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
     795                 :       EndDocumentLoad(aWebProgress, channel, aStatus,
     796               0 :                       IsProgressForTargetDocument(aWebProgress));
     797                 : #ifdef NOISY_DOC_LOADING
     798                 :       printf("STATE_STOP & STATE_IS_DOCUMENT flags=%x\n", aStateFlags);
     799                 : #endif
     800                 :     }
     801                 : 
     802                 :     // Page level notification...
     803               0 :     if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK)
     804                 :     {
     805               0 :       nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
     806               0 :       (void)EndPageLoad(aWebProgress, channel, aStatus);
     807                 : #ifdef NOISY_DOC_LOADING
     808                 :       printf("STATE_STOP & STATE_IS_NETWORK flags=%x\n", aStateFlags);
     809                 : #endif
     810                 :     }
     811                 :   }
     812                 : 
     813               0 :   return NS_OK;
     814                 : }
     815                 : 
     816                 : /*---------------------------------------------------------------------------
     817                 : 
     818                 :   OnProgressChange
     819                 : 
     820                 : ----------------------------------------------------------------------------*/
     821                 : NS_IMETHODIMP
     822               0 : nsEditingSession::OnProgressChange(nsIWebProgress *aWebProgress,
     823                 :                                    nsIRequest *aRequest,
     824                 :                                    PRInt32 aCurSelfProgress,
     825                 :                                    PRInt32 aMaxSelfProgress,
     826                 :                                    PRInt32 aCurTotalProgress,
     827                 :                                    PRInt32 aMaxTotalProgress)
     828                 : {
     829               0 :     NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     830               0 :     return NS_OK;
     831                 : }
     832                 : 
     833                 : /*---------------------------------------------------------------------------
     834                 : 
     835                 :   OnLocationChange
     836                 : 
     837                 : ----------------------------------------------------------------------------*/
     838                 : NS_IMETHODIMP
     839               0 : nsEditingSession::OnLocationChange(nsIWebProgress *aWebProgress, 
     840                 :                                    nsIRequest *aRequest, nsIURI *aURI,
     841                 :                                    PRUint32 aFlags)
     842                 : {
     843               0 :   nsCOMPtr<nsIDOMWindow> domWindow;
     844               0 :   nsresult rv = aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
     845               0 :   NS_ENSURE_SUCCESS(rv, rv);
     846                 : 
     847               0 :   nsCOMPtr<nsIDOMDocument> domDoc;
     848               0 :   rv = domWindow->GetDocument(getter_AddRefs(domDoc));
     849               0 :   NS_ENSURE_SUCCESS(rv, rv);
     850                 : 
     851               0 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
     852               0 :   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
     853                 : 
     854               0 :   doc->SetDocumentURI(aURI);
     855                 : 
     856                 :   // Notify the location-changed observer that
     857                 :   //  the document URL has changed
     858               0 :   nsIDocShell *docShell = GetDocShellFromWindow(domWindow);
     859               0 :   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
     860                 : 
     861               0 :   nsCOMPtr<nsICommandManager> commandManager = do_GetInterface(docShell);
     862                 :   nsCOMPtr<nsPICommandUpdater> commandUpdater =
     863               0 :                                   do_QueryInterface(commandManager);
     864               0 :   NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE);
     865                 : 
     866               0 :   return commandUpdater->CommandStatusChanged("obs_documentLocationChanged");
     867                 : }
     868                 : 
     869                 : /*---------------------------------------------------------------------------
     870                 : 
     871                 :   OnStatusChange
     872                 : 
     873                 : ----------------------------------------------------------------------------*/
     874                 : NS_IMETHODIMP
     875               0 : nsEditingSession::OnStatusChange(nsIWebProgress *aWebProgress,
     876                 :                                  nsIRequest *aRequest,
     877                 :                                  nsresult aStatus,
     878                 :                                  const PRUnichar *aMessage)
     879                 : {
     880               0 :     NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     881               0 :     return NS_OK;
     882                 : }
     883                 : 
     884                 : /*---------------------------------------------------------------------------
     885                 : 
     886                 :   OnSecurityChange
     887                 : 
     888                 : ----------------------------------------------------------------------------*/
     889                 : NS_IMETHODIMP
     890               0 : nsEditingSession::OnSecurityChange(nsIWebProgress *aWebProgress,
     891                 :                                    nsIRequest *aRequest, PRUint32 state)
     892                 : {
     893               0 :     NS_NOTREACHED("notification excluded in AddProgressListener(...)");
     894               0 :     return NS_OK;
     895                 : }
     896                 : 
     897                 : 
     898                 : /*---------------------------------------------------------------------------
     899                 : 
     900                 :   IsProgressForTargetDocument
     901                 : 
     902                 :   Check that this notification is for our document.
     903                 : ----------------------------------------------------------------------------*/
     904                 : 
     905                 : bool
     906               0 : nsEditingSession::IsProgressForTargetDocument(nsIWebProgress *aWebProgress)
     907                 : {
     908               0 :   nsCOMPtr<nsIWebProgress> editedWebProgress = do_QueryReferent(mDocShell);
     909               0 :   return editedWebProgress == aWebProgress;
     910                 : }
     911                 : 
     912                 : 
     913                 : /*---------------------------------------------------------------------------
     914                 : 
     915                 :   GetEditorStatus
     916                 : 
     917                 :   Called during GetCommandStateParams("obs_documentCreated"...) 
     918                 :   to determine if editor was created and document 
     919                 :   was loaded successfully
     920                 : ----------------------------------------------------------------------------*/
     921                 : NS_IMETHODIMP
     922               0 : nsEditingSession::GetEditorStatus(PRUint32 *aStatus)
     923                 : {
     924               0 :   NS_ENSURE_ARG_POINTER(aStatus);
     925               0 :   *aStatus = mEditorStatus;
     926               0 :   return NS_OK;
     927                 : }
     928                 : 
     929                 : /*---------------------------------------------------------------------------
     930                 : 
     931                 :   StartDocumentLoad
     932                 : 
     933                 :   Called on start of load in a single frame
     934                 : ----------------------------------------------------------------------------*/
     935                 : nsresult
     936               0 : nsEditingSession::StartDocumentLoad(nsIWebProgress *aWebProgress, 
     937                 :                                     bool aIsToBeMadeEditable)
     938                 : {
     939                 : #ifdef NOISY_DOC_LOADING
     940                 :   printf("======= StartDocumentLoad ========\n");
     941                 : #endif
     942                 : 
     943               0 :   NS_ENSURE_ARG_POINTER(aWebProgress);
     944                 :   
     945                 :   // If we have an editor here, then we got a reload after making the editor.
     946                 :   // We need to blow it away and make a new one at the end of the load.
     947               0 :   nsCOMPtr<nsIDOMWindow> domWindow;
     948               0 :   aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
     949               0 :   if (domWindow)
     950                 :   {
     951               0 :     nsIDocShell *docShell = GetDocShellFromWindow(domWindow);
     952               0 :     NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
     953               0 :     docShell->DetachEditorFromWindow();
     954                 :   }
     955                 :     
     956               0 :   if (aIsToBeMadeEditable)
     957               0 :     mEditorStatus = eEditorCreationInProgress;
     958                 : 
     959               0 :   return NS_OK;
     960                 : }
     961                 : 
     962                 : /*---------------------------------------------------------------------------
     963                 : 
     964                 :   EndDocumentLoad
     965                 : 
     966                 :   Called on end of load in a single frame
     967                 : ----------------------------------------------------------------------------*/
     968                 : nsresult
     969               0 : nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress,
     970                 :                                   nsIChannel* aChannel, nsresult aStatus,
     971                 :                                   bool aIsToBeMadeEditable)
     972                 : {
     973               0 :   NS_ENSURE_ARG_POINTER(aWebProgress);
     974                 :   
     975                 : #ifdef NOISY_DOC_LOADING
     976                 :   printf("======= EndDocumentLoad ========\n");
     977                 :   printf("with status %d, ", aStatus);
     978                 :   nsCOMPtr<nsIURI> uri;
     979                 :   nsXPIDLCString spec;
     980                 :   if (NS_SUCCEEDED(aChannel->GetURI(getter_AddRefs(uri)))) {
     981                 :     uri->GetSpec(spec);
     982                 :     printf(" uri %s\n", spec.get());
     983                 :   }
     984                 : #endif
     985                 : 
     986                 :   // We want to call the base class EndDocumentLoad,
     987                 :   // but avoid some of the stuff
     988                 :   // that nsDocShell does (need to refactor).
     989                 :   
     990                 :   // OK, time to make an editor on this document
     991               0 :   nsCOMPtr<nsIDOMWindow> domWindow;
     992               0 :   aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
     993                 :   
     994                 :   // Set the error state -- we will create an editor 
     995                 :   // anyway and load empty doc later
     996               0 :   if (aIsToBeMadeEditable) {
     997               0 :     if (aStatus == NS_ERROR_FILE_NOT_FOUND)
     998               0 :       mEditorStatus = eEditorErrorFileNotFound;
     999                 :   }
    1000                 : 
    1001               0 :   nsIDocShell *docShell = GetDocShellFromWindow(domWindow);
    1002               0 :   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);       // better error handling?
    1003                 : 
    1004                 :   // cancel refresh from meta tags
    1005                 :   // we need to make sure that all pages in editor (whether editable or not)
    1006                 :   // can't refresh contents being edited
    1007               0 :   nsCOMPtr<nsIRefreshURI> refreshURI = do_QueryInterface(docShell);
    1008               0 :   if (refreshURI)
    1009               0 :     refreshURI->CancelRefreshURITimers();
    1010                 : 
    1011               0 :   nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(docShell);
    1012                 : 
    1013               0 :   nsresult rv = NS_OK;
    1014                 : 
    1015                 :   // did someone set the flag to make this shell editable?
    1016               0 :   if (aIsToBeMadeEditable && mCanCreateEditor && editorDocShell)
    1017                 :   {
    1018                 :     bool    makeEditable;
    1019               0 :     editorDocShell->GetEditable(&makeEditable);
    1020                 :   
    1021               0 :     if (makeEditable)
    1022                 :     {
    1023                 :       // To keep pre Gecko 1.9 behavior, setup editor always when
    1024                 :       // mMakeWholeDocumentEditable.
    1025               0 :       bool needsSetup = false;
    1026               0 :       if (mMakeWholeDocumentEditable) {
    1027               0 :         needsSetup = true;
    1028                 :       } else {
    1029                 :         // do we already have an editor here?
    1030               0 :         nsCOMPtr<nsIEditor> editor;
    1031               0 :         rv = editorDocShell->GetEditor(getter_AddRefs(editor));
    1032               0 :         NS_ENSURE_SUCCESS(rv, rv);
    1033                 : 
    1034               0 :         needsSetup = !editor;
    1035                 :       }
    1036                 : 
    1037               0 :       if (needsSetup)
    1038                 :       {
    1039               0 :         mCanCreateEditor = false;
    1040               0 :         rv = SetupEditorOnWindow(domWindow);
    1041               0 :         if (NS_FAILED(rv))
    1042                 :         {
    1043                 :           // If we had an error, setup timer to load a blank page later
    1044               0 :           if (mLoadBlankDocTimer)
    1045                 :           {
    1046                 :             // Must cancel previous timer?
    1047               0 :             mLoadBlankDocTimer->Cancel();
    1048               0 :             mLoadBlankDocTimer = NULL;
    1049                 :           }
    1050                 :   
    1051               0 :           mLoadBlankDocTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
    1052               0 :           NS_ENSURE_SUCCESS(rv, rv);
    1053                 : 
    1054               0 :           mEditorStatus = eEditorCreationInProgress;
    1055               0 :           mLoadBlankDocTimer->InitWithFuncCallback(
    1056                 :                                           nsEditingSession::TimerCallback,
    1057               0 :                                           static_cast<void*> (mDocShell.get()),
    1058               0 :                                           10, nsITimer::TYPE_ONE_SHOT);
    1059                 :         }
    1060                 :       }
    1061                 :     }
    1062                 :   }
    1063               0 :   return rv;
    1064                 : }
    1065                 : 
    1066                 : 
    1067                 : void
    1068               0 : nsEditingSession::TimerCallback(nsITimer* aTimer, void* aClosure)
    1069                 : {
    1070               0 :   nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(static_cast<nsIWeakReference*> (aClosure));
    1071               0 :   if (docShell)
    1072                 :   {
    1073               0 :     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
    1074               0 :     if (webNav)
    1075               0 :       webNav->LoadURI(NS_LITERAL_STRING("about:blank").get(),
    1076               0 :                       0, nsnull, nsnull, nsnull);
    1077                 :   }
    1078               0 : }
    1079                 : 
    1080                 : /*---------------------------------------------------------------------------
    1081                 : 
    1082                 :   StartPageLoad
    1083                 : 
    1084                 :   Called on start load of the entire page (incl. subframes)
    1085                 : ----------------------------------------------------------------------------*/
    1086                 : nsresult
    1087               0 : nsEditingSession::StartPageLoad(nsIChannel *aChannel)
    1088                 : {
    1089                 : #ifdef NOISY_DOC_LOADING
    1090                 :   printf("======= StartPageLoad ========\n");
    1091                 : #endif
    1092               0 :   return NS_OK;
    1093                 : }
    1094                 : 
    1095                 : /*---------------------------------------------------------------------------
    1096                 : 
    1097                 :   EndPageLoad
    1098                 : 
    1099                 :   Called on end load of the entire page (incl. subframes)
    1100                 : ----------------------------------------------------------------------------*/
    1101                 : nsresult
    1102               0 : nsEditingSession::EndPageLoad(nsIWebProgress *aWebProgress,
    1103                 :                               nsIChannel* aChannel, nsresult aStatus)
    1104                 : {
    1105                 : #ifdef NOISY_DOC_LOADING
    1106                 :   printf("======= EndPageLoad ========\n");
    1107                 :   printf("  with status %d, ", aStatus);
    1108                 :   nsCOMPtr<nsIURI> uri;
    1109                 :   nsXPIDLCString spec;
    1110                 :   if (NS_SUCCEEDED(aChannel->GetURI(getter_AddRefs(uri)))) {
    1111                 :     uri->GetSpec(spec);
    1112                 :     printf("uri %s\n", spec.get());
    1113                 :   }
    1114                 :  
    1115                 :   nsCAutoString contentType;
    1116                 :   aChannel->GetContentType(contentType);
    1117                 :   if (!contentType.IsEmpty())
    1118                 :     printf("   flags = %d, status = %d, MIMETYPE = %s\n", 
    1119                 :                mEditorFlags, mEditorStatus, contentType.get());
    1120                 : #endif
    1121                 : 
    1122                 :   // Set the error state -- we will create an editor anyway 
    1123                 :   // and load empty doc later
    1124               0 :   if (aStatus == NS_ERROR_FILE_NOT_FOUND)
    1125               0 :     mEditorStatus = eEditorErrorFileNotFound;
    1126                 : 
    1127               0 :   nsCOMPtr<nsIDOMWindow> domWindow;
    1128               0 :   aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
    1129                 : 
    1130               0 :   nsIDocShell *docShell = GetDocShellFromWindow(domWindow);
    1131               0 :   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
    1132                 : 
    1133                 :   // cancel refresh from meta tags
    1134                 :   // we need to make sure that all pages in editor (whether editable or not)
    1135                 :   // can't refresh contents being edited
    1136               0 :   nsCOMPtr<nsIRefreshURI> refreshURI = do_QueryInterface(docShell);
    1137               0 :   if (refreshURI)
    1138               0 :     refreshURI->CancelRefreshURITimers();
    1139                 : 
    1140                 : #if 0
    1141                 :   // Shouldn't we do this when we want to edit sub-frames?
    1142                 :   return MakeWindowEditable(domWindow, "html", false, mInteractive);
    1143                 : #else
    1144               0 :   return NS_OK;
    1145                 : #endif
    1146                 : }
    1147                 : 
    1148                 : /*---------------------------------------------------------------------------
    1149                 : 
    1150                 :   GetDocShellFromWindow
    1151                 : 
    1152                 :   Utility method. This will always return nsnull if no docShell is found.
    1153                 : ----------------------------------------------------------------------------*/
    1154                 : nsIDocShell *
    1155               0 : nsEditingSession::GetDocShellFromWindow(nsIDOMWindow *aWindow)
    1156                 : {
    1157               0 :   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
    1158               0 :   NS_ENSURE_TRUE(window, nsnull);
    1159                 : 
    1160               0 :   return window->GetDocShell();
    1161                 : }
    1162                 : 
    1163                 : /*---------------------------------------------------------------------------
    1164                 : 
    1165                 :   GetEditorDocShellFromWindow
    1166                 : 
    1167                 :   Utility method. This will always return an error if no docShell
    1168                 :   is returned.
    1169                 : ----------------------------------------------------------------------------*/
    1170                 : nsresult
    1171               0 : nsEditingSession::GetEditorDocShellFromWindow(nsIDOMWindow *aWindow,
    1172                 :                                               nsIEditorDocShell** outDocShell)
    1173                 : {
    1174               0 :   nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
    1175               0 :   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
    1176                 :   
    1177                 :   return docShell->QueryInterface(NS_GET_IID(nsIEditorDocShell), 
    1178               0 :                                   (void **)outDocShell);
    1179                 : }
    1180                 : 
    1181                 : /*---------------------------------------------------------------------------
    1182                 : 
    1183                 :   PrepareForEditing
    1184                 : 
    1185                 :   Set up this editing session for one or more editors
    1186                 : ----------------------------------------------------------------------------*/
    1187                 : nsresult
    1188               0 : nsEditingSession::PrepareForEditing(nsIDOMWindow *aWindow)
    1189                 : {
    1190               0 :   if (mProgressListenerRegistered)
    1191               0 :     return NS_OK;
    1192                 :     
    1193               0 :   nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
    1194                 :   
    1195                 :   // register callback
    1196               0 :   nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
    1197               0 :   NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE);
    1198                 : 
    1199                 :   nsresult rv =
    1200               0 :     webProgress->AddProgressListener(this,
    1201                 :                                      (nsIWebProgress::NOTIFY_STATE_NETWORK  | 
    1202                 :                                       nsIWebProgress::NOTIFY_STATE_DOCUMENT |
    1203               0 :                                       nsIWebProgress::NOTIFY_LOCATION));
    1204                 : 
    1205               0 :   mProgressListenerRegistered = NS_SUCCEEDED(rv);
    1206                 : 
    1207               0 :   return rv;
    1208                 : }
    1209                 : 
    1210                 : /*---------------------------------------------------------------------------
    1211                 : 
    1212                 :   SetupEditorCommandController
    1213                 : 
    1214                 :   Create a command controller, append to controllers,
    1215                 :   get and return the controller ID, and set the context
    1216                 : ----------------------------------------------------------------------------*/
    1217                 : nsresult
    1218               0 : nsEditingSession::SetupEditorCommandController(
    1219                 :                                   const char *aControllerClassName,
    1220                 :                                   nsIDOMWindow *aWindow,
    1221                 :                                   nsISupports *aContext,
    1222                 :                                   PRUint32 *aControllerId)
    1223                 : {
    1224               0 :   NS_ENSURE_ARG_POINTER(aControllerClassName);
    1225               0 :   NS_ENSURE_ARG_POINTER(aWindow);
    1226               0 :   NS_ENSURE_ARG_POINTER(aContext);
    1227               0 :   NS_ENSURE_ARG_POINTER(aControllerId);
    1228                 :   
    1229               0 :   nsCOMPtr<nsIControllers> controllers;      
    1230               0 :   nsresult rv = aWindow->GetControllers(getter_AddRefs(controllers));
    1231               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1232                 : 
    1233                 :   // We only have to create each singleton controller once
    1234                 :   // We know this has happened once we have a controllerId value
    1235               0 :   if (!*aControllerId)
    1236                 :   {
    1237               0 :     nsCOMPtr<nsIController> controller;
    1238               0 :     controller = do_CreateInstance(aControllerClassName, &rv);
    1239               0 :     NS_ENSURE_SUCCESS(rv, rv);  
    1240                 : 
    1241                 :     // We must insert at head of the list to be sure our
    1242                 :     //   controller is found before other implementations
    1243                 :     //   (e.g., not-implemented versions by browser)
    1244               0 :     rv = controllers->InsertControllerAt(0, controller);
    1245               0 :     NS_ENSURE_SUCCESS(rv, rv);  
    1246                 : 
    1247                 :     // Remember the ID for the controller
    1248               0 :     rv = controllers->GetControllerId(controller, aControllerId);
    1249               0 :     NS_ENSURE_SUCCESS(rv, rv);  
    1250                 :   }  
    1251                 : 
    1252                 :   // Set the context
    1253               0 :   return SetContextOnControllerById(controllers, aContext, *aControllerId);
    1254                 : }
    1255                 : 
    1256                 : /*---------------------------------------------------------------------------
    1257                 : 
    1258                 :   SetEditorOnControllers
    1259                 : 
    1260                 :   Set the editor on the controller(s) for this window
    1261                 : ----------------------------------------------------------------------------*/
    1262                 : NS_IMETHODIMP
    1263               0 : nsEditingSession::SetEditorOnControllers(nsIDOMWindow *aWindow,
    1264                 :                                          nsIEditor* aEditor)
    1265                 : {
    1266               0 :   NS_ENSURE_TRUE(aWindow, NS_ERROR_NULL_POINTER);
    1267                 :   
    1268               0 :   nsCOMPtr<nsIControllers> controllers;      
    1269               0 :   nsresult rv = aWindow->GetControllers(getter_AddRefs(controllers));
    1270               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1271                 : 
    1272               0 :   nsCOMPtr<nsISupports> editorAsISupports = do_QueryInterface(aEditor);
    1273               0 :   if (mBaseCommandControllerId)
    1274                 :   {
    1275                 :     rv = SetContextOnControllerById(controllers, editorAsISupports,
    1276               0 :                                     mBaseCommandControllerId);
    1277               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1278                 :   }
    1279                 : 
    1280               0 :   if (mDocStateControllerId)
    1281                 :   {
    1282                 :     rv = SetContextOnControllerById(controllers, editorAsISupports,
    1283               0 :                                     mDocStateControllerId);
    1284               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1285                 :   }
    1286                 : 
    1287               0 :   if (mHTMLCommandControllerId)
    1288                 :     rv = SetContextOnControllerById(controllers, editorAsISupports,
    1289               0 :                                     mHTMLCommandControllerId);
    1290                 : 
    1291               0 :   return rv;
    1292                 : }
    1293                 : 
    1294                 : nsresult
    1295               0 : nsEditingSession::SetContextOnControllerById(nsIControllers* aControllers,
    1296                 :                                              nsISupports* aContext,
    1297                 :                                              PRUint32 aID)
    1298                 : {
    1299               0 :   NS_ENSURE_ARG_POINTER(aControllers);
    1300                 : 
    1301                 :   // aContext can be null (when destroying editor)
    1302               0 :   nsCOMPtr<nsIController> controller;    
    1303               0 :   aControllers->GetControllerById(aID, getter_AddRefs(controller));
    1304                 :   
    1305                 :   // ok with nil controller
    1306                 :   nsCOMPtr<nsIControllerContext> editorController =
    1307               0 :                                        do_QueryInterface(controller);
    1308               0 :   NS_ENSURE_TRUE(editorController, NS_ERROR_FAILURE);
    1309                 : 
    1310               0 :   return editorController->SetCommandContext(aContext);
    1311                 : }
    1312                 : 
    1313                 : void
    1314               0 : nsEditingSession::RemoveEditorControllers(nsIDOMWindow *aWindow)
    1315                 : {
    1316                 :   // Remove editor controllers from the aWindow, call when we're 
    1317                 :   // tearing down/detaching editor.
    1318                 : 
    1319               0 :   nsCOMPtr<nsIControllers> controllers;
    1320               0 :   if (aWindow)
    1321               0 :     aWindow->GetControllers(getter_AddRefs(controllers));
    1322                 : 
    1323               0 :   if (controllers)
    1324                 :   {
    1325               0 :     nsCOMPtr<nsIController> controller;
    1326               0 :     if (mBaseCommandControllerId)
    1327                 :     {
    1328               0 :       controllers->GetControllerById(mBaseCommandControllerId,
    1329               0 :                                      getter_AddRefs(controller));
    1330               0 :       if (controller)
    1331               0 :         controllers->RemoveController(controller);
    1332                 :     }
    1333                 : 
    1334               0 :     if (mDocStateControllerId)
    1335                 :     {
    1336               0 :       controllers->GetControllerById(mDocStateControllerId,
    1337               0 :                                      getter_AddRefs(controller));
    1338               0 :       if (controller)
    1339               0 :         controllers->RemoveController(controller);
    1340                 :     }
    1341                 : 
    1342               0 :     if (mHTMLCommandControllerId)
    1343                 :     {
    1344               0 :       controllers->GetControllerById(mHTMLCommandControllerId,
    1345               0 :                                      getter_AddRefs(controller));
    1346               0 :       if (controller)
    1347               0 :         controllers->RemoveController(controller);
    1348                 :     }
    1349                 :   }
    1350                 : 
    1351                 :   // Clear IDs to trigger creation of new controllers.
    1352               0 :   mBaseCommandControllerId = 0;
    1353               0 :   mDocStateControllerId = 0;
    1354               0 :   mHTMLCommandControllerId = 0;
    1355               0 : }
    1356                 : 
    1357                 : void
    1358               0 : nsEditingSession::RemoveWebProgressListener(nsIDOMWindow *aWindow)
    1359                 : {
    1360               0 :   nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
    1361               0 :   nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
    1362               0 :   if (webProgress)
    1363                 :   {
    1364               0 :     webProgress->RemoveProgressListener(this);
    1365               0 :     mProgressListenerRegistered = false;
    1366                 :   }
    1367               0 : }
    1368                 : 
    1369                 : void
    1370               0 : nsEditingSession::RestoreAnimationMode(nsIDOMWindow *aWindow)
    1371                 : {
    1372               0 :   if (!mInteractive)
    1373                 :   {
    1374               0 :     nsCOMPtr<nsIDOMWindowUtils> utils(do_GetInterface(aWindow));
    1375               0 :     if (utils)
    1376               0 :       utils->SetImageAnimationMode(mImageAnimationMode);
    1377                 :   }
    1378               0 : }
    1379                 : 
    1380                 : nsresult
    1381               0 : nsEditingSession::DetachFromWindow(nsIDOMWindow* aWindow)
    1382                 : {
    1383               0 :   NS_ENSURE_TRUE(mDoneSetup, NS_OK);
    1384                 : 
    1385               0 :   NS_ASSERTION(mStateMaintainer, "mStateMaintainer should exist.");
    1386                 : 
    1387                 :   // Kill any existing reload timer
    1388               0 :   if (mLoadBlankDocTimer)
    1389                 :   {
    1390               0 :     mLoadBlankDocTimer->Cancel();
    1391               0 :     mLoadBlankDocTimer = nsnull;
    1392                 :   }
    1393                 : 
    1394                 :   // Remove controllers, webprogress listener, and otherwise
    1395                 :   // make things the way they were before we started editing.
    1396               0 :   RemoveEditorControllers(aWindow);
    1397               0 :   RemoveWebProgressListener(aWindow);
    1398               0 :   RestoreJSAndPlugins(aWindow);
    1399               0 :   RestoreAnimationMode(aWindow);
    1400                 : 
    1401                 :   // Kill our weak reference to our original window, in case
    1402                 :   // it changes on restore, or otherwise dies.
    1403               0 :   mDocShell = nsnull;
    1404                 : 
    1405               0 :   return NS_OK;
    1406                 : }
    1407                 : 
    1408                 : nsresult
    1409               0 : nsEditingSession::ReattachToWindow(nsIDOMWindow* aWindow)
    1410                 : {
    1411               0 :   NS_ENSURE_TRUE(mDoneSetup, NS_OK);
    1412                 : 
    1413               0 :   NS_ASSERTION(mStateMaintainer, "mStateMaintainer should exist.");
    1414                 : 
    1415                 :   // Imitate nsEditorDocShell::MakeEditable() to reattach the
    1416                 :   // old editor ot the window.
    1417                 :   nsresult rv;
    1418                 : 
    1419               0 :   nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
    1420               0 :   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
    1421               0 :   mDocShell = do_GetWeakReference(docShell);
    1422                 : 
    1423                 :   // Disable plugins.
    1424               0 :   if (!mInteractive)
    1425                 :   {
    1426               0 :     rv = DisableJSAndPlugins(aWindow);
    1427               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1428                 :   }
    1429                 : 
    1430                 :   // Tells embedder that startup is in progress.
    1431               0 :   mEditorStatus = eEditorCreationInProgress;
    1432                 : 
    1433                 :   // Adds back web progress listener.
    1434               0 :   rv = PrepareForEditing(aWindow);
    1435               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1436                 : 
    1437                 :   // Setup the command controllers again.
    1438                 :   rv = SetupEditorCommandController("@mozilla.org/editor/editingcontroller;1",
    1439                 :                                     aWindow,
    1440                 :                                     static_cast<nsIEditingSession*>(this),
    1441               0 :                                     &mBaseCommandControllerId);
    1442               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1443                 : 
    1444                 :   rv = SetupEditorCommandController("@mozilla.org/editor/editordocstatecontroller;1",
    1445                 :                                     aWindow,
    1446                 :                                     static_cast<nsIEditingSession*>(this),
    1447               0 :                                     &mDocStateControllerId);
    1448               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1449                 : 
    1450               0 :   if (mStateMaintainer)
    1451               0 :     mStateMaintainer->Init(aWindow);
    1452                 : 
    1453                 :   // Get editor
    1454               0 :   nsCOMPtr<nsIEditor> editor;
    1455               0 :   rv = GetEditorForWindow(aWindow, getter_AddRefs(editor));
    1456               0 :   NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);
    1457                 : 
    1458               0 :   if (!mInteractive)
    1459                 :   {
    1460                 :     // Disable animation of images in this document:
    1461               0 :     nsCOMPtr<nsIDOMWindowUtils> utils(do_GetInterface(aWindow));
    1462               0 :     NS_ENSURE_TRUE(utils, NS_ERROR_FAILURE);
    1463                 : 
    1464               0 :     rv = utils->GetImageAnimationMode(&mImageAnimationMode);
    1465               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1466               0 :     utils->SetImageAnimationMode(imgIContainer::kDontAnimMode);
    1467                 :   }
    1468                 : 
    1469                 :   // The third controller takes an nsIEditor as the context
    1470                 :   rv = SetupEditorCommandController("@mozilla.org/editor/htmleditorcontroller;1",
    1471                 :                                     aWindow, editor,
    1472               0 :                                     &mHTMLCommandControllerId);
    1473               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1474                 : 
    1475                 :   // Set context on all controllers to be the editor
    1476               0 :   rv = SetEditorOnControllers(aWindow, editor);
    1477               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1478                 : 
    1479                 : #ifdef DEBUG
    1480                 :   {
    1481                 :     bool isEditable;
    1482               0 :     rv = WindowIsEditable(aWindow, &isEditable);
    1483               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1484               0 :     NS_ASSERTION(isEditable, "Window is not editable after reattaching editor.");
    1485                 :   }
    1486                 : #endif // DEBUG
    1487                 : 
    1488               0 :   return NS_OK;
    1489                 : }

Generated by: LCOV version 1.7