/*---------------------------------------------------------------------------

  StartDocumentLoad

  Called on start of load in a single frame
----------------------------------------------------------------------------*/
nsresult
nsEditingSession::StartDocumentLoad(nsIWebProgress *aWebProgress, 
                                    bool aIsToBeMadeEditable)
{
#ifdef NOISY_DOC_LOADING
  printf("======= StartDocumentLoad ========\n");
#endif

  NS_ENSURE_ARG_POINTER(aWebProgress);
  
  // If we have an editor here, then we got a reload after making the editor.
  // We need to blow it away and make a new one at the end of the load.
  nsCOMPtr<nsIDOMWindow> domWindow;
  aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
  if (domWindow)
  {
    nsIDocShell *docShell = GetDocShellFromWindow(domWindow);
    NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
    docShell->DetachEditorFromWindow();
  }
    
  if (aIsToBeMadeEditable)
    mEditorStatus = eEditorCreationInProgress;

  return NS_OK;
}
NS_IMETHODIMP
nsEditingSession::DisableJSAndPlugins(nsIDOMWindow *aWindow)
{
  nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);

  bool tmp;
  nsresult rv = docShell->GetAllowJavascript(&tmp);
  NS_ENSURE_SUCCESS(rv, rv);

  mScriptsEnabled = tmp;

  rv = docShell->SetAllowJavascript(false);
  NS_ENSURE_SUCCESS(rv, rv);

  // Disable plugins in this document:
  mPluginsEnabled = docShell->PluginsAllowedInCurrentDoc();

  rv = docShell->SetAllowPlugins(false);
  NS_ENSURE_SUCCESS(rv, rv);

  mDisabledJSAndPlugins = true;

  return NS_OK;
}
/*---------------------------------------------------------------------------

  OnLocationChange

----------------------------------------------------------------------------*/
NS_IMETHODIMP
nsEditingSession::OnLocationChange(nsIWebProgress *aWebProgress, 
                                   nsIRequest *aRequest, nsIURI *aURI,
                                   PRUint32 aFlags)
{
  nsCOMPtr<nsIDOMWindow> domWindow;
  nsresult rv = aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIDOMDocument> domDoc;
  rv = domWindow->GetDocument(getter_AddRefs(domDoc));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
  NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);

  doc->SetDocumentURI(aURI);

  // Notify the location-changed observer that
  //  the document URL has changed
  nsIDocShell *docShell = GetDocShellFromWindow(domWindow);
  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);

  nsCOMPtr<nsICommandManager> commandManager = do_GetInterface(docShell);
  nsCOMPtr<nsPICommandUpdater> commandUpdater =
                                  do_QueryInterface(commandManager);
  NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE);

  return commandUpdater->CommandStatusChanged("obs_documentLocationChanged");
}
NS_IMETHODIMP
nsRegressionTester::DumpFrameModel(nsIDOMWindow *aWindowToDump,
                                   nsIFile *aDestFile,
                                   uint32_t aFlagsMask, int32_t *aResult)
{
  NS_ENSURE_ARG(aWindowToDump);
  NS_ENSURE_ARG_POINTER(aResult);

  *aResult = DUMP_RESULT_ERROR;

#ifndef DEBUG
  return NS_ERROR_NOT_AVAILABLE;
#else
  nsresult    rv = NS_ERROR_NOT_AVAILABLE;
  uint32_t    busyFlags;
  bool        stillLoading;

  nsCOMPtr<nsIDocShell> docShell;
  rv = GetDocShellFromWindow(aWindowToDump, getter_AddRefs(docShell));
  if (NS_FAILED(rv)) return rv;

  // find out if the document is loaded
  docShell->GetBusyFlags(&busyFlags);
  stillLoading = busyFlags & (nsIDocShell::BUSY_FLAGS_BUSY |
                              nsIDocShell::BUSY_FLAGS_PAGE_LOADING);
  if (stillLoading)
  {
    *aResult = DUMP_RESULT_LOADING;
    return NS_OK;
  }

  nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();

  nsIFrame* root = presShell->GetRootFrame();

  FILE* fp = stdout;
  if (aDestFile)
  {
    rv = aDestFile->OpenANSIFileDesc("w", &fp);
    if (NS_FAILED(rv)) return rv;
  }
  if (aFlagsMask & DUMP_FLAGS_MASK_PRINT_MODE) {
    nsCOMPtr <nsIContentViewer> viewer;
    docShell->GetContentViewer(getter_AddRefs(viewer));
    if (viewer){
      nsCOMPtr<nsIContentViewerFile> viewerFile = do_QueryInterface(viewer);
      if (viewerFile) {
         viewerFile->Print(true, fp, nullptr);
      }
    }
  }
  else {
    root->DumpRegressionData(presShell->GetPresContext(), fp, 0);
  }
  if (fp != stdout)
    fclose(fp);
  *aResult = DUMP_RESULT_COMPLETED;
  return NS_OK;
#endif
}
Beispiel #5
0
NS_IMETHODIMP
nsEditingSession::DisableJSAndPlugins(nsIDOMWindow *aWindow)
{
  nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
  if (!docShell) return NS_ERROR_FAILURE;

  PRBool tmp;
  nsresult rv = docShell->GetAllowJavascript(&tmp);
  NS_ENSURE_SUCCESS(rv, rv);

  mScriptsEnabled = tmp;

  rv = docShell->SetAllowJavascript(PR_FALSE);
  NS_ENSURE_SUCCESS(rv, rv);

  // Disable plugins in this document:
  rv = docShell->GetAllowPlugins(&tmp);
  NS_ENSURE_SUCCESS(rv, rv);

  mPluginsEnabled = tmp;

  rv = docShell->SetAllowPlugins(PR_FALSE);
  NS_ENSURE_SUCCESS(rv, rv);

  mDisabledJSAndPlugins = PR_TRUE;

  return NS_OK;
}
/*---------------------------------------------------------------------------

  GetEditorDocShellFromWindow

  Utility method. This will always return an error if no docShell
  is returned.
----------------------------------------------------------------------------*/
nsresult
nsEditingSession::GetEditorDocShellFromWindow(nsIDOMWindow *aWindow,
                                              nsIEditorDocShell** outDocShell)
{
  nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
  
  return docShell->QueryInterface(NS_GET_IID(nsIEditorDocShell), 
                                  (void **)outDocShell);
}
void
nsEditingSession::RemoveWebProgressListener(nsIDOMWindow *aWindow)
{
  nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
  nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
  if (webProgress)
  {
    webProgress->RemoveProgressListener(this);
    mProgressListenerRegistered = false;
  }
}
NS_IMETHODIMP
nsEditingSession::RestoreJSAndPlugins(nsIDOMWindow *aWindow)
{
  NS_ENSURE_TRUE(mDisabledJSAndPlugins, NS_OK);

  mDisabledJSAndPlugins = false;

  nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);

  nsresult rv = docShell->SetAllowJavascript(mScriptsEnabled);
  NS_ENSURE_SUCCESS(rv, rv);

  // Disable plugins in this document:
  return docShell->SetAllowPlugins(mPluginsEnabled);
}
/*---------------------------------------------------------------------------

  EndPageLoad

  Called on end load of the entire page (incl. subframes)
----------------------------------------------------------------------------*/
nsresult
nsEditingSession::EndPageLoad(nsIWebProgress *aWebProgress,
                              nsIChannel* aChannel, nsresult aStatus)
{
#ifdef NOISY_DOC_LOADING
  printf("======= EndPageLoad ========\n");
  printf("  with status %d, ", aStatus);
  nsCOMPtr<nsIURI> uri;
  nsXPIDLCString spec;
  if (NS_SUCCEEDED(aChannel->GetURI(getter_AddRefs(uri)))) {
    uri->GetSpec(spec);
    printf("uri %s\n", spec.get());
  }
 
  nsCAutoString contentType;
  aChannel->GetContentType(contentType);
  if (!contentType.IsEmpty())
    printf("   flags = %d, status = %d, MIMETYPE = %s\n", 
               mEditorFlags, mEditorStatus, contentType.get());
#endif

  // Set the error state -- we will create an editor anyway 
  // and load empty doc later
  if (aStatus == NS_ERROR_FILE_NOT_FOUND)
    mEditorStatus = eEditorErrorFileNotFound;

  nsCOMPtr<nsIDOMWindow> domWindow;
  aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));

  nsIDocShell *docShell = GetDocShellFromWindow(domWindow);
  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);

  // cancel refresh from meta tags
  // we need to make sure that all pages in editor (whether editable or not)
  // can't refresh contents being edited
  nsCOMPtr<nsIRefreshURI> refreshURI = do_QueryInterface(docShell);
  if (refreshURI)
    refreshURI->CancelRefreshURITimers();

#if 0
  // Shouldn't we do this when we want to edit sub-frames?
  return MakeWindowEditable(domWindow, "html", false, mInteractive);
#else
  return NS_OK;
#endif
}
Beispiel #10
0
NS_IMETHODIMP
nsEditingSession::RestoreJSAndPlugins(nsIDOMWindow *aWindow)
{
  if (!mDisabledJSAndPlugins)
    return NS_OK;

  mDisabledJSAndPlugins = PR_FALSE;

  nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
  if (!docShell) return NS_ERROR_FAILURE;

  nsresult rv = docShell->SetAllowJavascript(mScriptsEnabled);
  NS_ENSURE_SUCCESS(rv, rv);

  // Disable plugins in this document:
  return docShell->SetAllowPlugins(mPluginsEnabled);
}
/*---------------------------------------------------------------------------

  PrepareForEditing

  Set up this editing session for one or more editors
----------------------------------------------------------------------------*/
nsresult
nsEditingSession::PrepareForEditing(nsIDOMWindow *aWindow)
{
  if (mProgressListenerRegistered)
    return NS_OK;
    
  nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
  
  // register callback
  nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
  NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE);

  nsresult rv =
    webProgress->AddProgressListener(this,
                                     (nsIWebProgress::NOTIFY_STATE_NETWORK  | 
                                      nsIWebProgress::NOTIFY_STATE_DOCUMENT |
                                      nsIWebProgress::NOTIFY_LOCATION));

  mProgressListenerRegistered = NS_SUCCEEDED(rv);

  return rv;
}
Beispiel #12
0
/* boolean findNext (); */
NS_IMETHODIMP nsWebBrowserFind::FindNext(bool *outDidFind)
{
    NS_ENSURE_ARG_POINTER(outDidFind);
    *outDidFind = false;

    NS_ENSURE_TRUE(CanFindNext(), NS_ERROR_NOT_INITIALIZED);

    nsresult rv = NS_OK;
    nsCOMPtr<nsIDOMWindow> searchFrame = do_QueryReferent(mCurrentSearchFrame);
    NS_ENSURE_TRUE(searchFrame, NS_ERROR_NOT_INITIALIZED);

    nsCOMPtr<nsIDOMWindow> rootFrame = do_QueryReferent(mRootSearchFrame);
    NS_ENSURE_TRUE(rootFrame, NS_ERROR_NOT_INITIALIZED);
    
    // first, if there's a "cmd_findagain" observer around, check to see if it
    // wants to perform the find again command . If it performs the find again
    // it will return true, in which case we exit ::FindNext() early.
    // Otherwise, nsWebBrowserFind needs to perform the find again command itself
    // this is used by nsTypeAheadFind, which controls find again when it was
    // the last executed find in the current window.
    nsCOMPtr<nsIObserverService> observerSvc =
      mozilla::services::GetObserverService();
    if (observerSvc) {
        nsCOMPtr<nsISupportsInterfacePointer> windowSupportsData = 
          do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv);
        NS_ENSURE_SUCCESS(rv, rv);
        nsCOMPtr<nsISupports> searchWindowSupports =
          do_QueryInterface(rootFrame);
        windowSupportsData->SetData(searchWindowSupports);
        NS_NAMED_LITERAL_STRING(dnStr, "down");
        NS_NAMED_LITERAL_STRING(upStr, "up");
        observerSvc->NotifyObservers(windowSupportsData, 
                                     "nsWebBrowserFind_FindAgain", 
                                     mFindBackwards? upStr.get(): dnStr.get());
        windowSupportsData->GetData(getter_AddRefs(searchWindowSupports));
        // findnext performed if search window data cleared out
        *outDidFind = searchWindowSupports == nullptr;
        if (*outDidFind)
            return NS_OK;
    }

    // next, look in the current frame. If found, return.

    // Beware! This may flush notifications via synchronous
    // ScrollSelectionIntoView.
    rv = SearchInFrame(searchFrame, false, outDidFind);
    if (NS_FAILED(rv)) return rv;
    if (*outDidFind)
        return OnFind(searchFrame);     // we are done

    // if we are not searching other frames, return
    if (!mSearchSubFrames && !mSearchParentFrames)
        return NS_OK;

    nsIDocShell *rootDocShell = GetDocShellFromWindow(rootFrame);
    if (!rootDocShell) return NS_ERROR_FAILURE;
    
    int32_t enumDirection;
    if (mFindBackwards)
        enumDirection = nsIDocShell::ENUMERATE_BACKWARDS;
    else
        enumDirection = nsIDocShell::ENUMERATE_FORWARDS;
        
    nsCOMPtr<nsISimpleEnumerator> docShellEnumerator;
    rv = rootDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeAll,
            enumDirection, getter_AddRefs(docShellEnumerator));    
    if (NS_FAILED(rv)) return rv;
        
    // remember where we started
    nsCOMPtr<nsIDocShellTreeItem> startingItem =
        do_QueryInterface(GetDocShellFromWindow(searchFrame), &rv);
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIDocShellTreeItem> curItem;

    // XXX We should avoid searching in frameset documents here.
    // We also need to honour mSearchSubFrames and mSearchParentFrames.
    bool hasMore, doFind = false;
    while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMore)) && hasMore)
    {
        nsCOMPtr<nsISupports> curSupports;
        rv = docShellEnumerator->GetNext(getter_AddRefs(curSupports));
        if (NS_FAILED(rv)) break;
        curItem = do_QueryInterface(curSupports, &rv);
        if (NS_FAILED(rv)) break;

        if (doFind)
        {
            searchFrame = do_GetInterface(curItem, &rv);
            if (NS_FAILED(rv)) break;

            OnStartSearchFrame(searchFrame);

            // Beware! This may flush notifications via synchronous
            // ScrollSelectionIntoView.
            rv = SearchInFrame(searchFrame, false, outDidFind);
            if (NS_FAILED(rv)) return rv;
            if (*outDidFind)
                return OnFind(searchFrame);     // we are done

            OnEndSearchFrame(searchFrame);
        }

        if (curItem.get() == startingItem.get())
            doFind = true;       // start looking in frames after this one
    };

    if (!mWrapFind)
    {
        // remember where we left off
        SetCurrentSearchFrame(searchFrame);
        return NS_OK;
    }

    // From here on, we're wrapping, first through the other frames,
    // then finally from the beginning of the starting frame back to
    // the starting point.

    // because nsISimpleEnumerator is totally lame and isn't resettable, I
    // have to make a new one
    docShellEnumerator = nullptr;
    rv = rootDocShell->GetDocShellEnumerator(nsIDocShellTreeItem::typeAll,
            enumDirection, getter_AddRefs(docShellEnumerator));    
    if (NS_FAILED(rv)) return rv;
    
    while (NS_SUCCEEDED(docShellEnumerator->HasMoreElements(&hasMore)) && hasMore)
    {
        nsCOMPtr<nsISupports> curSupports;
        rv = docShellEnumerator->GetNext(getter_AddRefs(curSupports));
        if (NS_FAILED(rv)) break;
        curItem = do_QueryInterface(curSupports, &rv);
        if (NS_FAILED(rv)) break;

        searchFrame = do_GetInterface(curItem, &rv);
        if (NS_FAILED(rv)) break;

        if (curItem.get() == startingItem.get())
        {
            // Beware! This may flush notifications via synchronous
            // ScrollSelectionIntoView.
            rv = SearchInFrame(searchFrame, true, outDidFind);
            if (NS_FAILED(rv)) return rv;
            if (*outDidFind)
                return OnFind(searchFrame);        // we are done
            break;
        }

        OnStartSearchFrame(searchFrame);

        // Beware! This may flush notifications via synchronous
        // ScrollSelectionIntoView.
        rv = SearchInFrame(searchFrame, false, outDidFind);
        if (NS_FAILED(rv)) return rv;
        if (*outDidFind)
            return OnFind(searchFrame);        // we are done
        
        OnEndSearchFrame(searchFrame);
    }

    // remember where we left off
    SetCurrentSearchFrame(searchFrame);
    
    NS_ASSERTION(NS_SUCCEEDED(rv), "Something failed");
    return rv;
}
/*---------------------------------------------------------------------------

  EndDocumentLoad

  Called on end of load in a single frame
----------------------------------------------------------------------------*/
nsresult
nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress,
                                  nsIChannel* aChannel, nsresult aStatus,
                                  bool aIsToBeMadeEditable)
{
  NS_ENSURE_ARG_POINTER(aWebProgress);
  
#ifdef NOISY_DOC_LOADING
  printf("======= EndDocumentLoad ========\n");
  printf("with status %d, ", aStatus);
  nsCOMPtr<nsIURI> uri;
  nsXPIDLCString spec;
  if (NS_SUCCEEDED(aChannel->GetURI(getter_AddRefs(uri)))) {
    uri->GetSpec(spec);
    printf(" uri %s\n", spec.get());
  }
#endif

  // We want to call the base class EndDocumentLoad,
  // but avoid some of the stuff
  // that nsDocShell does (need to refactor).
  
  // OK, time to make an editor on this document
  nsCOMPtr<nsIDOMWindow> domWindow;
  aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
  
  // Set the error state -- we will create an editor 
  // anyway and load empty doc later
  if (aIsToBeMadeEditable) {
    if (aStatus == NS_ERROR_FILE_NOT_FOUND)
      mEditorStatus = eEditorErrorFileNotFound;
  }

  nsIDocShell *docShell = GetDocShellFromWindow(domWindow);
  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);       // better error handling?

  // cancel refresh from meta tags
  // we need to make sure that all pages in editor (whether editable or not)
  // can't refresh contents being edited
  nsCOMPtr<nsIRefreshURI> refreshURI = do_QueryInterface(docShell);
  if (refreshURI)
    refreshURI->CancelRefreshURITimers();

  nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(docShell);

  nsresult rv = NS_OK;

  // did someone set the flag to make this shell editable?
  if (aIsToBeMadeEditable && mCanCreateEditor && editorDocShell)
  {
    bool    makeEditable;
    editorDocShell->GetEditable(&makeEditable);
  
    if (makeEditable)
    {
      // To keep pre Gecko 1.9 behavior, setup editor always when
      // mMakeWholeDocumentEditable.
      bool needsSetup = false;
      if (mMakeWholeDocumentEditable) {
        needsSetup = true;
      } else {
        // do we already have an editor here?
        nsCOMPtr<nsIEditor> editor;
        rv = editorDocShell->GetEditor(getter_AddRefs(editor));
        NS_ENSURE_SUCCESS(rv, rv);

        needsSetup = !editor;
      }

      if (needsSetup)
      {
        mCanCreateEditor = false;
        rv = SetupEditorOnWindow(domWindow);
        if (NS_FAILED(rv))
        {
          // If we had an error, setup timer to load a blank page later
          if (mLoadBlankDocTimer)
          {
            // Must cancel previous timer?
            mLoadBlankDocTimer->Cancel();
            mLoadBlankDocTimer = NULL;
          }
  
          mLoadBlankDocTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
          NS_ENSURE_SUCCESS(rv, rv);

          mEditorStatus = eEditorCreationInProgress;
          mLoadBlankDocTimer->InitWithFuncCallback(
                                          nsEditingSession::TimerCallback,
                                          static_cast<void*> (mDocShell.get()),
                                          10, nsITimer::TYPE_ONE_SHOT);
        }
      }
    }
  }
  return rv;
}
/*---------------------------------------------------------------------------

  SetupEditorOnWindow

  nsIEditor setupEditorOnWindow (in nsIDOMWindow aWindow);
----------------------------------------------------------------------------*/
NS_IMETHODIMP
nsEditingSession::SetupEditorOnWindow(nsIDOMWindow *aWindow)
{
  mDoneSetup = true;

  nsresult rv;

  //MIME CHECKING
  //must get the content type
  // Note: the doc gets this from the network channel during StartPageLoad,
  //    so we don't have to get it from there ourselves
  nsCOMPtr<nsIDOMDocument> doc;
  nsCAutoString mimeCType;

  //then lets check the mime type
  if (NS_SUCCEEDED(aWindow->GetDocument(getter_AddRefs(doc))) && doc)
  {
    nsAutoString mimeType;
    if (NS_SUCCEEDED(doc->GetContentType(mimeType)))
      AppendUTF16toUTF8(mimeType, mimeCType);

    if (IsSupportedTextType(mimeCType.get()))
    {
      mEditorType.AssignLiteral("text");
      mimeCType = "text/plain";
    }
    else if (!mimeCType.EqualsLiteral("text/html") &&
             !mimeCType.EqualsLiteral("application/xhtml+xml"))
    {
      // Neither an acceptable text or html type.
      mEditorStatus = eEditorErrorCantEditMimeType;

      // Turn editor into HTML -- we will load blank page later
      mEditorType.AssignLiteral("html");
      mimeCType.AssignLiteral("text/html");
    }

    // Flush out frame construction to make sure that the subframe's
    // presshell is set up if it needs to be.
    nsCOMPtr<nsIDocument> document = do_QueryInterface(doc);
    if (document) {
      document->FlushPendingNotifications(Flush_Frames);
      if (mMakeWholeDocumentEditable) {
        document->SetEditableFlag(true);
        nsCOMPtr<nsIHTMLDocument> htmlDocument = do_QueryInterface(document);
        if (htmlDocument) {
          // Enable usage of the execCommand API
          htmlDocument->SetEditingState(nsIHTMLDocument::eDesignMode);
        }
      }
    }
  }
  bool needHTMLController = false;

  const char *classString = "@mozilla.org/editor/htmleditor;1";
  if (mEditorType.EqualsLiteral("textmail"))
  {
    mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask | 
                   nsIPlaintextEditor::eEditorEnableWrapHackMask | 
                   nsIPlaintextEditor::eEditorMailMask;
  }
  else if (mEditorType.EqualsLiteral("text"))
  {
    mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask | 
                   nsIPlaintextEditor::eEditorEnableWrapHackMask;
  }
  else if (mEditorType.EqualsLiteral("htmlmail"))
  {
    if (mimeCType.EqualsLiteral("text/html"))
    {
      needHTMLController = true;
      mEditorFlags = nsIPlaintextEditor::eEditorMailMask;
    }
    else //set the flags back to textplain.
      mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask | 
                     nsIPlaintextEditor::eEditorEnableWrapHackMask;
  }
  else // Defaulted to html
  {
    needHTMLController = true;
  }

  if (mInteractive) {
    mEditorFlags |= nsIPlaintextEditor::eEditorAllowInteraction;
  }

  // make the UI state maintainer
  mStateMaintainer = new nsComposerCommandsUpdater();

  // now init the state maintainer
  // This allows notification of error state
  //  even if we don't create an editor
  rv = mStateMaintainer->Init(aWindow);
  NS_ENSURE_SUCCESS(rv, rv);

  if (mEditorStatus != eEditorCreationInProgress)
  {
    mStateMaintainer->NotifyDocumentCreated();
    return NS_ERROR_FAILURE;
  }

  // Create editor and do other things 
  //  only if we haven't found some error above,
  nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);  

  if (!mInteractive) {
    // Disable animation of images in this document:
    nsCOMPtr<nsIDOMWindowUtils> utils(do_GetInterface(aWindow));
    NS_ENSURE_TRUE(utils, NS_ERROR_FAILURE);

    rv = utils->GetImageAnimationMode(&mImageAnimationMode);
    NS_ENSURE_SUCCESS(rv, rv);
    utils->SetImageAnimationMode(imgIContainer::kDontAnimMode);
  }

  // create and set editor
  nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(docShell, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  // Try to reuse an existing editor
  nsCOMPtr<nsIEditor> editor = do_QueryReferent(mExistingEditor);
  if (editor) {
    editor->PreDestroy(false);
  } else {
    editor = do_CreateInstance(classString, &rv);
    NS_ENSURE_SUCCESS(rv, rv);
    mExistingEditor = do_GetWeakReference(editor);
  }
  // set the editor on the docShell. The docShell now owns it.
  rv = editorDocShell->SetEditor(editor);
  NS_ENSURE_SUCCESS(rv, rv);

  // setup the HTML editor command controller
  if (needHTMLController)
  {
    // The third controller takes an nsIEditor as the context
    rv = SetupEditorCommandController("@mozilla.org/editor/htmleditorcontroller;1",
                                      aWindow, editor,
                                      &mHTMLCommandControllerId);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // Set mimetype on editor
  rv = editor->SetContentsMIMEType(mimeCType.get());
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIContentViewer> contentViewer;
  rv = docShell->GetContentViewer(getter_AddRefs(contentViewer));
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_TRUE(contentViewer, NS_ERROR_FAILURE);

  nsCOMPtr<nsIDOMDocument> domDoc;  
  rv = contentViewer->GetDOMDocument(getter_AddRefs(domDoc));
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_TRUE(domDoc, NS_ERROR_FAILURE);

  // Set up as a doc state listener
  // Important! We must have this to broadcast the "obs_documentCreated" message
  rv = editor->AddDocumentStateListener(mStateMaintainer);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = editor->Init(domDoc, nullptr /* root content */,
                    nullptr, mEditorFlags);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsISelection> selection;
  editor->GetSelection(getter_AddRefs(selection));
  nsCOMPtr<nsISelectionPrivate> selPriv = do_QueryInterface(selection);
  NS_ENSURE_TRUE(selPriv, NS_ERROR_FAILURE);

  rv = selPriv->AddSelectionListener(mStateMaintainer);
  NS_ENSURE_SUCCESS(rv, rv);

  // and as a transaction listener
  nsCOMPtr<nsITransactionManager> txnMgr;
  editor->GetTransactionManager(getter_AddRefs(txnMgr));
  if (txnMgr)
    txnMgr->AddListener(mStateMaintainer);

  // Set context on all controllers to be the editor
  rv = SetEditorOnControllers(aWindow, editor);
  NS_ENSURE_SUCCESS(rv, rv);

  // Everything went fine!
  mEditorStatus = eEditorOK;

  // This will trigger documentCreation notification
  return editor->PostCreate();
}
nsresult
nsEditingSession::ReattachToWindow(nsIDOMWindow* aWindow)
{
  NS_ENSURE_TRUE(mDoneSetup, NS_OK);

  NS_ASSERTION(mStateMaintainer, "mStateMaintainer should exist.");

  // Imitate nsEditorDocShell::MakeEditable() to reattach the
  // old editor ot the window.
  nsresult rv;

  nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
  mDocShell = do_GetWeakReference(docShell);

  // Disable plugins.
  if (!mInteractive)
  {
    rv = DisableJSAndPlugins(aWindow);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // Tells embedder that startup is in progress.
  mEditorStatus = eEditorCreationInProgress;

  // Adds back web progress listener.
  rv = PrepareForEditing(aWindow);
  NS_ENSURE_SUCCESS(rv, rv);

  // Setup the command controllers again.
  rv = SetupEditorCommandController("@mozilla.org/editor/editingcontroller;1",
                                    aWindow,
                                    static_cast<nsIEditingSession*>(this),
                                    &mBaseCommandControllerId);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = SetupEditorCommandController("@mozilla.org/editor/editordocstatecontroller;1",
                                    aWindow,
                                    static_cast<nsIEditingSession*>(this),
                                    &mDocStateControllerId);
  NS_ENSURE_SUCCESS(rv, rv);

  if (mStateMaintainer)
    mStateMaintainer->Init(aWindow);

  // Get editor
  nsCOMPtr<nsIEditor> editor;
  rv = GetEditorForWindow(aWindow, getter_AddRefs(editor));
  NS_ENSURE_TRUE(editor, NS_ERROR_FAILURE);

  if (!mInteractive)
  {
    // Disable animation of images in this document:
    nsCOMPtr<nsIDOMWindowUtils> utils(do_GetInterface(aWindow));
    NS_ENSURE_TRUE(utils, NS_ERROR_FAILURE);

    rv = utils->GetImageAnimationMode(&mImageAnimationMode);
    NS_ENSURE_SUCCESS(rv, rv);
    utils->SetImageAnimationMode(imgIContainer::kDontAnimMode);
  }

  // The third controller takes an nsIEditor as the context
  rv = SetupEditorCommandController("@mozilla.org/editor/htmleditorcontroller;1",
                                    aWindow, editor,
                                    &mHTMLCommandControllerId);
  NS_ENSURE_SUCCESS(rv, rv);

  // Set context on all controllers to be the editor
  rv = SetEditorOnControllers(aWindow, editor);
  NS_ENSURE_SUCCESS(rv, rv);

#ifdef DEBUG
  {
    bool isEditable;
    rv = WindowIsEditable(aWindow, &isEditable);
    NS_ENSURE_SUCCESS(rv, rv);
    NS_ASSERTION(isEditable, "Window is not editable after reattaching editor.");
  }
#endif // DEBUG

  return NS_OK;
}
NS_IMETHODIMP
nsEditingSession::MakeWindowEditable(nsIDOMWindow *aWindow,
                                     const char *aEditorType, 
                                     bool aDoAfterUriLoad,
                                     bool aMakeWholeDocumentEditable,
                                     bool aInteractive)
{
  mEditorType.Truncate();
  mEditorFlags = 0;

  // disable plugins
  nsIDocShell *docShell = GetDocShellFromWindow(aWindow);
  NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);

  mDocShell = do_GetWeakReference(docShell);
  mInteractive = aInteractive;
  mMakeWholeDocumentEditable = aMakeWholeDocumentEditable;

  nsresult rv;
  if (!mInteractive) {
    rv = DisableJSAndPlugins(aWindow);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // Always remove existing editor
  TearDownEditorOnWindow(aWindow);
  
  // Tells embedder that startup is in progress
  mEditorStatus = eEditorCreationInProgress;

  //temporary to set editor type here. we will need different classes soon.
  if (!aEditorType)
    aEditorType = DEFAULT_EDITOR_TYPE;
  mEditorType = aEditorType;

  // if all this does is setup listeners and I don't need listeners, 
  // can't this step be ignored?? (based on aDoAfterURILoad)
  rv = PrepareForEditing(aWindow);
  NS_ENSURE_SUCCESS(rv, rv);  
  
  nsCOMPtr<nsIEditorDocShell> editorDocShell;
  rv = GetEditorDocShellFromWindow(aWindow, getter_AddRefs(editorDocShell));
  NS_ENSURE_SUCCESS(rv, rv);  
  
  // set the flag on the docShell to say that it's editable
  rv = editorDocShell->MakeEditable(aDoAfterUriLoad);
  NS_ENSURE_SUCCESS(rv, rv);  

  // Setup commands common to plaintext and html editors,
  //  including the document creation observers
  // the first is an editing controller
  rv = SetupEditorCommandController("@mozilla.org/editor/editingcontroller;1",
                                    aWindow,
                                    static_cast<nsIEditingSession*>(this),
                                    &mBaseCommandControllerId);
  NS_ENSURE_SUCCESS(rv, rv);

  // The second is a controller to monitor doc state,
  // such as creation and "dirty flag"
  rv = SetupEditorCommandController("@mozilla.org/editor/editordocstatecontroller;1",
                                    aWindow,
                                    static_cast<nsIEditingSession*>(this),
                                    &mDocStateControllerId);
  NS_ENSURE_SUCCESS(rv, rv);

  // aDoAfterUriLoad can be false only when making an existing window editable
  if (!aDoAfterUriLoad)
  {
    rv = SetupEditorOnWindow(aWindow);

    // mEditorStatus is set to the error reason
    // Since this is used only when editing an existing page,
    //  it IS ok to destroy current editor
    if (NS_FAILED(rv))
      TearDownEditorOnWindow(aWindow);
  }
  return rv;
}