LCOV - app.info - editor/composer/src/nsEditingSession.cpp

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-07-07 | 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