Bug 1638136 [wpt PR 23617] - Clipboard API Tests: Move permissions tests to WPT....
[gecko.git] / editor / composer / nsEditingSession.cpp
blob7c487e607659d34e93f6de26350aef9946359622
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 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include <string.h> // for nullptr, strcmp
9 #include "imgIContainer.h" // for imgIContainer, etc
10 #include "mozilla/ComposerCommandsUpdater.h" // for ComposerCommandsUpdater
11 #include "mozilla/FlushType.h" // for FlushType::Frames
12 #include "mozilla/HTMLEditor.h" // for HTMLEditor
13 #include "mozilla/mozalloc.h" // for operator new
14 #include "mozilla/PresShell.h" // for PresShell
15 #include "nsAString.h"
16 #include "nsBaseCommandController.h" // for nsBaseCommandController
17 #include "nsCommandManager.h" // for nsCommandManager
18 #include "nsComponentManagerUtils.h" // for do_CreateInstance
19 #include "nsContentUtils.h"
20 #include "nsDebug.h" // for NS_ENSURE_SUCCESS, etc
21 #include "nsEditingSession.h"
22 #include "nsError.h" // for NS_ERROR_FAILURE, NS_OK, etc
23 #include "nsIChannel.h" // for nsIChannel
24 #include "nsIContentViewer.h" // for nsIContentViewer
25 #include "nsIControllers.h" // for nsIControllers
26 #include "nsID.h" // for NS_GET_IID, etc
27 #include "nsHTMLDocument.h" // for nsHTMLDocument
28 #include "nsIDocShell.h" // for nsIDocShell
29 #include "mozilla/dom/Document.h" // for Document
30 #include "nsIEditor.h" // for nsIEditor
31 #include "nsIInterfaceRequestorUtils.h" // for do_GetInterface
32 #include "nsIRefreshURI.h" // for nsIRefreshURI
33 #include "nsIRequest.h" // for nsIRequest
34 #include "nsITimer.h" // for nsITimer, etc
35 #include "nsIWeakReference.h" // for nsISupportsWeakReference, etc
36 #include "nsIWebNavigation.h" // for nsIWebNavigation
37 #include "nsIWebProgress.h" // for nsIWebProgress, etc
38 #include "nsLiteralString.h" // for NS_LITERAL_STRING
39 #include "nsPIDOMWindow.h" // for nsPIDOMWindow
40 #include "nsPresContext.h" // for nsPresContext
41 #include "nsReadableUtils.h" // for AppendUTF16toUTF8
42 #include "nsStringFwd.h" // for nsString
43 #include "mozilla/dom/Selection.h" // for AutoHideSelectionChanges, etc
44 #include "nsFrameSelection.h" // for nsFrameSelection
45 #include "nsBaseCommandController.h" // for nsBaseCommandController
46 #include "mozilla/dom/LoadURIOptionsBinding.h"
48 class nsISupports;
49 class nsIURI;
51 using namespace mozilla;
52 using namespace mozilla::dom;
54 /*---------------------------------------------------------------------------
56 nsEditingSession
58 ----------------------------------------------------------------------------*/
59 nsEditingSession::nsEditingSession()
60 : mDoneSetup(false),
61 mCanCreateEditor(false),
62 mInteractive(false),
63 mMakeWholeDocumentEditable(true),
64 mDisabledJSAndPlugins(false),
65 mScriptsEnabled(true),
66 mPluginsEnabled(true),
67 mProgressListenerRegistered(false),
68 mImageAnimationMode(0),
69 mEditorFlags(0),
70 mEditorStatus(eEditorOK),
71 mBaseCommandControllerId(0),
72 mDocStateControllerId(0),
73 mHTMLCommandControllerId(0) {}
75 /*---------------------------------------------------------------------------
77 ~nsEditingSession
79 ----------------------------------------------------------------------------*/
80 nsEditingSession::~nsEditingSession() {
81 // Must cancel previous timer?
82 if (mLoadBlankDocTimer) mLoadBlankDocTimer->Cancel();
85 NS_IMPL_ISUPPORTS(nsEditingSession, nsIEditingSession, nsIWebProgressListener,
86 nsISupportsWeakReference)
88 /*---------------------------------------------------------------------------
90 MakeWindowEditable
92 aEditorType string, "html" "htmlsimple" "text" "textsimple"
93 void makeWindowEditable(in nsIDOMWindow aWindow, in string aEditorType,
94 in boolean aDoAfterUriLoad,
95 in boolean aMakeWholeDocumentEditable,
96 in boolean aInteractive);
97 ----------------------------------------------------------------------------*/
98 #define DEFAULT_EDITOR_TYPE "html"
100 NS_IMETHODIMP
101 nsEditingSession::MakeWindowEditable(mozIDOMWindowProxy* aWindow,
102 const char* aEditorType,
103 bool aDoAfterUriLoad,
104 bool aMakeWholeDocumentEditable,
105 bool aInteractive) {
106 mEditorType.Truncate();
107 mEditorFlags = 0;
109 NS_ENSURE_TRUE(aWindow, NS_ERROR_FAILURE);
110 auto* window = nsPIDOMWindowOuter::From(aWindow);
112 // disable plugins
113 nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
114 NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
115 mDocShell = do_GetWeakReference(docShell);
117 mInteractive = aInteractive;
118 mMakeWholeDocumentEditable = aMakeWholeDocumentEditable;
120 nsresult rv;
121 if (!mInteractive) {
122 rv = DisableJSAndPlugins(*docShell);
123 NS_ENSURE_SUCCESS(rv, rv);
126 // Always remove existing editor
127 TearDownEditorOnWindow(aWindow);
129 // Tells embedder that startup is in progress
130 mEditorStatus = eEditorCreationInProgress;
132 // temporary to set editor type here. we will need different classes soon.
133 if (!aEditorType) aEditorType = DEFAULT_EDITOR_TYPE;
134 mEditorType = aEditorType;
136 // if all this does is setup listeners and I don't need listeners,
137 // can't this step be ignored?? (based on aDoAfterURILoad)
138 rv = PrepareForEditing(window);
139 NS_ENSURE_SUCCESS(rv, rv);
141 // set the flag on the docShell to say that it's editable
142 rv = docShell->MakeEditable(aDoAfterUriLoad);
143 NS_ENSURE_SUCCESS(rv, rv);
145 // Setup commands common to plaintext and html editors,
146 // including the document creation observers
147 // the first is an editing controller
148 rv = SetupEditorCommandController(
149 nsBaseCommandController::CreateEditingController, aWindow,
150 static_cast<nsIEditingSession*>(this), &mBaseCommandControllerId);
151 NS_ENSURE_SUCCESS(rv, rv);
153 // The second is a controller to monitor doc state,
154 // such as creation and "dirty flag"
155 rv = SetupEditorCommandController(
156 nsBaseCommandController::CreateHTMLEditorDocStateController, aWindow,
157 static_cast<nsIEditingSession*>(this), &mDocStateControllerId);
158 NS_ENSURE_SUCCESS(rv, rv);
160 // aDoAfterUriLoad can be false only when making an existing window editable
161 if (!aDoAfterUriLoad) {
162 rv = SetupEditorOnWindow(MOZ_KnownLive(*window));
164 // mEditorStatus is set to the error reason
165 // Since this is used only when editing an existing page,
166 // it IS ok to destroy current editor
167 if (NS_FAILED(rv)) {
168 TearDownEditorOnWindow(aWindow);
171 return rv;
174 nsresult nsEditingSession::DisableJSAndPlugins(nsIDocShell& aDocShell) {
175 bool tmp;
176 nsresult rv = aDocShell.GetAllowJavascript(&tmp);
177 NS_ENSURE_SUCCESS(rv, rv);
179 mScriptsEnabled = tmp;
181 rv = aDocShell.SetAllowJavascript(false);
182 NS_ENSURE_SUCCESS(rv, rv);
184 // Disable plugins in this document:
185 mPluginsEnabled = aDocShell.PluginsAllowedInCurrentDoc();
187 aDocShell.GetBrowsingContext()->SetAllowPlugins(false);
189 mDisabledJSAndPlugins = true;
191 return NS_OK;
194 nsresult nsEditingSession::RestoreJSAndPlugins(nsPIDOMWindowOuter* aWindow) {
195 if (!mDisabledJSAndPlugins) {
196 return NS_OK;
199 mDisabledJSAndPlugins = false;
201 if (NS_WARN_IF(!aWindow)) {
202 // DetachFromWindow may call this method with nullptr.
203 return NS_ERROR_FAILURE;
205 nsIDocShell* docShell = aWindow->GetDocShell();
206 NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
208 nsresult rv = docShell->SetAllowJavascript(mScriptsEnabled);
209 NS_ENSURE_SUCCESS(rv, rv);
211 // Disable plugins in this document:
212 auto* browsingContext = aWindow->GetBrowsingContext();
213 NS_ENSURE_TRUE(browsingContext, NS_ERROR_FAILURE);
214 browsingContext->SetAllowPlugins(mPluginsEnabled);
216 return NS_OK;
219 /*---------------------------------------------------------------------------
221 WindowIsEditable
223 boolean windowIsEditable (in nsIDOMWindow aWindow);
224 ----------------------------------------------------------------------------*/
225 NS_IMETHODIMP
226 nsEditingSession::WindowIsEditable(mozIDOMWindowProxy* aWindow,
227 bool* outIsEditable) {
228 NS_ENSURE_STATE(aWindow);
229 nsCOMPtr<nsIDocShell> docShell =
230 nsPIDOMWindowOuter::From(aWindow)->GetDocShell();
231 NS_ENSURE_STATE(docShell);
233 return docShell->GetEditable(outIsEditable);
236 // These are MIME types that are automatically parsed as "text/plain"
237 // and thus we can edit them as plaintext
238 // Note: in older versions, we attempted to convert the mimetype of
239 // the network channel for these and "text/xml" to "text/plain",
240 // but further investigation reveals that strategy doesn't work
241 const char* const gSupportedTextTypes[] = {
242 "text/plain",
243 "text/css",
244 "text/rdf",
245 "text/xsl",
246 "text/javascript", // obsolete type
247 "text/ecmascript", // obsolete type
248 "application/javascript",
249 "application/ecmascript",
250 "application/x-javascript", // obsolete type
251 "text/xul", // obsolete type
252 nullptr // IMPORTANT! Null must be at end
255 bool IsSupportedTextType(const char* aMIMEType) {
256 NS_ENSURE_TRUE(aMIMEType, false);
258 for (size_t i = 0; gSupportedTextTypes[i]; ++i) {
259 if (!strcmp(gSupportedTextTypes[i], aMIMEType)) {
260 return true;
264 return false;
267 nsresult nsEditingSession::SetupEditorOnWindow(nsPIDOMWindowOuter& aWindow) {
268 mDoneSetup = true;
270 // MIME CHECKING
271 // must get the content type
272 // Note: the doc gets this from the network channel during StartPageLoad,
273 // so we don't have to get it from there ourselves
274 nsAutoCString mimeCType;
276 // then lets check the mime type
277 if (RefPtr<Document> doc = aWindow.GetDoc()) {
278 nsAutoString mimeType;
279 doc->GetContentType(mimeType);
280 AppendUTF16toUTF8(mimeType, mimeCType);
282 if (IsSupportedTextType(mimeCType.get())) {
283 mEditorType.AssignLiteral("text");
284 mimeCType = "text/plain";
285 } else if (!mimeCType.EqualsLiteral("text/html") &&
286 !mimeCType.EqualsLiteral("application/xhtml+xml")) {
287 // Neither an acceptable text or html type.
288 mEditorStatus = eEditorErrorCantEditMimeType;
290 // Turn editor into HTML -- we will load blank page later
291 mEditorType.AssignLiteral("html");
292 mimeCType.AssignLiteral("text/html");
295 // Flush out frame construction to make sure that the subframe's
296 // presshell is set up if it needs to be.
297 doc->FlushPendingNotifications(mozilla::FlushType::Frames);
298 if (mMakeWholeDocumentEditable) {
299 doc->SetEditableFlag(true);
300 // Enable usage of the execCommand API
301 doc->SetEditingState(Document::EditingState::eDesignMode);
304 bool needHTMLController = false;
306 if (mEditorType.EqualsLiteral("textmail")) {
307 mEditorFlags = nsIEditor::eEditorPlaintextMask |
308 nsIEditor::eEditorEnableWrapHackMask |
309 nsIEditor::eEditorMailMask;
310 } else if (mEditorType.EqualsLiteral("text")) {
311 mEditorFlags =
312 nsIEditor::eEditorPlaintextMask | nsIEditor::eEditorEnableWrapHackMask;
313 } else if (mEditorType.EqualsLiteral("htmlmail")) {
314 if (mimeCType.EqualsLiteral("text/html")) {
315 needHTMLController = true;
316 mEditorFlags = nsIEditor::eEditorMailMask;
317 } else {
318 // Set the flags back to textplain.
319 mEditorFlags = nsIEditor::eEditorPlaintextMask |
320 nsIEditor::eEditorEnableWrapHackMask;
322 } else {
323 // Defaulted to html
324 needHTMLController = true;
327 if (mInteractive) {
328 mEditorFlags |= nsIEditor::eEditorAllowInteraction;
331 // make the UI state maintainer
332 mComposerCommandsUpdater = new ComposerCommandsUpdater();
334 // now init the state maintainer
335 // This allows notification of error state
336 // even if we don't create an editor
337 mComposerCommandsUpdater->Init(aWindow);
339 if (mEditorStatus != eEditorCreationInProgress) {
340 RefPtr<ComposerCommandsUpdater> updater = mComposerCommandsUpdater;
341 updater->OnHTMLEditorCreated();
343 // At this point we have made a final decision that we don't support
344 // editing the current document. This is an internal failure state, but
345 // we return NS_OK to avoid throwing an exception from the designMode
346 // setter for web compatibility. The document editing APIs will tell the
347 // developer if editing has been disabled because we're in a document type
348 // that doesn't support editing.
349 return NS_OK;
352 // Create editor and do other things
353 // only if we haven't found some error above,
354 nsCOMPtr<nsIDocShell> docShell = aWindow.GetDocShell();
355 NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
356 RefPtr<PresShell> presShell = docShell->GetPresShell();
357 if (NS_WARN_IF(!presShell)) {
358 return NS_ERROR_FAILURE;
361 if (!mInteractive) {
362 // Disable animation of images in this document:
363 nsPresContext* presContext = presShell->GetPresContext();
364 NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
366 mImageAnimationMode = presContext->ImageAnimationMode();
367 presContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
370 // Hide selection changes during initialization, in order to hide this
371 // from web pages.
372 RefPtr<nsFrameSelection> fs = presShell->FrameSelection();
373 NS_ENSURE_TRUE(fs, NS_ERROR_FAILURE);
374 AutoHideSelectionChanges hideSelectionChanges(fs);
376 // create and set editor
377 // Try to reuse an existing editor
378 nsCOMPtr<nsIEditor> editor = do_QueryReferent(mExistingEditor);
379 RefPtr<HTMLEditor> htmlEditor = editor ? editor->AsHTMLEditor() : nullptr;
380 MOZ_ASSERT(!editor || htmlEditor);
381 if (htmlEditor) {
382 htmlEditor->PreDestroy(false);
383 } else {
384 htmlEditor = new HTMLEditor();
385 mExistingEditor =
386 do_GetWeakReference(static_cast<nsIEditor*>(htmlEditor.get()));
388 // set the editor on the docShell. The docShell now owns it.
389 nsresult rv = docShell->SetHTMLEditor(htmlEditor);
390 NS_ENSURE_SUCCESS(rv, rv);
392 // setup the HTML editor command controller
393 if (needHTMLController) {
394 // The third controller takes an nsIEditor as the context
395 rv = SetupEditorCommandController(
396 nsBaseCommandController::CreateHTMLEditorController, &aWindow,
397 static_cast<nsIEditor*>(htmlEditor), &mHTMLCommandControllerId);
398 NS_ENSURE_SUCCESS(rv, rv);
401 // Set mimetype on editor
402 rv = htmlEditor->SetContentsMIMEType(mimeCType.get());
403 NS_ENSURE_SUCCESS(rv, rv);
405 nsCOMPtr<nsIContentViewer> contentViewer;
406 rv = docShell->GetContentViewer(getter_AddRefs(contentViewer));
407 NS_ENSURE_SUCCESS(rv, rv);
408 NS_ENSURE_TRUE(contentViewer, NS_ERROR_FAILURE);
410 RefPtr<Document> doc = contentViewer->GetDocument();
411 if (NS_WARN_IF(!doc)) {
412 return NS_ERROR_FAILURE;
415 // Set up as a doc state listener
416 // Important! We must have this to broadcast the "obs_documentCreated" message
417 htmlEditor->SetComposerCommandsUpdater(mComposerCommandsUpdater);
419 rv = htmlEditor->Init(*doc, nullptr /* root content */, nullptr, mEditorFlags,
420 EmptyString());
421 NS_ENSURE_SUCCESS(rv, rv);
423 RefPtr<Selection> selection = htmlEditor->GetSelection();
424 if (NS_WARN_IF(!selection)) {
425 return NS_ERROR_FAILURE;
428 // and as a transaction listener
429 MOZ_ASSERT(mComposerCommandsUpdater);
430 DebugOnly<bool> addedTransactionListener =
431 htmlEditor->AddTransactionListener(*mComposerCommandsUpdater);
432 NS_WARNING_ASSERTION(addedTransactionListener,
433 "Failed to add transaction listener to the editor");
435 // Set context on all controllers to be the editor
436 rv = SetEditorOnControllers(aWindow, htmlEditor);
437 NS_ENSURE_SUCCESS(rv, rv);
439 // Everything went fine!
440 mEditorStatus = eEditorOK;
442 // This will trigger documentCreation notification
443 return htmlEditor->PostCreate();
446 // Removes all listeners and controllers from aWindow and aEditor.
447 void nsEditingSession::RemoveListenersAndControllers(
448 nsPIDOMWindowOuter* aWindow, HTMLEditor* aHTMLEditor) {
449 if (!mComposerCommandsUpdater || !aHTMLEditor) {
450 return;
453 // Remove all the listeners
454 aHTMLEditor->SetComposerCommandsUpdater(nullptr);
455 DebugOnly<bool> removedTransactionListener =
456 aHTMLEditor->RemoveTransactionListener(*mComposerCommandsUpdater);
457 NS_WARNING_ASSERTION(removedTransactionListener,
458 "Failed to remove transaction listener from the editor");
460 // Remove editor controllers from the window now that we're not
461 // editing in that window any more.
462 RemoveEditorControllers(aWindow);
465 /*---------------------------------------------------------------------------
467 TearDownEditorOnWindow
469 void tearDownEditorOnWindow (in nsIDOMWindow aWindow);
470 ----------------------------------------------------------------------------*/
471 NS_IMETHODIMP
472 nsEditingSession::TearDownEditorOnWindow(mozIDOMWindowProxy* aWindow) {
473 if (!mDoneSetup) {
474 return NS_OK;
477 NS_ENSURE_TRUE(aWindow, NS_ERROR_NULL_POINTER);
479 // Kill any existing reload timer
480 if (mLoadBlankDocTimer) {
481 mLoadBlankDocTimer->Cancel();
482 mLoadBlankDocTimer = nullptr;
485 mDoneSetup = false;
487 // Check if we're turning off editing (from contentEditable or designMode).
488 auto* window = nsPIDOMWindowOuter::From(aWindow);
490 RefPtr<Document> doc = window->GetDoc();
491 bool stopEditing = doc && doc->IsEditingOn();
492 if (stopEditing) {
493 RemoveWebProgressListener(window);
496 nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
497 NS_ENSURE_STATE(docShell);
499 RefPtr<HTMLEditor> htmlEditor = docShell->GetHTMLEditor();
500 if (stopEditing) {
501 doc->TearingDownEditor();
504 if (mComposerCommandsUpdater && htmlEditor) {
505 // Null out the editor on the controllers first to prevent their weak
506 // references from pointing to a destroyed editor.
507 SetEditorOnControllers(*window, nullptr);
510 // Null out the editor on the docShell to trigger PreDestroy which
511 // needs to happen before document state listeners are removed below.
512 docShell->SetEditor(nullptr);
514 RemoveListenersAndControllers(window, htmlEditor);
516 if (stopEditing) {
517 // Make things the way they were before we started editing.
518 RestoreJSAndPlugins(window);
519 RestoreAnimationMode(window);
521 if (mMakeWholeDocumentEditable) {
522 doc->SetEditableFlag(false);
523 doc->SetEditingState(Document::EditingState::eOff);
527 return NS_OK;
530 /*---------------------------------------------------------------------------
532 GetEditorForFrame
534 nsIEditor getEditorForFrame (in nsIDOMWindow aWindow);
535 ----------------------------------------------------------------------------*/
536 NS_IMETHODIMP
537 nsEditingSession::GetEditorForWindow(mozIDOMWindowProxy* aWindow,
538 nsIEditor** outEditor) {
539 if (NS_WARN_IF(!aWindow)) {
540 return NS_ERROR_INVALID_ARG;
542 nsCOMPtr<nsIEditor> editor = GetHTMLEditorForWindow(aWindow);
543 editor.forget(outEditor);
544 return NS_OK;
547 /*---------------------------------------------------------------------------
549 OnStateChange
551 ----------------------------------------------------------------------------*/
552 NS_IMETHODIMP
553 nsEditingSession::OnStateChange(nsIWebProgress* aWebProgress,
554 nsIRequest* aRequest, uint32_t aStateFlags,
555 nsresult aStatus) {
556 #ifdef NOISY_DOC_LOADING
557 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
558 if (channel) {
559 nsAutoCString contentType;
560 channel->GetContentType(contentType);
561 if (!contentType.IsEmpty()) {
562 printf(" ++++++ MIMETYPE = %s\n", contentType.get());
565 #endif
568 // A Request has started...
570 if (aStateFlags & nsIWebProgressListener::STATE_START) {
571 #ifdef NOISY_DOC_LOADING
573 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
574 if (channel) {
575 nsCOMPtr<nsIURI> uri;
576 channel->GetURI(getter_AddRefs(uri));
577 if (uri) {
578 nsCString spec;
579 uri->GetSpec(spec);
580 printf(" **** STATE_START: CHANNEL URI=%s, flags=%x\n", spec.get(),
581 aStateFlags);
583 } else {
584 printf(" STATE_START: NO CHANNEL flags=%x\n", aStateFlags);
587 #endif
588 // Page level notification...
589 if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) {
590 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
591 StartPageLoad(channel);
592 #ifdef NOISY_DOC_LOADING
593 printf("STATE_START & STATE_IS_NETWORK flags=%x\n", aStateFlags);
594 #endif
597 // Document level notification...
598 if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT &&
599 !(aStateFlags & nsIWebProgressListener::STATE_RESTORING)) {
600 #ifdef NOISY_DOC_LOADING
601 printf("STATE_START & STATE_IS_DOCUMENT flags=%x\n", aStateFlags);
602 #endif
604 bool progressIsForTargetDocument =
605 IsProgressForTargetDocument(aWebProgress);
607 if (progressIsForTargetDocument) {
608 nsCOMPtr<mozIDOMWindowProxy> window;
609 aWebProgress->GetDOMWindow(getter_AddRefs(window));
611 auto* piWindow = nsPIDOMWindowOuter::From(window);
612 RefPtr<Document> doc = piWindow->GetDoc();
613 nsHTMLDocument* htmlDoc =
614 doc && doc->IsHTMLOrXHTML() ? doc->AsHTMLDocument() : nullptr;
615 if (htmlDoc && doc->IsWriting()) {
616 nsAutoString designMode;
617 htmlDoc->GetDesignMode(designMode);
619 if (designMode.EqualsLiteral("on")) {
620 // This notification is for data coming in through
621 // document.open/write/close(), ignore it.
623 return NS_OK;
627 mCanCreateEditor = true;
628 StartDocumentLoad(aWebProgress, progressIsForTargetDocument);
633 // A Request is being processed
635 else if (aStateFlags & nsIWebProgressListener::STATE_TRANSFERRING) {
636 if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) {
637 // document transfer started
641 // Got a redirection
643 else if (aStateFlags & nsIWebProgressListener::STATE_REDIRECTING) {
644 if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) {
645 // got a redirect
649 // A network or document Request has finished...
651 else if (aStateFlags & nsIWebProgressListener::STATE_STOP) {
652 #ifdef NOISY_DOC_LOADING
654 nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
655 if (channel) {
656 nsCOMPtr<nsIURI> uri;
657 channel->GetURI(getter_AddRefs(uri));
658 if (uri) {
659 nsCString spec;
660 uri->GetSpec(spec);
661 printf(" **** STATE_STOP: CHANNEL URI=%s, flags=%x\n", spec.get(),
662 aStateFlags);
664 } else {
665 printf(" STATE_STOP: NO CHANNEL flags=%x\n", aStateFlags);
668 #endif
670 // Document level notification...
671 if (aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) {
672 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
673 EndDocumentLoad(aWebProgress, channel, aStatus,
674 IsProgressForTargetDocument(aWebProgress));
675 #ifdef NOISY_DOC_LOADING
676 printf("STATE_STOP & STATE_IS_DOCUMENT flags=%x\n", aStateFlags);
677 #endif
680 // Page level notification...
681 if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) {
682 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
683 (void)EndPageLoad(aWebProgress, channel, aStatus);
684 #ifdef NOISY_DOC_LOADING
685 printf("STATE_STOP & STATE_IS_NETWORK flags=%x\n", aStateFlags);
686 #endif
690 return NS_OK;
693 /*---------------------------------------------------------------------------
695 OnProgressChange
697 ----------------------------------------------------------------------------*/
698 NS_IMETHODIMP
699 nsEditingSession::OnProgressChange(nsIWebProgress* aWebProgress,
700 nsIRequest* aRequest,
701 int32_t aCurSelfProgress,
702 int32_t aMaxSelfProgress,
703 int32_t aCurTotalProgress,
704 int32_t aMaxTotalProgress) {
705 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
706 return NS_OK;
709 /*---------------------------------------------------------------------------
711 OnLocationChange
713 ----------------------------------------------------------------------------*/
714 NS_IMETHODIMP
715 nsEditingSession::OnLocationChange(nsIWebProgress* aWebProgress,
716 nsIRequest* aRequest, nsIURI* aURI,
717 uint32_t aFlags) {
718 nsCOMPtr<mozIDOMWindowProxy> domWindow;
719 nsresult rv = aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
720 NS_ENSURE_SUCCESS(rv, rv);
722 auto* piWindow = nsPIDOMWindowOuter::From(domWindow);
724 RefPtr<Document> doc = piWindow->GetDoc();
725 NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
727 doc->SetDocumentURI(aURI);
729 // Notify the location-changed observer that
730 // the document URL has changed
731 nsIDocShell* docShell = piWindow->GetDocShell();
732 NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
734 RefPtr<nsCommandManager> commandManager = docShell->GetCommandManager();
735 commandManager->CommandStatusChanged("obs_documentLocationChanged");
736 return NS_OK;
739 /*---------------------------------------------------------------------------
741 OnStatusChange
743 ----------------------------------------------------------------------------*/
744 NS_IMETHODIMP
745 nsEditingSession::OnStatusChange(nsIWebProgress* aWebProgress,
746 nsIRequest* aRequest, nsresult aStatus,
747 const char16_t* aMessage) {
748 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
749 return NS_OK;
752 /*---------------------------------------------------------------------------
754 OnSecurityChange
756 ----------------------------------------------------------------------------*/
757 NS_IMETHODIMP
758 nsEditingSession::OnSecurityChange(nsIWebProgress* aWebProgress,
759 nsIRequest* aRequest, uint32_t aState) {
760 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
761 return NS_OK;
764 /*---------------------------------------------------------------------------
766 OnContentBlockingEvent
768 ----------------------------------------------------------------------------*/
769 NS_IMETHODIMP
770 nsEditingSession::OnContentBlockingEvent(nsIWebProgress* aWebProgress,
771 nsIRequest* aRequest,
772 uint32_t aEvent) {
773 MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)");
774 return NS_OK;
777 /*---------------------------------------------------------------------------
779 IsProgressForTargetDocument
781 Check that this notification is for our document.
782 ----------------------------------------------------------------------------*/
784 bool nsEditingSession::IsProgressForTargetDocument(
785 nsIWebProgress* aWebProgress) {
786 nsCOMPtr<nsIWebProgress> editedWebProgress = do_QueryReferent(mDocShell);
787 return editedWebProgress == aWebProgress;
790 /*---------------------------------------------------------------------------
792 GetEditorStatus
794 Called during GetCommandStateParams("obs_documentCreated"...)
795 to determine if editor was created and document
796 was loaded successfully
797 ----------------------------------------------------------------------------*/
798 NS_IMETHODIMP
799 nsEditingSession::GetEditorStatus(uint32_t* aStatus) {
800 NS_ENSURE_ARG_POINTER(aStatus);
801 *aStatus = mEditorStatus;
802 return NS_OK;
805 /*---------------------------------------------------------------------------
807 StartDocumentLoad
809 Called on start of load in a single frame
810 ----------------------------------------------------------------------------*/
811 nsresult nsEditingSession::StartDocumentLoad(nsIWebProgress* aWebProgress,
812 bool aIsToBeMadeEditable) {
813 #ifdef NOISY_DOC_LOADING
814 printf("======= StartDocumentLoad ========\n");
815 #endif
817 NS_ENSURE_ARG_POINTER(aWebProgress);
819 if (aIsToBeMadeEditable) {
820 mEditorStatus = eEditorCreationInProgress;
823 return NS_OK;
826 /*---------------------------------------------------------------------------
828 EndDocumentLoad
830 Called on end of load in a single frame
831 ----------------------------------------------------------------------------*/
832 nsresult nsEditingSession::EndDocumentLoad(nsIWebProgress* aWebProgress,
833 nsIChannel* aChannel,
834 nsresult aStatus,
835 bool aIsToBeMadeEditable) {
836 NS_ENSURE_ARG_POINTER(aWebProgress);
838 #ifdef NOISY_DOC_LOADING
839 printf("======= EndDocumentLoad ========\n");
840 printf("with status %d, ", aStatus);
841 nsCOMPtr<nsIURI> uri;
842 nsCString spec;
843 if (NS_SUCCEEDED(aChannel->GetURI(getter_AddRefs(uri)))) {
844 uri->GetSpec(spec);
845 printf(" uri %s\n", spec.get());
847 #endif
849 // We want to call the base class EndDocumentLoad,
850 // but avoid some of the stuff
851 // that nsDocShell does (need to refactor).
853 // OK, time to make an editor on this document
854 nsCOMPtr<mozIDOMWindowProxy> domWindow;
855 aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
856 NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
858 // Set the error state -- we will create an editor
859 // anyway and load empty doc later
860 if (aIsToBeMadeEditable && aStatus == NS_ERROR_FILE_NOT_FOUND) {
861 mEditorStatus = eEditorErrorFileNotFound;
864 auto* window = nsPIDOMWindowOuter::From(domWindow);
865 nsIDocShell* docShell = window->GetDocShell();
866 NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); // better error handling?
868 // cancel refresh from meta tags
869 // we need to make sure that all pages in editor (whether editable or not)
870 // can't refresh contents being edited
871 nsCOMPtr<nsIRefreshURI> refreshURI = do_QueryInterface(docShell);
872 if (refreshURI) {
873 refreshURI->CancelRefreshURITimers();
876 nsresult rv = NS_OK;
878 // did someone set the flag to make this shell editable?
879 if (aIsToBeMadeEditable && mCanCreateEditor) {
880 bool makeEditable;
881 docShell->GetEditable(&makeEditable);
883 if (makeEditable) {
884 // To keep pre Gecko 1.9 behavior, setup editor always when
885 // mMakeWholeDocumentEditable.
886 bool needsSetup = false;
887 if (mMakeWholeDocumentEditable) {
888 needsSetup = true;
889 } else {
890 // do we already have an editor here?
891 needsSetup = !docShell->GetHTMLEditor();
894 if (needsSetup) {
895 mCanCreateEditor = false;
896 rv = SetupEditorOnWindow(MOZ_KnownLive(*window));
897 if (NS_FAILED(rv)) {
898 // If we had an error, setup timer to load a blank page later
899 if (mLoadBlankDocTimer) {
900 // Must cancel previous timer?
901 mLoadBlankDocTimer->Cancel();
902 mLoadBlankDocTimer = nullptr;
905 rv = NS_NewTimerWithFuncCallback(getter_AddRefs(mLoadBlankDocTimer),
906 nsEditingSession::TimerCallback,
907 static_cast<void*>(mDocShell.get()),
908 10, nsITimer::TYPE_ONE_SHOT,
909 "nsEditingSession::EndDocumentLoad");
910 NS_ENSURE_SUCCESS(rv, rv);
912 mEditorStatus = eEditorCreationInProgress;
917 return rv;
920 void nsEditingSession::TimerCallback(nsITimer* aTimer, void* aClosure) {
921 nsCOMPtr<nsIDocShell> docShell =
922 do_QueryReferent(static_cast<nsIWeakReference*>(aClosure));
923 if (docShell) {
924 nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
925 if (webNav) {
926 LoadURIOptions loadURIOptions;
927 loadURIOptions.mTriggeringPrincipal =
928 nsContentUtils::GetSystemPrincipal();
929 webNav->LoadURI(NS_LITERAL_STRING("about:blank"), loadURIOptions);
934 /*---------------------------------------------------------------------------
936 StartPageLoad
938 Called on start load of the entire page (incl. subframes)
939 ----------------------------------------------------------------------------*/
940 nsresult nsEditingSession::StartPageLoad(nsIChannel* aChannel) {
941 #ifdef NOISY_DOC_LOADING
942 printf("======= StartPageLoad ========\n");
943 #endif
944 return NS_OK;
947 /*---------------------------------------------------------------------------
949 EndPageLoad
951 Called on end load of the entire page (incl. subframes)
952 ----------------------------------------------------------------------------*/
953 nsresult nsEditingSession::EndPageLoad(nsIWebProgress* aWebProgress,
954 nsIChannel* aChannel, nsresult aStatus) {
955 #ifdef NOISY_DOC_LOADING
956 printf("======= EndPageLoad ========\n");
957 printf(" with status %d, ", aStatus);
958 nsCOMPtr<nsIURI> uri;
959 nsCString spec;
960 if (NS_SUCCEEDED(aChannel->GetURI(getter_AddRefs(uri)))) {
961 uri->GetSpec(spec);
962 printf("uri %s\n", spec.get());
965 nsAutoCString contentType;
966 aChannel->GetContentType(contentType);
967 if (!contentType.IsEmpty()) {
968 printf(" flags = %d, status = %d, MIMETYPE = %s\n", mEditorFlags,
969 mEditorStatus, contentType.get());
971 #endif
973 // Set the error state -- we will create an editor anyway
974 // and load empty doc later
975 if (aStatus == NS_ERROR_FILE_NOT_FOUND) {
976 mEditorStatus = eEditorErrorFileNotFound;
979 nsCOMPtr<mozIDOMWindowProxy> domWindow;
980 aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
982 nsIDocShell* docShell =
983 domWindow ? nsPIDOMWindowOuter::From(domWindow)->GetDocShell() : nullptr;
984 NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
986 // cancel refresh from meta tags
987 // we need to make sure that all pages in editor (whether editable or not)
988 // can't refresh contents being edited
989 nsCOMPtr<nsIRefreshURI> refreshURI = do_QueryInterface(docShell);
990 if (refreshURI) {
991 refreshURI->CancelRefreshURITimers();
994 #if 0
995 // Shouldn't we do this when we want to edit sub-frames?
996 return MakeWindowEditable(domWindow, "html", false, mInteractive);
997 #else
998 return NS_OK;
999 #endif
1002 /*---------------------------------------------------------------------------
1004 PrepareForEditing
1006 Set up this editing session for one or more editors
1007 ----------------------------------------------------------------------------*/
1008 nsresult nsEditingSession::PrepareForEditing(nsPIDOMWindowOuter* aWindow) {
1009 if (mProgressListenerRegistered) {
1010 return NS_OK;
1013 nsIDocShell* docShell = aWindow ? aWindow->GetDocShell() : nullptr;
1015 // register callback
1016 nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
1017 NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE);
1019 nsresult rv = webProgress->AddProgressListener(
1020 this, (nsIWebProgress::NOTIFY_STATE_NETWORK |
1021 nsIWebProgress::NOTIFY_STATE_DOCUMENT |
1022 nsIWebProgress::NOTIFY_LOCATION));
1024 mProgressListenerRegistered = NS_SUCCEEDED(rv);
1026 return rv;
1029 /*---------------------------------------------------------------------------
1031 SetupEditorCommandController
1033 Create a command controller, append to controllers,
1034 get and return the controller ID, and set the context
1035 ----------------------------------------------------------------------------*/
1036 nsresult nsEditingSession::SetupEditorCommandController(
1037 nsEditingSession::ControllerCreatorFn aControllerCreatorFn,
1038 mozIDOMWindowProxy* aWindow, nsISupports* aContext,
1039 uint32_t* aControllerId) {
1040 NS_ENSURE_ARG_POINTER(aControllerCreatorFn);
1041 NS_ENSURE_ARG_POINTER(aWindow);
1042 NS_ENSURE_ARG_POINTER(aContext);
1043 NS_ENSURE_ARG_POINTER(aControllerId);
1045 auto* piWindow = nsPIDOMWindowOuter::From(aWindow);
1046 MOZ_ASSERT(piWindow);
1048 nsCOMPtr<nsIControllers> controllers;
1049 nsresult rv = piWindow->GetControllers(getter_AddRefs(controllers));
1050 NS_ENSURE_SUCCESS(rv, rv);
1052 // We only have to create each singleton controller once
1053 // We know this has happened once we have a controllerId value
1054 if (!*aControllerId) {
1055 RefPtr<nsBaseCommandController> commandController = aControllerCreatorFn();
1056 NS_ENSURE_TRUE(commandController, NS_ERROR_FAILURE);
1058 // We must insert at head of the list to be sure our
1059 // controller is found before other implementations
1060 // (e.g., not-implemented versions by browser)
1061 rv = controllers->InsertControllerAt(0, commandController);
1062 NS_ENSURE_SUCCESS(rv, rv);
1064 // Remember the ID for the controller
1065 rv = controllers->GetControllerId(commandController, aControllerId);
1066 NS_ENSURE_SUCCESS(rv, rv);
1069 // Set the context
1070 return SetContextOnControllerById(controllers, aContext, *aControllerId);
1073 nsresult nsEditingSession::SetEditorOnControllers(nsPIDOMWindowOuter& aWindow,
1074 HTMLEditor* aEditor) {
1075 nsCOMPtr<nsIControllers> controllers;
1076 nsresult rv = aWindow.GetControllers(getter_AddRefs(controllers));
1077 NS_ENSURE_SUCCESS(rv, rv);
1079 nsCOMPtr<nsISupports> editorAsISupports = static_cast<nsIEditor*>(aEditor);
1080 if (mBaseCommandControllerId) {
1081 rv = SetContextOnControllerById(controllers, editorAsISupports,
1082 mBaseCommandControllerId);
1083 NS_ENSURE_SUCCESS(rv, rv);
1086 if (mDocStateControllerId) {
1087 rv = SetContextOnControllerById(controllers, editorAsISupports,
1088 mDocStateControllerId);
1089 NS_ENSURE_SUCCESS(rv, rv);
1092 if (mHTMLCommandControllerId) {
1093 rv = SetContextOnControllerById(controllers, editorAsISupports,
1094 mHTMLCommandControllerId);
1097 return rv;
1100 nsresult nsEditingSession::SetContextOnControllerById(
1101 nsIControllers* aControllers, nsISupports* aContext, uint32_t aID) {
1102 NS_ENSURE_ARG_POINTER(aControllers);
1104 // aContext can be null (when destroying editor)
1105 nsCOMPtr<nsIController> controller;
1106 aControllers->GetControllerById(aID, getter_AddRefs(controller));
1108 // ok with nil controller
1109 nsCOMPtr<nsIControllerContext> editorController =
1110 do_QueryInterface(controller);
1111 NS_ENSURE_TRUE(editorController, NS_ERROR_FAILURE);
1113 return editorController->SetCommandContext(aContext);
1116 void nsEditingSession::RemoveEditorControllers(nsPIDOMWindowOuter* aWindow) {
1117 // Remove editor controllers from the aWindow, call when we're
1118 // tearing down/detaching editor.
1120 nsCOMPtr<nsIControllers> controllers;
1121 if (aWindow) {
1122 aWindow->GetControllers(getter_AddRefs(controllers));
1125 if (controllers) {
1126 nsCOMPtr<nsIController> controller;
1127 if (mBaseCommandControllerId) {
1128 controllers->GetControllerById(mBaseCommandControllerId,
1129 getter_AddRefs(controller));
1130 if (controller) {
1131 controllers->RemoveController(controller);
1135 if (mDocStateControllerId) {
1136 controllers->GetControllerById(mDocStateControllerId,
1137 getter_AddRefs(controller));
1138 if (controller) {
1139 controllers->RemoveController(controller);
1143 if (mHTMLCommandControllerId) {
1144 controllers->GetControllerById(mHTMLCommandControllerId,
1145 getter_AddRefs(controller));
1146 if (controller) {
1147 controllers->RemoveController(controller);
1152 // Clear IDs to trigger creation of new controllers.
1153 mBaseCommandControllerId = 0;
1154 mDocStateControllerId = 0;
1155 mHTMLCommandControllerId = 0;
1158 void nsEditingSession::RemoveWebProgressListener(nsPIDOMWindowOuter* aWindow) {
1159 nsIDocShell* docShell = aWindow ? aWindow->GetDocShell() : nullptr;
1160 nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
1161 if (webProgress) {
1162 webProgress->RemoveProgressListener(this);
1163 mProgressListenerRegistered = false;
1167 void nsEditingSession::RestoreAnimationMode(nsPIDOMWindowOuter* aWindow) {
1168 if (mInteractive) {
1169 return;
1172 nsCOMPtr<nsIDocShell> docShell = aWindow ? aWindow->GetDocShell() : nullptr;
1173 NS_ENSURE_TRUE_VOID(docShell);
1174 RefPtr<PresShell> presShell = docShell->GetPresShell();
1175 if (NS_WARN_IF(!presShell)) {
1176 return;
1178 nsPresContext* presContext = presShell->GetPresContext();
1179 NS_ENSURE_TRUE_VOID(presContext);
1181 presContext->SetImageAnimationMode(mImageAnimationMode);
1184 nsresult nsEditingSession::DetachFromWindow(nsPIDOMWindowOuter* aWindow) {
1185 NS_ENSURE_TRUE(mDoneSetup, NS_OK);
1187 NS_ASSERTION(mComposerCommandsUpdater,
1188 "mComposerCommandsUpdater should exist.");
1190 // Kill any existing reload timer
1191 if (mLoadBlankDocTimer) {
1192 mLoadBlankDocTimer->Cancel();
1193 mLoadBlankDocTimer = nullptr;
1196 // Remove controllers, webprogress listener, and otherwise
1197 // make things the way they were before we started editing.
1198 RemoveEditorControllers(aWindow);
1199 RemoveWebProgressListener(aWindow);
1200 RestoreJSAndPlugins(aWindow);
1201 RestoreAnimationMode(aWindow);
1203 // Kill our weak reference to our original window, in case
1204 // it changes on restore, or otherwise dies.
1205 mDocShell = nullptr;
1207 return NS_OK;
1210 nsresult nsEditingSession::ReattachToWindow(nsPIDOMWindowOuter* aWindow) {
1211 NS_ENSURE_TRUE(mDoneSetup, NS_OK);
1212 NS_ENSURE_TRUE(aWindow, NS_ERROR_FAILURE);
1214 NS_ASSERTION(mComposerCommandsUpdater,
1215 "mComposerCommandsUpdater should exist.");
1217 // Imitate nsEditorDocShell::MakeEditable() to reattach the
1218 // old editor ot the window.
1219 nsresult rv;
1221 nsIDocShell* docShell = aWindow->GetDocShell();
1222 NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
1223 mDocShell = do_GetWeakReference(docShell);
1225 // Disable plugins.
1226 if (!mInteractive) {
1227 rv = DisableJSAndPlugins(*docShell);
1228 NS_ENSURE_SUCCESS(rv, rv);
1231 // Tells embedder that startup is in progress.
1232 mEditorStatus = eEditorCreationInProgress;
1234 // Adds back web progress listener.
1235 rv = PrepareForEditing(aWindow);
1236 NS_ENSURE_SUCCESS(rv, rv);
1238 // Setup the command controllers again.
1239 rv = SetupEditorCommandController(
1240 nsBaseCommandController::CreateEditingController, aWindow,
1241 static_cast<nsIEditingSession*>(this), &mBaseCommandControllerId);
1242 NS_ENSURE_SUCCESS(rv, rv);
1244 rv = SetupEditorCommandController(
1245 nsBaseCommandController::CreateHTMLEditorDocStateController, aWindow,
1246 static_cast<nsIEditingSession*>(this), &mDocStateControllerId);
1247 NS_ENSURE_SUCCESS(rv, rv);
1249 if (mComposerCommandsUpdater) {
1250 mComposerCommandsUpdater->Init(*aWindow);
1253 // Get editor
1254 RefPtr<HTMLEditor> htmlEditor = GetHTMLEditorForWindow(aWindow);
1255 if (NS_WARN_IF(!htmlEditor)) {
1256 return NS_ERROR_FAILURE;
1259 if (!mInteractive) {
1260 // Disable animation of images in this document:
1261 RefPtr<PresShell> presShell = docShell->GetPresShell();
1262 if (NS_WARN_IF(!presShell)) {
1263 return NS_ERROR_FAILURE;
1265 nsPresContext* presContext = presShell->GetPresContext();
1266 NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
1268 mImageAnimationMode = presContext->ImageAnimationMode();
1269 presContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
1272 // The third controller takes an nsIEditor as the context
1273 rv = SetupEditorCommandController(
1274 nsBaseCommandController::CreateHTMLEditorController, aWindow,
1275 static_cast<nsIEditor*>(htmlEditor.get()), &mHTMLCommandControllerId);
1276 NS_ENSURE_SUCCESS(rv, rv);
1278 // Set context on all controllers to be the editor
1279 rv = SetEditorOnControllers(*aWindow, htmlEditor);
1280 NS_ENSURE_SUCCESS(rv, rv);
1282 #ifdef DEBUG
1284 bool isEditable;
1285 rv = WindowIsEditable(aWindow, &isEditable);
1286 NS_ENSURE_SUCCESS(rv, rv);
1287 NS_ASSERTION(isEditable,
1288 "Window is not editable after reattaching editor.");
1290 #endif // DEBUG
1292 return NS_OK;
1295 HTMLEditor* nsIEditingSession::GetHTMLEditorForWindow(
1296 mozIDOMWindowProxy* aWindow) {
1297 if (NS_WARN_IF(!aWindow)) {
1298 return nullptr;
1301 nsCOMPtr<nsIDocShell> docShell =
1302 nsPIDOMWindowOuter::From(aWindow)->GetDocShell();
1303 if (NS_WARN_IF(!docShell)) {
1304 return nullptr;
1307 return docShell->GetHTMLEditor();